13bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski/*
23bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * V4L2 Driver for PXA camera host
33bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski *
43bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * Copyright (C) 2006, Sascha Hauer, Pengutronix
53bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
63bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski *
73bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * This program is free software; you can redistribute it and/or modify
83bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * it under the terms of the GNU General Public License as published by
93bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * the Free Software Foundation; either version 2 of the License, or
103bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * (at your option) any later version.
113bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski */
123bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/init.h>
143bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/module.h>
157102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#include <linux/io.h>
163bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/delay.h>
173bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/dma-mapping.h>
183bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/errno.h>
193bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/fs.h>
203bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/interrupt.h>
213bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/kernel.h>
223bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/mm.h>
233bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/moduleparam.h>
243bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/time.h>
253bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/device.h>
263bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/platform_device.h>
273bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/clk.h>
28d514edac5df2149207f1ae2f52de63882c692eecJonathan Cameron#include <linux/sched.h>
295a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <media/v4l2-common.h>
323bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <media/v4l2-dev.h>
33092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas#include <media/videobuf-dma-sg.h>
343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <media/soc_camera.h>
35760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski#include <media/soc_mediabus.h>
363bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#include <linux/videodev2.h>
383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
39cfbaf4dfe765ae33e1a26b3eb0eda64ff00fc481Eric Miao#include <mach/dma.h>
40a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/camera.h>
413bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
4264dc3c1a906467d90c24913b0b38dd13d9378f4fMauro Carvalho Chehab#define PXA_CAM_VERSION "0.0.6"
433bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#define PXA_CAM_DRV_NAME "pxa27x-camera"
443bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
455ca11fa3e0025864df930d6d97470b87c35919edEric Miao/* Camera Interface */
465ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0		0x0000
475ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1		0x0004
485ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2		0x0008
495ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3		0x000C
505ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4		0x0010
515ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR		0x0014
525ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR		0x0018
535ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CITOR		0x001C
545ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIBR0		0x0028
555ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIBR1		0x0030
565ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIBR2		0x0038
575ca11fa3e0025864df930d6d97470b87c35919edEric Miao
585ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_DMAEN	(1 << 31)	/* DMA request enable */
595ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_PAR_EN	(1 << 30)	/* Parity enable */
605ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_SL_CAP_EN	(1 << 29)	/* Capture enable for slave mode */
615ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_ENB	(1 << 28)	/* Camera interface enable */
625ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_DIS	(1 << 27)	/* Camera interface disable */
635ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_SIM	(0x7 << 24)	/* Sensor interface mode mask */
645ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_TOM	(1 << 9)	/* Time-out mask */
655ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_RDAVM	(1 << 8)	/* Receive-data-available mask */
665ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_FEM	(1 << 7)	/* FIFO-empty mask */
675ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_EOLM	(1 << 6)	/* End-of-line mask */
685ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_PERRM	(1 << 5)	/* Parity-error mask */
695ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_QDM	(1 << 4)	/* Quick-disable mask */
705ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_CDM	(1 << 3)	/* Disable-done mask */
715ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_SOFM	(1 << 2)	/* Start-of-frame mask */
725ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_EOFM	(1 << 1)	/* End-of-frame mask */
735ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR0_FOM	(1 << 0)	/* FIFO-overrun mask */
745ca11fa3e0025864df930d6d97470b87c35919edEric Miao
755ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_TBIT	(1 << 31)	/* Transparency bit */
765ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_RGBT_CONV	(0x3 << 29)	/* RGBT conversion mask */
775ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_PPL	(0x7ff << 15)	/* Pixels per line mask */
785ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_RGB_CONV	(0x7 << 12)	/* RGB conversion mask */
795ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_RGB_F	(1 << 11)	/* RGB format */
805ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_YCBCR_F	(1 << 10)	/* YCbCr format */
815ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_RGB_BPP	(0x7 << 7)	/* RGB bis per pixel mask */
825ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_RAW_BPP	(0x3 << 5)	/* Raw bis per pixel mask */
835ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_COLOR_SP	(0x3 << 3)	/* Color space mask */
845ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR1_DW	(0x7 << 0)	/* Data width mask */
855ca11fa3e0025864df930d6d97470b87c35919edEric Miao
865ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2_BLW	(0xff << 24)	/* Beginning-of-line pixel clock
875ca11fa3e0025864df930d6d97470b87c35919edEric Miao					   wait count mask */
885ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2_ELW	(0xff << 16)	/* End-of-line pixel clock
895ca11fa3e0025864df930d6d97470b87c35919edEric Miao					   wait count mask */
905ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2_HSW	(0x3f << 10)	/* Horizontal sync pulse width mask */
915ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2_BFPW	(0x3f << 3)	/* Beginning-of-frame pixel clock
925ca11fa3e0025864df930d6d97470b87c35919edEric Miao					   wait count mask */
935ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR2_FSW	(0x7 << 0)	/* Frame stabilization
945ca11fa3e0025864df930d6d97470b87c35919edEric Miao					   wait count mask */
955ca11fa3e0025864df930d6d97470b87c35919edEric Miao
965ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3_BFW	(0xff << 24)	/* Beginning-of-frame line clock
975ca11fa3e0025864df930d6d97470b87c35919edEric Miao					   wait count mask */
985ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3_EFW	(0xff << 16)	/* End-of-frame line clock
995ca11fa3e0025864df930d6d97470b87c35919edEric Miao					   wait count mask */
1005ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3_VSW	(0x3f << 10)	/* Vertical sync pulse width mask */
1015ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3_BFPW	(0x3f << 3)	/* Beginning-of-frame pixel clock
1025ca11fa3e0025864df930d6d97470b87c35919edEric Miao					   wait count mask */
1035ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR3_LPF	(0x7ff << 0)	/* Lines per frame mask */
1045ca11fa3e0025864df930d6d97470b87c35919edEric Miao
1055ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_MCLK_DLY	(0x3 << 24)	/* MCLK Data Capture Delay mask */
1065ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_PCLK_EN	(1 << 23)	/* Pixel clock enable */
1075ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_PCP	(1 << 22)	/* Pixel clock polarity */
1085ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_HSP	(1 << 21)	/* Horizontal sync polarity */
1095ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_VSP	(1 << 20)	/* Vertical sync polarity */
1105ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_MCLK_EN	(1 << 19)	/* MCLK enable */
1115ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_FR_RATE	(0x7 << 8)	/* Frame rate mask */
1125ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CICR4_DIV	(0xff << 0)	/* Clock divisor mask */
1135ca11fa3e0025864df930d6d97470b87c35919edEric Miao
1145ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_FTO	(1 << 15)	/* FIFO time-out */
1155ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_RDAV_2	(1 << 14)	/* Channel 2 receive data available */
1165ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_RDAV_1	(1 << 13)	/* Channel 1 receive data available */
1175ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_RDAV_0	(1 << 12)	/* Channel 0 receive data available */
1185ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_FEMPTY_2	(1 << 11)	/* Channel 2 FIFO empty */
1195ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_FEMPTY_1	(1 << 10)	/* Channel 1 FIFO empty */
1205ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_FEMPTY_0	(1 << 9)	/* Channel 0 FIFO empty */
1215ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_EOL	(1 << 8)	/* End of line */
1225ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_PAR_ERR	(1 << 7)	/* Parity error */
1235ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_CQD	(1 << 6)	/* Camera interface quick disable */
1245ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_CDD	(1 << 5)	/* Camera interface disable done */
1255ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_SOF	(1 << 4)	/* Start of frame */
1265ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_EOF	(1 << 3)	/* End of frame */
1275ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_IFO_2	(1 << 2)	/* FIFO overrun for Channel 2 */
1285ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_IFO_1	(1 << 1)	/* FIFO overrun for Channel 1 */
1295ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CISR_IFO_0	(1 << 0)	/* FIFO overrun for Channel 0 */
1305ca11fa3e0025864df930d6d97470b87c35919edEric Miao
1315ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FLVL2	(0x7f << 23)	/* FIFO 2 level mask */
1325ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FLVL1	(0x7f << 16)	/* FIFO 1 level mask */
1335ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FLVL0	(0xff << 8)	/* FIFO 0 level mask */
1345ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_THL_0	(0x3 << 4)	/* Threshold Level for Channel 0 FIFO */
1355ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_RESET_F	(1 << 3)	/* Reset input FIFOs */
1365ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FEN2	(1 << 2)	/* FIFO enable for channel 2 */
1375ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FEN1	(1 << 1)	/* FIFO enable for channel 1 */
1385ca11fa3e0025864df930d6d97470b87c35919edEric Miao#define CIFR_FEN0	(1 << 0)	/* FIFO enable for channel 0 */
1395ca11fa3e0025864df930d6d97470b87c35919edEric Miao
1407102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR0_SIM_MP	(0 << 24)
1417102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR0_SIM_SP	(1 << 24)
1427102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR0_SIM_MS	(2 << 24)
1437102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR0_SIM_EP	(3 << 24)
1447102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR0_SIM_ES	(4 << 24)
1457102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski
1467102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR1_DW_VAL(x)   ((x) & CICR1_DW)	    /* Data bus width */
1477102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR1_PPL_VAL(x)  (((x) << 15) & CICR1_PPL) /* Pixels per line */
148a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport#define CICR1_COLOR_SP_VAL(x)	(((x) << 3) & CICR1_COLOR_SP)	/* color space */
149a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport#define CICR1_RGB_BPP_VAL(x)	(((x) << 7) & CICR1_RGB_BPP)	/* bpp for rgb */
150a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport#define CICR1_RGBT_CONV_VAL(x)	(((x) << 29) & CICR1_RGBT_CONV)	/* rgbt conv */
1517102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski
1527102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR2_BLW_VAL(x)  (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */
1537102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR2_ELW_VAL(x)  (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */
1547102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR2_HSW_VAL(x)  (((x) << 10) & CICR2_HSW) /* Horizontal sync pulse width */
1557102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR2_BFPW_VAL(x) (((x) << 3) & CICR2_BFPW) /* Beginning-of-frame pixel clock wait count */
1567102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR2_FSW_VAL(x)  (((x) << 0) & CICR2_FSW)  /* Frame stabilization wait count */
1577102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski
1587102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR3_BFW_VAL(x)  (((x) << 24) & CICR3_BFW) /* Beginning-of-frame line clock wait count  */
1597102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR3_EFW_VAL(x)  (((x) << 16) & CICR3_EFW) /* End-of-frame line clock wait count */
1607102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR3_VSW_VAL(x)  (((x) << 11) & CICR3_VSW) /* Vertical sync pulse width */
1617102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski#define CICR3_LPF_VAL(x)  (((x) << 0) & CICR3_LPF)  /* Lines per frame */
1627102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski
1633bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#define CICR0_IRQ_MASK (CICR0_TOM | CICR0_RDAVM | CICR0_FEM | CICR0_EOLM | \
1643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski			CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \
1653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski			CICR0_EOFM | CICR0_FOM)
1663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
1673bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski/*
1683bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski * Structures
1693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski */
170a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportenum pxa_camera_active_dma {
171a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	DMA_Y = 0x1,
172a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	DMA_U = 0x2,
173a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	DMA_V = 0x4,
174a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport};
175a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
176a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport/* descriptor needed for the PXA DMA engine */
177a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstruct pxa_cam_dma {
178a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	dma_addr_t		sg_dma;
179a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	struct pxa_dma_desc	*sg_cpu;
180a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	size_t			sg_size;
181a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	int			sglen;
182a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport};
1833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
1843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski/* buffer for one video frame */
1853bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistruct pxa_buffer {
1863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	/* common v4l buffer stuff -- must be first */
187760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	struct videobuf_buffer		vb;
188760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	enum v4l2_mbus_pixelcode	code;
189a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	/* our descriptor lists for Y, U and V channels */
190760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	struct pxa_cam_dma		dmas[3];
191760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	int				inwork;
192760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	enum pxa_camera_active_dma	active_dma;
1933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski};
1943bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
1953bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistruct pxa_camera_dev {
196eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski	struct soc_camera_host	soc_host;
1975d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	/*
1985d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * PXA27x is only supposed to handle one camera on its Quick Capture
1993bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	 * interface. If anyone ever builds hardware to enable more than
2005d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * one camera, they will have to modify this driver too
2015d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 */
2023bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct soc_camera_device *icd;
2033bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct clk		*clk;
2043bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2053bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	unsigned int		irq;
2063bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	void __iomem		*base;
207a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
208e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski	int			channels;
209a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	unsigned int		dma_chans[3];
2103bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2113bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxacamera_platform_data *pdata;
2123bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct resource		*res;
2133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	unsigned long		platform_flags;
214cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	unsigned long		ciclk;
215cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	unsigned long		mclk;
216cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	u32			mclk_divisor;
217679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	u16			width_flags;	/* max 10 bits */
2183bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2193bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct list_head	capture;
2203bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2213bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	spinlock_t		lock;
2223bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2233bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_buffer	*active;
2245aa2110f3f33feb4a0c67a4996dc400dc594bc1dGuennadi Liakhovetski	struct pxa_dma_desc	*sg_tail[3];
2253f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik
2263f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik	u32			save_cicr[5];
2273bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski};
2283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2296a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetskistruct pxa_cam {
2306a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	unsigned long flags;
2316a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski};
2326a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
2333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic const char *pxa_cam_driver_description = "PXA_Camera";
2343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2353bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic unsigned int vid_limit = 16;	/* Video memory limit, in Mb */
2363bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski/*
2383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski *  Videobuf operations
2393bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski */
2407102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
2417102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski			      unsigned int *size)
2423bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
2433bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct soc_camera_device *icd = vq->priv_data;
244760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
245760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski						icd->current_fmt->host_fmt);
246760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski
247760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	if (bytes_per_line < 0)
248760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		return bytes_per_line;
2493bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2507dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size);
2513bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
252760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	*size = bytes_per_line * icd->user_height;
2533bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2543bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (0 == *count)
2553bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		*count = 32;
256dab7e3106ddd6cbc3b55301228407b9d17ce7773Andreas Bombe	if (*size * *count > vid_limit * 1024 * 1024)
257dab7e3106ddd6cbc3b55301228407b9d17ce7773Andreas Bombe		*count = (vid_limit * 1024 * 1024) / *size;
2583bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2593bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return 0;
2603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
2613bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2623bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
2633bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
2643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct soc_camera_device *icd = vq->priv_data;
2657dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
2663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
267a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	int i;
2683bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	BUG_ON(in_interrupt());
2703bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2717dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
2723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		&buf->vb, buf->vb.baddr, buf->vb.bsize);
2733bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2745d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	/*
2755d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * This waits until this buffer is out of danger, i.e., until it is no
2765d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * longer in STATE_QUEUED or STATE_ACTIVE
2775d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 */
2780e0809a58869e3e422985f868ad5e0da1fc0ba85Hans Verkuil	videobuf_waiton(vq, &buf->vb, 0, 0);
279952684035a91334dbe33b15063514cab5e7c6907Laurent Pinchart	videobuf_dma_unmap(vq->dev, dma);
2803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	videobuf_dma_free(dma);
2813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
282a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
283a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		if (buf->dmas[i].sg_cpu)
28496c75399544838e1752001c8abdde36dd459cf8fGuennadi Liakhovetski			dma_free_coherent(ici->v4l2_dev.dev,
28596c75399544838e1752001c8abdde36dd459cf8fGuennadi Liakhovetski					  buf->dmas[i].sg_size,
286a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport					  buf->dmas[i].sg_cpu,
287a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport					  buf->dmas[i].sg_dma);
288a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		buf->dmas[i].sg_cpu = NULL;
289a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	}
2903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
2913bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	buf->vb.state = VIDEOBUF_NEEDS_INIT;
2923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
2933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
29437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmikstatic int calculate_dma_sglen(struct scatterlist *sglist, int sglen,
29537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik			       int sg_first_ofs, int size)
29637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik{
29737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	int i, offset, dma_len, xfer_len;
29837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	struct scatterlist *sg;
29937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
30037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	offset = sg_first_ofs;
30137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	for_each_sg(sglist, sg, sglen, i) {
30237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		dma_len = sg_dma_len(sg);
30337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
30437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		/* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
30537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		xfer_len = roundup(min(dma_len - offset, size), 8);
30637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
30737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		size = max(0, size - xfer_len);
30837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		offset = 0;
30937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		if (size == 0)
31037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik			break;
31137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	}
31237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
31337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	BUG_ON(size != 0);
31437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	return i + 1;
31537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik}
31637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
31737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik/**
31837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * pxa_init_dma_channel - init dma descriptors
31937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @pcdev: pxa camera device
32037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @buf: pxa buffer to find pxa dma channel
32137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @dma: dma video buffer
32237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @channel: dma channel (0 => 'Y', 1 => 'U', 2 => 'V')
32337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @cibr: camera Receive Buffer Register
32437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @size: bytes to transfer
32537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @sg_first: first element of sg_list
32637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * @sg_first_ofs: offset in first element of sg_list
32737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik *
32837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * Prepares the pxa dma descriptors to transfer one camera channel.
32937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * Beware sg_first and sg_first_ofs are both input and output parameters.
33037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik *
33137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik * Returns 0 or -ENOMEM if no coherent memory is available
33237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik */
333a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
334a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport				struct pxa_buffer *buf,
335a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport				struct videobuf_dmabuf *dma, int channel,
33637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik				int cibr, int size,
33737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik				struct scatterlist **sg_first, int *sg_first_ofs)
338a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport{
339a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	struct pxa_cam_dma *pxa_dma = &buf->dmas[channel];
340979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	struct device *dev = pcdev->soc_host.v4l2_dev.dev;
34137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	struct scatterlist *sg;
34237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	int i, offset, sglen;
34337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	int dma_len = 0, xfer_len = 0;
344a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
345a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	if (pxa_dma->sg_cpu)
346979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski		dma_free_coherent(dev, pxa_dma->sg_size,
347a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport				  pxa_dma->sg_cpu, pxa_dma->sg_dma);
348a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
34937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	sglen = calculate_dma_sglen(*sg_first, dma->sglen,
35037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik				    *sg_first_ofs, size);
35137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
352a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
353979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	pxa_dma->sg_cpu = dma_alloc_coherent(dev, pxa_dma->sg_size,
354a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport					     &pxa_dma->sg_dma, GFP_KERNEL);
355a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	if (!pxa_dma->sg_cpu)
356a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		return -ENOMEM;
357a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
358a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pxa_dma->sglen = sglen;
35937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	offset = *sg_first_ofs;
360a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
361979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	dev_dbg(dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n",
36237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		*sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma);
363a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
36437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
36537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	for_each_sg(*sg_first, sg, sglen, i) {
36637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		dma_len = sg_dma_len(sg);
367a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
368a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		/* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
36937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		xfer_len = roundup(min(dma_len - offset, size), 8);
370a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
37137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		size = max(0, size - xfer_len);
37237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
37337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr;
37437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		pxa_dma->sg_cpu[i].dtadr = sg_dma_address(sg) + offset;
375a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		pxa_dma->sg_cpu[i].dcmd =
376a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport			DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len;
377256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik#ifdef DEBUG
378256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		if (!i)
379256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik			pxa_dma->sg_cpu[i].dcmd |= DCMD_STARTIRQEN;
380256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik#endif
381a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		pxa_dma->sg_cpu[i].ddadr =
382a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport			pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
38337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
384979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski		dev_vdbg(dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n",
38537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik			 pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc),
38637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik			 sg_dma_address(sg) + offset, xfer_len);
38737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		offset = 0;
38837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
38937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		if (size == 0)
39037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik			break;
391a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	}
392a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
393256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	pxa_dma->sg_cpu[sglen].ddadr = DDADR_STOP;
394256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	pxa_dma->sg_cpu[sglen].dcmd  = DCMD_FLOWSRC | DCMD_BURST8 | DCMD_ENDIRQEN;
395a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
39637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	/*
39737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	 * Handle 1 special case :
39837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	 *  - in 3 planes (YUV422P format), we might finish with xfer_len equal
39937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	 *    to dma_len (end on PAGE boundary). In this case, the sg element
40037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	 *    for next plane should be the next after the last used to store the
40137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	 *    last scatter gather RAM page
40237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	 */
40337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	if (xfer_len >= dma_len) {
40437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		*sg_first_ofs = xfer_len - dma_len;
40537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		*sg_first = sg_next(sg);
40637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	} else {
40737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		*sg_first_ofs = xfer_len;
40837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		*sg_first = sg;
40937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik	}
41037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
411a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	return 0;
412a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport}
413a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
414256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_videobuf_set_actdma(struct pxa_camera_dev *pcdev,
415256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik				    struct pxa_buffer *buf)
416256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{
417256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	buf->active_dma = DMA_Y;
418256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	if (pcdev->channels == 3)
419256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		buf->active_dma |= DMA_U | DMA_V;
420256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik}
421256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
422256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik/*
423256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Please check the DMA prepared buffer structure in :
424256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik *   Documentation/video4linux/pxa_camera.txt
425256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Please check also in pxa_camera_check_link_miss() to understand why DMA chain
426256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * modification while DMA chain is running will work anyway.
427256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik */
4287102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic int pxa_videobuf_prepare(struct videobuf_queue *vq,
4297102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski		struct videobuf_buffer *vb, enum v4l2_field field)
4303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
4313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct soc_camera_device *icd = vq->priv_data;
4327dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
4333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_camera_dev *pcdev = ici->priv;
434979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	struct device *dev = pcdev->soc_host.v4l2_dev.dev;
4353bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
436a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	int ret;
437a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	int size_y, size_u = 0, size_v = 0;
438760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
439760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski						icd->current_fmt->host_fmt);
440760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski
441760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	if (bytes_per_line < 0)
442760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		return bytes_per_line;
4433bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
444979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
4453bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		vb, vb->baddr, vb->bsize);
4463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
4473bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	/* Added list head initialization on alloc */
4483bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	WARN_ON(!list_empty(&vb->queue));
4493bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
4503bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#ifdef DEBUG
4515d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	/*
4525d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * This can be useful if you want to see if we actually fill
4535d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * the buffer with something
4545d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 */
4553bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	memset((void *)vb->baddr, 0xaa, vb->bsize);
4563bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#endif
4573bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
4583bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	BUG_ON(NULL == icd->current_fmt);
4593bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
4605d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	/*
4615d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * I think, in buf_prepare you only have to protect global data,
4625d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * the actual buffer is yours
4635d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 */
4643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	buf->inwork = 1;
4653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
466760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	if (buf->code	!= icd->current_fmt->code ||
4676a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	    vb->width	!= icd->user_width ||
4686a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	    vb->height	!= icd->user_height ||
4693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	    vb->field	!= field) {
470760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		buf->code	= icd->current_fmt->code;
4716a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		vb->width	= icd->user_width;
4726a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		vb->height	= icd->user_height;
4733bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		vb->field	= field;
4743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		vb->state	= VIDEOBUF_NEEDS_INIT;
4753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
4763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
477760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	vb->size = bytes_per_line * vb->height;
4783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (0 != vb->baddr && vb->bsize < vb->size) {
4793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		ret = -EINVAL;
4803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto out;
4813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
4823bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
4833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (vb->state == VIDEOBUF_NEEDS_INIT) {
48437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		int size = vb->size;
48537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		int next_ofs = 0;
4863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
48737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		struct scatterlist *sg;
4883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
4893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		ret = videobuf_iolock(vq, vb, NULL);
4903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		if (ret)
4913bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski			goto fail;
4923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
4935aa2110f3f33feb4a0c67a4996dc400dc594bc1dGuennadi Liakhovetski		if (pcdev->channels == 3) {
494a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport			size_y = size / 2;
495a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport			size_u = size_v = size / 4;
496a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		} else {
497a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport			size_y = size;
498a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		}
499a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
50037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		sg = dma->sglist;
5013bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
50237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		/* init DMA for Y channel */
50337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y,
50437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik					   &sg, &next_ofs);
505a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		if (ret) {
506979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski			dev_err(dev, "DMA initialization for Y/RGB failed\n");
5073bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski			goto fail;
5083bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		}
5093bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
51037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		/* init DMA for U channel */
51137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		if (size_u)
51237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik			ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1,
51337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik						   size_u, &sg, &next_ofs);
51437f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		if (ret) {
515979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski			dev_err(dev, "DMA initialization for U failed\n");
51637f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik			goto fail_u;
51737f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		}
51837f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik
51937f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		/* init DMA for V channel */
52037f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		if (size_v)
52137f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik			ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2,
52237f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik						   size_v, &sg, &next_ofs);
52337f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik		if (ret) {
524979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski			dev_err(dev, "DMA initialization for V failed\n");
52537f5aefd537d5f98b3fa9726362effeccf1d2161Robert Jarzmik			goto fail_v;
5263bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		}
5273bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
5283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		vb->state = VIDEOBUF_PREPARED;
5293bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
5303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
5313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	buf->inwork = 0;
532256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	pxa_videobuf_set_actdma(pcdev, buf);
5333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
5343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return 0;
5353bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
536a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportfail_v:
537979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	dma_free_coherent(dev, buf->dmas[1].sg_size,
538a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport			  buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
539a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportfail_u:
540979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	dma_free_coherent(dev, buf->dmas[0].sg_size,
541a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport			  buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
5423bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskifail:
5433bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	free_buffer(vq, buf);
5443bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiout:
5453bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	buf->inwork = 0;
5463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return ret;
5473bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
5483bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
549256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik/**
550256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * pxa_dma_start_channels - start DMA channel for active buffer
551256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * @pcdev: pxa camera device
552256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik *
553256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Initialize DMA channels to the beginning of the active video buffer, and
554256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * start these channels.
555256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik */
556256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_dma_start_channels(struct pxa_camera_dev *pcdev)
557256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{
558256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	int i;
559256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	struct pxa_buffer *active;
560256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
561256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	active = pcdev->active;
562256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
563256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	for (i = 0; i < pcdev->channels; i++) {
5640166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
5650166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski			"%s (channel=%d) ddadr=%08x\n", __func__,
566256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik			i, active->dmas[i].sg_dma);
567256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma;
568256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
569256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	}
570256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik}
571256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
572256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev)
573256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{
574256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	int i;
575256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
576256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	for (i = 0; i < pcdev->channels; i++) {
5770166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
5780166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski			"%s (channel=%d)\n", __func__, i);
579256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		DCSR(pcdev->dma_chans[i]) = 0;
580256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	}
581256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik}
582256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
583256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev,
584256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik				 struct pxa_buffer *buf)
585256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{
586256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	int i;
587256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	struct pxa_dma_desc *buf_last_desc;
588256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
589256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	for (i = 0; i < pcdev->channels; i++) {
590256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		buf_last_desc = buf->dmas[i].sg_cpu + buf->dmas[i].sglen;
591256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		buf_last_desc->ddadr = DDADR_STOP;
592256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
593ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski		if (pcdev->sg_tail[i])
594ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski			/* Link the new buffer to the old tail */
595ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski			pcdev->sg_tail[i]->ddadr = buf->dmas[i].sg_dma;
596256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
597ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski		/* Update the channel tail */
598ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski		pcdev->sg_tail[i] = buf_last_desc;
599ae7410e712b33d32337df80f71f702d12a8ebb81Guennadi Liakhovetski	}
600256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik}
601256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
602256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik/**
603256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * pxa_camera_start_capture - start video capturing
604256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * @pcdev: camera device
605256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik *
606256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Launch capturing. DMA channels should not be active yet. They should get
607256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * activated at the end of frame interrupt, to capture only whole frames, and
608256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * never begin the capture of a partial frame.
609256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik */
610256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_camera_start_capture(struct pxa_camera_dev *pcdev)
611256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{
612a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier	unsigned long cicr0;
613256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
614979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__);
615256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	/* Enable End-Of-Frame Interrupt */
616256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB;
617256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	cicr0 &= ~CICR0_EOFM;
618256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	__raw_writel(cicr0, pcdev->base + CICR0);
619256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik}
620256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
621256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev)
622256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{
623256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	unsigned long cicr0;
624256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
625256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	pxa_dma_stop_channels(pcdev);
626256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
627256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	cicr0 = __raw_readl(pcdev->base + CICR0) & ~CICR0_ENB;
628256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	__raw_writel(cicr0, pcdev->base + CICR0);
629256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
6308c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	pcdev->active = NULL;
631979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__);
632256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik}
633256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
6342dd54a54c19d0e5b50f4e1c591653772ead9d4a1Guennadi Liakhovetski/* Called under spinlock_irqsave(&pcdev->lock, ...) */
6357102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic void pxa_videobuf_queue(struct videobuf_queue *vq,
6367102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski			       struct videobuf_buffer *vb)
6373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
6383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct soc_camera_device *icd = vq->priv_data;
6397dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
6403bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_camera_dev *pcdev = ici->priv;
6413bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
6423bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
6437dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d active=%p\n",
6440166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski		__func__, vb, vb->baddr, vb->bsize, pcdev->active);
645256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
6463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	list_add_tail(&vb->queue, &pcdev->capture);
6473bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
6483bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	vb->state = VIDEOBUF_ACTIVE;
649256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	pxa_dma_add_tail_buf(pcdev, buf);
6503bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
651256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	if (!pcdev->active)
652256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		pxa_camera_start_capture(pcdev);
6533bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
6543bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
6553bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic void pxa_videobuf_release(struct videobuf_queue *vq,
6563bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski				 struct videobuf_buffer *vb)
6573bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
6583bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
6593bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#ifdef DEBUG
6603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct soc_camera_device *icd = vq->priv_data;
6617dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct device *dev = icd->parent;
6623bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
6630166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski	dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
6643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		vb, vb->baddr, vb->bsize);
6653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
6663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	switch (vb->state) {
6673bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	case VIDEOBUF_ACTIVE:
6680166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski		dev_dbg(dev, "%s (active)\n", __func__);
6693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		break;
6703bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	case VIDEOBUF_QUEUED:
6710166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski		dev_dbg(dev, "%s (queued)\n", __func__);
6723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		break;
6733bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	case VIDEOBUF_PREPARED:
6740166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski		dev_dbg(dev, "%s (prepared)\n", __func__);
6753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		break;
6763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	default:
6770166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski		dev_dbg(dev, "%s (unknown)\n", __func__);
6783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		break;
6793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
6803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski#endif
6813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
6823bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	free_buffer(vq, buf);
6833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
6843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
685a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
686a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport			      struct videobuf_buffer *vb,
687a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport			      struct pxa_buffer *buf)
688a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport{
689256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	int i;
6905ca11fa3e0025864df930d6d97470b87c35919edEric Miao
691a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	/* _init is used to debug races, see comment in pxa_camera_reqbufs() */
692a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	list_del_init(&vb->queue);
693a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	vb->state = VIDEOBUF_DONE;
694a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	do_gettimeofday(&vb->ts);
695a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	vb->field_count++;
696a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	wake_up(&vb->done);
697979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s dequeud buffer (vb=0x%p)\n",
698979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski		__func__, vb);
699a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
700a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	if (list_empty(&pcdev->capture)) {
701256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		pxa_camera_stop_capture(pcdev);
702256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		for (i = 0; i < pcdev->channels; i++)
703256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik			pcdev->sg_tail[i] = NULL;
704a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		return;
705a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	}
706a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
707a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pcdev->active = list_entry(pcdev->capture.next,
708a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport				   struct pxa_buffer, vb.queue);
709a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport}
710a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
711256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik/**
712256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * pxa_camera_check_link_miss - check missed DMA linking
713256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * @pcdev: camera device
714256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik *
715256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * The DMA chaining is done with DMA running. This means a tiny temporal window
716256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * remains, where a buffer is queued on the chain, while the chain is already
71725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * stopped. This means the tailed buffer would never be transferred by DMA.
718256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * This function restarts the capture for this corner case, where :
719256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik *  - DADR() == DADDR_STOP
720256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik *  - a videobuffer is queued on the pcdev->capture list
721256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik *
722256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Please check the "DMA hot chaining timeslice issue" in
723256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik *   Documentation/video4linux/pxa_camera.txt
724256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik *
725256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik * Context: should only be called within the dma irq handler
726256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik */
727256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmikstatic void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev)
728256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik{
729256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	int i, is_dma_stopped = 1;
730256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
731256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	for (i = 0; i < pcdev->channels; i++)
732256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP)
733256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik			is_dma_stopped = 0;
734979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	dev_dbg(pcdev->soc_host.v4l2_dev.dev,
735979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski		"%s : top queued buffer=%p, dma_stopped=%d\n",
736256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		__func__, pcdev->active, is_dma_stopped);
737256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	if (pcdev->active && is_dma_stopped)
738256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		pxa_camera_start_capture(pcdev);
739256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik}
740256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
741a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
742a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport			       enum pxa_camera_active_dma act_dma)
7433bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
744979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	struct device *dev = pcdev->soc_host.v4l2_dev.dev;
7453bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_buffer *buf;
7463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	unsigned long flags;
747e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski	u32 status, camera_status, overrun;
7483bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct videobuf_buffer *vb;
7493bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
7503bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	spin_lock_irqsave(&pcdev->lock, flags);
7513bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
752a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	status = DCSR(channel);
753256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	DCSR(channel) = status;
754256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
755256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	camera_status = __raw_readl(pcdev->base + CISR);
756256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	overrun = CISR_IFO_0;
757256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	if (pcdev->channels == 3)
758256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		overrun |= CISR_IFO_1 | CISR_IFO_2;
7597102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski
7603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (status & DCSR_BUSERR) {
761979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski		dev_err(dev, "DMA Bus Error IRQ!\n");
7623bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto out;
7633bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
7643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
765256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) {
766979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski		dev_err(dev, "Unknown DMA IRQ source, status: 0x%08x\n",
767979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski			status);
7683bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto out;
7693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
7703bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
7718c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	/*
7728c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	 * pcdev->active should not be NULL in DMA irq handler.
7738c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	 *
7748c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	 * But there is one corner case : if capture was stopped due to an
7758c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	 * overrun of channel 1, and at that same channel 2 was completed.
7768c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	 *
7778c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	 * When handling the overrun in DMA irq for channel 1, we'll stop the
7788c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	 * capture and restart it (and thus set pcdev->active to NULL). But the
7798c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	 * DMA irq handler will already be pending for channel 2. So on entering
7808c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	 * the DMA irq handler for channel 2 there will be no active buffer, yet
7818c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	 * that is normal.
7828c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	 */
7838c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik	if (!pcdev->active)
7843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto out;
7853bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
7863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	vb = &pcdev->active->vb;
7873bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	buf = container_of(vb, struct pxa_buffer, vb);
7883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	WARN_ON(buf->inwork || list_empty(&vb->queue));
7893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
790979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	dev_dbg(dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n",
791256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		__func__, channel, status & DCSR_STARTINTR ? "SOF " : "",
792256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel));
793256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
794256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	if (status & DCSR_ENDINTR) {
7958c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik		/*
7968c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik		 * It's normal if the last frame creates an overrun, as there
7978c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik		 * are no more DMA descriptors to fetch from QCI fifos
7988c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik		 */
7998c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik		if (camera_status & overrun &&
8008c62e221c71a0240f16ea8aa29609f93a68c2ff9Robert Jarzmik		    !list_is_last(pcdev->capture.next, &pcdev->capture)) {
801979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski			dev_dbg(dev, "FIFO overrun! CISR: %x\n",
802256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik				camera_status);
803256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik			pxa_camera_stop_capture(pcdev);
804256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik			pxa_camera_start_capture(pcdev);
805256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik			goto out;
806256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		}
807256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		buf->active_dma &= ~act_dma;
808256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		if (!buf->active_dma) {
809256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik			pxa_camera_wakeup(pcdev, vb, buf);
810256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik			pxa_camera_check_link_miss(pcdev);
811256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		}
812256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	}
8133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
8143bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiout:
8153bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	spin_unlock_irqrestore(&pcdev->lock, flags);
8163bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
8173bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
818a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic void pxa_camera_dma_irq_y(int channel, void *data)
819a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport{
820a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	struct pxa_camera_dev *pcdev = data;
821a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pxa_camera_dma_irq(channel, pcdev, DMA_Y);
822a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport}
823a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
824a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic void pxa_camera_dma_irq_u(int channel, void *data)
825a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport{
826a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	struct pxa_camera_dev *pcdev = data;
827a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pxa_camera_dma_irq(channel, pcdev, DMA_U);
828a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport}
829a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
830a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportstatic void pxa_camera_dma_irq_v(int channel, void *data)
831a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport{
832a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	struct pxa_camera_dev *pcdev = data;
833a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pxa_camera_dma_irq(channel, pcdev, DMA_V);
834a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport}
835a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
8367102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic struct videobuf_queue_ops pxa_videobuf_ops = {
8373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	.buf_setup      = pxa_videobuf_setup,
8383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	.buf_prepare    = pxa_videobuf_prepare,
8393bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	.buf_queue      = pxa_videobuf_queue,
8403bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	.buf_release    = pxa_videobuf_release,
8413bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski};
8423bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
843a034d1b76b173b37f9a3646aa8f50a2c14a0f3eaMagnus Dammstatic void pxa_camera_init_videobuf(struct videobuf_queue *q,
844092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas			      struct soc_camera_device *icd)
845092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas{
8467dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
847a034d1b76b173b37f9a3646aa8f50a2c14a0f3eaMagnus Damm	struct pxa_camera_dev *pcdev = ici->priv;
848a034d1b76b173b37f9a3646aa8f50a2c14a0f3eaMagnus Damm
8495d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	/*
8505d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * We must pass NULL as dev pointer, then all pci_* dma operations
8515d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * transform to normal dma_* ones.
8525d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 */
853a034d1b76b173b37f9a3646aa8f50a2c14a0f3eaMagnus Damm	videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock,
854092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas				V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
855b6a633c18ba83c0c8e96759a31d356bfb77e2b5fGuennadi Liakhovetski				sizeof(struct pxa_buffer), icd, &icd->video_lock);
856092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas}
857092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas
85840e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetskistatic u32 mclk_get_divisor(struct platform_device *pdev,
85940e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski			    struct pxa_camera_dev *pcdev)
8603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
861cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	unsigned long mclk = pcdev->mclk;
8626a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	struct device *dev = &pdev->dev;
863cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	u32 div;
8643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	unsigned long lcdclk;
8653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
866cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	lcdclk = clk_get_rate(pcdev->clk);
867cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	pcdev->ciclk = lcdclk;
8683bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
869cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	/* mclk <= ciclk / 4 (27.4.2) */
870cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	if (mclk > lcdclk / 4) {
871cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		mclk = lcdclk / 4;
872979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski		dev_warn(dev, "Limiting master clock to %lu\n", mclk);
873cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	}
874cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski
875cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	/* We verify mclk != 0, so if anyone breaks it, here comes their Oops */
876cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1;
8773bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
878cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	/* If we're not supplying MCLK, leave it at 0 */
879cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
880cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		pcdev->mclk = lcdclk / (2 * (div + 1));
8813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
882979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	dev_dbg(dev, "LCD clock %luHz, target freq %luHz, divisor %u\n",
88340e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski		lcdclk, mclk, div);
8843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
8853bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return div;
8863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
8873bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
888cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetskistatic void recalculate_fifo_timeout(struct pxa_camera_dev *pcdev,
889cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski				     unsigned long pclk)
890cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski{
891cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	/* We want a timeout > 1 pixel time, not ">=" */
892cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	u32 ciclk_per_pixel = pcdev->ciclk / pclk + 1;
893cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski
894cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	__raw_writel(ciclk_per_pixel, pcdev->base + CITOR);
895cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski}
896cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski
8977102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic void pxa_camera_activate(struct pxa_camera_dev *pcdev)
8983bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
8993bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	u32 cicr4 = 0;
9003bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
9015ca11fa3e0025864df930d6d97470b87c35919edEric Miao	/* disable all interrupts */
9025ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(0x3ff, pcdev->base + CICR0);
9033bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
9043bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
9053bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		cicr4 |= CICR4_PCLK_EN;
9063bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
9073bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		cicr4 |= CICR4_MCLK_EN;
9083bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_PCP)
9093bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		cicr4 |= CICR4_PCP;
9103bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_HSP)
9113bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		cicr4 |= CICR4_HSP;
9123bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_VSP)
9133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		cicr4 |= CICR4_VSP;
9143bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
915cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	__raw_writel(pcdev->mclk_divisor | cicr4, pcdev->base + CICR4);
916cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski
917cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
918cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		/* Initialise the timeout under the assumption pclk = mclk */
919cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		recalculate_fifo_timeout(pcdev, pcdev->mclk);
920cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	else
921cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		/* "Safe default" - 13MHz */
922cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		recalculate_fifo_timeout(pcdev, 13000000);
9233bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
92491acd962301af86d5af02ddefdb8147322a0b9b0Philipp Zabel	clk_prepare_enable(pcdev->clk);
9253bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
9263bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
9277102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic void pxa_camera_deactivate(struct pxa_camera_dev *pcdev)
9283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
92991acd962301af86d5af02ddefdb8147322a0b9b0Philipp Zabel	clk_disable_unprepare(pcdev->clk);
9303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
9313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
9323bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic irqreturn_t pxa_camera_irq(int irq, void *data)
9333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
9343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_camera_dev *pcdev = data;
935a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier	unsigned long status, cifr, cicr0;
936256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	struct pxa_buffer *buf;
937256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	struct videobuf_buffer *vb;
9383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
9395ca11fa3e0025864df930d6d97470b87c35919edEric Miao	status = __raw_readl(pcdev->base + CISR);
9400166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski	dev_dbg(pcdev->soc_host.v4l2_dev.dev,
9410166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski		"Camera interrupt status 0x%lx\n", status);
9423bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
943e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski	if (!status)
944e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski		return IRQ_NONE;
945e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski
9465ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(status, pcdev->base + CISR);
947e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski
948e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski	if (status & CISR_EOF) {
949a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier		/* Reset the FIFOs */
950a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier		cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F;
951a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier		__raw_writel(cifr, pcdev->base + CIFR);
952a47f6be45670465d45a3d27f7ff71986bd35d6c4Stefan Herbrechtsmeier
953256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		pcdev->active = list_first_entry(&pcdev->capture,
954256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik					   struct pxa_buffer, vb.queue);
955256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		vb = &pcdev->active->vb;
956256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		buf = container_of(vb, struct pxa_buffer, vb);
957256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		pxa_videobuf_set_actdma(pcdev, buf);
958256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
959256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		pxa_dma_start_channels(pcdev);
960256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik
9615ca11fa3e0025864df930d6d97470b87c35919edEric Miao		cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_EOFM;
9625ca11fa3e0025864df930d6d97470b87c35919edEric Miao		__raw_writel(cicr0, pcdev->base + CICR0);
963e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski	}
964e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski
9653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return IRQ_HANDLED;
9663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
9673bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
9681c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski/*
9691c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski * The following two functions absolutely depend on the fact, that
9701c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski * there can be only one camera on PXA quick capture interface
9711c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski * Called with .video_lock held
9721c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski */
9737102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic int pxa_camera_add_device(struct soc_camera_device *icd)
9743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
9757dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
9763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_camera_dev *pcdev = ici->priv;
9773bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
978979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	if (pcdev->icd)
979979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski		return -EBUSY;
9803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
9817102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski	pxa_camera_activate(pcdev);
98240e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski
98340e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski	pcdev->icd = icd;
9843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
9857dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	dev_info(icd->parent, "PXA Camera driver attached to camera %d\n",
98640e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski		 icd->devnum);
9873bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
98840e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski	return 0;
9893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
9903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
9911c3bb7431d16f7486a8523d54380bad89c485dc8Guennadi Liakhovetski/* Called with .video_lock held */
9927102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic void pxa_camera_remove_device(struct soc_camera_device *icd)
9933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
9947dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
9953bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_camera_dev *pcdev = ici->priv;
9963bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
9973bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	BUG_ON(icd != pcdev->icd);
9983bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
9997dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	dev_info(icd->parent, "PXA Camera driver detached from camera %d\n",
10003bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		 icd->devnum);
10013bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
10023bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	/* disable capture, disable interrupts */
10035ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(0x3ff, pcdev->base + CICR0);
1004a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
10053bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	/* Stop DMA engine */
1006a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	DCSR(pcdev->dma_chans[0]) = 0;
1007a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	DCSR(pcdev->dma_chans[1]) = 0;
1008a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	DCSR(pcdev->dma_chans[2]) = 0;
10093bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
10107102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski	pxa_camera_deactivate(pcdev);
10113bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
10123bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	pcdev->icd = NULL;
10133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
10143bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
1015ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetskistatic int test_platform_param(struct pxa_camera_dev *pcdev,
1016ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski			       unsigned char buswidth, unsigned long *flags)
10173bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
1018ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski	/*
1019ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski	 * Platform specified synchronization and pixel clock polarities are
1020ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski	 * only a recommendation and are only used during probing. The PXA270
1021ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski	 * quick capture interface supports both.
1022ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski	 */
1023ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski	*flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
1024679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		  V4L2_MBUS_MASTER : V4L2_MBUS_SLAVE) |
1025679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		V4L2_MBUS_HSYNC_ACTIVE_HIGH |
1026679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		V4L2_MBUS_HSYNC_ACTIVE_LOW |
1027679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		V4L2_MBUS_VSYNC_ACTIVE_HIGH |
1028679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		V4L2_MBUS_VSYNC_ACTIVE_LOW |
1029679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		V4L2_MBUS_DATA_ACTIVE_HIGH |
1030679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		V4L2_MBUS_PCLK_SAMPLE_RISING |
1031679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		V4L2_MBUS_PCLK_SAMPLE_FALLING;
10323bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
10333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	/* If requested data width is supported by the platform, use it */
1034679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if ((1 << (buswidth - 1)) & pcdev->width_flags)
1035679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		return 0;
1036ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski
1037679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	return -EINVAL;
1038ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski}
1039ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski
10406a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetskistatic void pxa_camera_setup_cicr(struct soc_camera_device *icd,
10416a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski				  unsigned long flags, __u32 pixfmt)
1042ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski{
10437dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1044ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski	struct pxa_camera_dev *pcdev = ici->priv;
1045325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
10466a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	unsigned long dw, bpp;
1047325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski	u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0, y_skip_top;
1048325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski	int ret = v4l2_subdev_call(sd, sensor, g_skip_top_lines, &y_skip_top);
1049325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski
1050325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski	if (ret < 0)
1051325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski		y_skip_top = 0;
10523bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
10535d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	/*
10545d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * Datawidth is now guaranteed to be equal to one of the three values.
10555d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * We fix bit-per-pixel equal to data-width...
10565d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 */
1057679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	switch (icd->current_fmt->host_fmt->bits_per_sample) {
1058679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	case 10:
10593bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		dw = 4;
10603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		bpp = 0x40;
10613bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		break;
1062679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	case 9:
10633bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		dw = 3;
10643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		bpp = 0x20;
10653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		break;
10663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	default:
10675d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski		/*
10685d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski		 * Actually it can only be 8 now,
10695d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski		 * default is just to silence compiler warnings
10705d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski		 */
1071679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	case 8:
10723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		dw = 2;
10733bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		bpp = 0;
10743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
10753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
10763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
10773bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		cicr4 |= CICR4_PCLK_EN;
10783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
10793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		cicr4 |= CICR4_MCLK_EN;
1080679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
10813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		cicr4 |= CICR4_PCP;
1082679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
10833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		cicr4 |= CICR4_HSP;
1084679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
10853bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		cicr4 |= CICR4_VSP;
10863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
10875ca11fa3e0025864df930d6d97470b87c35919edEric Miao	cicr0 = __raw_readl(pcdev->base + CICR0);
10883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (cicr0 & CICR0_ENB)
10895ca11fa3e0025864df930d6d97470b87c35919edEric Miao		__raw_writel(cicr0 & ~CICR0_ENB, pcdev->base + CICR0);
1090a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
10916a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	cicr1 = CICR1_PPL_VAL(icd->user_width - 1) | bpp | dw;
1092a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
1093a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	switch (pixfmt) {
1094a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	case V4L2_PIX_FMT_YUV422P:
1095e7c506881973d0c762d660005be54c4095219c59Guennadi Liakhovetski		pcdev->channels = 3;
1096a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		cicr1 |= CICR1_YCBCR_F;
10972a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		/*
10982a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		 * Normally, pxa bus wants as input UYVY format. We allow all
10992a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		 * reorderings of the YUV422 format, as no processing is done,
11002a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		 * and the YUV stream is just passed through without any
11012a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		 * transformation. Note that UYVY is the only format that
11022a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		 * should be used if pxa framebuffer Overlay2 is used.
11032a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		 */
11042a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	case V4L2_PIX_FMT_UYVY:
11052a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	case V4L2_PIX_FMT_VYUY:
1106a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	case V4L2_PIX_FMT_YUYV:
11072a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	case V4L2_PIX_FMT_YVYU:
1108a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		cicr1 |= CICR1_COLOR_SP_VAL(2);
1109a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		break;
1110a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	case V4L2_PIX_FMT_RGB555:
1111a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		cicr1 |= CICR1_RGB_BPP_VAL(1) | CICR1_RGBT_CONV_VAL(2) |
1112a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport			CICR1_TBIT | CICR1_COLOR_SP_VAL(1);
1113a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		break;
1114a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	case V4L2_PIX_FMT_RGB565:
1115a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		cicr1 |= CICR1_COLOR_SP_VAL(1) | CICR1_RGB_BPP_VAL(2);
1116a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		break;
1117a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	}
1118a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
11195ca11fa3e0025864df930d6d97470b87c35919edEric Miao	cicr2 = 0;
11206a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	cicr3 = CICR3_LPF_VAL(icd->user_height - 1) |
1121325361088b73269f4cc96256276a142addbf3454Guennadi Liakhovetski		CICR3_BFW_VAL(min((u32)255, y_skip_top));
1122cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	cicr4 |= pcdev->mclk_divisor;
11235ca11fa3e0025864df930d6d97470b87c35919edEric Miao
11245ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(cicr1, pcdev->base + CICR1);
11255ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(cicr2, pcdev->base + CICR2);
11265ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(cicr3, pcdev->base + CICR3);
11275ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(cicr4, pcdev->base + CICR4);
11283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
11293bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	/* CIF interrupts are not used, only DMA */
11305ca11fa3e0025864df930d6d97470b87c35919edEric Miao	cicr0 = (cicr0 & CICR0_ENB) | (pcdev->platform_flags & PXA_CAMERA_MASTER ?
11315ca11fa3e0025864df930d6d97470b87c35919edEric Miao		CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP));
11325ca11fa3e0025864df930d6d97470b87c35919edEric Miao	cicr0 |= CICR0_DMAEN | CICR0_IRQ_MASK;
11335ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(cicr0, pcdev->base + CICR0);
11346a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski}
11356a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
11368843d119eaf1a7a87a2cf8c3eadbd1937b16bc27Guennadi Liakhovetskistatic int pxa_camera_set_bus_param(struct soc_camera_device *icd)
11376a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski{
1138679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
11397dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
11406a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	struct pxa_camera_dev *pcdev = ici->priv;
1141679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
11428843d119eaf1a7a87a2cf8c3eadbd1937b16bc27Guennadi Liakhovetski	u32 pixfmt = icd->current_fmt->host_fmt->fourcc;
1143679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	unsigned long bus_flags, common_flags;
1144760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	int ret;
11456a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	struct pxa_cam *cam = icd->host_priv;
11466a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
1147d2dcad49bc346054b49bd40fd96f397fec695a0fGuennadi Liakhovetski	ret = test_platform_param(pcdev, icd->current_fmt->host_fmt->bits_per_sample,
1148d2dcad49bc346054b49bd40fd96f397fec695a0fGuennadi Liakhovetski				  &bus_flags);
11496a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	if (ret < 0)
11506a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		return ret;
11516a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
1152679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1153679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if (!ret) {
1154679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		common_flags = soc_mbus_config_compatible(&cfg,
1155679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski							  bus_flags);
1156679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		if (!common_flags) {
1157679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski			dev_warn(icd->parent,
1158679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski				 "Flags incompatible: camera 0x%x, host 0x%lx\n",
1159679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski				 cfg.flags, bus_flags);
1160679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski			return -EINVAL;
1161679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		}
1162679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	} else if (ret != -ENOIOCTLCMD) {
1163679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		return ret;
1164679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	} else {
1165679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		common_flags = bus_flags;
1166679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	}
11676a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
11686a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	pcdev->channels = 1;
11696a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
11706a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	/* Make choises, based on platform preferences */
1171679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
1172679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	    (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
11736a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		if (pcdev->platform_flags & PXA_CAMERA_HSP)
1174679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
11756a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		else
1176679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski			common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
11776a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	}
11786a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
1179679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
1180679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	    (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
11816a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		if (pcdev->platform_flags & PXA_CAMERA_VSP)
1182679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
11836a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		else
1184679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski			common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
11856a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	}
11866a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
1187679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
1188679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	    (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
11896a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		if (pcdev->platform_flags & PXA_CAMERA_PCP)
1190679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
11916a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		else
1192679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski			common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
11936a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	}
11946a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
1195679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	cfg.flags = common_flags;
1196679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
1197679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if (ret < 0 && ret != -ENOIOCTLCMD) {
1198679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
1199679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski			common_flags, ret);
12006a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		return ret;
1201679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	}
1202679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski
1203679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	cam->flags = common_flags;
12046a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
12056a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	pxa_camera_setup_cicr(icd, common_flags, pixfmt);
12063bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
12073bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return 0;
12083bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
12093bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
12102a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmikstatic int pxa_camera_try_bus_param(struct soc_camera_device *icd,
12112a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik				    unsigned char buswidth)
1212ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski{
1213679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
12147dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1215ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski	struct pxa_camera_dev *pcdev = ici->priv;
1216679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
1217679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	unsigned long bus_flags, common_flags;
12182a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	int ret = test_platform_param(pcdev, buswidth, &bus_flags);
1219ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski
1220ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski	if (ret < 0)
1221ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski		return ret;
1222ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski
1223679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
1224679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if (!ret) {
1225679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		common_flags = soc_mbus_config_compatible(&cfg,
1226679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski							  bus_flags);
1227679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		if (!common_flags) {
1228679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski			dev_warn(icd->parent,
1229679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski				 "Flags incompatible: camera 0x%x, host 0x%lx\n",
1230679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski				 cfg.flags, bus_flags);
1231679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski			return -EINVAL;
1232679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		}
1233679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	} else if (ret == -ENOIOCTLCMD) {
1234679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		ret = 0;
1235679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	}
1236ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski
1237679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	return ret;
1238ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski}
1239ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski
1240760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetskistatic const struct soc_mbus_pixelfmt pxa_camera_formats[] = {
12412a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	{
1242760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		.fourcc			= V4L2_PIX_FMT_YUV422P,
1243760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		.name			= "Planar YUV422 16 bit",
1244760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		.bits_per_sample	= 8,
1245760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
1246760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		.order			= SOC_MBUS_ORDER_LE,
12472a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	},
12482a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik};
12492a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik
1250760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski/* This will be corrected as we get more formats */
1251760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetskistatic bool pxa_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
1252ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski{
1253760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	return	fmt->packing == SOC_MBUS_PACKING_NONE ||
1254760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		(fmt->bits_per_sample == 8 &&
1255760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		 fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) ||
1256760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		(fmt->bits_per_sample > 8 &&
1257760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
12582a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik}
12592a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik
12603805f201934e5384f6e941222dc1968cb638a88cHans Verkuilstatic int pxa_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
12612a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik				  struct soc_camera_format_xlate *xlate)
12622a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik{
1263760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
12647dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct device *dev = icd->parent;
1265760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	int formats = 0, ret;
12666a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	struct pxa_cam *cam;
1267760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	enum v4l2_mbus_pixelcode code;
1268760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	const struct soc_mbus_pixelfmt *fmt;
12692a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik
1270760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1271760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	if (ret < 0)
1272760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		/* No more formats */
1273760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		return 0;
12742a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik
1275760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	fmt = soc_mbus_get_fmtdesc(code);
1276760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	if (!fmt) {
12773805f201934e5384f6e941222dc1968cb638a88cHans Verkuil		dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
12782a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		return 0;
1279760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	}
12803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
1281760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	/* This also checks support for the requested bits-per-sample */
1282760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	ret = pxa_camera_try_bus_param(icd, fmt->bits_per_sample);
12832a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	if (ret < 0)
12842a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		return 0;
12852a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik
12866a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	if (!icd->host_priv) {
12876a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		cam = kzalloc(sizeof(*cam), GFP_KERNEL);
12886a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		if (!cam)
12896a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski			return -ENOMEM;
12906a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
12916a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		icd->host_priv = cam;
12926a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	} else {
12936a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		cam = icd->host_priv;
12946a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	}
12956a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
1296760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	switch (code) {
1297ace6e9799f585994c92ac3c0696bc336e50077e6Guennadi Liakhovetski	case V4L2_MBUS_FMT_UYVY8_2X8:
12982a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		formats++;
12992a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		if (xlate) {
1300760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski			xlate->host_fmt	= &pxa_camera_formats[0];
1301760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski			xlate->code	= code;
13022a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik			xlate++;
1303760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski			dev_dbg(dev, "Providing format %s using code %d\n",
1304760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski				pxa_camera_formats[0].name, code);
13052a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		}
1306ace6e9799f585994c92ac3c0696bc336e50077e6Guennadi Liakhovetski	case V4L2_MBUS_FMT_VYUY8_2X8:
1307ace6e9799f585994c92ac3c0696bc336e50077e6Guennadi Liakhovetski	case V4L2_MBUS_FMT_YUYV8_2X8:
1308ace6e9799f585994c92ac3c0696bc336e50077e6Guennadi Liakhovetski	case V4L2_MBUS_FMT_YVYU8_2X8:
1309760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	case V4L2_MBUS_FMT_RGB565_2X8_LE:
1310760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
1311760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		if (xlate)
13120166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski			dev_dbg(dev, "Providing format %s packed\n",
1313760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski				fmt->name);
13142a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik		break;
13152a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	default:
1316760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		if (!pxa_camera_packing_supported(fmt))
1317760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski			return 0;
1318760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		if (xlate)
13190166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski			dev_dbg(dev,
13202a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik				"Providing format %s in pass-through mode\n",
1321760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski				fmt->name);
1322760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	}
1323760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski
1324760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	/* Generic pass-through */
1325760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	formats++;
1326760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	if (xlate) {
1327760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		xlate->host_fmt	= fmt;
1328760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		xlate->code	= code;
1329760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		xlate++;
13302a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	}
13312a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik
13322a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	return formats;
13332a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik}
13342a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik
13356a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetskistatic void pxa_camera_put_formats(struct soc_camera_device *icd)
13366a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski{
13376a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	kfree(icd->host_priv);
13386a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	icd->host_priv = NULL;
13396a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski}
13406a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
1341760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetskistatic int pxa_camera_check_frame(u32 width, u32 height)
13426a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski{
13436a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	/* limit to pxa hardware capabilities */
1344760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	return height < 32 || height > 2048 || width < 48 || width > 2048 ||
1345760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		(width & 0x01);
13466a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski}
13476a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
134809e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetskistatic int pxa_camera_set_crop(struct soc_camera_device *icd,
134908590b9613f7f624fe3a052586eea2dbb3584b38Guennadi Liakhovetski			       struct v4l2_crop *a)
135009e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski{
135108590b9613f7f624fe3a052586eea2dbb3584b38Guennadi Liakhovetski	struct v4l2_rect *rect = &a->c;
13527dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct device *dev = icd->parent;
13537dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(dev);
135409e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	struct pxa_camera_dev *pcdev = ici->priv;
1355c9c1f1c0dbe90b82939917fdc3e4c9ccad42342dGuennadi Liakhovetski	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
135609e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	struct soc_camera_sense sense = {
135709e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski		.master_clock = pcdev->mclk,
135809e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski		.pixel_clock_max = pcdev->ciclk / 4,
135909e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	};
1360760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	struct v4l2_mbus_framefmt mf;
13616a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	struct pxa_cam *cam = icd->host_priv;
1362760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	u32 fourcc = icd->current_fmt->host_fmt->fourcc;
136309e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	int ret;
136409e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski
136509e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	/* If PCLK is used to latch data from the sensor, check sense */
136609e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
136709e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski		icd->sense = &sense;
136809e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski
136908590b9613f7f624fe3a052586eea2dbb3584b38Guennadi Liakhovetski	ret = v4l2_subdev_call(sd, video, s_crop, a);
137009e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski
137109e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	icd->sense = NULL;
137209e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski
137309e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	if (ret < 0) {
13740166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski		dev_warn(dev, "Failed to crop to %ux%u@%u:%u\n",
137509e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski			 rect->width, rect->height, rect->left, rect->top);
13766a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		return ret;
13776a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	}
13786a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
1379760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
13806a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	if (ret < 0)
13816a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		return ret;
13826a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
1383760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	if (pxa_camera_check_frame(mf.width, mf.height)) {
13846a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		/*
13856a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		 * Camera cropping produced a frame beyond our capabilities.
13866a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		 * FIXME: just extract a subframe, that we can process.
13876a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		 */
1388760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		v4l_bound_align_image(&mf.width, 48, 2048, 1,
1389760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski			&mf.height, 32, 2048, 0,
1390760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski			fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0);
1391760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
13926a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		if (ret < 0)
13936a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski			return ret;
13946a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
1395760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		if (pxa_camera_check_frame(mf.width, mf.height)) {
13967dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski			dev_warn(icd->parent,
13976a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski				 "Inconsistent state. Use S_FMT to repair\n");
13986a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski			return -EINVAL;
13996a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		}
14006a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	}
14016a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
14026a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
140309e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski		if (sense.pixel_clock > sense.pixel_clock_max) {
14040166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski			dev_err(dev,
140509e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski				"pixel clock %lu set by the camera too high!",
140609e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski				sense.pixel_clock);
140709e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski			return -EIO;
140809e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski		}
140909e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski		recalculate_fifo_timeout(pcdev, sense.pixel_clock);
141009e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	}
141109e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski
1412760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	icd->user_width		= mf.width;
1413760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	icd->user_height	= mf.height;
14146a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
1415760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	pxa_camera_setup_cicr(icd, cam->flags, fourcc);
14166a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski
141709e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	return ret;
141809e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski}
141909e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski
1420d8fac217c58f0101a351b9c8c80f1665bd9efef9Guennadi Liakhovetskistatic int pxa_camera_set_fmt(struct soc_camera_device *icd,
142109e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski			      struct v4l2_format *f)
1422ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski{
14237dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct device *dev = icd->parent;
14247dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(dev);
1425cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	struct pxa_camera_dev *pcdev = ici->priv;
1426c9c1f1c0dbe90b82939917fdc3e4c9ccad42342dGuennadi Liakhovetski	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
14270ad675eb4533402fd7b03b25d1d4a0ab7a43ae6dGuennadi Liakhovetski	const struct soc_camera_format_xlate *xlate = NULL;
1428cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	struct soc_camera_sense sense = {
1429cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		.master_clock = pcdev->mclk,
1430cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		.pixel_clock_max = pcdev->ciclk / 4,
1431cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	};
143209e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	struct v4l2_pix_format *pix = &f->fmt.pix;
1433760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	struct v4l2_mbus_framefmt mf;
14340ad675eb4533402fd7b03b25d1d4a0ab7a43ae6dGuennadi Liakhovetski	int ret;
143525c4d74ea6f07f2aaa3df537619680ba967043f5Guennadi Liakhovetski
143609e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
143709e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	if (!xlate) {
14380166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski		dev_warn(dev, "Format %x not found\n", pix->pixelformat);
143909e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski		return -EINVAL;
14400ad675eb4533402fd7b03b25d1d4a0ab7a43ae6dGuennadi Liakhovetski	}
14412a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik
1442cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	/* If PCLK is used to latch data from the sensor, check sense */
1443cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
1444760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		/* The caller holds a mutex. */
1445cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		icd->sense = &sense;
1446cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski
1447760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	mf.width	= pix->width;
1448760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	mf.height	= pix->height;
1449760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	mf.field	= pix->field;
1450760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	mf.colorspace	= pix->colorspace;
1451760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	mf.code		= xlate->code;
1452760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski
1453760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1454760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski
1455760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	if (mf.code != xlate->code)
1456760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		return -EINVAL;
14572a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik
1458cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	icd->sense = NULL;
1459cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski
1460cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	if (ret < 0) {
14610166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski		dev_warn(dev, "Failed to configure for format %x\n",
146209e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski			 pix->pixelformat);
1463760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	} else if (pxa_camera_check_frame(mf.width, mf.height)) {
14646a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		dev_warn(dev,
14656a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski			 "Camera driver produced an unsupported frame %dx%d\n",
1466760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski			 mf.width, mf.height);
14676a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski		ret = -EINVAL;
1468cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	} else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
1469cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		if (sense.pixel_clock > sense.pixel_clock_max) {
14700166b74374cae3fa8bff0caef726a3d960a9a50aGuennadi Liakhovetski			dev_err(dev,
1471cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski				"pixel clock %lu set by the camera too high!",
1472cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski				sense.pixel_clock);
1473cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski			return -EIO;
1474cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		}
1475cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		recalculate_fifo_timeout(pcdev, sense.pixel_clock);
1476cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	}
14772a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik
1478760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	if (ret < 0)
1479760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		return ret;
1480760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski
1481760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	pix->width		= mf.width;
1482760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	pix->height		= mf.height;
1483760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	pix->field		= mf.field;
1484760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	pix->colorspace		= mf.colorspace;
1485760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	icd->current_fmt	= xlate;
148625c4d74ea6f07f2aaa3df537619680ba967043f5Guennadi Liakhovetski
148725c4d74ea6f07f2aaa3df537619680ba967043f5Guennadi Liakhovetski	return ret;
1488ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski}
1489ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski
1490d8fac217c58f0101a351b9c8c80f1665bd9efef9Guennadi Liakhovetskistatic int pxa_camera_try_fmt(struct soc_camera_device *icd,
1491d8fac217c58f0101a351b9c8c80f1665bd9efef9Guennadi Liakhovetski			      struct v4l2_format *f)
14923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
1493c9c1f1c0dbe90b82939917fdc3e4c9ccad42342dGuennadi Liakhovetski	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
14942a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	const struct soc_camera_format_xlate *xlate;
14952a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	struct v4l2_pix_format *pix = &f->fmt.pix;
1496760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	struct v4l2_mbus_framefmt mf;
14972a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	__u32 pixfmt = pix->pixelformat;
1498bf507158eb27ea94aca300b28ecee60fdbb40007Guennadi Liakhovetski	int ret;
1499a2c8c68cca3dbb0c87f5034ab8ea29350174ec4aGuennadi Liakhovetski
15002a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
15012a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	if (!xlate) {
15027dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski		dev_warn(icd->parent, "Format %x not found\n", pixfmt);
150325c4d74ea6f07f2aaa3df537619680ba967043f5Guennadi Liakhovetski		return -EINVAL;
15042a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	}
150525c4d74ea6f07f2aaa3df537619680ba967043f5Guennadi Liakhovetski
150692a8337b380f0978ac81f096d6324d3ad689f83eRobert Jarzmik	/*
15074a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho	 * Limit to pxa hardware capabilities.  YUV422P planar format requires
15084a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho	 * images size to be a multiple of 16 bytes.  If not, zeros will be
15094a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho	 * inserted between Y and U planes, and U and V planes, which violates
15104a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho	 * the YUV422P standard.
151192a8337b380f0978ac81f096d6324d3ad689f83eRobert Jarzmik	 */
15124a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho	v4l_bound_align_image(&pix->width, 48, 2048, 1,
15134a6b8df2133c1f218a503e0432a9e6cc3d461a30Trent Piepho			      &pix->height, 32, 2048, 0,
15146a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski			      pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0);
151592a8337b380f0978ac81f096d6324d3ad689f83eRobert Jarzmik
1516ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski	/* limit to sensor capabilities */
1517760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	mf.width	= pix->width;
1518760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	mf.height	= pix->height;
151991401219c073a565af79223215a84250bbc8c79eGuennadi Liakhovetski	/* Only progressive video supported so far */
152091401219c073a565af79223215a84250bbc8c79eGuennadi Liakhovetski	mf.field	= V4L2_FIELD_NONE;
1521760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	mf.colorspace	= pix->colorspace;
1522760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	mf.code		= xlate->code;
1523bf507158eb27ea94aca300b28ecee60fdbb40007Guennadi Liakhovetski
1524760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
1525760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	if (ret < 0)
1526760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		return ret;
152706daa1af4d207e93c9a8a3e54adef8635ba81c94Guennadi Liakhovetski
1528760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	pix->width	= mf.width;
1529760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	pix->height	= mf.height;
1530760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	pix->colorspace	= mf.colorspace;
1531760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski
1532760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	switch (mf.field) {
1533760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	case V4L2_FIELD_ANY:
1534760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	case V4L2_FIELD_NONE:
1535760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		pix->field	= V4L2_FIELD_NONE;
1536760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		break;
1537760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski	default:
1538760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski		/* TODO: support interlaced at least in pass-through mode */
15397dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski		dev_err(icd->parent, "Field type %d unsupported.\n",
1540760697beca338599a65484389c7abbe54aedb664Guennadi Liakhovetski			mf.field);
154106daa1af4d207e93c9a8a3e54adef8635ba81c94Guennadi Liakhovetski		return -EINVAL;
154206daa1af4d207e93c9a8a3e54adef8635ba81c94Guennadi Liakhovetski	}
154306daa1af4d207e93c9a8a3e54adef8635ba81c94Guennadi Liakhovetski
1544bf507158eb27ea94aca300b28ecee60fdbb40007Guennadi Liakhovetski	return ret;
15453bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
15463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
154757bee29d6e8cf721864fa47a18366bee5ff24f21Guennadi Liakhovetskistatic int pxa_camera_reqbufs(struct soc_camera_device *icd,
15487102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski			      struct v4l2_requestbuffers *p)
15493bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
15503bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	int i;
15513bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
15525d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	/*
15535d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * This is for locking debugging only. I removed spinlocks and now I
15543bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	 * check whether .prepare is ever called on a linked buffer, or whether
15553bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
15565d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 * it hadn't triggered
15575d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski	 */
15583bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	for (i = 0; i < p->count; i++) {
155957bee29d6e8cf721864fa47a18366bee5ff24f21Guennadi Liakhovetski		struct pxa_buffer *buf = container_of(icd->vb_vidq.bufs[i],
15603bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski						      struct pxa_buffer, vb);
15613bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		buf->inwork = 0;
15623bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		INIT_LIST_HEAD(&buf->vb.queue);
15633bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
15643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
15653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return 0;
15663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
15673bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
15687102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic unsigned int pxa_camera_poll(struct file *file, poll_table *pt)
15693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
157057bee29d6e8cf721864fa47a18366bee5ff24f21Guennadi Liakhovetski	struct soc_camera_device *icd = file->private_data;
15713bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_buffer *buf;
15723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
157357bee29d6e8cf721864fa47a18366bee5ff24f21Guennadi Liakhovetski	buf = list_entry(icd->vb_vidq.stream.next, struct pxa_buffer,
15743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski			 vb.stream);
15753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
15763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	poll_wait(file, &buf->vb.done, pt);
15773bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
15783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (buf->vb.state == VIDEOBUF_DONE ||
15793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	    buf->vb.state == VIDEOBUF_ERROR)
15803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		return POLLIN|POLLRDNORM;
15813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
15823bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return 0;
15833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
15843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
15857102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetskistatic int pxa_camera_querycap(struct soc_camera_host *ici,
15867102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski			       struct v4l2_capability *cap)
15873bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
15883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	/* cap->name is set by the firendly caller:-> */
15893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card));
15903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
15913bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
15923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return 0;
15933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
15943bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
15957254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetskistatic int pxa_camera_suspend(struct device *dev)
15963f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik{
15977254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(dev);
15983f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik	struct pxa_camera_dev *pcdev = ici->priv;
15993f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik	int i = 0, ret = 0;
16003f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik
16015ca11fa3e0025864df930d6d97470b87c35919edEric Miao	pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR0);
16025ca11fa3e0025864df930d6d97470b87c35919edEric Miao	pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR1);
16035ca11fa3e0025864df930d6d97470b87c35919edEric Miao	pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR2);
16045ca11fa3e0025864df930d6d97470b87c35919edEric Miao	pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR3);
16055ca11fa3e0025864df930d6d97470b87c35919edEric Miao	pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR4);
16063f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik
1607497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski	if (pcdev->icd) {
16087254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski		struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->icd);
1609497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski		ret = v4l2_subdev_call(sd, core, s_power, 0);
1610497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski		if (ret == -ENOIOCTLCMD)
1611497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski			ret = 0;
1612497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski	}
16133f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik
16143f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik	return ret;
16153f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik}
16163f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik
16177254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetskistatic int pxa_camera_resume(struct device *dev)
16183f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik{
16197254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski	struct soc_camera_host *ici = to_soc_camera_host(dev);
16203f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik	struct pxa_camera_dev *pcdev = ici->priv;
16213f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik	int i = 0, ret = 0;
16223f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik
162387f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
162487f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
162587f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao	DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;
16263f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik
16275ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(pcdev->save_cicr[i++] & ~CICR0_ENB, pcdev->base + CICR0);
16285ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR1);
16295ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR2);
16305ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR3);
16315ca11fa3e0025864df930d6d97470b87c35919edEric Miao	__raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR4);
16323f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik
1633497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski	if (pcdev->icd) {
16347254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski		struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->icd);
1635497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski		ret = v4l2_subdev_call(sd, core, s_power, 1);
1636497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski		if (ret == -ENOIOCTLCMD)
1637497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski			ret = 0;
1638497833c6813dde5ca27cc94e28c973d601d601e1Guennadi Liakhovetski	}
16393f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik
16403f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik	/* Restart frame capture if active buffer exists */
1641256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik	if (!ret && pcdev->active)
1642256b02332a0ba1d7382d736d776e605be63ded17Robert Jarzmik		pxa_camera_start_capture(pcdev);
16433f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik
16443f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik	return ret;
16453f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik}
16463f6ac497b036533d1a63ba04fdbe710c55e14cdaRobert Jarzmik
1647b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetskistatic struct soc_camera_host_ops pxa_soc_camera_host_ops = {
1648b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski	.owner		= THIS_MODULE,
1649b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski	.add		= pxa_camera_add_device,
1650b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski	.remove		= pxa_camera_remove_device,
165109e231b35173313cd92e27532e5028f2042dcee4Guennadi Liakhovetski	.set_crop	= pxa_camera_set_crop,
16522a48fc739df213b8f98b4effd95ce5ec93bca3daRobert Jarzmik	.get_formats	= pxa_camera_get_formats,
16536a6c8786725c0b3d143674effa8b772f47b1c189Guennadi Liakhovetski	.put_formats	= pxa_camera_put_formats,
1654d8fac217c58f0101a351b9c8c80f1665bd9efef9Guennadi Liakhovetski	.set_fmt	= pxa_camera_set_fmt,
1655d8fac217c58f0101a351b9c8c80f1665bd9efef9Guennadi Liakhovetski	.try_fmt	= pxa_camera_try_fmt,
1656092d3921195c4553a1818e698cee7a281ab361f4Paulius Zaleckas	.init_videobuf	= pxa_camera_init_videobuf,
1657b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski	.reqbufs	= pxa_camera_reqbufs,
1658b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski	.poll		= pxa_camera_poll,
1659b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski	.querycap	= pxa_camera_querycap,
1660b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski	.set_bus_param	= pxa_camera_set_bus_param,
1661b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski};
1662b8d9904c3525c0a149976ffaad48fcb03e8703f7Guennadi Liakhovetski
1663e36bc31f823d6089bedc935fea82b6d36793412aJean Delvarestatic int __devinit pxa_camera_probe(struct platform_device *pdev)
16643bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
16653bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct pxa_camera_dev *pcdev;
16663bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct resource *res;
16673bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	void __iomem *base;
166802da465945ae0a277aadf2bf37965a9e6c28f8c3Guennadi Liakhovetski	int irq;
16693bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	int err = 0;
16703bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
16713bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
16723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	irq = platform_get_irq(pdev, 0);
167302da465945ae0a277aadf2bf37965a9e6c28f8c3Guennadi Liakhovetski	if (!res || irq < 0) {
16743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		err = -ENODEV;
16753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto exit;
16763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
16773bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
16783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
16793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (!pcdev) {
16807102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski		dev_err(&pdev->dev, "Could not allocate pcdev\n");
16813bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		err = -ENOMEM;
16823bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto exit;
16833bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
16843bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
1685e0d8b13ae1e3ea747620580b6f777992148de182Russell King	pcdev->clk = clk_get(&pdev->dev, NULL);
16863bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (IS_ERR(pcdev->clk)) {
16873bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		err = PTR_ERR(pcdev->clk);
16883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto exit_kfree;
16893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
16903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
16913bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	pcdev->res = res;
16923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
16933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	pcdev->pdata = pdev->dev.platform_data;
16943bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	pcdev->platform_flags = pcdev->pdata->flags;
1695ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski	if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
1696ad5f2e859d76dccb7eb1aa942171b1a32211efc2Guennadi Liakhovetski			PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
16975d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski		/*
16985d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski		 * Platform hasn't set available data widths. This is bad.
16995d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski		 * Warn and use a default.
17005d28d525452f170e30bc038955439731462a5228Guennadi Liakhovetski		 */
17013bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
17023bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski			 "data widths, using default 10 bit\n");
17033bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
17043bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
1705679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8)
1706679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		pcdev->width_flags = 1 << 7;
1707679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9)
1708679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		pcdev->width_flags |= 1 << 8;
1709679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski	if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10)
1710679419aa6e2590d561a8c1df3858d6b284c5cc58Guennadi Liakhovetski		pcdev->width_flags |= 1 << 9;
1711cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
1712cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski	if (!pcdev->mclk) {
17133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		dev_warn(&pdev->dev,
1714cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski			 "mclk == 0! Please, fix your platform data. "
17153bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski			 "Using default 20MHz\n");
1716cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski		pcdev->mclk = 20000000;
17173bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
17183bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
171940e2e0927003424c25807b575dd40da2b8685857Guennadi Liakhovetski	pcdev->mclk_divisor = mclk_get_divisor(pdev, pcdev);
1720cf34cba78d0e0a7244bd7f11addb4d971293fb30Guennadi Liakhovetski
17213bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	INIT_LIST_HEAD(&pcdev->capture);
17223bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	spin_lock_init(&pcdev->lock);
17233bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
17243bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	/*
17253bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	 * Request the regions.
17263bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	 */
1727eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski	if (!request_mem_region(res->start, resource_size(res),
17283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski				PXA_CAM_DRV_NAME)) {
17293bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		err = -EBUSY;
17303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto exit_clk;
17313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
17323bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
1733eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski	base = ioremap(res->start, resource_size(res));
17343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (!base) {
17353bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		err = -ENOMEM;
17363bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto exit_release;
17373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
17383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	pcdev->irq = irq;
17393bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	pcdev->base = base;
17403bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
17413bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	/* request dma */
1742de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin	err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
1743de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin			      pxa_camera_dma_irq_y, pcdev);
1744de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin	if (err < 0) {
1745eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski		dev_err(&pdev->dev, "Can't request DMA for Y\n");
17463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto exit_iounmap;
17473bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
1748de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin	pcdev->dma_chans[0] = err;
1749eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski	dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
1750a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
1751de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin	err = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
1752de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin			      pxa_camera_dma_irq_u, pcdev);
1753de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin	if (err < 0) {
1754eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski		dev_err(&pdev->dev, "Can't request DMA for U\n");
1755a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		goto exit_free_dma_y;
1756a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	}
1757de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin	pcdev->dma_chans[1] = err;
1758eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski	dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
1759a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport
1760de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin	err = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
1761de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin			      pxa_camera_dma_irq_v, pcdev);
1762de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin	if (err < 0) {
1763eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski		dev_err(&pdev->dev, "Can't request DMA for V\n");
1764a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport		goto exit_free_dma_u;
1765a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	}
1766de3e3b82a6d15264798d4e36f42abaa69f53ca06roel kluin	pcdev->dma_chans[2] = err;
1767eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski	dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
17683bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
176987f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
177087f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
177187f3dd77974cba1ba0798abd741ede50f56b3eb3Eric Miao	DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;
17723bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
17733bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	/* request irq */
17743bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME,
17753bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski			  pcdev);
17763bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (err) {
1777eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski		dev_err(&pdev->dev, "Camera interrupt register failed \n");
17783bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto exit_free_dma;
17793bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	}
17803bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
1781eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski	pcdev->soc_host.drv_name	= PXA_CAM_DRV_NAME;
1782eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski	pcdev->soc_host.ops		= &pxa_soc_camera_host_ops;
1783eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski	pcdev->soc_host.priv		= pcdev;
1784979ea1ddf80ac7383acdea03471355ca62702539Guennadi Liakhovetski	pcdev->soc_host.v4l2_dev.dev	= &pdev->dev;
1785eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski	pcdev->soc_host.nr		= pdev->id;
1786eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski
1787eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski	err = soc_camera_host_register(&pcdev->soc_host);
17883bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	if (err)
17893bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		goto exit_free_irq;
17903bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
17913bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return 0;
17923bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
17933bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_free_irq:
17943bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	free_irq(pcdev->irq, pcdev);
17953bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_free_dma:
1796a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pxa_free_dma(pcdev->dma_chans[2]);
1797a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportexit_free_dma_u:
1798a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pxa_free_dma(pcdev->dma_chans[1]);
1799a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoportexit_free_dma_y:
1800a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pxa_free_dma(pcdev->dma_chans[0]);
18013bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_iounmap:
18023bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	iounmap(base);
18033bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_release:
1804eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski	release_mem_region(res->start, resource_size(res));
18053bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_clk:
18063bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	clk_put(pcdev->clk);
18073bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit_kfree:
18083bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	kfree(pcdev);
18093bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskiexit:
18103bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return err;
18113bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
18123bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
18133bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic int __devexit pxa_camera_remove(struct platform_device *pdev)
18143bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski{
1815eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski	struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
1816eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski	struct pxa_camera_dev *pcdev = container_of(soc_host,
1817eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski					struct pxa_camera_dev, soc_host);
18183bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	struct resource *res;
18193bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
18203bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	clk_put(pcdev->clk);
18213bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
1822a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pxa_free_dma(pcdev->dma_chans[0]);
1823a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pxa_free_dma(pcdev->dma_chans[1]);
1824a5462e5be3c1cec7e00e6af9985ff31bf4ef8aa0Mike Rapoport	pxa_free_dma(pcdev->dma_chans[2]);
18253bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	free_irq(pcdev->irq, pcdev);
18263bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
1827eff505fa1511b753b7cfb397a754b8ff4367cd55Guennadi Liakhovetski	soc_camera_host_unregister(soc_host);
18283bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
18293bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	iounmap(pcdev->base);
18303bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
18313bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	res = pcdev->res;
1832eb6c8558f7658b7f31ee022c7bea1d840eda33dcGuennadi Liakhovetski	release_mem_region(res->start, resource_size(res));
18333bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
18343bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	kfree(pcdev);
18353bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
18367102b773d538c1f064da22ae9a1fb86704747388Guennadi Liakhovetski	dev_info(&pdev->dev, "PXA Camera driver unloaded\n");
18373bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
18383bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	return 0;
18393bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski}
18403bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
18417254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetskistatic struct dev_pm_ops pxa_camera_pm = {
18427254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski	.suspend	= pxa_camera_suspend,
18437254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski	.resume		= pxa_camera_resume,
18447254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski};
18457254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski
18463bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetskistatic struct platform_driver pxa_camera_driver = {
18473bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	.driver 	= {
18483bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski		.name	= PXA_CAM_DRV_NAME,
18497254026cedd42d75009f8a7f2999045007dd444eGuennadi Liakhovetski		.pm	= &pxa_camera_pm,
18503bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	},
18513bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski	.probe		= pxa_camera_probe,
1852e36bc31f823d6089bedc935fea82b6d36793412aJean Delvare	.remove		= __devexit_p(pxa_camera_remove),
18533bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski};
18543bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
18551d6629b1561ad34a6e6d17ece00bd65e1bab3724Axel Linmodule_platform_driver(pxa_camera_driver);
18563bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi Liakhovetski
18573bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi LiakhovetskiMODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
18583bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi LiakhovetskiMODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
18593bc43840c3fbffaf8216883a37b336a41050d7f7Guennadi LiakhovetskiMODULE_LICENSE("GPL");
186064dc3c1a906467d90c24913b0b38dd13d9378f4fMauro Carvalho ChehabMODULE_VERSION(PXA_CAM_VERSION);
186140e2e0927003424c25807b575dd40da2b8685857Guennadi LiakhovetskiMODULE_ALIAS("platform:" PXA_CAM_DRV_NAME);
1862