* [PATCH v2] Samsung S5P SoC camera interface driver
@ 2010-07-15 9:10 Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and platform definitions Sylwester Nawrocki
` (9 more replies)
0 siblings, 10 replies; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
This is a second version of my patch series adding support for
camera interface, video output and video processing contained
in Samsung's S3C/S5P SoCs.
The first version can be found at:
http://www.mail-archive.com/linux-samsung-soc at vger.kernel.org/msg01698.html
Changes since v1:
- support for multiple SoC variants through the platform device name overriding
(S5PC100 and SPV210 version definitions included)
Kernel tree
-----------------
This patch series has been prepared in assumption that the following
patches for s3c-fb driver have been applied:
http://www.mail-archive.com/linux-samsung-soc at vger.kernel.org/msg02000.html
[PATCH v4 0/19] Various s3c-fb updates
Patches
-----------------
The following patch series contains:
[PATCH 01/10 v2] ARM: Samsung: Add FIMC register and platform definitions
[PATCH 02/10 v2] ARM: Samsung: Add FIMC resource definition and FIMC driver platform helpers
[PATCH 03/10 v2] ARM: Samsung: Add platform definitions for local FIMC/FIMD fifo path
[PATCH 04/10 v2] v4l: Add Samsung FIMC (video postprocessor) driver
[PATCH 05/10 v2] s3c-fb: Add v4l2 subdevice to support framebuffer local fifo input path
[PATCH 06/10 v2] ARM: S5PV210: Add fifo link definitions for FIMC and framebuffer
[PATCH 07/10 v2] ARM: S5PV210: add common Aquila & GONI code
[PATCH 08/10 v2] ARM: S5PV210: enable FIMC on Aquila
[PATCH 09/10 v2] ARM: s5pv210: enable FIMC on Goni
[PATCH 10/10 v2] ARM: S5PC100: enable FIMC on SMDKC100
Best regards,
--
Sylwester Nawrocki
Samsung Poland R&D Center
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and platform definitions
2010-07-15 9:10 [PATCH v2] Samsung S5P SoC camera interface driver Sylwester Nawrocki
@ 2010-07-15 9:10 ` Sylwester Nawrocki
2010-07-16 9:44 ` Kukjin Kim
2010-07-15 9:10 ` [PATCH 02/10 v2] ARM: Samsung: Add FIMC resource definition and FIMC driver platform helpers Sylwester Nawrocki
` (8 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
FIMC device is a camera interface embedded in S3C/S5P Samsung SOC series.
It supports ITU-R BT.601/656 and MIPI-CSI2 standards, memory to memory
operations, color conversion, resizing and rotation.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/plat-samsung/include/plat/fimc.h | 31 ++
arch/arm/plat-samsung/include/plat/regs-fimc.h | 361 ++++++++++++++++++++++++
2 files changed, 392 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/plat-samsung/include/plat/fimc.h
create mode 100644 arch/arm/plat-samsung/include/plat/regs-fimc.h
diff --git a/arch/arm/plat-samsung/include/plat/fimc.h b/arch/arm/plat-samsung/include/plat/fimc.h
new file mode 100644
index 0000000..be1e853
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/fimc.h
@@ -0,0 +1,31 @@
+/* linux/arch/arm/plat-samsung/include/plat/fimc.h
+ *
+ * Platform header file for FIMC driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Sylwester Nawrocki, <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef FIMC_H_
+#define FIMC_H_
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+
+#define FIMC_MAX_FIFO_TARGETS 1
+#define FIMC_LCD_FIFO_TARGET 0
+
+struct s3c_fifo_link;
+
+struct samsung_plat_fimc {
+ struct s3c_fifo_link *fifo_targets[FIMC_MAX_FIFO_TARGETS];
+};
+
+#endif /* FIMC_H_ */
+
diff --git a/arch/arm/plat-samsung/include/plat/regs-fimc.h b/arch/arm/plat-samsung/include/plat/regs-fimc.h
new file mode 100644
index 0000000..6946a93
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-fimc.h
@@ -0,0 +1,361 @@
+/* arch/arm/plat-s5p/include/plat/regs-fimc.h
+ *
+ * Register definition file for Samsung Camera Interface (FIMC) driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef REGS_FIMC_H_
+#define REGS_FIMC_H_
+
+#define S5P_CIOYSA(__x) (0x18 + (__x) * 4)
+#define S5P_CIOCBSA(__x) (0x28 + (__x) * 4)
+#define S5P_CIOCRSA(__x) (0x38 + (__x) * 4)
+
+/* Input source format */
+#define S5P_CISRCFMT 0x00
+/* Window offset */
+#define S5P_CIWDOFST 0x04
+/* Global control */
+#define S5P_CIGCTRL 0x08
+/* Window offset 2 */
+#define S5P_CIWDOFST2 0x14
+/* Output DMA Y 1st frame start address */
+#define S5P_CIOYSA1 0x18
+/* Output DMA Y 2nd frame start address */
+#define S5P_CIOYSA2 0x1c
+/* Output DMA Y 3rd frame start address */
+#define S5P_CIOYSA3 0x20
+/* Output DMA Y 4th frame start address */
+#define S5P_CIOYSA4 0x24
+/* Output DMA Cb 1st frame start address */
+#define S5P_CIOCBSA1 0x28
+/* Output DMA Cb 2nd frame start address */
+#define S5P_CIOCBSA2 0x2c
+/* Output DMA Cb 3rd frame start address */
+#define S5P_CIOCBSA3 0x30
+/* Output DMA Cb 4th frame start address */
+#define S5P_CIOCBSA4 0x34
+/* Output DMA Cr 1st frame start address */
+#define S5P_CIOCRSA1 0x38
+/* Output DMA Cr 2nd frame start address */
+#define S5P_CIOCRSA2 0x3c
+/* Output DMA Cr 3rd frame start address */
+#define S5P_CIOCRSA3 0x40
+/* Output DMA Cr 4th frame start address */
+#define S5P_CIOCRSA4 0x44
+/* Target image format */
+#define S5P_CITRGFMT 0x48
+/* Output DMA control */
+#define S5P_CIOCTRL 0x4c
+/* Pre-scaler control 1 */
+#define S5P_CISCPRERATIO 0x50
+/* Pre-scaler control 2 */
+#define S5P_CISCPREDST 0x54
+/* Main scaler control */
+#define S5P_CISCCTRL 0x58
+/* Target area */
+#define S5P_CITAREA 0x5c
+/* Status */
+#define S5P_CISTATUS 0x64
+/* Image capture enable command */
+#define S5P_CIIMGCPT 0xc0
+/* Capture sequence */
+#define S5P_CICPTSEQ 0xc4
+/* Image effects */
+#define S5P_CIIMGEFF 0xd0
+/* Y frame start address for input DMA */
+#define S5P_CIIYSA0 0xd4
+/* Cb frame start address for input DMA */
+#define S5P_CIICBSA0 0xd8
+/* Cr frame start address for input DMA */
+#define S5P_CIICRSA0 0xdc
+/* Real input DMA image size */
+#define S5P_CIREAL_ISIZE 0xf8
+/* Input DMA control */
+#define S5P_MSCTRL 0xfc
+/* Y frame start address for input DMA */
+#define S5P_CIIYSA1 0x144
+/* Cb frame start address for input DMA */
+#define S5P_CIICBSA1 0x148
+/* Cr frame start address for input DMA */
+#define S5P_CIICRSA1 0x14c
+/* Output DMA Y offset */
+#define S5P_CIOYOFF 0x168
+/* Output DMA CB offset */
+#define S5P_CIOCBOFF 0x16c
+/* Output DMA CR offset */
+#define S5P_CIOCROFF 0x170
+/* Input DMA Y offset */
+#define S5P_CIIYOFF 0x174
+/* Input DMA CB offset */
+#define S5P_CIICBOFF 0x178
+/* Input DMA CR offset */
+#define S5P_CIICROFF 0x17c
+/* Input DMA original image size */
+#define S5P_ORGISIZE 0x180
+/* Output DMA original image size */
+#define S5P_ORGOSIZE 0x184
+/* Real output DMA image size */
+#define S5P_CIEXTEN 0x188
+/* DMA parameter */
+#define S5P_CIDMAPARAM 0x18c
+/* MIPI CSI image format */
+#define S5P_CSIIMGFMT 0x194
+
+
+#define S5P_CISRCFMT_SOURCEHSIZE(x) ((x) << 16)
+#define S5P_CISRCFMT_SOURCEVSIZE(x) ((x) << 0)
+
+#define S5P_CIWDOFST_WINHOROFST(x) ((x) << 16)
+#define S5P_CIWDOFST_WINVEROFST(x) ((x) << 0)
+
+#define S5P_CIWDOFST2_WINHOROFST2(x) ((x) << 16)
+#define S5P_CIWDOFST2_WINVEROFST2(x) ((x) << 0)
+
+#define S5P_CITRGFMT_TARGETHSIZE(x) ((x) << 16)
+#define S5P_CITRGFMT_TARGETVSIZE(x) ((x) << 0)
+
+#define S5P_CISCPRERATIO_SHFACTOR(x) ((x) << 28)
+#define S5P_CISCPRERATIO_PREHORRATIO(x) ((x) << 16)
+#define S5P_CISCPRERATIO_PREVERRATIO(x) ((x) << 0)
+
+#define S5P_CISCPREDST_PREDSTWIDTH(x) ((x) << 16)
+#define S5P_CISCPREDST_PREDSTHEIGHT(x) ((x) << 0)
+
+#define S5P_CISCCTRL_MAINHORRATIO(x) ((x) << 16)
+#define S5P_CISCCTRL_MAINVERRATIO(x) ((x) << 0)
+
+#define S5P_CITAREA_TARGET_AREA(x) ((x) << 0)
+
+#define S5P_CIIMGEFF_PAT_CB(x) ((x) << 13)
+#define S5P_CIIMGEFF_PAT_CR(x) ((x) << 0)
+
+#define S5P_CIREAL_ISIZE_HEIGHT(x) ((x) << 16)
+#define S5P_CIREAL_ISIZE_WIDTH(x) ((x) << 0)
+
+#define S5P_MSCTRL_SUCCESSIVE_COUNT(x) ((x) << 24)
+
+#define S5P_CIOYOFF_VERTICAL(x) ((x) << 16)
+#define S5P_CIOYOFF_HORIZONTAL(x) ((x) << 0)
+
+#define S5P_CIOCBOFF_VERTICAL(x) ((x) << 16)
+#define S5P_CIOCBOFF_HORIZONTAL(x) ((x) << 0)
+
+#define S5P_CIOCROFF_VERTICAL(x) ((x) << 16)
+#define S5P_CIOCROFF_HORIZONTAL(x) ((x) << 0)
+
+#define S5P_CIIYOFF_VERTICAL(x) ((x) << 16)
+#define S5P_CIIYOFF_HORIZONTAL(x) ((x) << 0)
+
+#define S5P_CIICBOFF_VERTICAL(x) ((x) << 16)
+#define S5P_CIICBOFF_HORIZONTAL(x) ((x) << 0)
+
+#define S5P_CIICROFF_VERTICAL(x) ((x) << 16)
+#define S5P_CIICROFF_HORIZONTAL(x) ((x) << 0)
+
+#define S5P_ORGISIZE_VERTICAL(x) ((x) << 16)
+#define S5P_ORGISIZE_HORIZONTAL(x) ((x) << 0)
+
+#define S5P_ORGOSIZE_VERTICAL(x) ((x) << 16)
+#define S5P_ORGOSIZE_HORIZONTAL(x) ((x) << 0)
+
+
+/* Register's bit definitions */
+
+/* Source format register */
+#define S5P_CISRCFMT_ITU601_8BIT (1 << 31)
+#define S5P_CISRCFMT_ITU656_8BIT (0 << 31)
+#define S5P_CISRCFMT_ITU601_16BIT (1 << 29)
+#define S5P_CISRCFMT_ORDER422_YCBYCR (0 << 14)
+#define S5P_CISRCFMT_ORDER422_YCRYCB (1 << 14)
+#define S5P_CISRCFMT_ORDER422_CBYCRY (2 << 14)
+#define S5P_CISRCFMT_ORDER422_CRYCBY (3 << 14)
+/* ITU601 16bit only */
+#define S5P_CISRCFMT_ORDER422_Y4CBCRCBCR (0 << 14)
+/* ITU601 16bit only */
+#define S5P_CISRCFMT_ORDER422_Y4CRCBCRCB (1 << 14)
+
+/* Window offset register */
+#define S5P_CIWDOFST_WINOFSEN (1 << 31)
+#define S5P_CIWDOFST_CLROVFIY (1 << 30)
+#define S5P_CIWDOFST_CLROVRLB (1 << 29)
+#define S5P_CIWDOFST_WINHOROFST_MASK (0x7ff << 16)
+#define S5P_CIWDOFST_CLROVFICB (1 << 15)
+#define S5P_CIWDOFST_CLROVFICR (1 << 14)
+#define S5P_CIWDOFST_WINVEROFST_MASK (0xfff << 0)
+
+/* Global control register */
+#define S5P_CIGCTRL_SWRST (1 << 31)
+#define S5P_CIGCTRL_CAMRST_A (1 << 30)
+#define S5P_CIGCTRL_SELCAM_ITU_B (0 << 29)
+#define S5P_CIGCTRL_SELCAM_ITU_A (1 << 29)
+#define S5P_CIGCTRL_SELCAM_ITU_MASK (1 << 29)
+#define S5P_CIGCTRL_TESTPAT_NORMAL (0 << 27)
+#define S5P_CIGCTRL_TESTPAT_COLOR_BAR (1 << 27)
+#define S5P_CIGCTRL_TESTPAT_HOR_INC (2 << 27)
+#define S5P_CIGCTRL_TESTPAT_VER_INC (3 << 27)
+#define S5P_CIGCTRL_TESTPAT_MASK (3 << 27)
+#define S5P_CIGCTRL_TESTPAT_SHIFT (27)
+#define S5P_CIGCTRL_INVPOLPCLK (1 << 26)
+#define S5P_CIGCTRL_INVPOLVSYNC (1 << 25)
+#define S5P_CIGCTRL_INVPOLHREF (1 << 24)
+#define S5P_CIGCTRL_IRQ_OVFEN (1 << 22)
+#define S5P_CIGCTRL_HREF_MASK (1 << 21)
+#define S5P_CIGCTRL_IRQ_EDGE (0 << 20)
+#define S5P_CIGCTRL_IRQ_LEVEL (1 << 20)
+#define S5P_CIGCTRL_IRQ_CLR (1 << 19)
+#define S5P_CIGCTRL_IRQ_DISABLE (0 << 16)
+#define S5P_CIGCTRL_IRQ_ENABLE (1 << 16)
+#define S5P_CIGCTRL_SHDW_DISABLE (1 << 12)
+#define S5P_CIGCTRL_SELCAM_MIPI_B (0 << 7)
+#define S5P_CIGCTRL_SELCAM_MIPI_A (1 << 7)
+#define S5P_CIGCTRL_SELCAM_MIPI_MASK (1 << 7)
+#define S5P_CIGCTRL_CAMIF_SELWB (1 << 6)
+#define S5P_CIGCTRL_INVPOLHSYNC (1 << 4)
+#define S5P_CIGCTRL_SELCAM_ITU (0 << 3)
+#define S5P_CIGCTRL_SELCAM_MIPI (1 << 3)
+#define S5P_CIGCTRL_PROGRESSIVE (0 << 0)
+#define S5P_CIGCTRL_INTERLACE (1 << 0)
+
+/* Window offset2 register */
+#define S5P_CIWDOFST_WINHOROFST2_MASK (0xfff << 16)
+#define S5P_CIWDOFST_WINVEROFST2_MASK (0xfff << 16)
+
+/* Target format register */
+#define S5P_CITRGFMT_INROT90 (1 << 31)
+#define S5P_CITRGFMT_OUTFORMAT_YCBCR420 (0 << 29)
+#define S5P_CITRGFMT_OUTFORMAT_YCBCR422 (1 << 29)
+#define S5P_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE (2 << 29)
+#define S5P_CITRGFMT_OUTFORMAT_RGB (3 << 29)
+#define S5P_CITRGFMT_OUT_FMT_MASK (3 << 29)
+#define S5P_CITRGFMT_HSIZE_MASK (0xfff << 16)
+#define S5P_CITRGFMT_FLIP_SHIFT (14)
+#define S5P_CITRGFMT_FLIP_NORMAL (0 << 14)
+#define S5P_CITRGFMT_FLIP_X_MIRROR (1 << 14)
+#define S5P_CITRGFMT_FLIP_Y_MIRROR (2 << 14)
+#define S5P_CITRGFMT_FLIP_180 (3 << 14)
+#define S5P_CITRGFMT_FLIP_MASK (3 << 14)
+#define S5P_CITRGFMT_OUTROT90 (1 << 13)
+#define S5P_CITRGFMT_VSIZE_MASK (0xfff << 0)
+
+/* Output DMA control register */
+#define S5P_CIOCTRL_ORDER422_MASK (3 << 0)
+#define S5P_CIOCTRL_ORDER422_CRYCBY (0 << 0)
+#define S5P_CIOCTRL_ORDER422_YCRYCB (1 << 0)
+#define S5P_CIOCTRL_ORDER422_CBYCRY (2 << 0)
+#define S5P_CIOCTRL_ORDER422_YCBYCR (3 << 0)
+#define S5P_CIOCTRL_LASTIRQ_ENABLE (1 << 2)
+#define S5P_CIOCTRL_YCBCR_3PLANE (0 << 3)
+#define S5P_CIOCTRL_YCBCR_2PLANE (1 << 3)
+#define S5P_CIOCTRL_YCBCR_PLANE_MASK (1 << 3)
+#define S5P_CIOCTRL_ORDER2P_SHIFT (24)
+#define S5P_CIOCTRL_ORDER2P_MASK (3 << 24)
+#define S5P_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24)
+
+
+/* Main scaler control register */
+#define S5P_CISCCTRL_SCALERBYPASS (1 << 31)
+#define S5P_CISCCTRL_SCALEUP_H (1 << 30)
+#define S5P_CISCCTRL_SCALEUP_V (1 << 29)
+#define S5P_CISCCTRL_CSCR2Y_NARROW (0 << 28)
+#define S5P_CISCCTRL_CSCR2Y_WIDE (1 << 28)
+#define S5P_CISCCTRL_CSCY2R_NARROW (0 << 27)
+#define S5P_CISCCTRL_CSCY2R_WIDE (1 << 27)
+#define S5P_CISCCTRL_LCDPATHEN_FIFO (1 << 26)
+#define S5P_CISCCTRL_PROGRESSIVE (0 << 25)
+#define S5P_CISCCTRL_INTERLACE (1 << 25)
+#define S5P_CISCCTRL_SCALERSTART (1 << 15)
+#define S5P_CISCCTRL_INRGB_FMT_RGB565 (0 << 13)
+#define S5P_CISCCTRL_INRGB_FMT_RGB666 (1 << 13)
+#define S5P_CISCCTRL_INRGB_FMT_RGB888 (2 << 13)
+#define S5P_CISCCTRL_INRGB_FMT_MASK (3 << 13)
+#define S5P_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11)
+#define S5P_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11)
+#define S5P_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11)
+#define S5P_CISCCTRL_OUTRGB_FMT_MASK (3 << 11)
+#define S5P_CISCCTRL_EXTRGB_NORMAL (0 << 10)
+#define S5P_CISCCTRL_EXTRGB_EXTENSION (1 << 10)
+#define S5P_CISCCTRL_ONE2ONE (1 << 9)
+
+/* Status register */
+#define S5P_CISTATUS_OVFIY (1 << 31)
+#define S5P_CISTATUS_OVFICB (1 << 30)
+#define S5P_CISTATUS_OVFICR (1 << 29)
+#define S5P_CISTATUS_VSYNC (1 << 28)
+#define S5P_CISTATUS_WINOFSTEN (1 << 25)
+#define S5P_CISTATUS_IMGCPTEN (1 << 22)
+#define S5P_CISTATUS_IMGCPTENSC (1 << 21)
+#define S5P_CISTATUS_VSYNC_A (1 << 20)
+#define S5P_CISTATUS_VSYNC_B (1 << 19)
+#define S5P_CISTATUS_OVRLB (1 << 18)
+#define S5P_CISTATUS_FRAMEEND (1 << 17)
+#define S5P_CISTATUS_LASTCAPTUREEND (1 << 16)
+#define S5P_CISTATUS_VVALID_A (1 << 15)
+#define S5P_CISTATUS_VVALID_B (1 << 14)
+
+/* Image capture enable register */
+#define S5P_CIIMGCPT_IMGCPTEN (1 << 31)
+#define S5P_CIIMGCPT_IMGCPTEN_SC (1 << 30)
+#define S5P_CIIMGCPT_CPT_FREN_ENABLE (1 << 25)
+#define S5P_CIIMGCPT_CPT_FRMOD_EN (0 << 18)
+#define S5P_CIIMGCPT_CPT_FRMOD_CNT (1 << 18)
+
+/* Image effects register */
+#define S5P_CIIMGEFF_IE_DISABLE (0 << 30)
+#define S5P_CIIMGEFF_IE_ENABLE (1 << 30)
+#define S5P_CIIMGEFF_IE_SC_BEFORE (0 << 29)
+#define S5P_CIIMGEFF_IE_SC_AFTER (1 << 29)
+#define S5P_CIIMGEFF_FIN_BYPASS (0 << 26)
+#define S5P_CIIMGEFF_FIN_ARBITRARY (1 << 26)
+#define S5P_CIIMGEFF_FIN_NEGATIVE (2 << 26)
+#define S5P_CIIMGEFF_FIN_ARTFREEZE (3 << 26)
+#define S5P_CIIMGEFF_FIN_EMBOSSING (4 << 26)
+#define S5P_CIIMGEFF_FIN_SILHOUETTE (5 << 26)
+#define S5P_CIIMGEFF_FIN_MASK (7 << 26)
+#define S5P_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff < 0))
+
+/* Real input DMA size register */
+#define S5P_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31)
+#define S5P_CIREAL_ISIZE_ADDR_CH_DISABLE (1 << 30)
+
+/* Input DMA control register */
+#define S5P_MSCTRL_IN_BURST_COUNT_MASK (3 << 24)
+#define S5P_MSCTRL_2P_IN_ORDER_MASK (3 << 16)
+#define S5P_MSCTRL_2P_IN_ORDER_SHIFT (16)
+#define S5P_MSCTRL_C_INT_IN_3PLANE (0 << 15)
+#define S5P_MSCTRL_C_INT_IN_2PLANE (1 << 15)
+#define S5P_MSCTRL_C_INT_IN_MASK (1 << 15)
+#define S5P_MSCTRL_FLIP_SHIFT (13)
+#define S5P_MSCTRL_FLIP_MASK (3 << 13)
+#define S5P_MSCTRL_FLIP_NORMAL (0 << 13)
+#define S5P_MSCTRL_FLIP_X_MIRROR (1 << 13)
+#define S5P_MSCTRL_FLIP_Y_MIRROR (2 << 13)
+#define S5P_MSCTRL_FLIP_180 (3 << 13)
+#define S5P_MSCTRL_ORDER422_SHIFT (4)
+#define S5P_MSCTRL_ORDER422_CRYCBY (0 << 4)
+#define S5P_MSCTRL_ORDER422_YCRYCB (1 << 4)
+#define S5P_MSCTRL_ORDER422_CBYCRY (2 << 4)
+#define S5P_MSCTRL_ORDER422_YCBYCR (3 << 4)
+#define S5P_MSCTRL_ORDER422_MASK (3 << 4)
+#define S5P_MSCTRL_INPUT_EXTCAM (0 << 3)
+#define S5P_MSCTRL_INPUT_MEMORY (1 << 3)
+#define S5P_MSCTRL_INPUT_MASK (1 << 3)
+#define S5P_MSCTRL_INFORMAT_YCBCR420 (0 << 1)
+#define S5P_MSCTRL_INFORMAT_YCBCR422 (1 << 1)
+#define S5P_MSCTRL_INFORMAT_YCBCR422_1PLANE (2 << 1)
+#define S5P_MSCTRL_INFORMAT_RGB (3 << 1)
+#define S5P_MSCTRL_INFORMAT_MASK (3 << 1)
+#define S5P_MSCTRL_ENVID (1 << 0)
+
+/* DMA parameter register */
+#define S5P_CIDMAPARAM_R_MODE_64X32 (3 << 29)
+#define S5P_CIDMAPARAM_W_MODE_LINEAR (0 << 13)
+#define S5P_CIDMAPARAM_W_MODE_CONFTILE (1 << 13)
+#define S5P_CIDMAPARAM_W_MODE_64X32 (3 << 13)
+
+#endif /* REGS_FIMC_H_ */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 02/10 v2] ARM: Samsung: Add FIMC resource definition and FIMC driver platform helpers
2010-07-15 9:10 [PATCH v2] Samsung S5P SoC camera interface driver Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and platform definitions Sylwester Nawrocki
@ 2010-07-15 9:10 ` Sylwester Nawrocki
2010-07-16 10:07 ` Kukjin Kim
2010-07-15 9:10 ` [PATCH 03/10 v2] ARM: Samsung: Add platform definitions for local FIMC/FIMD fifo path Sylwester Nawrocki
` (7 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
Add camera interface SoC resource definitions and setup code
for FIMC/FB fifo links.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-s5pc100/Kconfig | 15 ++++++
arch/arm/mach-s5pc100/Makefile | 3 +
arch/arm/mach-s5pc100/include/mach/map.h | 8 +++
arch/arm/mach-s5pc100/setup-fimc0.c | 14 ++++++
arch/arm/mach-s5pc100/setup-fimc1.c | 14 ++++++
arch/arm/mach-s5pc100/setup-fimc2.c | 14 ++++++
arch/arm/mach-s5pv210/Kconfig | 15 ++++++
arch/arm/mach-s5pv210/Makefile | 3 +
arch/arm/mach-s5pv210/cpu.c | 5 ++
arch/arm/mach-s5pv210/include/mach/map.h | 8 +++
arch/arm/mach-s5pv210/setup-fimc0.c | 14 ++++++
arch/arm/mach-s5pv210/setup-fimc1.c | 14 ++++++
arch/arm/mach-s5pv210/setup-fimc2.c | 14 ++++++
arch/arm/plat-s5p/Kconfig | 16 +++++++
arch/arm/plat-s5p/Makefile | 3 +
arch/arm/plat-s5p/dev-fimc0.c | 56 ++++++++++++++++++++++++
arch/arm/plat-s5p/dev-fimc1.c | 55 +++++++++++++++++++++++
arch/arm/plat-s5p/dev-fimc2.c | 55 +++++++++++++++++++++++
arch/arm/plat-samsung/include/plat/fimc-core.h | 45 +++++++++++++++++++
arch/arm/plat-samsung/include/plat/fimc.h | 12 +++++
20 files changed, 383 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-s5pc100/setup-fimc0.c
create mode 100644 arch/arm/mach-s5pc100/setup-fimc1.c
create mode 100644 arch/arm/mach-s5pc100/setup-fimc2.c
create mode 100644 arch/arm/mach-s5pv210/setup-fimc0.c
create mode 100644 arch/arm/mach-s5pv210/setup-fimc1.c
create mode 100644 arch/arm/mach-s5pv210/setup-fimc2.c
create mode 100644 arch/arm/plat-s5p/dev-fimc0.c
create mode 100644 arch/arm/plat-s5p/dev-fimc1.c
create mode 100644 arch/arm/plat-s5p/dev-fimc2.c
create mode 100644 arch/arm/plat-samsung/include/plat/fimc-core.h
diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index d421f80..791270d 100644
--- a/arch/arm/mach-s5pc100/Kconfig
+++ b/arch/arm/mach-s5pc100/Kconfig
@@ -36,6 +36,21 @@ config S5PC100_SETUP_SDHCI_GPIO
help
Common setup code for SDHCI gpio.
+config S5PC100_SETUP_FIMC0
+ bool
+ help
+ Setup code for FIMC controller 0
+
+config S5PC100_SETUP_FIMC1
+ bool
+ help
+ Setup code for FIMC controller 1
+
+config S5PC100_SETUP_FIMC2
+ bool
+ help
+ Setup code for FIMC controller 2
+
config MACH_SMDKC100
bool "SMDKC100"
select CPU_S5PC100
diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile
index f2073bc..7b43337 100644
--- a/arch/arm/mach-s5pc100/Makefile
+++ b/arch/arm/mach-s5pc100/Makefile
@@ -25,6 +25,9 @@ obj-$(CONFIG_S5PC100_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
# device support
obj-y += dev-audio.o
obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
+obj-$(CONFIG_S5PC100_SETUP_FIMC0) += setup-fimc0.o
+obj-$(CONFIG_S5PC100_SETUP_FIMC1) += setup-fimc1.o
+obj-$(CONFIG_S5PC100_SETUP_FIMC2) += setup-fimc2.o
# machine support
diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h
index c025064..a1c6f22 100644
--- a/arch/arm/mach-s5pc100/include/mach/map.h
+++ b/arch/arm/mach-s5pc100/include/mach/map.h
@@ -112,6 +112,11 @@
#define S5PC100_PA_SDRAM (0x30000000)
#define S5P_PA_SDRAM S5PC100_PA_SDRAM
+/* FIMC */
+#define S5PC100_PA_FIMC0 (0xEE200000)
+#define S5PC100_PA_FIMC1 (0xEE300000)
+#define S5PC100_PA_FIMC2 (0xEE400000)
+
/* compatibiltiy defines. */
#define S3C_PA_UART S5PC100_PA_UART
#define S3C_PA_IIC S5PC100_PA_IIC0
@@ -134,5 +139,8 @@
#define S3C_PA_ONENAND S5PC100_PA_ONENAND
#define S3C_PA_ONENAND_BUF S5PC100_PA_ONENAND_BUF
#define S3C_SZ_ONENAND_BUF S5PC100_SZ_ONENAND_BUF
+#define S5P_PA_FIMC0 S5PC100_PA_FIMC0
+#define S5P_PA_FIMC1 S5PC100_PA_FIMC1
+#define S5P_PA_FIMC2 S5PC100_PA_FIMC2
#endif /* __ASM_ARCH_C100_MAP_H */
diff --git a/arch/arm/mach-s5pc100/setup-fimc0.c b/arch/arm/mach-s5pc100/setup-fimc0.c
new file mode 100644
index 0000000..dea33c2
--- /dev/null
+++ b/arch/arm/mach-s5pc100/setup-fimc0.c
@@ -0,0 +1,14 @@
+/* linux/arch/arm/mach-s5pc100/setup-fimc0.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * S5PC100 - setup for S5P FIMC device 0
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <plat/fimc.h>
+
+struct samsung_plat_fimc s5p_fimc0_default_data __initdata = {};
diff --git a/arch/arm/mach-s5pc100/setup-fimc1.c b/arch/arm/mach-s5pc100/setup-fimc1.c
new file mode 100644
index 0000000..1833377
--- /dev/null
+++ b/arch/arm/mach-s5pc100/setup-fimc1.c
@@ -0,0 +1,14 @@
+/* linux/arch/arm/mach-s5pc100/setup-fimc1.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * S5PC100 - setup for S5P FIMC device 1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <plat/fimc.h>
+
+struct samsung_plat_fimc s5p_fimc1_default_data __initdata = {};
diff --git a/arch/arm/mach-s5pc100/setup-fimc2.c b/arch/arm/mach-s5pc100/setup-fimc2.c
new file mode 100644
index 0000000..746e0f0
--- /dev/null
+++ b/arch/arm/mach-s5pc100/setup-fimc2.c
@@ -0,0 +1,14 @@
+/* linux/arch/arm/mach-s5pc100/setup-fimc2.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * S5PC100 - setup for S5P FIMC device 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <plat/fimc.h>
+
+struct samsung_plat_fimc s5p_fimc2_default_data __initdata = {};
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index d876ff0..4bb5a85 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -32,6 +32,21 @@ config S5PV210_SETUP_FB_24BPP
help
Common setup code for S5PV210 with an 24bpp RGB display helper.
+config S5PV210_SETUP_FIMC0
+ bool
+ help
+ Setup code for FIMC controller 0
+
+config S5PV210_SETUP_FIMC1
+ bool
+ help
+ Setup code for FIMC controller 1
+
+config S5PV210_SETUP_FIMC2
+ bool
+ help
+ Setup code for FIMC controller 2
+
config S5PV210_SETUP_SDHCI
bool
select S5PV210_SETUP_SDHCI_GPIO
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 7b3a984..6eceeb8 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -35,3 +35,6 @@ obj-$(CONFIG_S5PV210_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S5PV210_SETUP_I2C2) += setup-i2c2.o
obj-$(CONFIG_S5PV210_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_S5PV210_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
+obj-$(CONFIG_S5PV210_SETUP_FIMC0) += setup-fimc0.o
+obj-$(CONFIG_S5PV210_SETUP_FIMC1) += setup-fimc1.o
+obj-$(CONFIG_S5PV210_SETUP_FIMC2) += setup-fimc2.o
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index fc3801b..4133cae 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -35,6 +35,7 @@
#include <plat/iic-core.h>
#include <plat/sdhci.h>
#include <plat/fb-core.h>
+#include <plat/fimc-core.h>
/* Initial IO mappings */
@@ -95,6 +96,10 @@ void __init s5pv210_map_io(void)
s3c_i2c2_setname("s3c2440-i2c");
s3c_fb_setname("s5pv210-fb");
+
+ s3c_fimc_setname(0, "s5pv210-fimc");
+ s3c_fimc_setname(1, "s5pv210-fimc");
+ s3c_fimc_setname(2, "s5pv210-fimc");
}
void __init s5pv210_init_clocks(int xtal)
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index e78bd47..9b8cf69 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -96,6 +96,11 @@
#define S5PV210_PA_ADC (0xE1700000)
+/* FIMC */
+#define S5PV210_PA_FIMC0 (0xFB200000)
+#define S5PV210_PA_FIMC1 (0xFB300000)
+#define S5PV210_PA_FIMC2 (0xFB400000)
+
/* compatibiltiy defines. */
#define S3C_PA_UART S5PV210_PA_UART
#define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0)
@@ -111,5 +116,8 @@
#define SAMSUNG_PA_ADC S5PV210_PA_ADC
#define S3C_PA_USB_HSOTG S5PV210_PA_USB_HSOTG
#define S3C_PA_USB_HSPHY S5PV210_PA_USB_HSPHY
+#define S5P_PA_FIMC0 S5PV210_PA_FIMC0
+#define S5P_PA_FIMC1 S5PV210_PA_FIMC1
+#define S5P_PA_FIMC2 S5PV210_PA_FIMC2
#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5pv210/setup-fimc0.c b/arch/arm/mach-s5pv210/setup-fimc0.c
new file mode 100644
index 0000000..0e5ef0a
--- /dev/null
+++ b/arch/arm/mach-s5pv210/setup-fimc0.c
@@ -0,0 +1,14 @@
+/* linux/arch/arm/mach-s5pv210/setup-fimc0.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * S5PV210 - setup for S5P FIMC device 0
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <plat/fimc.h>
+
+struct samsung_plat_fimc s5p_fimc0_default_data __initdata = {};
diff --git a/arch/arm/mach-s5pv210/setup-fimc1.c b/arch/arm/mach-s5pv210/setup-fimc1.c
new file mode 100644
index 0000000..80da0e7
--- /dev/null
+++ b/arch/arm/mach-s5pv210/setup-fimc1.c
@@ -0,0 +1,14 @@
+/* linux/arch/arm/mach-s5pv210/setup-fimc1.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * S5PV210 - setup for S5P FIMC device 1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <plat/fimc.h>
+
+struct samsung_plat_fimc s5p_fimc1_default_data __initdata = {};
diff --git a/arch/arm/mach-s5pv210/setup-fimc2.c b/arch/arm/mach-s5pv210/setup-fimc2.c
new file mode 100644
index 0000000..bc6a27b
--- /dev/null
+++ b/arch/arm/mach-s5pv210/setup-fimc2.c
@@ -0,0 +1,14 @@
+/* linux/arch/arm/mach-s5pv210/setup-fimc2.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * S5PV210 - setup for S5P FIMC device 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <plat/fimc.h>
+
+struct samsung_plat_fimc s5p_fimc2_default_data __initdata = {};
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 11d6a1b..38b60c7 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -5,6 +5,22 @@
#
# Licensed under GPLv2
+config S5P_DEV_FIMC0
+ bool
+ help
+ Compile in platform device definitions for FIMC controller 0
+
+config S5P_DEV_FIMC1
+ bool
+ help
+ Compile in platform device definitions for FIMC controller 1
+
+config S5P_DEV_FIMC2
+ bool
+ help
+ Compile in platform device definitions for FIMC controller 2
+
+
config PLAT_S5P
bool
depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210)
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index b56b4d3..a7d3c35 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -18,3 +18,6 @@ obj-y += clock.o
obj-y += irq.o irq-gpioint.o
obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o
+obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o
+obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o
+obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o
diff --git a/arch/arm/plat-s5p/dev-fimc0.c b/arch/arm/plat-s5p/dev-fimc0.c
new file mode 100644
index 0000000..cfa10f0
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-fimc0.c
@@ -0,0 +1,56 @@
+/* linux/arch/arm/plat-s5p/dev-fimc0.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Base S5P FIMC0 resource and device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <plat/fimc.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+
+static struct resource s5p_fimc_resource[] = {
+ [0] = {
+ .start = S5P_PA_FIMC0,
+ .end = S5P_PA_FIMC0 + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_FIMC0,
+ .end = IRQ_FIMC0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device s5p_device_fimc0 = {
+ .name = "s5p-fimc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p_fimc_resource),
+ .resource = s5p_fimc_resource,
+};
+
+
+void __init s5p_fimc0_set_platdata(struct samsung_plat_fimc *pd)
+{
+ struct samsung_plat_fimc *npd;
+
+ if (!pd)
+ pd = &s5p_fimc0_default_data;
+
+ npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
+ if (!npd)
+ printk(KERN_ERR "%s: out of memory\n", __func__);
+
+ s5p_device_fimc0.dev.platform_data = npd;
+}
+
diff --git a/arch/arm/plat-s5p/dev-fimc1.c b/arch/arm/plat-s5p/dev-fimc1.c
new file mode 100644
index 0000000..7178477
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-fimc1.c
@@ -0,0 +1,55 @@
+/* linux/arch/arm/plat-s5p/dev-fimc1.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Base S5P FIMC1 resource and device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <plat/fimc.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+
+static struct resource s5p_fimc_resource[] = {
+ [0] = {
+ .start = S5P_PA_FIMC1,
+ .end = S5P_PA_FIMC1 + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_FIMC1,
+ .end = IRQ_FIMC1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device s5p_device_fimc1 = {
+ .name = "s5p-fimc",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s5p_fimc_resource),
+ .resource = s5p_fimc_resource,
+};
+
+void __init s5p_fimc1_set_platdata(struct samsung_plat_fimc *pd)
+{
+ struct samsung_plat_fimc *npd;
+
+ if (!pd)
+ pd = &s5p_fimc1_default_data;
+
+ npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
+ if (!npd)
+ printk(KERN_ERR "%s: out of memory\n", __func__);
+
+ s5p_device_fimc1.dev.platform_data = npd;
+}
+
diff --git a/arch/arm/plat-s5p/dev-fimc2.c b/arch/arm/plat-s5p/dev-fimc2.c
new file mode 100644
index 0000000..fe1a6c0
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-fimc2.c
@@ -0,0 +1,55 @@
+/* linux/arch/arm/plat-s5p/dev-fimc2.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Base S5P FIMC2 resource and device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <plat/fimc.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+
+static struct resource s5p_fimc_resource[] = {
+ [0] = {
+ .start = S5P_PA_FIMC2,
+ .end = S5P_PA_FIMC2 + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_FIMC2,
+ .end = IRQ_FIMC2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device s5p_device_fimc2 = {
+ .name = "s5p-fimc",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(s5p_fimc_resource),
+ .resource = s5p_fimc_resource,
+};
+
+void __init s5p_fimc2_set_platdata(struct samsung_plat_fimc *pd)
+{
+ struct samsung_plat_fimc *npd;
+
+ if (!pd)
+ pd = &s5p_fimc2_default_data;
+
+ npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
+ if (!npd)
+ printk(KERN_ERR "%s: out of memory\n", __func__);
+
+ s5p_device_fimc2.dev.platform_data = npd;
+}
+
diff --git a/arch/arm/plat-samsung/include/plat/fimc-core.h b/arch/arm/plat-samsung/include/plat/fimc-core.h
new file mode 100644
index 0000000..a126bbd
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/fimc-core.h
@@ -0,0 +1,45 @@
+/*
+ * arch/arm/plat-samsung/include/plat/fimc-core.h
+ *
+ * Copyright 2010 Samsung Electronics Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * Samsung camera interface driver core functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_PLAT_FIMC_CORE_H
+#define __ASM_PLAT_FIMC_CORE_H __FILE__
+
+/*
+ * These functions are only for use with the core support code, such as
+ * the CPU-specific initialization code.
+ */
+
+#include <plat/fimc.h>
+
+/* Re-define device name to differentiate the subsystem in various SoCs. */
+static inline void s3c_fimc_setname(int id, char *name)
+{
+ switch(id) {
+#ifdef CONFIG_S5P_DEV_FIMC0
+ case 0:
+ s5p_device_fimc0.name = name;
+ break;
+#endif
+#ifdef CONFIG_S5P_DEV_FIMC1
+ case 1:
+ s5p_device_fimc1.name = name;
+ break;
+#endif
+#ifdef CONFIG_S5P_DEV_FIMC2
+ case 2:
+ s5p_device_fimc2.name = name;
+ break;
+#endif
+ }
+}
+
+#endif /* __ASM_PLAT_FIMC_CORE_H */
diff --git a/arch/arm/plat-samsung/include/plat/fimc.h b/arch/arm/plat-samsung/include/plat/fimc.h
index be1e853..cf7d2fb 100644
--- a/arch/arm/plat-samsung/include/plat/fimc.h
+++ b/arch/arm/plat-samsung/include/plat/fimc.h
@@ -27,5 +27,17 @@ struct samsung_plat_fimc {
struct s3c_fifo_link *fifo_targets[FIMC_MAX_FIFO_TARGETS];
};
+extern struct platform_device s5p_device_fimc0;
+extern struct platform_device s5p_device_fimc1;
+extern struct platform_device s5p_device_fimc2;
+
+extern struct samsung_plat_fimc s5p_fimc0_default_data;
+extern struct samsung_plat_fimc s5p_fimc1_default_data;
+extern struct samsung_plat_fimc s5p_fimc2_default_data;
+
+extern void s5p_fimc0_set_platdata(struct samsung_plat_fimc *fimc);
+extern void s5p_fimc1_set_platdata(struct samsung_plat_fimc *fimc);
+extern void s5p_fimc2_set_platdata(struct samsung_plat_fimc *fimc);
+
#endif /* FIMC_H_ */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 03/10 v2] ARM: Samsung: Add platform definitions for local FIMC/FIMD fifo path
2010-07-15 9:10 [PATCH v2] Samsung S5P SoC camera interface driver Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and platform definitions Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 02/10 v2] ARM: Samsung: Add FIMC resource definition and FIMC driver platform helpers Sylwester Nawrocki
@ 2010-07-15 9:10 ` Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 04/10 v2] v4l: Add Samsung FIMC (video postprocessor) driver Sylwester Nawrocki
` (6 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
From: Marek Szyprowski <m.szyprowski@samsung.com>
Add a common s3c_fifo_link structure that describes a local path link
between 2 multimedia devices (like FIMC and FrameBuffer).
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
arch/arm/plat-samsung/include/plat/fifo.h | 37 +++++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/plat-samsung/include/plat/fifo.h
diff --git a/arch/arm/plat-samsung/include/plat/fifo.h b/arch/arm/plat-samsung/include/plat/fifo.h
new file mode 100644
index 0000000..84d242b
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/fifo.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef FIFO_H_
+#define FIFO_H_
+
+#include <linux/device.h>
+#include <media/v4l2-subdev.h>
+
+/*
+ * The multimedia devices contained in Samsung S3C/S5P SoC series
+ * like framebuffer, camera interface or tv scaler can transfer data
+ * directly between each other through hardware fifo channels.
+ * s3c_fifo_link data structure is an abstraction for such links,
+ * it allows to define V4L2 device drivers hierarchy according to
+ * the hardware structure. Fifo links are mostly unidirectional, exclusive
+ * data buses. To control data transfer in fifo mode synchronization is
+ * is required between drivers at both ends of the fifo channel
+ * (master_dev, slave_dev). s3c_fifo_link:sub_dev is intended to export
+ * in a consistent way all the functionality of the slave device required
+ * at master device driver to enable transfer through fifo channel.
+ * master_dev and slave_dev is to be setup by the platform code whilst
+ * sub_dev entry will mostly be initlized during slave_dev probe().
+ */
+struct s3c_fifo_link {
+ struct device *master_dev;
+ struct device *slave_dev;
+ struct v4l2_subdev *sub_dev;
+};
+
+#endif /* FIFO_H_ */
+
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 04/10 v2] v4l: Add Samsung FIMC (video postprocessor) driver
2010-07-15 9:10 [PATCH v2] Samsung S5P SoC camera interface driver Sylwester Nawrocki
` (2 preceding siblings ...)
2010-07-15 9:10 ` [PATCH 03/10 v2] ARM: Samsung: Add platform definitions for local FIMC/FIMD fifo path Sylwester Nawrocki
@ 2010-07-15 9:10 ` Sylwester Nawrocki
2010-07-16 11:39 ` Kukjin Kim
2010-07-15 9:10 ` [PATCH 05/10 v2] s3c-fb: Add v4l2 subdevice to support framebuffer local fifo input path Sylwester Nawrocki
` (5 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
This driver exports two video device nodes per each FIMC device,
one for for memory to memory (color conversion, image resizing,
flipping and rotation) operations and one for direct
V4L2 output interface to framebuffer.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Pawel Osciak <p.osciak@samsung.com>
Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/media/video/Kconfig | 20 +
drivers/media/video/Makefile | 1 +
drivers/media/video/samsung/fimc/Makefile | 3 +
drivers/media/video/samsung/fimc/fimc-core.c | 1664 ++++++++++++++++++++++++++
drivers/media/video/samsung/fimc/fimc-core.h | 541 +++++++++
drivers/media/video/samsung/fimc/fimc-fifo.c | 814 +++++++++++++
drivers/media/video/samsung/fimc/fimc-reg.c | 585 +++++++++
include/linux/videodev2.h | 1 +
8 files changed, 3629 insertions(+), 0 deletions(-)
create mode 100644 drivers/media/video/samsung/fimc/Makefile
create mode 100644 drivers/media/video/samsung/fimc/fimc-core.c
create mode 100644 drivers/media/video/samsung/fimc/fimc-core.h
create mode 100644 drivers/media/video/samsung/fimc/fimc-fifo.c
create mode 100644 drivers/media/video/samsung/fimc/fimc-reg.c
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index bdbc9d3..5895646 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -969,6 +969,16 @@ config VIDEO_OMAP2
---help---
This is a v4l2 driver for the TI OMAP2 camera capture interface
+config VIDEO_SAMSUNG_FIMC
+ tristate "Samsung S3C/S5P FIMC (video postprocessor) driver"
+ depends on VIDEO_DEV && VIDEO_V4L2
+ select VIDEOBUF_DMA_CONTIG
+ select V4L2_MEM2MEM_DEV
+ default n
+ help
+ This is a v4l2 driver for the S3C/S5P camera interface
+ (video postprocessor).
+
#
# USB Multimedia device configuration
#
@@ -1150,4 +1160,14 @@ config VIDEO_MEM2MEM_TESTDEV
This is a virtual test device for the memory-to-memory driver
framework.
+config VIDEO_SAMSUNG_FIMC
+ tristate "Samsung S3C/S5P FIMC (video postprocessor) driver"
+ depends on VIDEO_DEV && VIDEO_V4L2
+ select VIDEOBUF_DMA_CONTIG
+ select V4L2_MEM2MEM_DEV
+ default n
+ help
+ This is a v4l2 driver for the S3C/S5P camera interface
+ (video postprocessor)
+
endif # V4L_MEM2MEM_DRIVERS
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index cc93859..e4c2e1f 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -165,6 +165,7 @@ obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o
obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
+obj-$(CONFIG_VIDEO_SAMSUNG_FIMC) += samsung/fimc/
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
diff --git a/drivers/media/video/samsung/fimc/Makefile b/drivers/media/video/samsung/fimc/Makefile
new file mode 100644
index 0000000..c5c40c1
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/Makefile
@@ -0,0 +1,3 @@
+
+obj-$(CONFIG_VIDEO_SAMSUNG_FIMC) := samsung-fimc.o
+samsung-fimc-y := fimc-core.o fimc-reg.o fimc-fifo.o
diff --git a/drivers/media/video/samsung/fimc/fimc-core.c b/drivers/media/video/samsung/fimc/fimc-core.c
new file mode 100644
index 0000000..448550b
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc-core.c
@@ -0,0 +1,1664 @@
+/*
+ * S5P camera interface (video postprocessor) driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Sylwester Nawrocki, s.nawrocki at samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundiation. either version 2 of the License,
+ * or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/bug.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf-dma-contig.h>
+
+#include "fimc-core.h"
+
+static char *fimc_clock_name[NUM_FIMC_CLOCKS] = { "sclk_fimc", "fimc" };
+
+struct fimc_fmt fimc_formats[] = {
+ {
+ .name = "RGB565",
+ .fourcc = V4L2_PIX_FMT_RGB565X,
+ .depth = 16,
+ .color = S5P_FIMC_RGB565,
+ .buff_cnt = 1,
+ .planes_cnt = 1
+ }, {
+ .name = "RGB666",
+ .fourcc = V4L2_PIX_FMT_RGB666,
+ .depth = 32,
+ .color = S5P_FIMC_RGB666,
+ .buff_cnt = 1,
+ .planes_cnt = 1
+ }, {
+ .name = "XRGB-8-8-8-8, 24 bpp",
+ .fourcc = V4L2_PIX_FMT_RGB24,
+ .depth = 32,
+ .color = S5P_FIMC_RGB888,
+ .buff_cnt = 1,
+ .planes_cnt = 1
+ }, {
+ .name = "YUV 4:2:2 packed, YCbYCr",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+ .color = S5P_FIMC_YCBYCR422,
+ .buff_cnt = 1,
+ .planes_cnt = 1
+ }, {
+ .name = "YUV 4:2:2 packed, CbYCrY",
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .depth = 16,
+ .color = S5P_FIMC_CBYCRY422,
+ .buff_cnt = 1,
+ .planes_cnt = 1
+ }, {
+ .name = "YUV 4:2:2 packed, CrYCbY",
+ .fourcc = V4L2_PIX_FMT_VYUY,
+ .depth = 16,
+ .color = S5P_FIMC_CRYCBY422,
+ .buff_cnt = 1,
+ .planes_cnt = 1
+ }, {
+ .name = "YUV 4:2:2 packed, YCrYCb",
+ .fourcc = V4L2_PIX_FMT_YVYU,
+ .depth = 16,
+ .color = S5P_FIMC_YCRYCB422,
+ .buff_cnt = 1,
+ .planes_cnt = 1
+ }, {
+ .name = "YUV 4:2:2 planar, Y/Cb/Cr",
+ .fourcc = V4L2_PIX_FMT_YUV422P,
+ .depth = 12,
+ .color = S5P_FIMC_YCBCR422,
+ .buff_cnt = 1,
+ .planes_cnt = 3
+ }, {
+ .name = "YUV 4:2:2 planar, Y/CbCr",
+ .fourcc = V4L2_PIX_FMT_NV16,
+ .depth = 16,
+ .color = S5P_FIMC_YCBCR422,
+ .buff_cnt = 1,
+ .planes_cnt = 2
+ }, {
+ .name = "YUV 4:2:2 planar, Y/CrCb",
+ .fourcc = V4L2_PIX_FMT_NV61,
+ .depth = 16,
+ .color = S5P_FIMC_RGB565,
+ .buff_cnt = 1,
+ .planes_cnt = 2
+ }, {
+ .name = "YUV 4:2:0 planar, YCbCr",
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .depth = 12,
+ .color = S5P_FIMC_YCBCR420,
+ .buff_cnt = 1,
+ .planes_cnt = 3
+ }, {
+ .name = "YUV 4:2:0 planar, Y/CbCr",
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .depth = 12,
+ .color = S5P_FIMC_YCBCR420,
+ .buff_cnt = 1,
+ .planes_cnt = 2
+ }
+ };
+
+static struct v4l2_queryctrl fimc_ctrls[] = {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Horizontal flip",
+ .minimum = 0,
+ .maximum = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vertical flip",
+ .minimum = 0,
+ .maximum = 1,
+ .default_value = 0,
+ },
+ {
+ .id = V4L2_CID_ROTATE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Rotation (CCW)",
+ .minimum = 0,
+ .maximum = 270,
+ .step = 90,
+ .default_value = 0,
+ },
+};
+
+
+static struct v4l2_queryctrl *get_ctrl(int id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(fimc_ctrls); ++i)
+ if (id == fimc_ctrls[i].id)
+ return &fimc_ctrls[i];
+ return NULL;
+}
+
+int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f)
+{
+ int ret = 0;
+ if (r->width > f->width) {
+ if (f->width > (r->width * SCALER_MAX_HRATIO))
+ ret = 1;
+ } else {
+ if ((f->width * SCALER_MAX_HRATIO) < r->width)
+ ret = 1;
+ }
+
+ if (r->height > f->height) {
+ if (f->height > (r->height * SCALER_MAX_VRATIO))
+ ret = 1;
+ } else {
+ if ((f->height * SCALER_MAX_VRATIO) < r->height)
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
+{
+ if (src >= tar * 64) {
+ return -EINVAL;
+ } else if (src >= tar * 32) {
+ *ratio = 32;
+ *shift = 5;
+ } else if (src >= tar * 16) {
+ *ratio = 16;
+ *shift = 4;
+ } else if (src >= tar * 8) {
+ *ratio = 8;
+ *shift = 3;
+ } else if (src >= tar * 4) {
+ *ratio = 4;
+ *shift = 2;
+ } else if (src >= tar * 2) {
+ *ratio = 2;
+ *shift = 1;
+ } else {
+ *ratio = 1;
+ *shift = 0;
+ }
+
+ return 0;
+}
+
+int fimc_set_scaler_info(struct fimc_ctx *ctx)
+{
+ struct fimc_scaler *sc = &ctx->scaler;
+ struct fimc_dma_offset *d_ofs = &ctx->s_frame.dma_offset;
+ struct fimc_frame *s_frame = &ctx->s_frame;
+ struct fimc_frame *d_frame = &ctx->d_frame;
+ int width, height, h_ofs, v_ofs;
+ int tx, ty, sx, sy;
+ int ret;
+
+ if (ctx->in_path == FIMC_DMA) {
+ if ((ctx->rotation == 90 || ctx->rotation == 270)
+ && FIMC_LCDFIFO == ctx->out_path) {
+ /* here we are using only the input rotator */
+ width = s_frame->height;
+ height = s_frame->width;
+ h_ofs = d_ofs->y_v;
+ v_ofs = d_ofs->y_h;
+ } else {
+ width = s_frame->width;
+ height = s_frame->height;
+ h_ofs = d_ofs->y_h;
+ v_ofs = d_ofs->y_v;
+ }
+ } else {
+ width = s_frame->width;
+ height = s_frame->height;
+ h_ofs = d_ofs->y_h;
+ v_ofs = d_ofs->y_v;
+ }
+
+ tx = d_frame->width;
+ ty = d_frame->height;
+
+ if (tx <= 0 || ty <= 0) {
+ v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
+ "invalid target size: %d %d", tx, ty);
+ return -EINVAL;
+ }
+
+ sx = width;
+ sy = height;
+
+ sc->real_width = width;
+ sc->real_height = height;
+
+ if (sx <= 0 || sy <= 0) {
+ err("invalid source size: s: %d %d, t: %d %d", sx, sy, tx, ty);
+ return -EINVAL;
+ }
+
+ dbg("sx= %d, sy= %d, tx= %d, ty= %d", sx, sy, tx, ty);
+
+ ret = fimc_get_scaler_factor(sx, tx,
+ &sc->pre_hratio, &sc->hfactor);
+ if (ret)
+ return ret;
+
+ ret = fimc_get_scaler_factor(sy, ty,
+ &sc->pre_vratio, &sc->vfactor);
+ if (ret)
+ return ret;
+
+ sc->pre_dst_width = sx/sc->pre_hratio;
+ sc->pre_dst_height = sy/sc->pre_vratio;
+
+ sc->main_hratio = (sx << 8) / (tx << sc->hfactor);
+ sc->main_vratio = (sy << 8) / (ty << sc->vfactor);
+
+ dbg("sc->main_hratio= %d, sc->main_vratio= %d",
+ sc->main_hratio, sc->main_vratio);
+ dbg("sc->hfactor= %d, sc->vfactor= %d", sc->hfactor, sc->vfactor);
+
+ sc->scaleup_h = (tx >= sx) ? 1 : 0;
+ sc->scaleup_v = (ty >= sy) ? 1 : 0;
+
+ /* check to see if input and output size/format differ */
+ if (s_frame->fmt->color == d_frame->fmt->color
+ && s_frame->width == d_frame->width
+ && s_frame->height == d_frame->height)
+ sc->copy_mode = 1;
+ else
+ sc->copy_mode = 0;
+
+ return 0;
+}
+
+
+static irqreturn_t fimc_isr(int irq, void *priv)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_vid_buffer *src_buf, *dst_buf;
+ struct fimc_dev *fimc = (struct fimc_dev *)priv;
+ struct fimc_output_device *outp = &fimc->outp;
+
+ BUG_ON(!fimc);
+ fimc_hw_clear_irq(fimc);
+
+ spin_lock(&fimc->slock);
+
+ /* v4l2-mem2mem */
+ if (test_and_clear_bit(ST_M2M_PEND, &fimc->state)) {
+ ctx = v4l2_m2m_get_curr_priv(fimc->m2m.m2m_dev);
+ if (!ctx || !ctx->m2m_ctx)
+ goto isr_unlock;
+ src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+ if (src_buf && dst_buf) {
+ spin_lock(&fimc->irqlock);
+ src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE;
+ wake_up(&src_buf->vb.done);
+ wake_up(&dst_buf->vb.done);
+ spin_unlock(&fimc->irqlock);
+ v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx);
+ }
+ goto isr_unlock;
+ }
+
+ /* local fifo mode */
+ fimc_hw_reset_fifo_ov(fimc);
+
+ if (test_bit(ST_LCDFIFO_RUN, &fimc->state)) {
+ /* schedule next buffer in hw if there is any available */
+ if (!list_empty(&outp->buf_q)) {
+ ctx = outp->ctx;
+
+ spin_lock(&fimc->irqlock);
+ outp->curr_buf->vb.state = VIDEOBUF_DONE;
+ spin_unlock(&fimc->irqlock);
+ wake_up(&outp->curr_buf->vb.done);
+
+ outp->curr_buf = list_entry(outp->buf_q.next,
+ struct fimc_vid_buffer, vb.queue);
+ outp->curr_buf->vb.state = VIDEOBUF_ACTIVE;
+ list_del(&outp->curr_buf->vb.queue);
+
+ spin_lock(&ctx->slock);
+ fimc_prepare_addr(ctx, outp->curr_buf,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ /* set source buffer address in hw */
+ fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr);
+ spin_unlock(&ctx->slock);
+ }
+
+ } else if (test_and_clear_bit(ST_LCDFIFO_PEND, &fimc->state)) {
+ set_bit(ST_LCDFIFO_RUN, &fimc->state);
+ }
+
+isr_unlock:
+ spin_unlock(&fimc->slock);
+ return IRQ_HANDLED;
+}
+
+
+static void fimc_dma_run(void *priv)
+{
+ struct fimc_ctx *ctx = priv;
+ struct fimc_dev *fimc = ctx->fimc_dev;
+ u32 ret;
+
+ if (!ctx || ctx->out_path != FIMC_DMA)
+ return;
+
+ set_bit(ST_M2M_PEND, &fimc->state);
+
+ ctx->flags |= (FIMC_SRC_ADDR | FIMC_DST_ADDR);
+ ret = fimc_prepare_config(ctx, ctx->flags);
+ if (ret) {
+ err("general configuration error");
+ return;
+ }
+
+ if (fimc->m2m.ctx != ctx)
+ ctx->flags |= FIMC_PARAMS;
+
+ fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr);
+
+ if (ctx->flags & FIMC_PARAMS) {
+ fimc_hw_set_input_path(ctx);
+ fimc_hw_set_in_dma(ctx);
+ if (fimc_set_scaler_info(ctx)) {
+ err("scaler configuration error");
+ return;
+ }
+ fimc_hw_set_prescaler(ctx);
+ fimc_hw_set_scaler(ctx);
+ fimc_hw_set_target_format(ctx);
+ fimc_hw_set_rotation(ctx);
+ fimc_hw_set_effect(ctx);
+ }
+
+ fimc_hw_set_output_path(ctx);
+ if (ctx->flags & (FIMC_DST_ADDR | FIMC_PARAMS))
+ fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr);
+
+ if (ctx->flags & FIMC_PARAMS)
+ fimc_hw_set_out_dma(ctx);
+
+ if (ctx->scaler.enabled)
+ fimc_hw_start_scaler(fimc);
+ fimc_hw_en_capture(ctx);
+
+ ctx->flags = 0;
+
+ fimc_hw_start_in_dma(fimc);
+
+ fimc->m2m.ctx = ctx;
+}
+
+static void fimc_job_abort(void *priv)
+{
+
+}
+
+/* set order for 1 and 2 plane YCBCR 4:2:2 formats */
+static void fimc_set_yuv_order(struct fimc_ctx *ctx)
+{
+ /* the one only mode supported in SoC */
+ ctx->in_order_2p = S5P_FIMC_LSB_CRCB;
+ ctx->out_order_2p = S5P_FIMC_LSB_CRCB;
+
+ /* set order for 1 plane input formats */
+ switch (ctx->s_frame.fmt->color) {
+ case S5P_FIMC_YCRYCB422:
+ ctx->in_order_1p = S5P_FIMC_IN_YCRYCB;
+ break;
+ case S5P_FIMC_CBYCRY422:
+ ctx->in_order_1p = S5P_FIMC_IN_CBYCRY;
+ break;
+ case S5P_FIMC_CRYCBY422:
+ ctx->in_order_1p = S5P_FIMC_IN_CRYCBY;
+ break;
+ case S5P_FIMC_YCBYCR422:
+ default:
+ ctx->in_order_1p = S5P_FIMC_IN_YCBYCR;
+ break;
+ }
+ dbg("ctx->in_order_1p= %d", ctx->in_order_1p);
+
+ switch (ctx->d_frame.fmt->color) {
+ case S5P_FIMC_YCRYCB422:
+ ctx->out_order_1p = S5P_FIMC_OUT_YCRYCB;
+ break;
+ case S5P_FIMC_CBYCRY422:
+ ctx->out_order_1p = S5P_FIMC_OUT_CBYCRY;
+ break;
+ case S5P_FIMC_CRYCBY422:
+ ctx->out_order_1p = S5P_FIMC_OUT_CRYCBY;
+ break;
+ case S5P_FIMC_YCBYCR422:
+ default:
+ ctx->out_order_1p = S5P_FIMC_OUT_YCBYCR;
+ break;
+ }
+ dbg("ctx->out_order_1p= %d", ctx->out_order_1p);
+}
+
+/**
+ * fimc_prepare_config - check dimensions, operation and color mode
+ * and pre-calculate offset and the scaling coefficients.
+ *
+ * @ctx: hardware context information
+ * @flags: flags indicating which parameters to check/update
+ *
+ * Return: 0 if dimensions are valid or non zero otherwise.
+ */
+int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
+{
+ struct fimc_frame *s_frame, *d_frame;
+ struct fimc_vid_buffer *buf = NULL;
+ struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
+ int ret = 0;
+
+ s_frame = &ctx->s_frame;
+ d_frame = &ctx->d_frame;
+
+ if (flags & FIMC_PARAMS) {
+ if ((ctx->out_path == FIMC_DMA) &&
+ (ctx->rotation == 90 || ctx->rotation == 270)) {
+ swap(d_frame->f_width, d_frame->f_height);
+ swap(d_frame->width, d_frame->height);
+ }
+
+ /* Prepare the output offset related attributes for scaler. */
+ d_frame->dma_offset.y_h = d_frame->offs_h;
+ if (!variant->pix_hoff)
+ d_frame->dma_offset.y_h *= (d_frame->fmt->depth >> 3);
+
+ d_frame->dma_offset.y_v = d_frame->offs_v;
+
+ d_frame->dma_offset.cb_h = d_frame->offs_h;
+ d_frame->dma_offset.cb_v = d_frame->offs_v;
+
+ d_frame->dma_offset.cr_h = d_frame->offs_h;
+ d_frame->dma_offset.cr_v = d_frame->offs_v;
+
+ if (!variant->pix_hoff && d_frame->fmt->planes_cnt == 3) {
+ d_frame->dma_offset.cb_h >>= 1;
+ d_frame->dma_offset.cb_v >>= 1;
+ d_frame->dma_offset.cr_h >>= 1;
+ d_frame->dma_offset.cr_v >>= 1;
+ }
+
+ dbg("out offset: color= %d, y_h= %d, y_v= %d",
+ d_frame->fmt->color,
+ d_frame->dma_offset.y_h, d_frame->dma_offset.y_v);
+
+ /* Prepare the input offset related attributes for scaler. */
+ s_frame->dma_offset.y_h = s_frame->offs_h;
+ if (!variant->pix_hoff)
+ s_frame->dma_offset.y_h *= (s_frame->fmt->depth >> 3);
+ s_frame->dma_offset.y_v = s_frame->offs_v;
+
+ s_frame->dma_offset.cb_h = s_frame->offs_h;
+ s_frame->dma_offset.cb_v = s_frame->offs_v;
+
+ s_frame->dma_offset.cr_h = s_frame->offs_h;
+ s_frame->dma_offset.cr_v = s_frame->offs_v;
+
+ if (!variant->pix_hoff && s_frame->fmt->planes_cnt == 3) {
+ s_frame->dma_offset.cb_h >>= 1;
+ s_frame->dma_offset.cb_v >>= 1;
+ s_frame->dma_offset.cr_h >>= 1;
+ s_frame->dma_offset.cr_v >>= 1;
+ }
+
+ dbg("in offset: color= %d, y_h= %d, y_v= %d",
+ s_frame->fmt->color, s_frame->dma_offset.y_h,
+ s_frame->dma_offset.y_v);
+
+ fimc_set_yuv_order(ctx);
+
+ /* Check against the scaler ratio */
+ if (s_frame->height > (SCALER_MAX_VRATIO * d_frame->height) ||
+ s_frame->width > (SCALER_MAX_HRATIO * d_frame->width)) {
+ err("out of scaler range");
+ return -EINVAL;
+ }
+ }
+
+ /* Input DMA mode is not allowed when the scaler is disabled. */
+ ctx->scaler.enabled = 1;
+
+ if (flags & FIMC_SRC_ADDR) {
+ buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+ ret = fimc_prepare_addr(ctx, buf,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ if (ret)
+ return ret;
+ }
+
+ if (flags & FIMC_DST_ADDR) {
+ buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ ret = fimc_prepare_addr(ctx, buf,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ }
+
+ return ret;
+}
+
+/* The color format (planes_cnt, buff_cnt) must be already configured. */
+int fimc_prepare_addr(struct fimc_ctx *ctx,
+ struct fimc_vid_buffer *buf, enum v4l2_buf_type type)
+{
+ struct fimc_frame *frame;
+ struct fimc_addr *paddr;
+ u32 pix_size;
+ int ret = 0;
+
+ ctx_m2m_get_frame(frame, ctx, type);
+ paddr = &frame->paddr;
+
+ if (!buf)
+ return -EINVAL;
+
+ pix_size = frame->width * frame->height;
+
+ dbg("buff_cnt= %d, planes_cnt= %d, frame->size= %d, pix_size= %d",
+ frame->fmt->buff_cnt, frame->fmt->planes_cnt,
+ frame->size, pix_size);
+
+ if (frame->fmt->buff_cnt == 1) {
+ paddr->y = videobuf_to_dma_contig(&buf->vb);
+ switch (frame->fmt->planes_cnt) {
+ case 1:
+ paddr->cb = 0;
+ paddr->cr = 0;
+ break;
+ case 2:
+ /* decompose Y into Y/Cb */
+ paddr->cb = (u32)(paddr->y + pix_size);
+ paddr->cr = 0;
+ break;
+ case 3:
+ paddr->cb = (u32)(paddr->y + pix_size);
+ /* decompose Y into Y/Cb/Cr */
+ if (S5P_FIMC_YCBCR420 == frame->fmt->color)
+ paddr->cr = (u32)(paddr->cb
+ + (pix_size >> 2));
+ else /* 422 */
+ paddr->cr = (u32)(paddr->cb
+ + (pix_size >> 1));
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ dbg("PHYS_ADDR: type= %d, y= 0x%X cb= 0x%X cr= 0x%X ret= %d",
+ type, paddr->y, paddr->cb, paddr->cr, ret);
+
+ return ret;
+}
+
+static void fimc_buf_release(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb)
+{
+ videobuf_dma_contig_free(vq, vb);
+ vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int fimc_buf_setup(struct videobuf_queue *vq, unsigned int *count,
+ unsigned int *size)
+{
+ struct fimc_ctx *ctx = vq->priv_data;
+ struct fimc_frame *frame;
+
+ ctx_m2m_get_frame(frame, ctx, vq->type);
+
+ *size = (frame->width * frame->height * frame->fmt->depth) >> 3;
+ if (0 == *count)
+ *count = 1;
+ return 0;
+}
+
+static int fimc_buf_prepare(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb, enum v4l2_field field)
+{
+ struct fimc_ctx *ctx = vq->priv_data;
+ struct v4l2_device *v4l2_dev = &ctx->fimc_dev->m2m.v4l2_dev;
+ struct fimc_frame *frame;
+ int ret;
+
+ ctx_m2m_get_frame(frame, ctx, vq->type);
+
+ if (vb->baddr) {
+ if (vb->bsize < frame->size) {
+ v4l2_err(v4l2_dev,
+ "User-provided buffer too small (%d < %d)\n",
+ vb->bsize, frame->size);
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ } else if (vb->state != VIDEOBUF_NEEDS_INIT
+ && vb->bsize < frame->size) {
+ return -EINVAL;
+ }
+
+ vb->width = frame->width;
+ vb->height = frame->height;
+ vb->bytesperline = (frame->width * frame->fmt->depth) >> 3;
+ vb->size = frame->size;
+ vb->field = field;
+
+ if (VIDEOBUF_NEEDS_INIT == vb->state) {
+ ret = videobuf_iolock(vq, vb, NULL);
+ if (ret) {
+ v4l2_err(v4l2_dev, "Iolock failed\n");
+ fimc_buf_release(vq, vb);
+ return ret;
+ }
+ }
+ vb->state = VIDEOBUF_PREPARED;
+
+ return 0;
+}
+
+static void fimc_buf_queue(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb)
+{
+ unsigned long flags;
+ struct fimc_ctx *ctx = vq->priv_data;
+ struct fimc_dev *fimc = ctx->fimc_dev;
+
+ if (ctx->out_path != FIMC_LCDFIFO) {
+ v4l2_m2m_buf_queue(ctx->m2m_ctx, vq, vb);
+ } else {
+ /* Queue the buffer and start transaction if required. */
+ spin_lock_irqsave(&ctx->slock, flags);
+ list_add_tail(&vb->queue, &fimc->outp.buf_q);
+ vb->state = VIDEOBUF_QUEUED;
+ spin_unlock_irqrestore(&ctx->slock, flags);
+
+ spin_lock_irqsave(&fimc->slock, flags);
+ if (!test_bit(ST_LCDFIFO_RUN, &fimc->state)) {
+ set_bit(ST_LCDFIFO_PEND, &fimc->state);
+ queue_work(fimc->work_queue, &fimc->outp.work);
+ }
+ spin_unlock_irqrestore(&fimc->slock, flags);
+ }
+}
+
+struct videobuf_queue_ops fimc_qops = {
+ .buf_setup = fimc_buf_setup,
+ .buf_prepare = fimc_buf_prepare,
+ .buf_queue = fimc_buf_queue,
+ .buf_release = fimc_buf_release,
+};
+
+static int fimc_m2m_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ struct fimc_ctx *ctx = file->private_data;
+ struct fimc_dev *fimc = ctx->fimc_dev;
+
+ strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
+ strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
+ cap->bus_info[0] = 0;
+ cap->version = KERNEL_VERSION(1, 0, 0);
+ cap->capabilities = V4L2_CAP_STREAMING |
+ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT;
+
+ return 0;
+}
+
+int fimc_m2m_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f)
+{
+ struct fimc_fmt *fmt;
+
+ if (f->index >= ARRAY_SIZE(fimc_formats))
+ return -EINVAL;
+
+ fmt = &fimc_formats[f->index];
+ strncpy(f->description, fmt->name, sizeof(f->description) - 1);
+ f->pixelformat = fmt->fourcc;
+ return 0;
+}
+
+static int fimc_m2m_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+ struct fimc_ctx *ctx = priv;
+ struct fimc_frame *frame;
+
+ ctx_m2m_get_frame(frame, ctx, f->type);
+
+ f->fmt.pix.width = frame->width;
+ f->fmt.pix.height = frame->height;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.pixelformat = frame->fmt->fourcc;
+
+ return 0;
+}
+
+struct fimc_fmt *find_format(struct v4l2_format *f)
+{
+ struct fimc_fmt *fmt;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
+ fmt = &fimc_formats[i];
+ if (fmt->fourcc == f->fmt.pix.pixelformat)
+ break;
+ }
+ if (i == ARRAY_SIZE(fimc_formats))
+ return NULL;
+
+ return fmt;
+}
+
+static int fimc_m2m_try_fmt(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct fimc_fmt *fmt;
+ u32 max_width, max_height, mod_x, mod_y;
+ struct fimc_ctx *ctx = priv;
+ struct fimc_dev *fimc = ctx->fimc_dev;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ struct samsung_fimc_variant *variant = fimc->variant;
+
+ fmt = find_format(f);
+ if (!fmt) {
+ v4l2_err(&fimc->m2m.v4l2_dev,
+ "Fourcc format (0x%X) invalid.\n", pix->pixelformat);
+ return -EINVAL;
+ }
+
+ if (pix->field == V4L2_FIELD_ANY)
+ pix->field = V4L2_FIELD_NONE;
+ else if (V4L2_FIELD_NONE != pix->field)
+ return -EINVAL;
+
+ if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ max_width = variant->scaler_dis_w;
+ max_height = variant->scaler_dis_w;
+ mod_x = variant->min_inp_pixsize;
+ mod_y = variant->min_inp_pixsize;
+ } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ max_width = variant->out_rot_dis_w;
+ max_height = variant->out_rot_dis_w;
+ mod_x = variant->min_out_pixsize;
+ mod_y = variant->min_out_pixsize;
+ } else {
+ err("Wrong stream type (%d)", f->type);
+ return -EINVAL;
+ }
+
+ dbg("max_w= %d, max_h= %d", max_width, max_height);
+
+ if (pix->height > max_height)
+ pix->height = max_height;
+ if (pix->width > max_width)
+ pix->width = max_width;
+
+ if (tiled_fmt(fmt)) {
+ mod_x = 64; /* 64x32 tile */
+ mod_y = 32;
+ }
+
+ dbg("mod_x= 0x%X, mod_y= 0x%X", mod_x, mod_y);
+
+ pix->width = (pix->width == 0) ? mod_x : ALIGN(pix->width, mod_x);
+ pix->height = (pix->height == 0) ? mod_y : ALIGN(pix->height, mod_y);
+
+ if (pix->bytesperline == 0 ||
+ pix->bytesperline * 8 / fmt->depth > pix->width)
+ pix->bytesperline = (pix->width * fmt->depth) >> 3;
+
+ if (pix->sizeimage == 0)
+ pix->sizeimage = pix->height * pix->bytesperline;
+
+ dbg("pix->bytesperline= %d, fmt->depth= %d",
+ pix->bytesperline, fmt->depth);
+
+ return 0;
+}
+
+
+static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+ struct fimc_frame *frame;
+ struct v4l2_pix_format *pix;
+ struct videobuf_queue *src_vq = NULL,
+ *dst_vq = NULL;
+ struct fimc_ctx *ctx = priv;
+ struct v4l2_device *v4l2_dev = &ctx->fimc_dev->m2m.v4l2_dev;
+ int ret = 0;
+
+ BUG_ON(!ctx);
+
+ ret = fimc_m2m_try_fmt(file, priv, f);
+ if (ret)
+ return ret;
+
+ mutex_lock(&ctx->fimc_dev->lock);
+
+ src_vq = v4l2_m2m_get_src_vq(ctx->m2m_ctx);
+ dst_vq = v4l2_m2m_get_dst_vq(ctx->m2m_ctx);
+
+ mutex_lock(&src_vq->vb_lock);
+ mutex_lock(&dst_vq->vb_lock);
+
+ if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ if (videobuf_queue_is_busy(src_vq)) {
+ v4l2_err(v4l2_dev, "%s queue busy\n", __func__);
+ ret = -EBUSY;
+ goto s_fmt_out;
+ }
+ frame = &ctx->s_frame;
+ ctx->flags |= FIMC_SRC_FMT;
+
+ } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ if (videobuf_queue_is_busy(dst_vq)) {
+ v4l2_err(v4l2_dev, "%s queue busy\n", __func__);
+ ret = -EBUSY;
+ goto s_fmt_out;
+ }
+ frame = &(ctx)->d_frame;
+ ctx->flags |= FIMC_DST_FMT;
+
+ } else {
+ v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
+ "Wrong buffer/video queue type (%d)\n", f->type);
+ return -EINVAL;
+ }
+
+ pix = &f->fmt.pix;
+ frame->fmt = find_format(f);
+ if (!frame->fmt) {
+ ret = -EINVAL;
+ goto s_fmt_out;
+ }
+
+ frame->f_width = pix->bytesperline * 8 / frame->fmt->depth;
+ frame->f_height = pix->sizeimage/pix->bytesperline;
+ frame->width = pix->width;
+ frame->height = pix->height;
+ frame->o_width = pix->width;
+ frame->o_height = pix->height;
+ frame->offs_h = 0;
+ frame->offs_v = 0;
+ frame->size = (pix->width * pix->height * frame->fmt->depth) >> 3;
+ ctx->flags |= FIMC_PARAMS;
+ src_vq->field = dst_vq->field = pix->field;
+
+ dbg("f_width= %d, f_height= %d", frame->f_width, frame->f_height);
+
+s_fmt_out:
+ mutex_unlock(&dst_vq->vb_lock);
+ mutex_unlock(&src_vq->vb_lock);
+ mutex_unlock(&ctx->fimc_dev->lock);
+ return ret;
+}
+
+static int fimc_m2m_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *reqbufs)
+{
+ struct fimc_ctx *ctx = priv;
+ return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
+}
+
+static int fimc_m2m_querybuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct fimc_ctx *ctx = priv;
+ return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
+}
+
+static int fimc_m2m_qbuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct fimc_ctx *ctx = priv;
+
+ if (!fimc_fifo_active(ctx->fimc_dev))
+ return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+ else
+ return -EBUSY;
+}
+
+static int fimc_m2m_dqbuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct fimc_ctx *ctx = priv;
+ return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int fimc_m2m_streamon(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct fimc_ctx *ctx = priv;
+
+ if (!fimc_fifo_active(ctx->fimc_dev))
+ return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
+ else
+ return -EBUSY;
+}
+
+static int fimc_m2m_streamoff(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct fimc_ctx *ctx = priv;
+ return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
+}
+
+int fimc_m2m_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ struct v4l2_queryctrl *c;
+ c = get_ctrl(qc->id);
+ if (!c)
+ return -EINVAL;
+ *qc = *c;
+ return 0;
+}
+
+int fimc_m2m_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct fimc_ctx *ctx = priv;
+
+ switch (ctrl->id) {
+ case V4L2_CID_HFLIP:
+ ctrl->value = (FLIP_X_AXIS & ctx->flip) ? 1 : 0;
+ break;
+ case V4L2_CID_VFLIP:
+ ctrl->value = (FLIP_Y_AXIS & ctx->flip) ? 1 : 0;
+ break;
+ case V4L2_CID_ROTATE:
+ ctrl->value = ctx->rotation;
+ break;
+ default:
+ v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, "Invalid control\n");
+ return -EINVAL;
+ }
+ dbg("ctrl->value= %d", ctrl->value);
+ return 0;
+}
+
+static int check_ctrl_val(struct fimc_ctx *ctx,
+ struct v4l2_control *ctrl)
+{
+ struct v4l2_queryctrl *c;
+ c = get_ctrl(ctrl->id);
+ if (!c)
+ return -EINVAL;
+
+ if (ctrl->value < c->minimum || ctrl->value > c->maximum
+ || (c->step != 0 && ctrl->value % c->step != 0)) {
+ v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
+ "Invalid control value\n");
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
+int fimc_m2m_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct fimc_ctx *ctx = priv;
+ struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
+ int ret = 0;
+
+ ret = check_ctrl_val(ctx, ctrl);
+ if (ret)
+ return ret;
+
+ switch (ctrl->id) {
+ case V4L2_CID_HFLIP:
+ if (ctx->rotation != 0)
+ return 0;
+ if (ctrl->value)
+ ctx->flip |= FLIP_X_AXIS;
+ else
+ ctx->flip &= ~FLIP_X_AXIS;
+ break;
+
+ case V4L2_CID_VFLIP:
+ if (ctx->rotation != 0)
+ return 0;
+ if (ctrl->value)
+ ctx->flip |= FLIP_Y_AXIS;
+ else
+ ctx->flip &= ~FLIP_Y_AXIS;
+ break;
+
+ case V4L2_CID_ROTATE:
+ if (ctrl->value == 90 || ctrl->value == 270) {
+ if (ctx->out_path == FIMC_LCDFIFO &&
+ !variant->has_inp_rot) {
+ return -EINVAL;
+ } else if (ctx->in_path == FIMC_DMA &&
+ !variant->has_out_rot) {
+ return -EINVAL;
+ }
+ }
+ ctx->rotation = ctrl->value;
+ if (ctrl->value == 180)
+ ctx->flip = FLIP_XY_AXIS;
+ break;
+
+ default:
+ v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, "Invalid control\n");
+ return -EINVAL;
+ }
+
+ ctx->flags |= FIMC_PARAMS;
+ return 0;
+}
+
+
+static int fimc_m2m_cropcap(struct file *file, void *fh,
+ struct v4l2_cropcap *cr)
+{
+ struct fimc_frame *frame;
+ struct fimc_ctx *ctx = fh;
+
+ ctx_m2m_get_frame(frame, ctx, cr->type);
+
+ cr->bounds.left = 0;
+ cr->bounds.top = 0;
+ cr->bounds.width = frame->f_width;
+ cr->bounds.height = frame->f_height;
+ cr->defrect.left = frame->offs_h;
+ cr->defrect.top = frame->offs_v;
+ cr->defrect.width = frame->o_width;
+ cr->defrect.height = frame->o_height;
+ return 0;
+}
+
+static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
+{
+ struct fimc_frame *frame;
+ struct fimc_ctx *ctx = file->private_data;
+
+ ctx_m2m_get_frame(frame, ctx, cr->type);
+
+ cr->c.left = frame->offs_h;
+ cr->c.top = frame->offs_v;
+ cr->c.width = frame->width;
+ cr->c.height = frame->height;
+
+ return 0;
+}
+
+static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
+{
+ struct fimc_ctx *ctx = file->private_data;
+ struct fimc_dev *fimc = ctx->fimc_dev;
+ struct fimc_frame *f;
+ u32 min_size;
+ int ret = 0;
+
+ if (cr->c.top < 0 || cr->c.left < 0) {
+ v4l2_err(&fimc->m2m.v4l2_dev,
+ "doesn't support negative values for top & left\n");
+ return -EINVAL;
+ }
+
+ if (cr->c.width <= 0 || cr->c.height <= 0) {
+ v4l2_err(&fimc->m2m.v4l2_dev,
+ "crop width and height must be greater than 0\n");
+ return -EINVAL;
+ }
+
+ ctx_m2m_get_frame(f, ctx, cr->type);
+
+ dbg("%d %d %d %d f_w= %d, f_h= %d",
+ cr->c.left, cr->c.top, cr->c.width, cr->c.height,
+ f->f_width, f->f_height);
+
+ /* Adjust to required pixel boundary. */
+ min_size = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?
+ fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;
+
+ cr->c.width = round_down(cr->c.width, min_size);
+ cr->c.height = round_down(cr->c.height, min_size);
+ cr->c.left = round_down(cr->c.left + 1, min_size);
+ cr->c.top = round_down(cr->c.top + 1, min_size);
+
+ if ((cr->c.left + cr->c.width > f->o_width)
+ || (cr->c.top + cr->c.height > f->o_height)) {
+ v4l2_err(&fimc->m2m.v4l2_dev, "Error in S_CROP params\n");
+ return -EINVAL;
+ }
+
+ if ((ctx->flags & FIMC_SRC_FMT) && (ctx->flags & FIMC_DST_FMT)) {
+ /* Check for the pixel scaling ratio when cropping input img. */
+ if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame);
+ else if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame);
+
+ if (ret) {
+ v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range");
+ return -EINVAL;
+ }
+ }
+
+ f->offs_h = cr->c.left;
+ f->offs_v = cr->c.top;
+ f->width = cr->c.width;
+ f->height = cr->c.height;
+ ctx->flags |= FIMC_PARAMS;
+ return 0;
+}
+
+static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
+ .vidioc_querycap = fimc_m2m_querycap,
+
+ .vidioc_enum_fmt_vid_cap = fimc_m2m_enum_fmt,
+ .vidioc_enum_fmt_vid_out = fimc_m2m_enum_fmt,
+
+ .vidioc_g_fmt_vid_cap = fimc_m2m_g_fmt,
+ .vidioc_g_fmt_vid_out = fimc_m2m_g_fmt,
+
+ .vidioc_try_fmt_vid_cap = fimc_m2m_try_fmt,
+ .vidioc_try_fmt_vid_out = fimc_m2m_try_fmt,
+
+ .vidioc_s_fmt_vid_cap = fimc_m2m_s_fmt,
+ .vidioc_s_fmt_vid_out = fimc_m2m_s_fmt,
+
+ .vidioc_reqbufs = fimc_m2m_reqbufs,
+ .vidioc_querybuf = fimc_m2m_querybuf,
+
+ .vidioc_qbuf = fimc_m2m_qbuf,
+ .vidioc_dqbuf = fimc_m2m_dqbuf,
+
+ .vidioc_streamon = fimc_m2m_streamon,
+ .vidioc_streamoff = fimc_m2m_streamoff,
+
+ .vidioc_queryctrl = fimc_m2m_queryctrl,
+ .vidioc_g_ctrl = fimc_m2m_g_ctrl,
+ .vidioc_s_ctrl = fimc_m2m_s_ctrl,
+
+ .vidioc_g_crop = fimc_m2m_g_crop,
+ .vidioc_s_crop = fimc_m2m_s_crop,
+ .vidioc_cropcap = fimc_m2m_cropcap
+
+};
+
+static void queue_init(void *priv, struct videobuf_queue *vq,
+ enum v4l2_buf_type type)
+{
+ struct fimc_ctx *ctx = priv;
+ struct fimc_dev *fimc = ctx->fimc_dev;
+
+ videobuf_queue_dma_contig_init(vq, &fimc_qops,
+ fimc->m2m.v4l2_dev.dev,
+ &fimc->irqlock, type, V4L2_FIELD_NONE,
+ sizeof(struct fimc_vid_buffer), priv);
+}
+
+static int fimc_m2m_open(struct file *file)
+{
+ struct fimc_dev *fimc = video_drvdata(file);
+ struct fimc_ctx *ctx = NULL;
+ int err = 0;
+
+ mutex_lock(&fimc->lock);
+ fimc->m2m.refcnt++;
+ set_bit(ST_OUTDMA_RUN, &fimc->state);
+ mutex_unlock(&fimc->lock);
+
+
+ ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ file->private_data = ctx;
+ ctx->fimc_dev = fimc;
+ /* default format */
+ ctx->s_frame.fmt = &fimc_formats[0];
+ ctx->d_frame.fmt = &fimc_formats[0];
+ /* per user process device context initialization */
+ ctx->flags = 0;
+ ctx->effect.type = S5P_FIMC_EFFECT_ORIGINAL;
+ ctx->in_path = FIMC_DMA;
+ ctx->out_path = FIMC_DMA;
+
+ ctx->m2m_ctx = v4l2_m2m_ctx_init(ctx, fimc->m2m.m2m_dev, queue_init);
+
+ if (IS_ERR(ctx->m2m_ctx)) {
+ err = PTR_ERR(ctx->m2m_ctx);
+ kfree(ctx);
+ return err;
+ }
+
+ return 0;
+}
+
+static int fimc_m2m_release(struct file *file)
+{
+ struct fimc_ctx *ctx = file->private_data;
+ struct fimc_dev *fimc = ctx->fimc_dev;
+
+ v4l2_m2m_ctx_release(ctx->m2m_ctx);
+ kfree(ctx);
+ mutex_lock(&fimc->lock);
+ if (--fimc->m2m.refcnt <= 0)
+ clear_bit(ST_OUTDMA_RUN, &fimc->state);
+ mutex_unlock(&fimc->lock);
+ return 0;
+}
+
+static unsigned int fimc_m2m_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct fimc_ctx *ctx = file->private_data;
+ return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+}
+
+
+static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct fimc_ctx *ctx = file->private_data;
+ return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+}
+
+static const struct v4l2_file_operations fimc_m2m_fops = {
+ .owner = THIS_MODULE,
+ .open = fimc_m2m_open,
+ .release = fimc_m2m_release,
+ .poll = fimc_m2m_poll,
+ .ioctl = video_ioctl2,
+ .mmap = fimc_m2m_mmap,
+};
+
+static struct v4l2_m2m_ops m2m_ops = {
+ .device_run = fimc_dma_run,
+ .job_abort = fimc_job_abort,
+};
+
+
+static int fimc_register_m2m_device(struct fimc_dev *fimc)
+{
+ struct video_device *vfd;
+ struct platform_device *pdev;
+ struct v4l2_device *v4l2_dev;
+ int ret = 0;
+
+ if (!fimc)
+ return -ENODEV;
+
+ pdev = fimc->pdev;
+ v4l2_dev = &fimc->m2m.v4l2_dev;
+
+ /* set name if it is empty */
+ if (!v4l2_dev->name[0])
+ snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
+ "%s.%d.v4l2_m2m", MODULE_NAME, fimc->id);
+
+ ret = v4l2_device_register(&pdev->dev, v4l2_dev);
+ if (ret)
+ return ret;;
+
+ vfd = video_device_alloc();
+ if (!vfd) {
+ v4l2_err(v4l2_dev, "Failed to allocate video device\n");
+ goto err_m2m_r1;
+ }
+
+ vfd->fops = &fimc_m2m_fops;
+ vfd->ioctl_ops = &fimc_m2m_ioctl_ops;
+ vfd->minor = -1;
+ vfd->release = video_device_release;
+
+ snprintf(vfd->name, sizeof(vfd->name), "%s.%d:v4l2_m2m",
+ MODULE_NAME, fimc->id);
+
+ ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
+ if (ret) {
+ v4l2_err(v4l2_dev,
+ "%s(): failed to register video device\n", __func__);
+ goto err_m2m_r2;
+ }
+ video_set_drvdata(vfd, fimc);
+ fimc->m2m.vfd = vfd;
+ v4l2_info(v4l2_dev,
+ "FIMC m2m driver registered as /dev/video%d\n", vfd->num);
+
+ platform_set_drvdata(pdev, fimc);
+
+ fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops);
+
+ if (IS_ERR(fimc->m2m.m2m_dev)) {
+ v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n");
+ ret = PTR_ERR(fimc->m2m.m2m_dev);
+ goto err_m2m_r3;
+ }
+ return 0;
+
+err_m2m_r1:
+ v4l2_device_unregister(&fimc->m2m.v4l2_dev);
+err_m2m_r2:
+ video_device_release(fimc->m2m.vfd);
+err_m2m_r3:
+ video_unregister_device(fimc->m2m.vfd);
+
+ return ret;
+}
+
+static void fimc_unregister_m2m_device(struct fimc_dev *fimc)
+{
+ if (fimc) {
+ v4l2_m2m_release(fimc->m2m.m2m_dev);
+ video_unregister_device(fimc->m2m.vfd);
+ video_device_release(fimc->m2m.vfd);
+ v4l2_device_unregister(&fimc->m2m.v4l2_dev);
+ }
+}
+
+static void fimc_clk_release(struct fimc_dev *fimc)
+{
+ int i;
+ for(i = 0; i < NUM_FIMC_CLOCKS; i++) {
+ if(fimc->clock[i]) {
+ clk_disable(fimc->clock[i]);
+ clk_put(fimc->clock[i]);
+ }
+ }
+}
+
+static int fimc_clk_get(struct fimc_dev *fimc)
+{
+ int i;
+ for(i = 0; i < NUM_FIMC_CLOCKS; i++) {
+ fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clock_name[i]);
+ if (IS_ERR(fimc->clock[i])) {
+ dev_err(&fimc->pdev->dev,
+ "failed to get fimc clock: %s\n",
+ fimc_clock_name[i]);
+ return -ENXIO;
+ }
+ clk_enable(fimc->clock[i]);
+ }
+ return 0;
+}
+
+static int fimc_probe(struct platform_device *pdev)
+{
+ struct fimc_dev *fimc;
+ struct resource *res;
+ struct samsung_fimc_driverdata *drv_data;
+ int ret = 0;
+
+ dev_dbg(&pdev->dev, "%s():\n", __func__);
+
+ drv_data = (struct samsung_fimc_driverdata *)
+ platform_get_device_id(pdev)->driver_data;
+
+ if (pdev->id >= drv_data->devs_cnt) {
+ dev_err(&pdev->dev, "Invalid platform device id: %d\n",
+ pdev->id);
+ return -EINVAL;
+ }
+
+ fimc = kzalloc(sizeof(struct fimc_dev), GFP_KERNEL);
+ if (!fimc)
+ return -ENOMEM;
+
+ fimc->id = pdev->id;
+ fimc->variant = drv_data->variant[fimc->id];
+ fimc->pdev = pdev;
+ fimc->pdata = pdev->dev.platform_data;
+ fimc->state = ST_IDLE;
+
+ spin_lock_init(&fimc->irqlock);
+ spin_lock_init(&fimc->slock);
+
+ mutex_init(&fimc->lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to find the registers\n");
+ ret = -ENOENT;
+ goto err_info;
+ }
+
+ fimc->regs_res = request_mem_region(res->start, resource_size(res),
+ dev_name(&pdev->dev));
+ if (!fimc->regs_res) {
+ dev_err(&pdev->dev, "failed to obtain register region\n");
+ ret = -ENOENT;
+ goto err_info;
+ }
+
+ fimc->regs = ioremap(res->start, resource_size(res));
+ if (!fimc->regs) {
+ dev_err(&pdev->dev, "failed to map registers\n");
+ ret = -ENXIO;
+ goto err_req_region;
+ }
+
+ ret = fimc_clk_get(fimc);
+ if(ret)
+ goto err_regs_unmap;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get IRQ resource\n");
+ ret = -ENXIO;
+ goto err_clk;
+ }
+ fimc->irq = res->start;
+
+ fimc_hw_reset(fimc);
+
+ ret = request_irq(fimc->irq, fimc_isr, 0, pdev->name, fimc);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
+ goto err_clk;
+ }
+
+ fimc->work_queue = create_workqueue(dev_name(&fimc->pdev->dev));
+ if (!fimc->work_queue)
+ goto err_irq;
+
+ ret = fimc_register_m2m_device(fimc);
+ if (ret)
+ goto err_wq;
+
+ if (fimc->variant->fifo_capable) {
+ ret = fimc_register_fifo_device(fimc);
+ if (ret)
+ goto err_m2m;
+ }
+
+ fimc_hw_en_lastirq(fimc, 1);
+
+ dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n",
+ __func__, fimc->id);
+
+ return 0;
+
+err_m2m:
+ fimc_unregister_m2m_device(fimc);
+err_wq:
+ destroy_workqueue(fimc->work_queue);
+err_irq:
+ free_irq(fimc->irq, fimc);
+err_clk:
+ fimc_clk_release(fimc);
+err_regs_unmap:
+ iounmap(fimc->regs);
+err_req_region:
+ release_resource(fimc->regs_res);
+ kfree(fimc->regs_res);
+err_info:
+ dev_err(&pdev->dev, "failed to install\n");
+ return ret;
+}
+
+static int __devexit fimc_remove(struct platform_device *pdev)
+{
+ struct fimc_dev *fimc =
+ (struct fimc_dev *)platform_get_drvdata(pdev);
+
+ v4l2_info(&fimc->m2m.v4l2_dev, "Removing %s\n", pdev->name);
+
+ free_irq(fimc->irq, fimc);
+
+ fimc_hw_reset(fimc);
+
+ fimc_unregister_m2m_device(fimc);
+ fimc_unregister_fifo_device(fimc);
+ fimc_clk_release(fimc);
+ iounmap(fimc->regs);
+ release_resource(fimc->regs_res);
+ kfree(fimc->regs_res);
+ kfree(fimc);
+ return 0;
+}
+
+
+static struct samsung_fimc_variant fimc01_variant_s5pc100 = {
+ .has_inp_rot = 1,
+ .has_out_rot = 1,
+ .fifo_capable = 1,
+ .min_inp_pixsize = 16,
+ .min_out_pixsize = 16,
+
+ .scaler_en_w = 3264,
+ .scaler_dis_w = 8192,
+ .in_rot_en_h = 1920,
+ .in_rot_dis_w = 8192,
+ .out_rot_en_w = 1920,
+ .out_rot_dis_w = 4224,
+};
+
+static struct samsung_fimc_variant fimc2_variant_s5pc100 = {
+ .fifo_capable = 1,
+ .min_inp_pixsize = 16,
+ .min_out_pixsize = 16,
+
+ .scaler_en_w = 4224,
+ .scaler_dis_w = 8192,
+ .in_rot_en_h = 1920,
+ .in_rot_dis_w = 8192,
+ .out_rot_en_w = 1920,
+ .out_rot_dis_w = 4224,
+};
+
+static struct samsung_fimc_variant fimc01_variant_s5pv210 = {
+ .has_inp_rot = 1,
+ .has_out_rot = 1,
+ .min_inp_pixsize = 16,
+ .min_out_pixsize = 32,
+
+ .scaler_en_w = 4224,
+ .scaler_dis_w = 8192,
+ .in_rot_en_h = 1920,
+ .in_rot_dis_w = 8192,
+ .out_rot_en_w = 1920,
+ .out_rot_dis_w = 4224,
+};
+
+static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
+ .min_inp_pixsize = 16,
+ .min_out_pixsize = 32,
+
+ .scaler_en_w = 1920,
+ .scaler_dis_w = 8192,
+ .in_rot_en_h = 1280,
+ .in_rot_dis_w = 8192,
+ .out_rot_en_w = 1280,
+ .out_rot_dis_w = 1920,
+};
+
+static struct samsung_fimc_driverdata fimc_drvdata_s5pc100 = {
+ .variant = {
+ [0] = &fimc01_variant_s5pc100,
+ [1] = &fimc01_variant_s5pc100,
+ [2] = &fimc2_variant_s5pc100,
+ },
+ .devs_cnt = 3
+};
+
+static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = {
+ .variant = {
+ [0] = &fimc01_variant_s5pv210,
+ [1] = &fimc01_variant_s5pv210,
+ [2] = &fimc2_variant_s5pv210,
+ },
+ .devs_cnt = 3
+};
+
+static struct platform_device_id fimc_driver_ids[] = {
+ {
+ .name = "s5pc100-fimc",
+ .driver_data = (unsigned long)&fimc_drvdata_s5pc100,
+ }, {
+ .name = "s5pv210-fimc",
+ .driver_data = (unsigned long)&fimc_drvdata_s5pv210,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(platform, s3c_fimc_driver_ids);
+
+static struct platform_driver fimc_driver = {
+ .probe = fimc_probe,
+ .remove = __devexit_p(fimc_remove),
+ .id_table = fimc_driver_ids,
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ }
+};
+
+static char banner[] __initdata = KERN_INFO
+ "S5PC Camera Interface V4L2 Driver, (c) 2010 Samsung Electronics\n";
+
+static int __init fimc_init(void)
+{
+ u32 ret;
+ printk(banner);
+
+ ret = platform_driver_register(&fimc_driver);
+ if (ret) {
+ printk(KERN_ERR "FIMC platform driver register failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+static void __exit fimc_exit(void)
+{
+ platform_driver_unregister(&fimc_driver);
+}
+
+module_init(fimc_init);
+module_exit(fimc_exit);
+
+MODULE_AUTHOR("Sylwester Nawrocki, s.nawrocki at samsung.com");
+MODULE_DESCRIPTION("S5PV210 FIMC (video postprocessor) driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/samsung/fimc/fimc-core.h b/drivers/media/video/samsung/fimc/fimc-core.h
new file mode 100644
index 0000000..377c815
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc-core.h
@@ -0,0 +1,541 @@
+/*
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Sylwester Nawrocki, s.nawrocki at samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef FIMC_CORE_H_
+#define FIMC_CORE_H_
+
+#include <linux/types.h>
+#include <plat/fimc.h>
+#include <plat/regs-fimc.h>
+#include <media/videobuf-core.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <linux/videodev2.h>
+
+
+#define err(fmt, args...) \
+ printk(KERN_ERR "%s:%d: " fmt "\n", __func__, __LINE__, ##args)
+
+#ifdef DEBUG
+#define dbg(fmt, args...) \
+ printk(KERN_DEBUG "%s:%d: " fmt "\n", __func__, __LINE__, ##args)
+#else
+#define dbg(fmt, args...)
+#endif
+
+#define ctx_m2m_get_frame(frame, ctx, type) do { \
+ if (V4L2_BUF_TYPE_VIDEO_OUTPUT == (type)) { \
+ frame = &(ctx)->s_frame; \
+ } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE == (type)) { \
+ frame = &(ctx)->d_frame; \
+ } else { \
+ v4l2_err(&(ctx)->fimc_dev->m2m.v4l2_dev,\
+ "Wrong buffer/video queue type (%d)\n", type); \
+ return -EINVAL; \
+ } \
+} while (0)
+
+
+/* Time to wait for an interrupt whilst shutting down the lcdfifo mode. */
+#define FIMC_FIFO_SHDWN_TIMEOUT ((100*HZ)/1000)
+#define NUM_FIMC_CLOCKS 2
+#define MODULE_NAME "s5p-fimc"
+#define FIMC_MAX_DEVS 3
+#define FIMC_MAX_OUT_BUFS 4
+#define SCALER_MAX_HRATIO 64
+#define SCALER_MAX_VRATIO 64
+
+/* The hardware context flags. */
+#define FIMC_PARAMS (1 << 0)
+#define FIMC_SRC_ADDR (1 << 1)
+#define FIMC_DST_ADDR (1 << 2)
+#define FIMC_SRC_FMT (1 << 3)
+#define FIMC_DST_FMT (1 << 4)
+
+
+enum fimc_dev_flags {
+ ST_IDLE,
+ ST_OUTDMA_RUN,
+ ST_M2M_PEND,
+ ST_LCDFIFO_PEND,
+ ST_LCDFIFO_RUN
+};
+
+#define fimc_m2m_active(dev) test_bit(ST_OUTDMA_RUN, &(dev)->state)
+#define fimc_m2m_pending(dev) test_bit(ST_M2M_PEND, &(dev)->state)
+
+#define fimc_fifo_active(dev) test_bit(ST_LCDFIFO_RUN, &(dev)->state)
+#define fimc_fifo_pending(dev) test_bit(ST_LCDFIFO_PEND, &(dev)->state)
+
+enum fimc_datapath {
+ FIMC_ITU_CAM_A,
+ FIMC_ITU_CAM_B,
+ FIMC_MIPI_CAM,
+ FIMC_DMA,
+ FIMC_LCDFIFO,
+ FIMC_WRITEBACK
+};
+
+enum fimc_color_fmt {
+ S5P_FIMC_RGB565,
+ S5P_FIMC_RGB666,
+ S5P_FIMC_RGB888,
+ S5P_FIMC_YCBCR420,
+ S5P_FIMC_YCBCR422,
+ S5P_FIMC_YCBYCR422,
+ S5P_FIMC_YCRYCB422,
+ S5P_FIMC_CBYCRY422,
+ S5P_FIMC_CRYCBY422,
+ S5P_FIMC_RGB30_LOCAL,
+ S5P_FIMC_YCBCR444_LOCAL,
+ S5P_FIMC_MAX_COLOR = S5P_FIMC_YCBCR444_LOCAL,
+ S5P_FIMC_COLOR_MASK = 0x0F,
+};
+
+/* Y/Cb/Cr components order at DMA output for 1 plane YCbCr 4:2:2 formats. */
+#define S5P_FIMC_OUT_CRYCBY S5P_CIOCTRL_ORDER422_CRYCBY
+#define S5P_FIMC_OUT_CBYCRY S5P_CIOCTRL_ORDER422_YCRYCB
+#define S5P_FIMC_OUT_YCRYCB S5P_CIOCTRL_ORDER422_CBYCRY
+#define S5P_FIMC_OUT_YCBYCR S5P_CIOCTRL_ORDER422_YCBYCR
+
+/* Input Y/Cb/Cr components order for 1 plane YCbCr 4:2:2 color formats. */
+#define S5P_FIMC_IN_CRYCBY S5P_MSCTRL_ORDER422_CRYCBY
+#define S5P_FIMC_IN_CBYCRY S5P_MSCTRL_ORDER422_YCRYCB
+#define S5P_FIMC_IN_YCRYCB S5P_MSCTRL_ORDER422_CBYCRY
+#define S5P_FIMC_IN_YCBYCR S5P_MSCTRL_ORDER422_YCBYCR
+
+/* Cb/Cr chrominance components order for 2 plane Y/CbCr 4:2:2 formats. */
+#define S5P_FIMC_LSB_CRCB S5P_CIOCTRL_ORDER422_2P_LSB_CRCB
+
+/* The embedded image effect selection */
+#define S5P_FIMC_EFFECT_ORIGINAL S5P_CIIMGEFF_FIN_BYPASS
+#define S5P_FIMC_EFFECT_ARBITRARY S5P_CIIMGEFF_FIN_ARBITRARY
+#define S5P_FIMC_EFFECT_NEGATIVE S5P_CIIMGEFF_FIN_NEGATIVE
+#define S5P_FIMC_EFFECT_ARTFREEZE S5P_CIIMGEFF_FIN_ARTFREEZE
+#define S5P_FIMC_EFFECT_EMBOSSING S5P_CIIMGEFF_FIN_EMBOSSING
+#define S5P_FIMC_EFFECT_SIKHOUETTE S5P_CIIMGEFF_FIN_SILHOUETTE
+
+
+/* Definitions for flags field in struct fimc_ctx */
+#define IN_DMA_ACCESS_LINEAR 0 /* default */
+#define IN_DMA_ACCESS_TILED (1 << 0)
+#define OUT_DMA_ACCESS_LINEAR (0 << 1)
+#define OUT_DMA_ACCESS_TILED (1 << 1)
+#define SCAN_MODE_PROGRESSIVE (0 << 2)
+#define SCAN_MODE_INTERLACED (1 << 2)
+/* YCbCr data dynamic range selection for the RGB <-> YCBCR color space
+ * conversion. Y/Cb/Cr (0 ~ 255) : Wide default */
+#define S5P_FIMC_COLOR_RANGE_WIDE (0 << 3)
+/* Y (16 ~ 235), Cb/Cr (16 ~ 240) : Narrow */
+#define S5P_FIMC_COLOR_RANGE_NARROW (1 << 3)
+
+#define FLIP_NONE 0
+#define FLIP_X_AXIS 1
+#define FLIP_Y_AXIS 2
+#define FLIP_XY_AXIS (FLIP_X_AXIS | FLIP_Y_AXIS)
+
+/**
+ * struct fimc_fmt - the driver's internal color format data
+ * @name: format description
+ * @fourcc: the fourcc code for this format
+ * @color: the corresponding fimc_color_fmt
+ * @depth: number of bits per pixel
+ * @buff_cnt: number of physically non-contiguous data planes
+ * @planes_cnt: number of physically contiguous data planes
+ */
+struct fimc_fmt {
+ char *name;
+ u32 fourcc;
+ u32 color;
+ u32 depth;
+ u16 buff_cnt;
+ u16 planes_cnt;
+};
+
+/**
+ * struct fimc_dma_offset - pixel offset information for DMA
+ * @y_h: y value horizontal offset
+ * @y_v: y value vertical offset
+ * @cb_h: cb value horizontal offset
+ * @cb_v: cb value vertical offset
+ * @cr_h: cr value horizontal offset
+ * @cr_v: cr value vertical offset
+ */
+struct fimc_dma_offset {
+ int y_h;
+ int y_v;
+ int cb_h;
+ int cb_v;
+ int cr_h;
+ int cr_v;
+};
+
+/**
+ * struct fimc_effect - the configuration data for the "Arbitrary" image effect
+ * @type: effect type
+ * @pat_cb: cr value when type is "arbitrary"
+ * @pat_cr: cr value when type is "arbitrary"
+ */
+struct fimc_effect {
+ u32 type;
+ u8 pat_cb;
+ u8 pat_cr;
+};
+
+/**
+ * struct fimc_scaler - the configuration data for FIMC inetrnal scaler
+ *
+ * @enabled: the flag set when the scaler is used
+ * @hfactor: horizontal shift factor
+ * @vfactor: vertical shift factor
+ * @pre_hratio: horizontal ratio of the prescaler
+ * @pre_vratio: vertical ratio of the prescaler
+ * @pre_dst_width: the prescaler's destination width
+ * @pre_dst_height: the prescaler's destination height
+ * @scaleup_h: flag indicating scaling up horizontally
+ * @scaleup_v: flag indicating scaling up vertically
+ * @main_hratio: the main scaler's horizontal ratio
+ * @main_vratio: the main scaler's vertical ratio
+ * @real_width: source width - offset
+ * @real_height: source height - offset
+ * @copy_mode: flag set if one-to-one mode is used, i.e. no scaling
+ * and color format conversion
+ */
+struct fimc_scaler {
+ u32 enabled;
+ u32 hfactor;
+ u32 vfactor;
+ u32 pre_hratio;
+ u32 pre_vratio;
+ u32 pre_dst_width;
+ u32 pre_dst_height;
+ u32 scaleup_h;
+ u32 scaleup_v;
+ u32 main_hratio;
+ u32 main_vratio;
+ u32 real_width;
+ u32 real_height;
+ u32 copy_mode;
+};
+
+/**
+ * struct fimc_addr - the FIMC physical address set for DMA
+ *
+ * @y: luminance plane physical address
+ * @cb: Cb plane physical address
+ * @cr: Cr plane physical address
+ */
+struct fimc_addr {
+ u32 y;
+ u32 cb;
+ u32 cr;
+};
+
+/**
+ * struct fimc_vid_buffer - the driver's video buffer
+ * @vb: v4l videobuf buffer
+ */
+struct fimc_vid_buffer {
+ struct videobuf_buffer vb;
+};
+
+/**
+ * struct fimc_frame - input/output frame format properties
+ *
+ * @f_width: image full width (virtual screen size)
+ * @f_height: image full height (virtual screen size)
+ * @o_width: original image width as set by S_FMT
+ * @o_height: original image height as set by S_FMT
+ * @offs_h: image horizontal pixel offset
+ * @offs_v: image vertical pixel offset
+ * @width: image pixel width
+ * @height: image pixel weight
+ * @paddr: image frame buffer physical addresses
+ * @buf_cnt: number of buffers depending on a color format
+ * @size: image size in bytes
+ * @color: color format
+ * @dma_offset: DMA offset in bytes
+ */
+struct fimc_frame {
+ u32 f_width;
+ u32 f_height;
+ u32 o_width;
+ u32 o_height;
+ u32 offs_h;
+ u32 offs_v;
+ u32 width;
+ u32 height;
+ u32 size;
+ struct fimc_addr paddr;
+ struct fimc_dma_offset dma_offset;
+ struct fimc_fmt *fmt;
+};
+
+/**
+ * struct fimc_m2m_device - v4l2 memory-to-memory device data
+ * @vfd: the video device node for v4l2 m2m mode
+ * @v4l2_dev: v4l2 device for m2m mode
+ * @m2m_dev: v4l2 memory-to-memory device data
+ * @ctx: hardware context data
+ * @refcnt: the reference counter
+ */
+struct fimc_m2m_device {
+ struct video_device *vfd;
+ struct v4l2_device v4l2_dev;
+ struct v4l2_m2m_dev *m2m_dev;
+ struct fimc_ctx *ctx;
+ int refcnt;
+};
+
+/**
+ * struct fimc_output_device - v4l2 output device data
+ *
+ * @vfd: the video device node for v4l2 output mode
+ * @v4l2_dev: v4l2 device for managing the subdevices
+ * @m2m_dev: v4l2 memory-to-memory device data
+ * @sd[]: the v4l2 subdevices to control fifo link@framebuffer
+ * @work:
+ * @buf_q: the driver's internal video buffer queue head
+ * @curr_buf: the pointer to curently processed video buffer
+ * @vbq: video buffer queue for v4l2 output stream
+ * @fmt: pixel format information for lcd controller fifo input
+ * @ctx: hardware context data
+ * @refcnt: the reference counter
+ */
+struct fimc_output_device {
+ struct video_device *vfd;
+ struct v4l2_device v4l2_dev;
+ struct v4l2_subdev *sd[FIMC_MAX_FIFO_TARGETS];
+ struct work_struct work;
+ struct list_head buf_q;
+ struct fimc_vid_buffer *curr_buf;
+ struct videobuf_queue vbq;
+ struct v4l2_format fmt;
+ struct fimc_ctx *ctx;
+ int refcnt;
+};
+
+/**
+ * struct samsung_fimc_variant - camera interface variant information
+ *
+ * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes
+ * @has_inp_rot: set if has input rotator
+ * @has_out_rot: set if has output rotator
+ * @fifo_capable: set if direct local path to lcd controller is supported
+ * @min_inp_pixsize: minimum input pixel size
+ * @min_out_pixsize: minimum output pixel size
+ * @scaler_en_w: maximum input pixel width when the scaler is enabled
+ * @scaler_dis_w: maximum input pixel width when the scaler is disabled
+ * @in_rot_en_h: maximum input width when the input rotator is used
+ * @in_rot_dis_w: maximum input width when the input rotator is used
+ * @out_rot_en_w: maximum output width for the output rotator enabled
+ * @out_rot_dis_w: maximum output width for the output rotator enabled
+ */
+struct samsung_fimc_variant {
+ unsigned int pix_hoff:1;
+ unsigned int has_inp_rot:1;
+ unsigned int has_out_rot:1;
+ unsigned int fifo_capable:1;
+
+ u16 min_inp_pixsize;
+ u16 min_out_pixsize;
+
+ u16 scaler_en_w;
+ u16 scaler_dis_w;
+ u16 in_rot_en_h;
+ u16 in_rot_dis_w;
+ u16 out_rot_en_w;
+ u16 out_rot_dis_w;
+};
+
+/**
+ * struct samsung_fimc_driverdata - per-device type driver data for init time.
+ *
+ * @variant: the variant information for this driver.
+ * @dev_cnt: number of fimc sub-devices available in SoC
+ */
+struct samsung_fimc_driverdata {
+ struct samsung_fimc_variant *variant[FIMC_MAX_DEVS];
+ int devs_cnt;
+};
+
+struct fimc_ctx;
+
+/**
+ * struct fimc_subdev - abstraction for a FIMC entity
+ *
+ * @slock: the spinlock protecting this data structure
+ * @lock: the mutex protecting this data structure
+ * @pdev: pointer to the FIMC platform device
+ * @pdata: pointer to the device platform data
+ * @id: FIMC device index (0..2)
+ * @clock[]: the clocks required for FIMC operation
+ * @regs: the mapped hardware registers
+ * @regs_res: the resource claimed for IO registers
+ * @irq: interrupt number of the FIMC subdevice
+ * @irqlock: spinlock protecting videbuffer queue
+ * @work_queue: the workqueue used to start FIMC in fifo mode
+ * @m2m: memory-to-memory V4L2 device information
+ * @outp: V4L2 output device information
+ * @state: the FIMC device state flags
+ */
+struct fimc_dev {
+ spinlock_t slock;
+ struct mutex lock;
+ struct platform_device *pdev;
+ struct samsung_plat_fimc *pdata;
+ struct samsung_fimc_variant *variant;
+ int id;
+ struct clk *clock[NUM_FIMC_CLOCKS];
+ void __iomem *regs;
+ struct resource *regs_res;
+ int irq;
+ spinlock_t irqlock;
+ struct workqueue_struct *work_queue;
+ struct fimc_m2m_device m2m;
+ struct fimc_output_device outp;
+ unsigned long state;
+};
+
+/**
+ * fimc_ctx - the device context data
+ *
+ * @lock: mutex protecting this data structure
+ * @s_frame: source frame properties
+ * @d_frame: destination frame properties
+ * @out_order_1p: output 1-plane YCBCR order
+ * @out_order_2p: output 2-plane YCBCR order
+ * @in_order_1p input 1-plane YCBCR order
+ * @in_order_2p: input 2-plane YCBCR order
+ * @in_path: input mode (DMA or camera)
+ * @out_path: output mode (DMA or FIFO)
+ * @scaler: image scaler properties
+ * @effect: image effect
+ * @rotation: image clockwise rotation in degrees
+ * @flip: image flip mode
+ * @updated: flags to keep track of user configuration sequence
+ * @fimc_dev: the FIMC device this context applies to
+ * @m2m_ctx: memory-to-memory device context
+ */
+struct fimc_ctx {
+ spinlock_t slock;
+ struct fimc_frame s_frame;
+ struct fimc_frame d_frame;
+ u32 out_order_1p;
+ u32 out_order_2p;
+ u32 in_order_1p;
+ u32 in_order_2p;
+ enum fimc_datapath in_path;
+ enum fimc_datapath out_path;
+ struct fimc_scaler scaler;
+ struct fimc_effect effect;
+ int rotation;
+ u32 flip;
+ u32 flags;
+ struct fimc_dev *fimc_dev;
+ struct v4l2_m2m_ctx *m2m_ctx;
+};
+
+
+extern struct fimc_fmt fimc_formats[];
+extern struct videobuf_queue_ops fimc_qops;
+
+static inline int tiled_fmt(struct fimc_fmt *fmt)
+{
+ return 0;
+}
+
+static inline void fimc_hw_clear_irq(struct fimc_dev *dev)
+{
+ u32 cfg = readl(dev->regs + S5P_CIGCTRL);
+ cfg |= S5P_CIGCTRL_IRQ_CLR;
+ writel(cfg, dev->regs + S5P_CIGCTRL);
+}
+
+static inline void fimc_hw_start_scaler(struct fimc_dev *dev)
+{
+ u32 cfg = readl(dev->regs + S5P_CISCCTRL);
+ cfg |= S5P_CISCCTRL_SCALERSTART;
+ writel(cfg, dev->regs + S5P_CISCCTRL);
+}
+
+static inline void fimc_hw_stop_scaler(struct fimc_dev *dev)
+{
+ u32 cfg = readl(dev->regs + S5P_CISCCTRL);
+ cfg &= ~S5P_CISCCTRL_SCALERSTART;
+ writel(cfg, dev->regs + S5P_CISCCTRL);
+}
+
+static inline void fimc_hw_dis_capture(struct fimc_dev *dev)
+{
+ u32 cfg = readl(dev->regs + S5P_CIIMGCPT);
+ cfg &= ~(S5P_CIIMGCPT_IMGCPTEN | S5P_CIIMGCPT_IMGCPTEN_SC);
+ writel(cfg, dev->regs + S5P_CIIMGCPT);
+}
+
+static inline void fimc_hw_start_in_dma(struct fimc_dev *dev)
+{
+ u32 cfg = readl(dev->regs + S5P_MSCTRL);
+ cfg |= S5P_MSCTRL_ENVID;
+ writel(cfg, dev->regs + S5P_MSCTRL);
+}
+
+static inline void fimc_hw_stop_in_dma(struct fimc_dev *dev)
+{
+ u32 cfg = readl(dev->regs + S5P_MSCTRL);
+ cfg &= ~S5P_MSCTRL_ENVID;
+ writel(cfg, dev->regs + S5P_MSCTRL);
+}
+
+
+/* -----------------------------------------------------*/
+/* fimc-core.c */
+int fimc_set_scaler_info(struct fimc_ctx *ctx);
+struct fimc_fmt *find_format(struct v4l2_format *f);
+int fimc_m2m_enum_fmt(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f);
+int fimc_m2m_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc);
+int fimc_m2m_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl);
+int fimc_m2m_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl);
+int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f);
+int fimc_prepare_addr(struct fimc_ctx *ctx,
+ struct fimc_vid_buffer *buf, enum v4l2_buf_type type);
+int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags);
+
+/* -----------------------------------------------------*/
+/* fimc-fifo.c */
+int fimc_register_fifo_device(struct fimc_dev *dev);
+void fimc_unregister_fifo_device(struct fimc_dev *dev);
+
+/* -----------------------------------------------------*/
+/* fimc-reg.c */
+int fimc_hw_reset_fifo_ov(struct fimc_dev *dev);
+void fimc_hw_reset(struct fimc_dev *dev);
+void fimc_hw_set_rotation(struct fimc_ctx *ctx);
+void fimc_hw_set_target_format(struct fimc_ctx *ctx);
+void fimc_hw_set_out_dma(struct fimc_ctx *ctx);
+void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable);
+void fimc_hw_en_irq(struct fimc_dev *dev, int enable);
+void fimc_hw_en_autoload(struct fimc_dev *dev, int enable);
+void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
+void fimc_hw_set_scaler(struct fimc_ctx *ctx);
+void fimc_hw_en_capture(struct fimc_ctx *ctx);
+void fimc_hw_set_effect(struct fimc_ctx *ctx);
+void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
+void fimc_hw_set_input_path(struct fimc_ctx *ctx);
+void fimc_hw_set_output_path(struct fimc_ctx *ctx);
+void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr);
+void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr);
+void fimc_hw_shadow_dis(struct fimc_dev *ctx, int off);
+
+#endif /* FIMC_CORE_H_ */
diff --git a/drivers/media/video/samsung/fimc/fimc-fifo.c b/drivers/media/video/samsung/fimc/fimc-fifo.c
new file mode 100644
index 0000000..3917034
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc-fifo.c
@@ -0,0 +1,814 @@
+/*
+ * S5P camera interface (video postprocessor) driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Sylwester Nawrocki, s.nawrocki at samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundiation. either version 2 of the License,
+ * or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <linux/fb.h>
+#include <mach/regs-fb.h>
+#include <plat/fb.h>
+#include <plat/fimc.h>
+#include <plat/fifo.h>
+
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf-dma-contig.h>
+
+#include "fimc-core.h"
+
+
+static int fimc_stop_lcdfifo(struct fimc_dev *dev)
+{
+ unsigned long flags;
+ struct fimc_output_device *outp;
+
+ outp = &dev->outp;
+
+ if (fimc_fifo_active(dev) || fimc_fifo_pending(dev)) {
+ flush_workqueue(dev->work_queue);
+
+ /* Disable fifo at frambuffer and fimc side. */
+ v4l2_subdev_call(dev->outp.sd[FIMC_LCD_FIFO_TARGET],
+ video, s_stream, 0);
+ }
+
+ spin_lock_irqsave(&dev->slock, flags);
+
+ /* Processing of the last buffer in the videobuf queue is never finished
+ within the interrupt routine, so it needs to be done here.*/
+ if (outp->curr_buf) {
+ spin_lock(&dev->irqlock);
+ outp->curr_buf->vb.state = VIDEOBUF_DONE;
+ spin_unlock(&dev->irqlock);
+
+ wake_up(&outp->curr_buf->vb.done);
+ outp->curr_buf = NULL;
+ }
+ clear_bit(ST_LCDFIFO_RUN, &dev->state);
+ spin_unlock_irqrestore(&dev->slock, flags);
+ return 0;
+}
+
+void fimc_v4l2_dev_notify(struct v4l2_subdev *sd,
+ unsigned int notification, void *arg)
+{
+ struct fimc_dev *dev = v4l2_get_subdevdata(sd);
+
+ BUG_ON(!dev);
+
+ switch (notification) {
+ case 0:
+ spin_lock(&dev->slock);
+ fimc_hw_en_autoload(dev, false);
+ fimc_hw_dis_capture(dev);
+ fimc_hw_stop_in_dma(dev);
+ fimc_hw_stop_scaler(dev);
+ clear_bit(ST_LCDFIFO_RUN, &dev->state);
+ spin_unlock(&dev->slock);
+ break;
+ default:
+ break;
+ }
+}
+
+static void fimc_fifo_try_run(void *priv)
+{
+ struct fimc_ctx *ctx = priv;
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_frame *f;
+ unsigned long flags;
+
+ BUG_ON(dev->outp.sd[FIMC_LCD_FIFO_TARGET] == NULL);
+
+ f = &ctx->s_frame;
+ dbg("SRC: w= %d, h= %d, f_w= %d, f_h= %d off_h= %d, off_v= %d",
+ f->width, f->height, f->f_width, f->f_height,
+ f->offs_h, f->offs_v);
+
+ f = &ctx->d_frame;
+ dbg("DST: w= %d, h= %d, f_w= %d, f_h= %d off_h= %d, off_v= %d",
+ f->width, f->height, f->f_width, f->f_height,
+ f->offs_h, f->offs_v);
+
+ spin_lock_irqsave(&dev->slock, flags);
+ fimc_hw_set_input_addr(dev, &ctx->s_frame.paddr);
+ spin_unlock_irqrestore(&dev->slock, flags);
+
+ if (ctx->flags & FIMC_PARAMS) {
+ fimc_hw_set_input_path(ctx);
+ fimc_hw_set_in_dma(ctx);
+
+ if (fimc_set_scaler_info(ctx)) {
+ err("scaler configuration failed");
+ return;
+ }
+
+ spin_lock_irqsave(&dev->slock, flags);
+ fimc_hw_set_prescaler(ctx);
+ fimc_hw_set_scaler(ctx);
+ fimc_hw_set_target_format(ctx);
+ fimc_hw_set_rotation(ctx);
+ fimc_hw_set_effect(ctx);
+ spin_unlock_irqrestore(&dev->slock, flags);
+ }
+
+ v4l2_subdev_call(dev->outp.sd[FIMC_LCD_FIFO_TARGET], video,
+ s_stream, 1);
+
+ spin_lock_irqsave(&dev->slock, flags);
+
+ fimc_hw_set_output_path(ctx);
+ if (ctx->scaler.enabled)
+ fimc_hw_start_scaler(dev);
+
+ fimc_hw_en_capture(ctx);
+ fimc_hw_start_in_dma(dev);
+
+ ctx->flags = 0;
+ spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+static void fimc_worker(struct work_struct *work)
+{
+ int ret;
+ unsigned long flags;
+ struct fimc_output_device *outp =
+ container_of(work, struct fimc_output_device, work);
+ struct fimc_ctx *ctx = outp->ctx;
+ struct fimc_frame *f = &ctx->d_frame;
+ struct fimc_dev *dev;
+ struct v4l2_crop cr;
+
+ BUG_ON(!ctx || !ctx->fimc_dev);
+ dev = ctx->fimc_dev;
+
+ mutex_lock(&dev->lock);
+
+ if (fimc_fifo_active(dev) || list_empty(&outp->buf_q))
+ goto w_unlock;
+
+ /* Get the window parameters from framebuffer to apply its any
+ aligment requirements. */
+ cr.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ v4l2_subdev_call(outp->sd[FIMC_LCD_FIFO_TARGET],
+ video, g_crop, &cr);
+
+ f->offs_h = cr.c.left;
+ f->offs_v = cr.c.top;
+ f->width = cr.c.width;
+ f->height = cr.c.height;
+
+ ctx->flags &= ~(FIMC_SRC_ADDR | FIMC_DST_ADDR);
+ ret = fimc_prepare_config(ctx, ctx->flags);
+ if (ret)
+ goto w_unlock;
+
+ spin_lock_irqsave(&dev->slock, flags);
+ outp->curr_buf = list_entry(outp->buf_q.next,
+ struct fimc_vid_buffer, vb.queue);
+
+ spin_lock(&dev->irqlock);
+ outp->curr_buf->vb.state = VIDEOBUF_ACTIVE;
+ spin_unlock(&dev->irqlock);
+
+ list_del(&outp->curr_buf->vb.queue);
+ fimc_prepare_addr(ctx, outp->curr_buf,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ spin_unlock_irqrestore(&dev->slock, flags);
+
+ fimc_fifo_try_run(ctx);
+
+w_unlock:
+ mutex_unlock(&dev->lock);
+}
+
+
+static int fimc_target_osd_sync(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct v4l2_cropcap osd;
+ struct v4l2_rect *r;
+ struct fimc_frame *frame;
+ u32 pix_mod;
+ int ret;
+
+ if (!dev || !dev->outp.sd[FIMC_LCD_FIFO_TARGET])
+ return -EINVAL;
+
+ ret = v4l2_subdev_call(dev->outp.sd[FIMC_LCD_FIFO_TARGET],
+ video, cropcap, &osd);
+ if (ret)
+ return ret;
+
+ pix_mod = dev->variant->min_out_pixsize;
+
+ r = &osd.defrect;
+ r->left = round_down(r->left, pix_mod);
+ r->top = round_down(r->top, pix_mod);
+ r->width = round_down(r->width, pix_mod);
+ r->height = round_down(r->height, pix_mod);
+
+ frame = &ctx->d_frame;
+ frame->f_width = r->width;
+ frame->f_height = r->height;
+ frame->width = r->width;
+ frame->height = r->height;
+ frame->o_width = r->width;
+ frame->o_height = r->height;
+ return 0;
+}
+
+/* Register any framebuffer fifo subdevices if not already registered. */
+static int fimc_register_fb_subdevices(struct fimc_dev *dev)
+{
+ struct s3c_fifo_link *link;
+ int i, ret = 0;
+
+ for (i = 0; i < FIMC_MAX_FIFO_TARGETS; i++) {
+ link = dev->pdata->fifo_targets[i];
+ if (!link)
+ continue;
+ mutex_lock(&link->slave_dev->mutex);
+ if (link->sub_dev) {
+ if (link->sub_dev->v4l2_dev) {
+ mutex_unlock(&link->slave_dev->mutex);
+ continue;
+ }
+ if (!v4l2_device_register_subdev(&dev->outp.v4l2_dev,
+ link->sub_dev)) {
+ v4l2_set_subdevdata(link->sub_dev, dev);
+ dev->outp.sd[i] = link->sub_dev;
+ } else {
+ dev->outp.sd[i] = NULL;
+ mutex_unlock(&link->slave_dev->mutex);
+ v4l2_err(&dev->outp.v4l2_dev,
+ "Failed to register fb subdevice\n");
+ return -ENODEV;
+ }
+ }
+ mutex_unlock(&link->slave_dev->mutex);
+ }
+ return ret;
+}
+
+/* Unregister fifo target subdevices. */
+static void fimc_unregister_fb_subdevices(struct fimc_dev *dev)
+{
+ int i;
+ struct s3c_fifo_link *link;
+
+ for (i = 0; i < FIMC_MAX_FIFO_TARGETS; i++) {
+ link = dev->pdata->fifo_targets[i];
+ if (!link)
+ continue;
+ mutex_lock(&link->slave_dev->mutex);
+ if (dev->outp.sd[i]) {
+ v4l2_device_unregister_subdev(dev->outp.sd[i]);
+ dev->outp.sd[i] = NULL;
+ }
+ mutex_unlock(&link->slave_dev->mutex);
+ }
+}
+
+static int fimc_open(struct file *file)
+{
+ struct fimc_dev *dev = video_drvdata(file);
+ int ret;
+
+ mutex_lock(&dev->lock);
+
+ dbg("pid: %d, state: 0x%lx, refcnt= %d",
+ task_pid_nr(current), dev->state, dev->outp.refcnt);
+
+ if (dev->outp.refcnt++ == 0) {
+ ret = fimc_register_fb_subdevices(dev);
+ if (ret)
+ goto op_err;
+
+ if (!dev->outp.sd[FIMC_LCD_FIFO_TARGET]) {
+ v4l2_err(&dev->outp.v4l2_dev,
+ "Lcd fifo subdevice not found\n");
+ ret = -ENODEV;
+ goto op_err;
+ }
+ }
+
+ file->private_data = dev->outp.ctx;
+
+op_err:
+ mutex_unlock(&dev->lock);
+ return ret;
+}
+
+static int fimc_close(struct file *file)
+{
+ struct fimc_dev *dev = video_drvdata(file);
+
+ mutex_lock(&dev->lock);
+
+ dbg("pid: %d, state: 0x%lx, refcnt= %d",
+ task_pid_nr(current), dev->state, dev->outp.refcnt);
+
+ if (--dev->outp.refcnt <= 0) {
+ fimc_stop_lcdfifo(dev);
+ videobuf_stop(&dev->outp.vbq);
+ fimc_unregister_fb_subdevices(dev);
+ }
+ dbg("pid: %d, state: 0x%lx, refcnt= %d",
+ task_pid_nr(current), dev->state, dev->outp.refcnt);
+
+ mutex_unlock(&dev->lock);
+ return 0;
+}
+
+static unsigned int fimc_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ return POLLERR;
+}
+
+static int fimc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct fimc_ctx *ctx = file->private_data;
+ struct fimc_output_device *outp = &ctx->fimc_dev->outp;
+
+ return videobuf_mmap_mapper(&outp->vbq, vma);
+}
+
+
+static const struct v4l2_file_operations fimc_fops = {
+ .owner = THIS_MODULE,
+ .open = fimc_open,
+ .release = fimc_close,
+ .poll = fimc_poll,
+ .ioctl = video_ioctl2,
+ .mmap = fimc_mmap,
+};
+
+static int fimc_querycap_output(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ struct fimc_ctx *ctx = file->private_data;
+ struct fimc_dev *dev = ctx->fimc_dev;
+
+ strncpy(cap->driver, dev->pdev->name, sizeof(cap->driver) - 1);
+ strncpy(cap->card, dev->pdev->name, sizeof(cap->card) - 1);
+ cap->bus_info[0] = 0;
+ cap->version = KERNEL_VERSION(1, 0, 0);
+ cap->capabilities = V4L2_CAP_STREAMING |
+ V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_OUTPUT;
+
+ return 0;
+}
+
+static int fimc_g_fmt_output(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct fimc_ctx *ctx = priv;
+ struct fimc_frame *frame = &ctx->s_frame;
+
+ f->fmt.pix.width = frame->width;
+ f->fmt.pix.height = frame->height;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.pixelformat = frame->fmt->fourcc;
+
+ return 0;
+}
+
+static int fimc_try_fmt_output(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct fimc_fmt *fmt;
+ struct fimc_ctx *ctx = priv;
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ u32 max_width, max_height;
+ u32 mod_x, mod_y;
+
+ fmt = find_format(f);
+ if (!fmt) {
+ v4l2_err(&dev->outp.v4l2_dev,
+ "Fourcc format (0x%08x) invalid.\n",
+ pix->pixelformat);
+ return -EINVAL;
+ }
+
+ if (pix->field == V4L2_FIELD_ANY)
+ pix->field = V4L2_FIELD_NONE;
+ else if (V4L2_FIELD_NONE != pix->field)
+ return -EINVAL;
+
+ max_width = dev->variant->scaler_dis_w;
+ max_height = dev->variant->scaler_dis_w;
+ mod_x = dev->variant->min_inp_pixsize;
+ mod_y = mod_x;
+
+
+ if (pix->height > max_height)
+ pix->height = max_height;
+ if (pix->width > max_width)
+ pix->width = max_width;
+
+ if (tiled_fmt(fmt)) {
+ mod_x = 64; /* 64x32 tile */
+ mod_y = 32;
+ }
+
+ pix->width = (pix->width == 0) ? mod_x : ALIGN(pix->width, mod_x);
+ pix->height = (pix->height == 0) ? mod_y : ALIGN(pix->height, mod_y);
+
+ if (pix->bytesperline == 0 ||
+ pix->bytesperline * 8 / fmt->depth > pix->width)
+ pix->bytesperline = (pix->width * fmt->depth) >> 3;
+
+ if (pix->sizeimage == 0)
+ pix->sizeimage = pix->height * pix->bytesperline;
+
+ dbg("pix->bytesperline= %d, fmt->depth= %d",
+ pix->bytesperline, fmt->depth);
+
+ return 0;
+}
+
+
+static int fimc_s_fmt_output(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct fimc_frame *frame;
+ struct v4l2_pix_format *pix;
+ struct v4l2_format fmt;
+ struct fimc_ctx *ctx = priv;
+ struct fimc_dev *dev = ctx->fimc_dev;
+ int ret;
+
+ BUG_ON(!ctx);
+
+ if (fimc_fifo_active(dev))
+ return -EBUSY;
+
+ ret = fimc_try_fmt_output(file, priv, f);
+ if (ret)
+ return ret;
+
+ mutex_lock(&dev->lock);
+
+ frame = &ctx->s_frame;
+ pix = &f->fmt.pix;
+ frame->fmt = find_format(f);
+ if (!frame->fmt) {
+ mutex_unlock(&dev->lock);
+ return -EINVAL;
+ }
+
+ /* source frame format */
+ frame->f_width = pix->bytesperline * 8 / frame->fmt->depth;
+ frame->f_height = pix->sizeimage / pix->bytesperline;
+ frame->width = pix->width;
+ frame->height = pix->height;
+ frame->o_width = pix->width;
+ frame->o_height = pix->height;
+ frame->offs_h = 0;
+ frame->offs_v = 0;
+ frame->size = (pix->width * pix->height * frame->fmt->depth) >> 3;
+
+ /* FIMC target frame format */
+ fimc_target_osd_sync(ctx);
+
+ fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
+ ret = v4l2_subdev_call(dev->outp.sd[FIMC_LCD_FIFO_TARGET],
+ video, s_fmt, &fmt);
+
+ ctx->flags |= FIMC_PARAMS | FIMC_SRC_FMT;
+ mutex_unlock(&dev->lock);
+ return ret;
+}
+
+static int fimc_streamon_output(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct fimc_ctx *ctx = priv;
+ struct fimc_output_device *outp = &ctx->fimc_dev->outp;
+
+ if (fimc_fifo_active(ctx->fimc_dev))
+ return -EBUSY;
+
+ return videobuf_streamon(&outp->vbq);
+}
+
+static int fimc_streamoff_output(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ unsigned long flags;
+ struct fimc_ctx *ctx = priv;
+ struct fimc_dev *dev = ctx->fimc_dev;
+ int ret = 0;
+
+ spin_lock_irqsave(&dev->slock, flags);
+
+ if (!fimc_fifo_active(dev)) {
+ spin_unlock_irqrestore(&dev->slock, flags);
+ } else {
+ spin_unlock_irqrestore(&dev->slock, flags);
+ fimc_stop_lcdfifo(dev);
+ ret = videobuf_streamoff(&dev->outp.vbq);
+ }
+ return ret;
+}
+
+static int fimc_reqbufs_output(struct file *file, void *priv,
+ struct v4l2_requestbuffers *reqbufs)
+{
+ struct fimc_ctx *ctx = priv;
+ struct fimc_output_device *outp = &ctx->fimc_dev->outp;
+
+ if (fimc_fifo_active(ctx->fimc_dev))
+ return -EBUSY;
+
+ return videobuf_reqbufs(&outp->vbq, reqbufs);
+}
+
+static int fimc_querybuf_output(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct fimc_ctx *ctx = priv;
+ struct fimc_output_device *outp = &ctx->fimc_dev->outp;
+
+ if (fimc_fifo_active(ctx->fimc_dev))
+ return -EBUSY;
+
+ return videobuf_querybuf(&outp->vbq, buf);
+}
+
+static int fimc_qbuf_output(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct fimc_ctx *ctx = priv;
+ struct fimc_output_device *outp = &ctx->fimc_dev->outp;
+
+ return videobuf_qbuf(&outp->vbq, buf);
+}
+
+static int fimc_dqbuf_output(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct fimc_ctx *ctx = priv;
+
+ return videobuf_dqbuf(&ctx->fimc_dev->outp.vbq, buf,
+ file->f_flags & O_NONBLOCK);
+}
+
+static int fimc_cropcap_output(struct file *file, void *fh,
+ struct v4l2_cropcap *cr)
+{
+ struct fimc_ctx *ctx = fh;
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_frame *f = &ctx->s_frame;
+
+ if (cr->type == V4L2_BUF_TYPE_VIDEO_OVERLAY) {
+ return v4l2_subdev_call(dev->outp.sd[FIMC_LCD_FIFO_TARGET],
+ video, cropcap, cr);
+ } else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ cr->bounds.left = 0;
+ cr->bounds.top = 0;
+ cr->bounds.width = f->f_width;
+ cr->bounds.height = f->f_height;
+ cr->defrect.left = f->offs_h;
+ cr->defrect.top = f->offs_v;
+ cr->defrect.width = f->o_width;
+ cr->defrect.height = f->o_height;
+ } else {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int fimc_g_crop_output(struct file *file, void *fh, struct v4l2_crop *cr)
+{
+ struct fimc_ctx *ctx = file->private_data;
+ struct fimc_frame *f = &ctx->s_frame;
+ struct fimc_dev *dev = ctx->fimc_dev;
+
+ if (cr->type == V4L2_BUF_TYPE_VIDEO_OVERLAY) {
+ return v4l2_subdev_call(dev->outp.sd[FIMC_LCD_FIFO_TARGET],
+ video, g_crop, cr);
+ } else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ cr->c.left = f->offs_h;
+ cr->c.top = f->offs_v;
+ cr->c.width = f->width;
+ cr->c.height = f->height;
+ } else {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int fimc_s_crop_output(struct file *file, void *fh, struct v4l2_crop *cr)
+{
+ struct fimc_frame *f;
+ struct fimc_ctx *ctx = file->private_data;
+ struct fimc_dev *dev = ctx->fimc_dev;
+ u32 pix_mod;
+ int ret = 0;
+
+ if (fimc_fifo_active(dev))
+ return -EBUSY;
+
+ if (cr->c.top < 0 || cr->c.left < 0) {
+ v4l2_err(&dev->outp.v4l2_dev,
+ "doesn't support negative values for top & left\n");
+ return -EINVAL;
+ }
+
+ if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ f = &ctx->s_frame;
+ pix_mod = dev->variant->min_out_pixsize;
+ } else if (cr->type == V4L2_BUF_TYPE_VIDEO_OVERLAY) {
+ f = &ctx->d_frame;
+ pix_mod = dev->variant->min_inp_pixsize;
+ } else {
+ v4l2_err(&ctx->fimc_dev->outp.v4l2_dev,
+ "Wrong buffer/video queue type (%d)\n", cr->type);
+ return -EINVAL;
+ }
+
+ /* Adjust to required pixel boundary. */
+ cr->c.width = ALIGN(cr->c.width, pix_mod);
+ cr->c.height = ALIGN(cr->c.height, pix_mod);
+ cr->c.left = ALIGN(cr->c.left, pix_mod);
+ cr->c.top = ALIGN(cr->c.top, pix_mod);
+
+ dbg("%d %d %d %d f_w= %d, f_h= %d",
+ cr->c.left, cr->c.top, cr->c.width, cr->c.height,
+ f->f_width, f->f_height);
+
+ if ((cr->c.left + cr->c.width > f->o_width)
+ || (cr->c.top + cr->c.height > f->o_height)) {
+ v4l2_err(&dev->outp.v4l2_dev, "Error in S_CROP params\n");
+ return -EINVAL;
+ }
+
+ if ((ctx->flags & FIMC_SRC_FMT) && (ctx->flags & FIMC_DST_FMT)) {
+ if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame);
+ else if (cr->type == V4L2_BUF_TYPE_VIDEO_OVERLAY)
+ ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame);
+
+ if (ret) {
+ v4l2_err(&dev->outp.v4l2_dev, "Out of scaler range");
+ return -EINVAL;
+ }
+ }
+
+ f->offs_h = cr->c.left;
+ f->offs_v = cr->c.top;
+ f->width = cr->c.width;
+ f->height = cr->c.height;
+
+ if (cr->type == V4L2_BUF_TYPE_VIDEO_OVERLAY)
+ return v4l2_subdev_call(dev->outp.sd[FIMC_LCD_FIFO_TARGET],
+ video, s_crop, cr);
+ return 0;
+}
+
+
+static const struct v4l2_ioctl_ops fimc_ioctl_ops = {
+ .vidioc_querycap = fimc_querycap_output,
+
+ .vidioc_enum_fmt_vid_out = fimc_m2m_enum_fmt,
+ .vidioc_try_fmt_vid_out = fimc_try_fmt_output,
+ .vidioc_s_fmt_vid_out = fimc_s_fmt_output,
+ .vidioc_g_fmt_vid_out = fimc_g_fmt_output,
+
+ .vidioc_reqbufs = fimc_reqbufs_output,
+ .vidioc_querybuf = fimc_querybuf_output,
+
+ .vidioc_qbuf = fimc_qbuf_output,
+ .vidioc_dqbuf = fimc_dqbuf_output,
+
+ .vidioc_streamon = fimc_streamon_output,
+ .vidioc_streamoff = fimc_streamoff_output,
+
+ .vidioc_queryctrl = fimc_m2m_queryctrl,
+ .vidioc_g_ctrl = fimc_m2m_g_ctrl,
+ .vidioc_s_ctrl = fimc_m2m_s_ctrl,
+
+ .vidioc_g_crop = fimc_g_crop_output,
+ .vidioc_s_crop = fimc_s_crop_output,
+ .vidioc_cropcap = fimc_cropcap_output
+};
+
+/* Register FIMC video device for local fifo path mode. */
+int fimc_register_fifo_device(struct fimc_dev *dev)
+{
+ int ret = 0;
+ struct video_device *vfd;
+ struct fimc_ctx *ctx;
+ struct v4l2_device *v4l2_dev = &dev->outp.v4l2_dev;
+
+ if (!v4l2_dev->name[0])
+ snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
+ "%s.%d.v4l2_output", MODULE_NAME, dev->id);
+
+ ret = v4l2_device_register(NULL, v4l2_dev);
+ if (ret)
+ goto err_info;
+
+ vfd = video_device_alloc();
+ if (!vfd) {
+ v4l2_err(v4l2_dev, "Failed to allocate video device\n");
+ ret = -ENOMEM;
+ goto err_v4l2_reg;
+ }
+
+ vfd->fops = &fimc_fops;
+ vfd->ioctl_ops = &fimc_ioctl_ops;
+ vfd->minor = -1;
+ vfd->release = video_device_release;
+ snprintf(vfd->name, sizeof(vfd->name), "%s%d", MODULE_NAME, dev->id);
+
+ ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
+ if (ret) {
+ v4l2_err(v4l2_dev, "Failed to register video device\n");
+ goto err_vd_reg;
+ }
+ video_set_drvdata(vfd, dev);
+
+ INIT_WORK(&dev->outp.work, fimc_worker);
+
+ dev->outp.vfd = vfd;
+ v4l2_dev->notify = fimc_v4l2_dev_notify;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx) {
+ ret = -ENOMEM;
+ goto err_ctx;
+ }
+ ctx->fimc_dev = dev;
+ /* Defaults to RGB888. */
+ ctx->s_frame.fmt = &fimc_formats[2];
+ ctx->d_frame.fmt = &fimc_formats[2];
+
+ ctx->in_path = FIMC_DMA;
+ ctx->out_path = FIMC_LCDFIFO;
+ ctx->effect.type = S5P_FIMC_EFFECT_ORIGINAL;
+ ctx->flags |= FIMC_DST_FMT;
+ fimc_target_osd_sync(ctx);
+
+ dev->outp.ctx = ctx;
+
+ spin_lock_init(&ctx->slock);
+ INIT_LIST_HEAD(&dev->outp.buf_q);
+
+ /* The video bufer queue for FIMC fifo V4L2 output device. */
+ videobuf_queue_dma_contig_init(&dev->outp.vbq, &fimc_qops,
+ dev->outp.v4l2_dev.dev, &dev->irqlock,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_FIELD_NONE,
+ sizeof(struct fimc_vid_buffer), (void *)ctx);
+
+ dev->outp.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
+ dev->outp.refcnt = 0;
+
+ v4l2_info(v4l2_dev, "FIMC fifo driver registered as /dev/video%d\n",
+ vfd->num);
+ return 0;
+
+err_ctx:
+ video_unregister_device(dev->outp.vfd);
+err_vd_reg:
+ video_device_release(vfd);
+err_v4l2_reg:
+ v4l2_device_unregister(v4l2_dev);
+err_info:
+ dev_err(&dev->pdev->dev, "failed to install\n");
+ return ret;
+}
+
+void fimc_unregister_fifo_device(struct fimc_dev *dev)
+{
+ if (dev && dev->outp.vfd) {
+ video_unregister_device(dev->outp.vfd);
+ video_device_release(dev->outp.vfd);
+ v4l2_device_unregister(&dev->outp.v4l2_dev);
+ kfree(dev->outp.ctx);
+ }
+}
diff --git a/drivers/media/video/samsung/fimc/fimc-reg.c b/drivers/media/video/samsung/fimc/fimc-reg.c
new file mode 100644
index 0000000..cc4ea68
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc-reg.c
@@ -0,0 +1,585 @@
+/*
+ * Register interface file for Samsung Camera Interface (FIMC) driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Sylwester Nawrocki, s.nawrocki at samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <mach/map.h>
+
+#include "fimc-core.h"
+
+
+int fimc_hw_reset_fifo_ov(struct fimc_dev *dev)
+{
+ u32 cfg, status;
+
+ status = readl(dev->regs + S5P_CISTATUS);
+
+ if ((S5P_CISTATUS_OVFIY | S5P_CISTATUS_OVFICB | S5P_CISTATUS_OVFICR)
+ & status) {
+ cfg = readl(dev->regs + S5P_CIWDOFST);
+ cfg |= (S5P_CIWDOFST_CLROVFIY | S5P_CIWDOFST_CLROVFICB
+ | S5P_CIWDOFST_CLROVFICR);
+ writel(cfg, dev->regs + S5P_CIWDOFST);
+
+ cfg = readl(dev->regs + S5P_CIWDOFST);
+ cfg &= ~(S5P_CIWDOFST_CLROVFIY | S5P_CIWDOFST_CLROVFICB
+ | S5P_CIWDOFST_CLROVFICR);
+ writel(cfg, dev->regs + S5P_CIWDOFST);
+ }
+
+ return 0;
+}
+
+void fimc_hw_reset(struct fimc_dev *dev)
+{
+ u32 cfg;
+
+ cfg = readl(dev->regs + S5P_CISRCFMT);
+ cfg |= S5P_CISRCFMT_ITU601_8BIT;
+ writel(cfg, dev->regs + S5P_CISRCFMT);
+
+ /* Software reset. */
+ cfg = readl(dev->regs + S5P_CIGCTRL);
+ cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL);
+ writel(cfg, dev->regs + S5P_CIGCTRL);
+ msleep(1);
+
+ cfg = readl(dev->regs + S5P_CIGCTRL);
+ cfg &= ~S5P_CIGCTRL_SWRST;
+ writel(cfg, dev->regs + S5P_CIGCTRL);
+
+}
+
+void fimc_hw_set_rotation(struct fimc_ctx *ctx)
+{
+ u32 cfg, flip;
+ struct fimc_dev *dev = ctx->fimc_dev;
+
+ cfg = readl(dev->regs + S5P_CITRGFMT);
+ cfg &= ~(S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90);
+
+ flip = readl(dev->regs + S5P_MSCTRL);
+ flip &= ~S5P_MSCTRL_FLIP_MASK;
+
+ /*
+ * The input and output rotator cannot work simultaneously.
+ * Use the output rotator in output DMA mode or the input rotator
+ * in direct fifo output mode.
+ */
+ if (ctx->rotation == 90 || ctx->rotation == 270) {
+ if (ctx->out_path == FIMC_LCDFIFO) {
+ cfg |= S5P_CITRGFMT_INROT90;
+ if (ctx->rotation == 270)
+ flip |= S5P_MSCTRL_FLIP_180;
+ } else {
+ cfg |= S5P_CITRGFMT_OUTROT90;
+ if (ctx->rotation == 270)
+ cfg |= S5P_CITRGFMT_FLIP_180;
+ }
+ } else if (ctx->rotation == 180) {
+ if (ctx->out_path == FIMC_LCDFIFO)
+ flip |= S5P_MSCTRL_FLIP_180;
+ else
+ cfg |= S5P_CITRGFMT_FLIP_180;
+ }
+ if (ctx->rotation == 180 || ctx->rotation == 270)
+ writel(flip, dev->regs + S5P_MSCTRL);
+ writel(cfg, dev->regs + S5P_CITRGFMT);
+}
+
+static u32 fimc_hw_get_in_flip(u32 ctx_flip)
+{
+ u32 flip = S5P_MSCTRL_FLIP_NORMAL;
+
+ switch (ctx_flip) {
+ case FLIP_X_AXIS:
+ flip = S5P_MSCTRL_FLIP_X_MIRROR;
+ break;
+ case FLIP_Y_AXIS:
+ flip = S5P_MSCTRL_FLIP_Y_MIRROR;
+ break;
+ case FLIP_XY_AXIS:
+ flip = S5P_MSCTRL_FLIP_180;
+ break;
+ }
+
+ return flip;
+}
+
+static u32 fimc_hw_get_target_flip(u32 ctx_flip)
+{
+ u32 flip = S5P_CITRGFMT_FLIP_NORMAL;
+
+ switch (ctx_flip) {
+ case FLIP_X_AXIS:
+ flip = S5P_CITRGFMT_FLIP_X_MIRROR;
+ break;
+ case FLIP_Y_AXIS:
+ flip = S5P_CITRGFMT_FLIP_Y_MIRROR;
+ break;
+ case FLIP_XY_AXIS:
+ flip = S5P_CITRGFMT_FLIP_180;
+ break;
+ case FLIP_NONE:
+ break;
+
+ }
+ return flip;
+}
+
+void fimc_hw_set_target_format(struct fimc_ctx *ctx)
+{
+ u32 cfg;
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_frame *frame = &ctx->d_frame;
+
+ dbg("w= %d, h= %d color: %d", frame->width,
+ frame->height, frame->fmt->color);
+
+ cfg = readl(dev->regs + S5P_CITRGFMT);
+ cfg &= ~(S5P_CITRGFMT_OUT_FMT_MASK |
+ S5P_CITRGFMT_HSIZE_MASK |
+ S5P_CITRGFMT_VSIZE_MASK);
+
+ switch (frame->fmt->color) {
+ case S5P_FIMC_RGB565:
+ case S5P_FIMC_RGB666:
+ case S5P_FIMC_RGB888:
+ cfg |= S5P_CITRGFMT_OUTFORMAT_RGB;
+ break;
+ case S5P_FIMC_YCBCR420:
+ cfg |= S5P_CITRGFMT_OUTFORMAT_YCBCR420;
+ break;
+ case S5P_FIMC_YCBYCR422:
+ case S5P_FIMC_YCRYCB422:
+ case S5P_FIMC_CBYCRY422:
+ case S5P_FIMC_CRYCBY422:
+ if (frame->fmt->planes_cnt == 1)
+ cfg |= S5P_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
+ else
+ cfg |= S5P_CITRGFMT_OUTFORMAT_YCBCR422;
+ break;
+ default:
+ break;
+ }
+
+ cfg |= S5P_CITRGFMT_TARGETHSIZE(frame->width);
+ cfg |= S5P_CITRGFMT_TARGETVSIZE(frame->height);
+
+ if (!ctx->rotation) {
+ cfg &= ~S5P_CITRGFMT_FLIP_MASK;
+ cfg |= fimc_hw_get_target_flip(ctx->flip);
+ }
+ writel(cfg, dev->regs + S5P_CITRGFMT);
+
+ cfg = S5P_CITAREA_TARGET_AREA(frame->width * frame->height);
+ writel(cfg, dev->regs + S5P_CITAREA);
+}
+
+static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_frame *frame = &ctx->d_frame;
+ u32 cfg = 0;
+
+ dbg("h= 0x%X w= 0x%X", frame->f_width, frame->f_height);
+
+ if (ctx->rotation == 90 || ctx->rotation == 270) {
+ cfg |= S5P_ORGOSIZE_HORIZONTAL(frame->f_height);
+ cfg |= S5P_ORGOSIZE_VERTICAL(frame->f_width);
+ } else {
+ cfg |= S5P_ORGOSIZE_HORIZONTAL(frame->f_width);
+ cfg |= S5P_ORGOSIZE_VERTICAL(frame->f_height);
+ }
+ dbg("ORGOSIZE: 0x%X", cfg);
+ writel(cfg, dev->regs + S5P_ORGOSIZE);
+}
+
+void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
+{
+ u32 cfg;
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_frame *frame = &ctx->d_frame;
+ struct fimc_dma_offset *offset = &frame->dma_offset;
+
+ /* Set the input dma offsets. */
+ cfg = 0;
+ cfg |= S5P_CIOYOFF_HORIZONTAL(offset->y_h);
+ cfg |= S5P_CIOYOFF_VERTICAL(offset->y_v);
+ writel(cfg, dev->regs + S5P_CIOYOFF);
+
+ cfg = 0;
+ cfg |= S5P_CIOCBOFF_HORIZONTAL(offset->cb_h);
+ cfg |= S5P_CIOCBOFF_VERTICAL(offset->cb_v);
+ writel(cfg, dev->regs + S5P_CIOCBOFF);
+
+ cfg = 0;
+ cfg |= S5P_CIOCROFF_HORIZONTAL(offset->cr_h);
+ cfg |= S5P_CIOCROFF_VERTICAL(offset->cr_v);
+ writel(cfg, dev->regs + S5P_CIOCROFF);
+
+ fimc_hw_set_out_dma_size(ctx);
+
+ /* Configure chroma components order. */
+ cfg = readl(dev->regs + S5P_CIOCTRL);
+
+ cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK |
+ S5P_CIOCTRL_YCBCR_PLANE_MASK);
+
+ if (frame->fmt->planes_cnt == 1)
+ cfg |= ctx->out_order_1p;
+ else if (frame->fmt->planes_cnt == 2)
+ cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE;
+ else if (frame->fmt->planes_cnt == 3)
+ cfg |= S5P_CIOCTRL_YCBCR_3PLANE;
+
+ writel(cfg, dev->regs + S5P_CIOCTRL);
+}
+
+void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
+{
+ u32 cfg = readl(dev->regs + S5P_ORGISIZE);
+ if (enable)
+ cfg |= S5P_CIREAL_ISIZE_AUTOLOAD_ENABLE;
+ else
+ cfg &= ~S5P_CIREAL_ISIZE_AUTOLOAD_ENABLE;
+ writel(cfg, dev->regs + S5P_ORGISIZE);
+}
+
+void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
+{
+ unsigned long flags;
+ u32 cfg;
+
+ spin_lock_irqsave(&dev->slock, flags);
+
+ cfg = readl(dev->regs + S5P_CIOCTRL);
+ if (enable)
+ cfg |= S5P_CIOCTRL_LASTIRQ_ENABLE;
+ else
+ cfg &= ~S5P_CIOCTRL_LASTIRQ_ENABLE;
+ writel(cfg, dev->regs + S5P_CIOCTRL);
+
+ spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_scaler *sc = &ctx->scaler;
+ u32 cfg = 0, shfactor;
+
+ shfactor = 10 - (sc->hfactor + sc->vfactor);
+
+ cfg |= S5P_CISCPRERATIO_SHFACTOR(shfactor);
+ cfg |= S5P_CISCPRERATIO_PREHORRATIO(sc->pre_hratio);
+ cfg |= S5P_CISCPRERATIO_PREVERRATIO(sc->pre_vratio);
+
+ writel(cfg, dev->regs + S5P_CISCPRERATIO);
+
+ cfg = 0;
+ cfg |= S5P_CISCPREDST_PREDSTWIDTH(sc->pre_dst_width);
+ cfg |= S5P_CISCPREDST_PREDSTHEIGHT(sc->pre_dst_height);
+
+ writel(cfg, dev->regs + S5P_CISCPREDST);
+}
+
+void fimc_hw_set_scaler(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_scaler *sc = &ctx->scaler;
+ struct fimc_frame *src_frame = &ctx->s_frame;
+ struct fimc_frame *dst_frame = &ctx->d_frame;
+ u32 cfg;
+
+ if (ctx->flags & S5P_FIMC_COLOR_RANGE_NARROW)
+ cfg = (S5P_CISCCTRL_CSCR2Y_NARROW|S5P_CISCCTRL_CSCY2R_NARROW);
+ else
+ cfg = (S5P_CISCCTRL_CSCR2Y_WIDE|S5P_CISCCTRL_CSCY2R_WIDE);
+
+ if (!sc->enabled)
+ cfg |= S5P_CISCCTRL_SCALERBYPASS;
+
+ if (sc->scaleup_h)
+ cfg |= S5P_CISCCTRL_SCALEUP_H;
+
+ if (sc->scaleup_v)
+ cfg |= S5P_CISCCTRL_SCALEUP_V;
+
+ if (sc->copy_mode)
+ cfg |= S5P_CISCCTRL_ONE2ONE;
+
+
+ if (ctx->in_path == FIMC_DMA) {
+ if (src_frame->fmt->color == S5P_FIMC_RGB565)
+ cfg |= S5P_CISCCTRL_INRGB_FMT_RGB565;
+ else if (src_frame->fmt->color == S5P_FIMC_RGB666)
+ cfg |= S5P_CISCCTRL_INRGB_FMT_RGB666;
+ else if (src_frame->fmt->color == S5P_FIMC_RGB888)
+ cfg |= S5P_CISCCTRL_INRGB_FMT_RGB888;
+ }
+
+ if (ctx->out_path == FIMC_DMA) {
+ if (dst_frame->fmt->color == S5P_FIMC_RGB565)
+ cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB565;
+ else if (dst_frame->fmt->color == S5P_FIMC_RGB666)
+ cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB666;
+ else if (dst_frame->fmt->color == S5P_FIMC_RGB888)
+ cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
+ } else {
+ cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
+
+ if (ctx->flags&SCAN_MODE_INTERLACED)
+ cfg |= S5P_CISCCTRL_INTERLACE;
+ else
+ cfg |= S5P_CISCCTRL_PROGRESSIVE;
+ }
+
+ dbg("main_hratio= 0x%X main_vratio= 0x%X",
+ sc->main_hratio, sc->main_vratio);
+
+ cfg |= S5P_CISCCTRL_MAINHORRATIO(sc->main_hratio);
+ cfg |= S5P_CISCCTRL_MAINVERRATIO(sc->main_vratio);
+
+ writel(cfg, dev->regs + S5P_CISCCTRL);
+}
+
+
+void fimc_hw_en_capture(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+ u32 cfg = readl(dev->regs + S5P_CIIMGCPT);
+
+ if (FIMC_DMA == ctx->out_path) {
+ /* One shot mode. */
+ cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE | S5P_CIIMGCPT_IMGCPTEN
+ | S5P_CIIMGCPT_CPT_FRMOD_EN;
+ } else {
+ /* Continous frame capture mode (freerun). */
+ cfg &= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE |
+ S5P_CIIMGCPT_CPT_FRMOD_EN);
+ cfg |= S5P_CIIMGCPT_IMGCPTEN;
+ }
+
+ if (ctx->scaler.enabled)
+ cfg |= S5P_CIIMGCPT_IMGCPTEN_SC;
+
+ writel(cfg, dev->regs + S5P_CIIMGCPT);
+}
+
+void fimc_hw_shadow_dis(struct fimc_dev *dev, int off)
+{
+ u32 cfg = readl(dev->regs + S5P_CIGCTRL);
+ if (off)
+ cfg |= S5P_CIGCTRL_SHDW_DISABLE;
+ else
+ cfg &= ~S5P_CIGCTRL_SHDW_DISABLE;
+ writel(cfg, dev->regs + S5P_CIGCTRL);
+}
+
+
+void fimc_hw_overflow_irq_en(struct fimc_dev *dev, int on)
+{
+ u32 cfg = readl(dev->regs + S5P_CIGCTRL);
+ if (on)
+ cfg |= S5P_CIGCTRL_IRQ_OVFEN;
+ else
+ cfg &= ~S5P_CIGCTRL_IRQ_OVFEN;
+ writel(cfg, dev->regs + S5P_CIGCTRL);
+}
+
+
+void fimc_hw_set_effect(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_effect *effect = &ctx->effect;
+ u32 cfg = (S5P_CIIMGEFF_IE_ENABLE | S5P_CIIMGEFF_IE_SC_AFTER);
+
+ cfg |= effect->type;
+
+ if (effect->type == S5P_FIMC_EFFECT_ARBITRARY) {
+ cfg |= S5P_CIIMGEFF_PAT_CB(effect->pat_cb);
+ cfg |= S5P_CIIMGEFF_PAT_CR(effect->pat_cr);
+ }
+
+ writel(cfg, dev->regs + S5P_CIIMGEFF);
+}
+
+static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_frame *frame = &ctx->s_frame;
+ u32 cfg_o = 0;
+ u32 cfg_r = 0;
+
+ if (FIMC_LCDFIFO == ctx->out_path)
+ cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_ENABLE;
+
+ cfg_o |= S5P_ORGISIZE_HORIZONTAL(frame->f_width);
+ cfg_o |= S5P_ORGISIZE_VERTICAL(frame->f_height);
+ cfg_r |= S5P_CIREAL_ISIZE_WIDTH(frame->width);
+ cfg_r |= S5P_CIREAL_ISIZE_HEIGHT(frame->height);
+
+ writel(cfg_o, dev->regs + S5P_ORGISIZE);
+ writel(cfg_r, dev->regs + S5P_CIREAL_ISIZE);
+}
+
+void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_frame *frame = &ctx->s_frame;
+ struct fimc_dma_offset *offset = &frame->dma_offset;
+ u32 cfg = 0;
+
+ /* Set the pixel offsets. */
+ cfg |= S5P_CIIYOFF_HORIZONTAL(offset->y_h);
+ cfg |= S5P_CIIYOFF_VERTICAL(offset->y_v);
+ writel(cfg, dev->regs + S5P_CIIYOFF);
+
+ cfg = 0;
+ cfg |= S5P_CIICBOFF_HORIZONTAL(offset->cb_h);
+ cfg |= S5P_CIICBOFF_VERTICAL(offset->cb_v);
+ writel(cfg, dev->regs + S5P_CIICBOFF);
+
+ cfg = 0;
+ cfg |= S5P_CIICROFF_HORIZONTAL(offset->cr_h);
+ cfg |= S5P_CIICROFF_VERTICAL(offset->cr_v);
+ writel(cfg, dev->regs + S5P_CIICROFF);
+
+ /* Input original and real size. */
+ fimc_hw_set_in_dma_size(ctx);
+
+ /* Autoload is used currently only in FIFO mode. */
+ fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO);
+
+ /* Set the input DMA to process single frame only. */
+ cfg = readl(dev->regs + S5P_MSCTRL);
+ cfg &= ~(S5P_MSCTRL_FLIP_MASK
+ | S5P_MSCTRL_INFORMAT_MASK
+ | S5P_MSCTRL_IN_BURST_COUNT_MASK
+ | S5P_MSCTRL_INPUT_MASK
+ | S5P_MSCTRL_C_INT_IN_MASK
+ | S5P_MSCTRL_2P_IN_ORDER_MASK);
+
+ cfg |= (S5P_MSCTRL_SUCCESSIVE_COUNT(1) | S5P_MSCTRL_INPUT_MEMORY);
+
+ switch (frame->fmt->color) {
+ case S5P_FIMC_RGB565:
+ case S5P_FIMC_RGB666:
+ case S5P_FIMC_RGB888:
+ cfg |= S5P_MSCTRL_INFORMAT_RGB;
+ break;
+ case S5P_FIMC_YCBCR420:
+ cfg |= S5P_MSCTRL_INFORMAT_YCBCR420;
+
+ if (frame->fmt->planes_cnt == 2)
+ cfg |= ctx->in_order_2p | S5P_MSCTRL_C_INT_IN_2PLANE;
+ else
+ cfg |= S5P_MSCTRL_C_INT_IN_3PLANE;
+
+ break;
+ case S5P_FIMC_YCBYCR422:
+ case S5P_FIMC_YCRYCB422:
+ case S5P_FIMC_CBYCRY422:
+ case S5P_FIMC_CRYCBY422:
+ if (frame->fmt->planes_cnt == 1) {
+ cfg |= ctx->in_order_1p
+ | S5P_MSCTRL_INFORMAT_YCBCR422_1PLANE;
+ } else {
+ cfg |= S5P_MSCTRL_INFORMAT_YCBCR422;
+
+ if (frame->fmt->planes_cnt == 2)
+ cfg |= ctx->in_order_2p
+ | S5P_MSCTRL_C_INT_IN_2PLANE;
+ else
+ cfg |= S5P_MSCTRL_C_INT_IN_3PLANE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Input DMA flip mode (and rotation).
+ * Do not allow simultaneous rotation and flipping.
+ */
+ if (!ctx->rotation && ctx->out_path == FIMC_LCDFIFO)
+ cfg |= fimc_hw_get_in_flip(ctx->flip);
+
+ writel(cfg, dev->regs + S5P_MSCTRL);
+
+ /* Input/output DMA linear/tiled mode. */
+ cfg = readl(dev->regs + S5P_CIDMAPARAM);
+ cfg &= ~(S5P_CIDMAPARAM_R_MODE_64X32 | S5P_CIDMAPARAM_W_MODE_64X32);
+
+ if (tiled_fmt(ctx->s_frame.fmt))
+ cfg |= S5P_CIDMAPARAM_R_MODE_64X32;
+
+ if (tiled_fmt(ctx->d_frame.fmt))
+ cfg |= S5P_CIDMAPARAM_W_MODE_64X32;
+
+ writel(cfg, dev->regs + S5P_CIDMAPARAM);
+}
+
+
+void fimc_hw_set_input_path(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+
+ u32 cfg = readl(dev->regs + S5P_MSCTRL);
+ cfg &= ~S5P_MSCTRL_INPUT_MASK;
+
+ if (ctx->in_path == FIMC_DMA)
+ cfg |= S5P_MSCTRL_INPUT_MEMORY;
+ else
+ cfg |= S5P_MSCTRL_INPUT_EXTCAM;
+
+ writel(cfg, dev->regs + S5P_MSCTRL);
+}
+
+void fimc_hw_set_output_path(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+
+ u32 cfg = readl(dev->regs + S5P_CISCCTRL);
+ cfg &= ~S5P_CISCCTRL_LCDPATHEN_FIFO;
+ if (ctx->out_path == FIMC_LCDFIFO)
+ cfg |= S5P_CISCCTRL_LCDPATHEN_FIFO;
+ writel(cfg, dev->regs + S5P_CISCCTRL);
+}
+
+void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
+{
+ u32 cfg = 0;
+
+ cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
+ cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DISABLE;
+ writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
+
+ writel(paddr->y, dev->regs + S5P_CIIYSA0);
+ writel(paddr->cb, dev->regs + S5P_CIICBSA0);
+ writel(paddr->cr, dev->regs + S5P_CIICRSA0);
+
+ cfg &= ~S5P_CIREAL_ISIZE_ADDR_CH_DISABLE;
+ writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
+}
+
+void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
+{
+ int i;
+ /* Set all the output register sets to point to single video buffer. */
+ for (i = 0; i < FIMC_MAX_OUT_BUFS; i++) {
+ writel(paddr->y, dev->regs + S5P_CIOYSA(i));
+ writel(paddr->cb, dev->regs + S5P_CIOCBSA(i));
+ writel(paddr->cr, dev->regs + S5P_CIOCRSA(i));
+ }
+}
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 047f7e6..974dc51 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -277,6 +277,7 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */
#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16 RGB-5-5-5 BE */
#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16 RGB-5-6-5 BE */
+#define V4L2_PIX_FMT_RGB666 v4l2_fourcc('R', 'G', 'B', 'H') /* 18 RGB-6-6-6 */
#define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */
#define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */
#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 05/10 v2] s3c-fb: Add v4l2 subdevice to support framebuffer local fifo input path
2010-07-15 9:10 [PATCH v2] Samsung S5P SoC camera interface driver Sylwester Nawrocki
` (3 preceding siblings ...)
2010-07-15 9:10 ` [PATCH 04/10 v2] v4l: Add Samsung FIMC (video postprocessor) driver Sylwester Nawrocki
@ 2010-07-15 9:10 ` Sylwester Nawrocki
2010-07-15 10:32 ` Maurus Cuelenaere
2010-07-15 9:10 ` [PATCH 06/10 v2] ARM: S5PV210: Add fifo link definitions for FIMC and framebuffer Sylwester Nawrocki
` (4 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
Selected multimedia devices in Samsung S3C/S5P SoC series are capable of
transferring data directly between each other, bypassing the main system
bus. Such a datapath exists between the camera interface/video
postprocessor and the lcd controller. To control the data flow from the
fimc driver level v4l2-subdevice driver is added to the framebuffer.
It enables to configure the lcd controller into FIFO or DMA input mode.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
arch/arm/plat-samsung/include/plat/fb.h | 6 +
drivers/video/s3c-fb.c | 487 +++++++++++++++++++++++++++++--
2 files changed, 472 insertions(+), 21 deletions(-)
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h
index cb3ca3a..7dc6110 100644
--- a/arch/arm/plat-samsung/include/plat/fb.h
+++ b/arch/arm/plat-samsung/include/plat/fb.h
@@ -22,6 +22,10 @@
*/
#define S3C_FB_MAX_WIN (5)
+#define S3C_FB_MAX_WIN_SOURCES (2)
+
+struct s3c_fifo_link;
+
/**
* struct s3c_fb_pd_win - per window setup data
* @win_mode: The display parameters to initialise (not for window 0)
@@ -35,6 +39,8 @@ struct s3c_fb_pd_win {
unsigned short max_bpp;
unsigned short virtual_x;
unsigned short virtual_y;
+
+ struct s3c_fifo_link *fifo_sources[S3C_FB_MAX_WIN_SOURCES];
};
/**
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 8ea974d..5a453cf 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -24,9 +24,14 @@
#include <linux/uaccess.h>
#include <linux/interrupt.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
#include <mach/map.h>
#include <plat/regs-fb-v4.h>
#include <plat/fb.h>
+#include <plat/fifo.h>
/* This driver will export a number of framebuffer interfaces depending
* on the configuration passed in via the platform data. Each fb instance
@@ -56,6 +61,18 @@
#define VSYNC_TIMEOUT_MSEC 50
struct s3c_fb;
+struct s3c_fb_win;
+
+struct s3c_fb_win_sd {
+ struct v4l2_subdev sd;
+ unsigned int index;
+ struct s3c_fb_win *win;
+ struct s3c_fifo_link *link;
+ struct v4l2_format fmt;
+ int streaming;
+ struct v4l2_rect default_osd_win;
+ struct v4l2_rect curr_osd_win;
+};
#define VALID_BPP(x) (1 << ((x) - 1))
@@ -65,6 +82,9 @@ struct s3c_fb;
#define VIDOSD_C(win, variant) (OSD_BASE(win, variant) + 0x08)
#define VIDOSD_D(win, variant) (OSD_BASE(win, variant) + 0x0C)
+#define s3c_fb_get_line_count(sfb) \
+ VIDCON1_LINECNT_GET(readl((sfb)->regs + VIDCON1))
+
/**
* struct s3c_fb_variant - fb variant information
* @is_2443: Set if S3C2443/S3C2416 style hardware.
@@ -156,6 +176,9 @@ struct s3c_fb_palette {
* @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/
* @index: The window number of this window.
* @palette: The bitfields for changing r/g/b into a hardware palette entry.
+ * @sources: The fifo mode data sources for this window
+ * @local_path: The flag indicating the lcd controller input mode:
+ * 0 - local path from other SoC subsystem, 1 - DMA
*/
struct s3c_fb_win {
struct s3c_fb_pd_win *windata;
@@ -167,6 +190,8 @@ struct s3c_fb_win {
u32 *palette_buffer;
u32 pseudo_palette[16];
unsigned int index;
+ struct s3c_fb_win_sd *sources[S3C_FB_MAX_WIN_SOURCES];
+ bool local_path;
};
/**
@@ -360,13 +385,10 @@ static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
*/
static int s3c_fb_align_word(unsigned int bpp, unsigned int pix)
{
- int pix_per_word;
-
if (bpp > 16)
return pix;
- pix_per_word = (8 * 32) / bpp;
- return ALIGN(pix, pix_per_word);
+ return ALIGN(pix, (bpp > 8) ? 2 : 4);
}
/**
@@ -430,6 +452,84 @@ static void shadow_protect_win(struct s3c_fb_win *win, bool protect)
}
/**
+ * s3c_fb_set_osd() - set position and size of the framebuffer window
+ *
+ * @win: framebuffer window to get data for
+ * @cr: pixel cropping reactangle
+ *
+ * Set framebuffer window position and size. cr rectangle will be modified
+ * if it does not meet the hardware alignment requirements.
+ */
+int s3c_fb_set_osd(struct s3c_fb_win *win, struct v4l2_rect *cr, int bpp)
+{
+ u32 data, width;
+ struct s3c_fb *sfb = win->parent;
+ void __iomem *regs = sfb->regs;
+
+ if (win->index >= S3C_FB_MAX_WIN)
+ return -EINVAL;
+
+ shadow_protect_win(win, 1);
+
+ cr->left = s3c_fb_align_word(bpp, cr->left);
+ data = VIDOSDxA_TOPLEFT_X(cr->left) | VIDOSDxA_TOPLEFT_Y(cr->top);
+ writel(data, regs + VIDOSD_A(win->index, sfb->variant));
+
+ width = s3c_fb_align_word(bpp, cr->width - 1);
+ data = VIDOSDxB_BOTRIGHT_X(cr->left + width)
+ | VIDOSDxB_BOTRIGHT_Y(cr->top + cr->height - 1);
+ cr->width = ++width;
+
+ writel(data, regs + VIDOSD_B(win->index, sfb->variant));
+
+ data = cr->width * cr->height;
+ vidosd_set_size(win, data);
+
+ shadow_protect_win(win, 0);
+
+ dev_dbg(sfb->dev, "%s(): l:%d t:%d w:%d h:%d", __func__,
+ cr->left, cr->top, cr->width, cr->height);
+
+ return 0;
+}
+
+/**
+ * s3c_fb_gegt_osd() - get position and size of the frame buffer window
+ *
+ * @win: framebuffer window to get data for
+ * @cr: current cropping rectangle
+ */
+int s3c_fb_get_osd(struct s3c_fb_win *win, struct v4l2_rect *cr)
+{
+ u32 reg, ltx, lty;
+ struct s3c_fb *sfb = win->parent;
+ void __iomem *regs = sfb->regs;
+
+ if (!cr || win->index >= S3C_FB_MAX_WIN)
+ return -EINVAL;
+
+ reg = readl(regs + VIDOSD_A(win->index, sfb->variant));
+
+ ltx = (reg >> VIDOSDxA_TOPLEFT_X_SHIFT) & VIDOSDxA_TOPLEFT_X_LIMIT;
+ lty = (reg >> VIDOSDxA_TOPLEFT_Y_SHIFT) & VIDOSDxA_TOPLEFT_Y_LIMIT;
+
+ reg = readl(regs + VIDOSD_B(win->index, sfb->variant));
+
+ cr->width = ((reg >> VIDOSDxB_BOTRIGHT_X_SHIFT)
+ & VIDOSDxB_BOTRIGHT_X_LIMIT) - ltx + 1;
+
+ cr->height = ((reg >> VIDOSDxB_BOTRIGHT_Y_SHIFT)
+ & VIDOSDxB_BOTRIGHT_Y_LIMIT) - lty + 1;
+ cr->left = ltx;
+ cr->top = lty;
+
+ dev_dbg(sfb->dev, "%s(): l:%d t:%d w:%d h:%d", __func__,
+ cr->left, cr->top, cr->width, cr->height);
+
+ return 0;
+}
+
+/**
* s3c_fb_set_par() - framebuffer request to set new framebuffer state.
* @info: The framebuffer to change.
*
@@ -444,10 +544,14 @@ static int s3c_fb_set_par(struct fb_info *info)
void __iomem *buf = regs;
int win_no = win->index;
u32 alpha = 0;
+ struct v4l2_rect osd_win;
u32 data;
u32 pagewidth;
int clkdiv;
+ if (win->local_path)
+ return -EBUSY;
+
dev_dbg(sfb->dev, "setting framebuffer parameters\n");
shadow_protect_win(win, 1);
@@ -517,7 +621,7 @@ static int s3c_fb_set_par(struct fb_info *info)
data = VIDTCON2_LINEVAL(var->yres - 1) |
VIDTCON2_HOZVAL(var->xres - 1);
- writel(data, regs +sfb->variant.vidtcon + 8 );
+ writel(data, regs + sfb->variant.vidtcon + 8);
}
/* write the buffer address */
@@ -536,24 +640,17 @@ static int s3c_fb_set_par(struct fb_info *info)
writel(data, regs + sfb->variant.buf_size + (win_no * 4));
/* write 'OSD' registers to control position of framebuffer */
-
- data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0);
- writel(data, regs + VIDOSD_A(win_no, sfb->variant));
-
- data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel,
- var->xres - 1)) |
- VIDOSDxB_BOTRIGHT_Y(var->yres - 1);
-
- writel(data, regs + VIDOSD_B(win_no, sfb->variant));
-
- data = var->xres * var->yres;
+ osd_win.left = 0;
+ osd_win.top = 0;
+ osd_win.width = var->xres;
+ osd_win.height = var->yres;
+ s3c_fb_set_osd(win, &osd_win, var->bits_per_pixel);
alpha = VIDISD14C_ALPHA1_R(0xf) |
VIDISD14C_ALPHA1_G(0xf) |
VIDISD14C_ALPHA1_B(0xf);
vidosd_set_alpha(win, alpha);
- vidosd_set_size(win, data);
data = WINCONx_ENWIN;
@@ -714,6 +811,9 @@ static int s3c_fb_setcolreg(unsigned regno,
dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n",
__func__, win->index, regno, red, green, blue);
+ if (win->local_path)
+ return -EBUSY;
+
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
/* true-colour, use pseudo-palette */
@@ -789,6 +889,9 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
+ if (win->local_path)
+ return -EBUSY;
+
wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4));
switch (blank_mode) {
@@ -896,6 +999,101 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
}
/**
+ * s3c_fb_enable_local() - switch window between input DMA and fifo modes
+ *
+ * @fb_sd: window subdevice for fifo input
+ * @en: 1 - switch from input DMA to fifo mode and apply
+ * window size and position set by the window's subdevice
+ * 0 - restore from fifo to DMA mode
+ */
+static int s3c_fb_enable_local_in(struct s3c_fb_win_sd *fb_sd, int en)
+{
+ struct s3c_fb_win *win = fb_sd->win;
+ struct s3c_fb *sfb = win->parent;
+ static u32 wincon;
+ u32 reg, data;
+ int ret = 0, bpp = 32;
+
+ /* disable video output and the window logic */
+ reg = readl(sfb->regs + WINCON(win->index));
+ writel(reg & ~WINCONx_ENWIN, sfb->regs + WINCON(win->index));
+
+ shadow_protect_win(win, 1);
+
+ if (en == 1) {
+ if (fb_sd->streaming)
+ return 0;
+
+ wincon = reg;
+
+ switch (fb_sd->fmt.fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_YUYV: /* YCbCr 4:4:4 */
+ reg |= WINCONx_YCbCr | WINCONx_ENLOCAL;
+ bpp = 16;
+ break;
+
+ case V4L2_PIX_FMT_RGB24:
+ default:
+ reg &= ~(WINCONx_YCbCr | WINCONx_WSWP | WINCONx_HAWSWP |
+ WINCONx_BYTSWP | WINCONx_BITSWP |
+ WINCON0_BPPMODE_MASK | WINCONx_BURSTLEN_MASK);
+
+ reg |= WINCON0_BPPMODE_24BPP_888 |
+ WINCONx_BURSTLEN_4WORD;
+ bpp = 24;
+ break;
+ }
+
+ fb_sd->streaming = 1;
+ writel(reg, sfb->regs + WINCON(win->index));
+
+ s3c_fb_set_osd(fb_sd->win, &fb_sd->curr_osd_win, bpp);
+
+ writel(reg | WINCONx_ENLOCAL, sfb->regs + WINCON(win->index));
+
+ shadow_protect_win(win, 0);
+
+ reg = readl(sfb->regs + WINCON(win->index));
+ writel(reg | WINCONx_ENWIN, sfb->regs + WINCON(win->index));
+
+ if (sfb->variant.has_shadowcon) {
+ data = readl(sfb->regs + SHADOWCON);
+ data |= SHADOWCON_CHx_LOCAL_ENABLE(win->index);
+ writel(data, sfb->regs + SHADOWCON);
+ }
+
+ } else if (en == 0) {
+ if (!fb_sd->streaming)
+ return 0;
+
+ fb_sd->streaming = 0;
+
+ /* need to be aligned with VSYNC interrupt */
+ writel(wincon & ~WINCONx_ENLOCAL,
+ sfb->regs + WINCON(win->index));
+
+ /* restore OSD values from before we enabled local mode */
+ bpp = win->fbinfo->var.bits_per_pixel;
+ s3c_fb_set_osd(fb_sd->win, &fb_sd->default_osd_win, bpp);
+
+ shadow_protect_win(win, 0);
+
+ if (sfb->variant.has_shadowcon) {
+ data = readl(sfb->regs + SHADOWCON);
+ data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index);
+ writel(data, sfb->regs + SHADOWCON);
+ }
+
+ reg = readl(sfb->regs + WINCON(win->index));
+ writel(reg | WINCONx_ENWIN, sfb->regs + WINCON(win->index));
+ } else {
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+/**
* s3c_fb_enable_irq() - enable framebuffer interrupts
* @sfb: main hardware state
*/
@@ -912,7 +1110,7 @@ static void s3c_fb_enable_irq(struct s3c_fb *sfb)
irq_ctrl_reg |= VIDINTCON0_INT_FRAME;
irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL0_MASK;
- irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_VSYNC;
+ irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_FRONTPORCH;
irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL1_MASK;
irq_ctrl_reg |= VIDINTCON0_FRAMESEL1_NONE;
@@ -952,7 +1150,6 @@ static irqreturn_t s3c_fb_irq(int irq, void *dev_id)
/* VSYNC interrupt, accept it */
writel(VIDINTCON1_INT_FRAME, regs + VIDINTCON1);
-
sfb->vsync_info.count++;
wake_up_interruptible(&sfb->vsync_info.wait);
}
@@ -1089,6 +1286,246 @@ static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
fbi->screen_base, fbi->fix.smem_start);
}
+
+static struct s3c_fb_win_sd *to_fb_win_sd(struct v4l2_subdev *s)
+{
+ return container_of(s, struct s3c_fb_win_sd, sd);
+}
+
+/**
+ * v4l2_sd_fb_s_stream() - switch between DMA on local path mode
+ *
+ * @win: window to change operation mode for.
+ * @sd:
+ * @en: 1 - apply cropping rectangle and switch to local path,
+ * 0 - restore cropping rectangle and switch to input DMA mode.
+ */
+static int v4l2_sd_fb_s_stream(struct v4l2_subdev *sd, int en)
+{
+ unsigned long flags;
+ struct s3c_fb_win_sd *w_sd = to_fb_win_sd(sd);
+ struct s3c_fb_win *win = w_sd->win;
+ struct s3c_fb *sfb = win->parent;
+ int ret = 0;
+
+ if (win->index > 2)
+ return -EINVAL;
+
+ mutex_lock(&win->fbinfo->lock);
+
+ if (en == 1) {
+ ret = s3c_fb_enable_local_in(w_sd, en);
+ win->local_path = 1;
+ } else if (en == 0) {
+ /*
+ * The fmc-frambuffer fifo need to be stopped shortly after
+ * VSYNC, for this reason horizontal line count is additionally
+ * examined after waking up by an interrupt. If it is 0 we are
+ * still at VSYNC and therefore are save to disable fifo.
+ */
+ ret = s3c_fb_wait_for_vsync(sfb, 0);
+
+ if (ret == -ETIMEDOUT)
+ goto ss_out;
+
+ local_irq_save(flags);
+
+ while (s3c_fb_get_line_count(sfb) != 0)
+ cpu_relax();
+
+ /* Stop FIFO at FIMC side */
+ v4l2_subdev_notify(&w_sd->sd, 0, NULL);
+
+ s3c_fb_enable_local_in(w_sd, 0);
+ local_irq_restore(flags);
+
+ win->local_path = 0;
+ ret = 0;
+ }
+ss_out:
+ mutex_unlock(&win->fbinfo->lock);
+ return ret;
+}
+
+/**
+ * v4l2_sd_fb_s_fmt() - set format for local input path mode
+ *
+ * @sd: pointer to v4l2 subdevice
+ * @fmt: pixel format to set
+ */
+static int v4l2_sd_fb_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+ struct s3c_fb_win_sd *fb_sd = to_fb_win_sd(sd);
+ int fourcc = fmt->fmt.pix.pixelformat;
+
+ if (!fmt || (fourcc != V4L2_PIX_FMT_YUYV
+ && fourcc != V4L2_PIX_FMT_RGB24))
+ return -EINVAL;
+ fb_sd->fmt.fmt.pix.pixelformat = fmt->fmt.pix.pixelformat;
+ return 0;
+}
+
+/**
+ * v4l2_sd_fb_cropcap() - get cropping capabilities for local fifo input mode
+ *
+ * @sd: pointer to v4l2 subdevice
+ * @cc:
+ */
+static int v4l2_sd_fb_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cc)
+{
+ struct s3c_fb_win *win = to_fb_win_sd(sd)->win;
+ struct s3c_fb_pd_win *windata = win->windata;
+
+ if (!windata)
+ return -ENODEV;
+
+ mutex_lock(&win->fbinfo->lock);
+
+ cc->defrect.width = windata->win_mode.xres;
+ cc->defrect.height = windata->win_mode.yres;
+ cc->defrect.left = 0;
+ cc->defrect.top = 0;
+ cc->bounds = cc->defrect;
+
+ mutex_unlock(&win->fbinfo->lock);
+
+ return 0;
+}
+
+/**
+ * v4l2_sd_fb_s_crop() - set window position and size
+ *
+ * @sd: pointer to v4l2 subdevice
+ * @cr: cropping rectangle to set for local path mode
+ */
+static int v4l2_sd_fb_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *cr)
+{
+ struct v4l2_rect *r;
+ struct s3c_fb_win_sd *fb_sd = to_fb_win_sd(sd);
+ u32 fourcc = fb_sd->fmt.fmt.pix.pixelformat;
+
+ fb_sd->curr_osd_win = cr->c;
+
+ if (fourcc == V4L2_PIX_FMT_YUYV) {
+ r = &cr->c;
+ r->left = round_down(r->left, 8);
+ r->top = round_down(r->top, 8);
+ r->width = round_down(r->width, 8);
+ r->height = round_down(r->height, 8);
+ }
+
+ return 0;
+}
+
+/**
+ * v4l2_sd_fb_g_crop() - set window position and size
+ *
+ * @sd: pointer to v4l2 subdevice
+ * @cr: rectangle to return current cropping parameters to
+ *
+ * Implements g_crop operation for camera interface driver.
+ */
+static int v4l2_sd_fb_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *cr)
+{
+ struct s3c_fb_win_sd *fb_sd = to_fb_win_sd(sd);
+
+ cr->c = fb_sd->curr_osd_win;
+
+ return 0;
+}
+
+
+static struct v4l2_subdev_core_ops v4l2_sd_core_fb_ops = { NULL };
+
+static struct v4l2_subdev_video_ops v4l2_sd_video_fb_ops = {
+ .s_stream = v4l2_sd_fb_s_stream,
+ .s_fmt = v4l2_sd_fb_s_fmt,
+ .cropcap = v4l2_sd_fb_cropcap,
+ .s_crop = v4l2_sd_fb_s_crop,
+ .g_crop = v4l2_sd_fb_g_crop,
+};
+
+static struct v4l2_subdev_ops v4l2_sd_fb_ops = {
+ .core = &v4l2_sd_core_fb_ops,
+ .video = &v4l2_sd_video_fb_ops,
+};
+
+static int s3c_fb_unregister_subdevices(struct s3c_fb_win *win)
+{
+ int i;
+ struct s3c_fb *sfb = win->parent;
+
+ if (win->index >= S3C_FB_MAX_WIN)
+ return -ENODEV;
+
+ for (i = 0; i < S3C_FB_MAX_WIN_SOURCES; i++) {
+ if (win->sources[i]) {
+ /* remove sub_dev pointer from link */
+ win->sources[i]->link->sub_dev = NULL;
+ kfree(win->sources[i]);
+ dev_dbg(sfb->dev,
+ "s3c-fb subdevice %d removed from window %d\n",
+ i, win->index);
+ }
+ }
+
+ return 0;
+}
+
+/* Create the subdevice per each data source of the framebuffer window.
+ Locking: The caller holds win->parent->dev->mutex. */
+static int s3c_fb_register_subdevices(struct s3c_fb_win *win)
+{
+ int i;
+ struct s3c_fb *sfb = win->parent;
+ struct s3c_fb_pd_win *windata = win->windata;
+ struct s3c_fb_win_sd *win_sd;
+ struct v4l2_rect *r;
+
+
+ if (win->index >= S3C_FB_MAX_WIN)
+ return -ENODEV;
+
+ for (i = 0; i < S3C_FB_MAX_WIN_SOURCES; i++) {
+ if (!windata->fifo_sources[i])
+ continue;
+ win_sd = kzalloc(sizeof(struct s3c_fb_win_sd), GFP_KERNEL);
+ if (win_sd == NULL)
+ return -ENOMEM;
+
+ win_sd->index = i;
+ win_sd->win = win;
+ win_sd->link = windata->fifo_sources[i];
+ win_sd->streaming = 0;
+ v4l2_subdev_init(&win_sd->sd, &v4l2_sd_fb_ops);
+ snprintf(win_sd->sd.name, sizeof(win_sd->sd.name),
+ "s3cfb-local");
+
+ /* hook up pointer to slave device */
+ win_sd->link->sub_dev = &win_sd->sd;
+ win->sources[i] = win_sd;
+
+ /* set default rectangle to current window */
+ s3c_fb_get_osd(win, &win_sd->default_osd_win);
+
+ /* set fimc fifo output rectangle to current window */
+ r = &win_sd->curr_osd_win;
+ r->width = windata->win_mode.xres;
+ r->height = windata->win_mode.yres;
+ r->left = 0;
+ r->top = 0;
+
+ win_sd->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
+
+ dev_dbg(sfb->dev, "%s(): l:%d t:%d w:%d h:%d",
+ __func__, r->left, r->top, r->width, r->height);
+
+ dev_dbg(sfb->dev, "subdevice %d registered at window %d\n",
+ i, win->index);
+ }
+ return 0;
+}
+
/**
* s3c_fb_release_win() - release resources for a framebuffer window.
* @win: The window to cleanup the resources for.
@@ -1107,6 +1544,7 @@ static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index);
writel(data, sfb->regs + SHADOWCON);
}
+ s3c_fb_unregister_subdevices(win);
unregister_framebuffer(win->fbinfo);
if (win->fbinfo->cmap.len)
fb_dealloc_cmap(&win->fbinfo->cmap);
@@ -1165,6 +1603,7 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
win->windata = windata;
win->index = win_no;
win->palette_buffer = (u32 *)(win + 1);
+ win->local_path = 0;
ret = s3c_fb_alloc_memory(sfb, win);
if (ret) {
@@ -1220,11 +1659,16 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
else
dev_err(sfb->dev, "failed to allocate fb cmap\n");
+ /* run the check_var and set_par on our configuration. */
s3c_fb_set_par(fbinfo);
- dev_dbg(sfb->dev, "about to register framebuffer\n");
+ ret = s3c_fb_register_subdevices(win);
+ if (ret < 0) {
+ dev_err(sfb->dev, "failed to register s3c-fb subdevices\n");
+ return ret;
+ }
- /* run the check_var and set_par on our configuration. */
+ dev_dbg(sfb->dev, "about to register framebuffer\n");
ret = register_framebuffer(fbinfo);
if (ret < 0) {
@@ -1328,6 +1772,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
ret = -ENOENT;
goto err_ioremap;
}
+
sfb->irq_no = res->start;
ret = request_irq(sfb->irq_no, s3c_fb_irq,
0, "s3c_fb", sfb);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 06/10 v2] ARM: S5PV210: Add fifo link definitions for FIMC and framebuffer
2010-07-15 9:10 [PATCH v2] Samsung S5P SoC camera interface driver Sylwester Nawrocki
` (4 preceding siblings ...)
2010-07-15 9:10 ` [PATCH 05/10 v2] s3c-fb: Add v4l2 subdevice to support framebuffer local fifo input path Sylwester Nawrocki
@ 2010-07-15 9:10 ` Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 07/10 v2] ARM: S5PV210: add common Aquila & GONI code Sylwester Nawrocki
` (3 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
Add definition of local paths that are available on Samsung S5PV210 SoCs.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
arch/arm/mach-s5pv210/setup-fimc0.c | 23 +++++++++++++++++++++++
arch/arm/mach-s5pv210/setup-fimc1.c | 23 +++++++++++++++++++++++
arch/arm/mach-s5pv210/setup-fimc2.c | 23 +++++++++++++++++++++++
arch/arm/plat-samsung/include/plat/fimc.h | 4 ++++
4 files changed, 73 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv210/setup-fimc0.c b/arch/arm/mach-s5pv210/setup-fimc0.c
index 0e5ef0a..b869d87 100644
--- a/arch/arm/mach-s5pv210/setup-fimc0.c
+++ b/arch/arm/mach-s5pv210/setup-fimc0.c
@@ -10,5 +10,28 @@
*/
#include <plat/fimc.h>
+#include <plat/fifo.h>
+#include <linux/fb.h>
+#include <plat/fb.h>
+#include <plat/devs.h>
struct samsung_plat_fimc s5p_fimc0_default_data __initdata = {};
+
+static struct s3c_fifo_link s5pv210_fimc0_win0_link = {
+ .master_dev = &s5p_device_fimc0.dev,
+ .slave_dev = &s3c_device_fb.dev,
+};
+
+void __init s5pv210_setup_fimc0_fb_link(void)
+{
+ struct s3c_fb_platdata *fb_pd;
+ struct samsung_plat_fimc *fimc_pd;
+
+ fimc_pd = s5p_device_fimc0.dev.platform_data;
+ fb_pd = s3c_device_fb.dev.platform_data;
+
+ if (fimc_pd && fb_pd && fb_pd->win[0]) {
+ fb_pd->win[0]->fifo_sources[0] = &s5pv210_fimc0_win0_link;
+ fimc_pd->fifo_targets[0] = &s5pv210_fimc0_win0_link;
+ }
+}
diff --git a/arch/arm/mach-s5pv210/setup-fimc1.c b/arch/arm/mach-s5pv210/setup-fimc1.c
index 80da0e7..62a7804 100644
--- a/arch/arm/mach-s5pv210/setup-fimc1.c
+++ b/arch/arm/mach-s5pv210/setup-fimc1.c
@@ -10,5 +10,28 @@
*/
#include <plat/fimc.h>
+#include <plat/fifo.h>
+#include <linux/fb.h>
+#include <plat/fb.h>
+#include <plat/devs.h>
struct samsung_plat_fimc s5p_fimc1_default_data __initdata = {};
+
+static struct s3c_fifo_link s5pv210_fimc1_win1_link = {
+ .master_dev = &s5p_device_fimc1.dev,
+ .slave_dev = &s3c_device_fb.dev,
+};
+
+void __init s5pv210_setup_fimc1_fb_link(void)
+{
+ struct s3c_fb_platdata *fb_pd;
+ struct samsung_plat_fimc *fimc_pd;
+
+ fimc_pd = s5p_device_fimc1.dev.platform_data;
+ fb_pd = s3c_device_fb.dev.platform_data;
+
+ if (fimc_pd && fb_pd && fb_pd->win[1]) {
+ fb_pd->win[1]->fifo_sources[0] = &s5pv210_fimc1_win1_link;
+ fimc_pd->fifo_targets[0] = &s5pv210_fimc1_win1_link;
+ }
+}
diff --git a/arch/arm/mach-s5pv210/setup-fimc2.c b/arch/arm/mach-s5pv210/setup-fimc2.c
index bc6a27b..1515eac 100644
--- a/arch/arm/mach-s5pv210/setup-fimc2.c
+++ b/arch/arm/mach-s5pv210/setup-fimc2.c
@@ -10,5 +10,28 @@
*/
#include <plat/fimc.h>
+#include <plat/fifo.h>
+#include <linux/fb.h>
+#include <plat/fb.h>
+#include <plat/devs.h>
struct samsung_plat_fimc s5p_fimc2_default_data __initdata = {};
+
+static struct s3c_fifo_link s5pv210_fimc2_win2_link = {
+ .master_dev = &s5p_device_fimc2.dev,
+ .slave_dev = &s3c_device_fb.dev,
+};
+
+void __init s5pv210_setup_fimc2_fb_link(void)
+{
+ struct s3c_fb_platdata *fb_pd;
+ struct samsung_plat_fimc *fimc_pd;
+
+ fimc_pd = s5p_device_fimc2.dev.platform_data;
+ fb_pd = s3c_device_fb.dev.platform_data;
+
+ if (fimc_pd && fb_pd && fb_pd->win[2]) {
+ fb_pd->win[2]->fifo_sources[0] = &s5pv210_fimc2_win2_link;
+ fimc_pd->fifo_targets[0] = &s5pv210_fimc2_win2_link;
+ }
+}
diff --git a/arch/arm/plat-samsung/include/plat/fimc.h b/arch/arm/plat-samsung/include/plat/fimc.h
index cf7d2fb..304ef42 100644
--- a/arch/arm/plat-samsung/include/plat/fimc.h
+++ b/arch/arm/plat-samsung/include/plat/fimc.h
@@ -39,5 +39,9 @@ extern void s5p_fimc0_set_platdata(struct samsung_plat_fimc *fimc);
extern void s5p_fimc1_set_platdata(struct samsung_plat_fimc *fimc);
extern void s5p_fimc2_set_platdata(struct samsung_plat_fimc *fimc);
+extern void __init s5pv210_setup_fimc0_fb_link(void);
+extern void __init s5pv210_setup_fimc1_fb_link(void);
+extern void __init s5pv210_setup_fimc2_fb_link(void);
+
#endif /* FIMC_H_ */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 07/10 v2] ARM: S5PV210: add common Aquila & GONI code
2010-07-15 9:10 [PATCH v2] Samsung S5P SoC camera interface driver Sylwester Nawrocki
` (5 preceding siblings ...)
2010-07-15 9:10 ` [PATCH 06/10 v2] ARM: S5PV210: Add fifo link definitions for FIMC and framebuffer Sylwester Nawrocki
@ 2010-07-15 9:10 ` Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 08/10 v2] ARM: S5PV210: enable FIMC on Aquila Sylwester Nawrocki
` (2 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Pawel Osciak <p.osciak@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-s5pv210/Kconfig | 5 +++
arch/arm/mach-s5pv210/Makefile | 2 +
arch/arm/mach-s5pv210/common-aquila-goni.c | 39 ++++++++++++++++++++++++++++
arch/arm/mach-s5pv210/common-aquila-goni.h | 2 +
4 files changed, 48 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-s5pv210/common-aquila-goni.c
create mode 100644 arch/arm/mach-s5pv210/common-aquila-goni.h
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 4bb5a85..5206562 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -126,6 +126,11 @@ config MACH_P1P2
endmenu
+config COMMON_AQUILA_GONI
+ bool
+ help
+ Compile common code for Samsung Aquila and Samsung GONI machines
+
config S5PC110_DEV_ONENAND
bool
help
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 6eceeb8..06de97f 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -24,6 +24,8 @@ obj-$(CONFIG_MACH_GONI) += mach-goni.o
obj-$(CONFIG_MACH_UNIVERSAL) += mach-universal.o
obj-$(CONFIG_MACH_P1P2) += mach-p1p2.o
+obj-$(CONFIG_COMMON_AQUILA_GONI) += common-aquila-goni.o
+
# device support
obj-y += dev-audio.o
diff --git a/arch/arm/mach-s5pv210/common-aquila-goni.c b/arch/arm/mach-s5pv210/common-aquila-goni.c
new file mode 100644
index 0000000..cdfc40e
--- /dev/null
+++ b/arch/arm/mach-s5pv210/common-aquila-goni.c
@@ -0,0 +1,39 @@
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <plat/fimc.h>
+
+#include "common-aquila-goni.h"
+
+void __init s5pv210_common_fimc_clk_init(void)
+{
+ int i;
+ struct clk *clk_fimc, *parent;
+
+ struct device *fimc_devs[] = {
+ &s5p_device_fimc0.dev,
+ &s5p_device_fimc1.dev,
+ &s5p_device_fimc2.dev
+ };
+
+ parent = clk_get(NULL, "mout_epll");
+ if (IS_ERR(parent)) {
+ printk("%s: Could not get FIMC parent clock\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(fimc_devs); i++) {
+ if (fimc_devs[i]) {
+ clk_fimc = clk_get(fimc_devs[i], "sclk_fimc");
+
+ if (IS_ERR(clk_fimc)) {
+ printk("%s: Could not get sclk_fimc clock\n",
+ __func__);
+ continue;
+ }
+
+ clk_set_parent(clk_fimc, parent);
+ clk_set_rate(clk_fimc, 133000000);
+ }
+ }
+ clk_put(parent);
+}
diff --git a/arch/arm/mach-s5pv210/common-aquila-goni.h b/arch/arm/mach-s5pv210/common-aquila-goni.h
new file mode 100644
index 0000000..f666462
--- /dev/null
+++ b/arch/arm/mach-s5pv210/common-aquila-goni.h
@@ -0,0 +1,2 @@
+
+extern void s5pv210_common_fimc_clk_init(void);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 08/10 v2] ARM: S5PV210: enable FIMC on Aquila
2010-07-15 9:10 [PATCH v2] Samsung S5P SoC camera interface driver Sylwester Nawrocki
` (6 preceding siblings ...)
2010-07-15 9:10 ` [PATCH 07/10 v2] ARM: S5PV210: add common Aquila & GONI code Sylwester Nawrocki
@ 2010-07-15 9:10 ` Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 09/10 v2] ARM: s5pv210: enable FIMC on Goni Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 10/10 v2] ARM: S5PC100: enable FIMC on SMDKC100 Sylwester Nawrocki
9 siblings, 0 replies; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
From: Marek Szyprowski <m.szyprowski@samsung.com>
Add support for FIMC on Samsung Aquila board. Enable support for local
path mode between fimc and frame buffer.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-s5pv210/Kconfig | 7 +++++++
arch/arm/mach-s5pv210/mach-aquila.c | 20 ++++++++++++++++++++
2 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 5206562..fed64f5 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -63,10 +63,17 @@ menu "S5PC110 Machines"
config MACH_AQUILA
bool "Aquila"
select CPU_S5PV210
+ select COMMON_AQUILA_GONI
select ARCH_SPARSEMEM_ENABLE
select S5PV210_SETUP_FB_24BPP
select S5PV210_SETUP_SDHCI
select S3C_DEV_FB
+ select S5P_DEV_FIMC0
+ select S5PV210_SETUP_FIMC0
+ select S5P_DEV_FIMC1
+ select S5PV210_SETUP_FIMC1
+ select S5P_DEV_FIMC2
+ select S5PV210_SETUP_FIMC2
select S5PC110_DEV_ONENAND
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 6b60358..927bf47 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/fb.h>
+#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
@@ -41,9 +42,13 @@
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/fb.h>
+#include <plat/fimc.h>
+#include <plat/fifo.h>
#include <plat/gpio-cfg.h>
#include <plat/sdhci.h>
+#include "common-aquila-goni.h"
+
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
S3C2410_UCON_RXILEVEL | \
@@ -577,6 +582,9 @@ static struct platform_device *aquila_devices[] __initdata = {
&universal_spi_gpio,
&s5pc110_device_onenand,
&s3c_device_usbgadget,
+ &s5p_device_fimc0,
+ &s5p_device_fimc1,
+ &s5p_device_fimc2,
&s3c_device_hsmmc0,
&s3c_device_hsmmc1,
&s3c_device_hsmmc2,
@@ -599,13 +607,25 @@ static void __init aquila_machine_init(void)
/* SPI */
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+ /* FIMC */
+ s5p_fimc0_set_platdata(NULL);
+ s5p_fimc1_set_platdata(NULL);
+ s5p_fimc2_set_platdata(NULL);
+
/* SDHCI */
aquila_setup_sdhci();
/* FB */
s3c_fb_set_platdata(&aquila_lcd_pdata);
+ /* FIMC->FB fifo links */
+ s5pv210_setup_fimc0_fb_link();
+ s5pv210_setup_fimc1_fb_link();
+ s5pv210_setup_fimc2_fb_link();
+
platform_add_devices(aquila_devices, ARRAY_SIZE(aquila_devices));
+
+ s5pv210_common_fimc_clk_init();
}
MACHINE_START(AQUILA, "Aquila")
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 09/10 v2] ARM: s5pv210: enable FIMC on Goni
2010-07-15 9:10 [PATCH v2] Samsung S5P SoC camera interface driver Sylwester Nawrocki
` (7 preceding siblings ...)
2010-07-15 9:10 ` [PATCH 08/10 v2] ARM: S5PV210: enable FIMC on Aquila Sylwester Nawrocki
@ 2010-07-15 9:10 ` Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 10/10 v2] ARM: S5PC100: enable FIMC on SMDKC100 Sylwester Nawrocki
9 siblings, 0 replies; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
From: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-s5pv210/Kconfig | 1 +
arch/arm/mach-s5pv210/mach-goni.c | 18 ++++++++++++++++++
2 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index fed64f5..e9e033e 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -85,6 +85,7 @@ config MACH_AQUILA
config MACH_GONI
bool "GONI"
select CPU_S5PV210
+ select COMMON_AQUILA_GONI
select ARCH_SPARSEMEM_ENABLE
select S5PV210_SETUP_FB_24BPP
select S3C_DEV_FB
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 4792bf8..fde12df 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -40,6 +40,9 @@
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/fb.h>
+#include <plat/fimc.h>
+
+#include "common-aquila-goni.h"
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -498,6 +501,9 @@ static struct platform_device *goni_devices[] __initdata = {
&s3c_device_usbgadget,
&goni_i2c_gpio_pmic,
&goni_device_gpiokeys,
+ &s5p_device_fimc0,
+ &s5p_device_fimc1,
+ &s5p_device_fimc2,
};
static void __init goni_map_io(void)
@@ -520,7 +526,19 @@ static void __init goni_machine_init(void)
/* SPI */
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+ /* FIMC */
+ s5p_fimc0_set_platdata(NULL);
+ s5p_fimc1_set_platdata(NULL);
+ s5p_fimc2_set_platdata(NULL);
+
+ /* FIMC->FB fifo links */
+ s5pv210_setup_fimc0_fb_link();
+ s5pv210_setup_fimc1_fb_link();
+ s5pv210_setup_fimc2_fb_link();
+
platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices));
+
+ s5pv210_common_fimc_clk_init();
}
MACHINE_START(GONI, "GONI")
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 10/10 v2] ARM: S5PC100: enable FIMC on SMDKC100
2010-07-15 9:10 [PATCH v2] Samsung S5P SoC camera interface driver Sylwester Nawrocki
` (8 preceding siblings ...)
2010-07-15 9:10 ` [PATCH 09/10 v2] ARM: s5pv210: enable FIMC on Goni Sylwester Nawrocki
@ 2010-07-15 9:10 ` Sylwester Nawrocki
9 siblings, 0 replies; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 9:10 UTC (permalink / raw)
To: linux-arm-kernel
Add support for FIMC on Samsung SMDKC100 board.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-s5pc100/Kconfig | 6 ++++++
arch/arm/mach-s5pc100/mach-smdkc100.c | 9 +++++++++
2 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index 791270d..8839c07 100644
--- a/arch/arm/mach-s5pc100/Kconfig
+++ b/arch/arm/mach-s5pc100/Kconfig
@@ -63,6 +63,12 @@ config MACH_SMDKC100
select S5PC100_SETUP_FB_24BPP
select S5PC100_SETUP_I2C1
select S5PC100_SETUP_SDHCI
+ select S5P_DEV_FIMC0
+ select S5PC100_SETUP_FIMC0
+ select S5P_DEV_FIMC1
+ select S5PC100_SETUP_FIMC1
+ select S5P_DEV_FIMC2
+ select S5PC100_SETUP_FIMC2
help
Machine support for the Samsung SMDKC100
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index ce3fcde..262de8e 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -42,6 +42,7 @@
#include <plat/s5pc100.h>
#include <plat/fb.h>
#include <plat/iic.h>
+#include <plat/fimc.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define S5PC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -160,6 +161,9 @@ static struct platform_device *smdkc100_devices[] __initdata = {
&s5pc100_device_iis0,
&s5pc100_device_ac97,
&s3c_device_onenand,
+ &s5p_device_fimc0,
+ &s5p_device_fimc1,
+ &s5p_device_fimc2,
};
static void __init smdkc100_map_io(void)
@@ -179,6 +183,11 @@ static void __init smdkc100_machine_init(void)
s3c_fb_set_platdata(&smdkc100_lcd_pdata);
+ /* FIMC */
+ s5p_fimc0_set_platdata(NULL);
+ s5p_fimc1_set_platdata(NULL);
+ s5p_fimc2_set_platdata(NULL);
+
/* LCD init */
gpio_request(S5PC100_GPD(0), "GPD");
gpio_request(S5PC100_GPH0(6), "GPH0");
--
1.7.0.4
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 05/10 v2] s3c-fb: Add v4l2 subdevice to support framebuffer local fifo input path
2010-07-15 9:10 ` [PATCH 05/10 v2] s3c-fb: Add v4l2 subdevice to support framebuffer local fifo input path Sylwester Nawrocki
@ 2010-07-15 10:32 ` Maurus Cuelenaere
2010-07-15 11:18 ` Sylwester Nawrocki
0 siblings, 1 reply; 21+ messages in thread
From: Maurus Cuelenaere @ 2010-07-15 10:32 UTC (permalink / raw)
To: linux-arm-kernel
Op 15-07-10 11:10, Sylwester Nawrocki schreef:
> Selected multimedia devices in Samsung S3C/S5P SoC series are capable of
> transferring data directly between each other, bypassing the main system
> bus. Such a datapath exists between the camera interface/video
> postprocessor and the lcd controller. To control the data flow from the
> fimc driver level v4l2-subdevice driver is added to the framebuffer.
> It enables to configure the lcd controller into FIFO or DMA input mode.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
> arch/arm/plat-samsung/include/plat/fb.h | 6 +
> drivers/video/s3c-fb.c | 487 +++++++++++++++++++++++++++++--
> 2 files changed, 472 insertions(+), 21 deletions(-)
<snip>
> /**
> + * s3c_fb_enable_local() - switch window between input DMA and fifo modes
> + *
> + * @fb_sd: window subdevice for fifo input
> + * @en: 1 - switch from input DMA to fifo mode and apply
> + * window size and position set by the window's subdevice
> + * 0 - restore from fifo to DMA mode
> + */
> +static int s3c_fb_enable_local_in(struct s3c_fb_win_sd *fb_sd, int en)
> +{
> + struct s3c_fb_win *win = fb_sd->win;
> + struct s3c_fb *sfb = win->parent;
> + static u32 wincon;
> + u32 reg, data;
> + int ret = 0, bpp = 32;
> +
> + /* disable video output and the window logic */
> + reg = readl(sfb->regs + WINCON(win->index));
> + writel(reg & ~WINCONx_ENWIN, sfb->regs + WINCON(win->index));
> +
> + shadow_protect_win(win, 1);
> +
> + if (en == 1) {
> + if (fb_sd->streaming)
> + return 0;
Shouldn't you do shadow_protect_win(win, 0) before returning here?
> +
> + wincon = reg;
> +
> + switch (fb_sd->fmt.fmt.pix.pixelformat) {
> + case V4L2_PIX_FMT_YUYV: /* YCbCr 4:4:4 */
> + reg |= WINCONx_YCbCr | WINCONx_ENLOCAL;
> + bpp = 16;
> + break;
> +
> + case V4L2_PIX_FMT_RGB24:
> + default:
> + reg &= ~(WINCONx_YCbCr | WINCONx_WSWP | WINCONx_HAWSWP |
> + WINCONx_BYTSWP | WINCONx_BITSWP |
> + WINCON0_BPPMODE_MASK | WINCONx_BURSTLEN_MASK);
> +
> + reg |= WINCON0_BPPMODE_24BPP_888 |
> + WINCONx_BURSTLEN_4WORD;
> + bpp = 24;
> + break;
> + }
> +
> + fb_sd->streaming = 1;
> + writel(reg, sfb->regs + WINCON(win->index));
> +
> + s3c_fb_set_osd(fb_sd->win, &fb_sd->curr_osd_win, bpp);
> +
> + writel(reg | WINCONx_ENLOCAL, sfb->regs + WINCON(win->index));
> +
> + shadow_protect_win(win, 0);
> +
> + reg = readl(sfb->regs + WINCON(win->index));
> + writel(reg | WINCONx_ENWIN, sfb->regs + WINCON(win->index));
> +
> + if (sfb->variant.has_shadowcon) {
> + data = readl(sfb->regs + SHADOWCON);
> + data |= SHADOWCON_CHx_LOCAL_ENABLE(win->index);
> + writel(data, sfb->regs + SHADOWCON);
> + }
> +
> + } else if (en == 0) {
> + if (!fb_sd->streaming)
> + return 0;
Same comment
> +
> + fb_sd->streaming = 0;
> +
> + /* need to be aligned with VSYNC interrupt */
> + writel(wincon & ~WINCONx_ENLOCAL,
> + sfb->regs + WINCON(win->index));
> +
> + /* restore OSD values from before we enabled local mode */
> + bpp = win->fbinfo->var.bits_per_pixel;
> + s3c_fb_set_osd(fb_sd->win, &fb_sd->default_osd_win, bpp);
> +
> + shadow_protect_win(win, 0);
> +
> + if (sfb->variant.has_shadowcon) {
> + data = readl(sfb->regs + SHADOWCON);
> + data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index);
> + writel(data, sfb->regs + SHADOWCON);
> + }
> +
> + reg = readl(sfb->regs + WINCON(win->index));
> + writel(reg | WINCONx_ENWIN, sfb->regs + WINCON(win->index));
> + } else {
> + return -EINVAL;
> + }
> +
> + return ret;
> +}
> +
--
Maurus Cuelenaere
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 05/10 v2] s3c-fb: Add v4l2 subdevice to support framebuffer local fifo input path
2010-07-15 10:32 ` Maurus Cuelenaere
@ 2010-07-15 11:18 ` Sylwester Nawrocki
0 siblings, 0 replies; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-15 11:18 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
> -----Original Message-----
> From: linux-samsung-soc-owner at vger.kernel.org [mailto:linux-samsung-
> soc-owner at vger.kernel.org] On Behalf Of Maurus Cuelenaere
> Sent: Thursday, July 15, 2010 12:32 PM
> To: Sylwester Nawrocki
> Cc: linux-samsung-soc at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; p.osciak at samsung.com;
> m.szyprowski at samsung.com; kyungmin.park at samsung.com;
> kgene.kim at samsung.com; ben-linux at fluff.org; linux-fbdev at vger.kernel.org
> Subject: Re: [PATCH 05/10 v2] s3c-fb: Add v4l2 subdevice to support
> framebuffer local fifo input path
>
> Op 15-07-10 11:10, Sylwester Nawrocki schreef:
> > Selected multimedia devices in Samsung S3C/S5P SoC series are capable
> of
> > transferring data directly between each other, bypassing the main
> system
> > bus. Such a datapath exists between the camera interface/video
> > postprocessor and the lcd controller. To control the data flow from
> the
> > fimc driver level v4l2-subdevice driver is added to the framebuffer.
> > It enables to configure the lcd controller into FIFO or DMA input
> mode.
> >
> > Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> > ---
> > arch/arm/plat-samsung/include/plat/fb.h | 6 +
> > drivers/video/s3c-fb.c | 487
> +++++++++++++++++++++++++++++--
> > 2 files changed, 472 insertions(+), 21 deletions(-)
>
> <snip>
>
> > /**
> > + * s3c_fb_enable_local() - switch window between input DMA and fifo
> modes
> > + *
> > + * @fb_sd: window subdevice for fifo input
> > + * @en: 1 - switch from input DMA to fifo mode and apply
> > + * window size and position set by the window's subdevice
> > + * 0 - restore from fifo to DMA mode
> > + */
> > +static int s3c_fb_enable_local_in(struct s3c_fb_win_sd *fb_sd, int
> en)
> > +{
> > + struct s3c_fb_win *win = fb_sd->win;
> > + struct s3c_fb *sfb = win->parent;
> > + static u32 wincon;
> > + u32 reg, data;
> > + int ret = 0, bpp = 32;
> > +
> > + /* disable video output and the window logic */
> > + reg = readl(sfb->regs + WINCON(win->index));
> > + writel(reg & ~WINCONx_ENWIN, sfb->regs + WINCON(win->index));
> > +
> > + shadow_protect_win(win, 1);
> > +
> > + if (en == 1) {
> > + if (fb_sd->streaming)
> > + return 0;
>
> Shouldn't you do shadow_protect_win(win, 0) before returning here?
Yes, indeed the error path is wrong and also WINCONx_ENWIN
needs to be restored.
Thank you for pointing this out.
>
> > +
> > + wincon = reg;
> > +
> > + switch (fb_sd->fmt.fmt.pix.pixelformat) {
> > + case V4L2_PIX_FMT_YUYV: /* YCbCr 4:4:4 */
> > + reg |= WINCONx_YCbCr | WINCONx_ENLOCAL;
> > + bpp = 16;
> > + break;
> > +
> > + case V4L2_PIX_FMT_RGB24:
> > + default:
> > + reg &= ~(WINCONx_YCbCr | WINCONx_WSWP |
> WINCONx_HAWSWP |
> > + WINCONx_BYTSWP | WINCONx_BITSWP |
> > + WINCON0_BPPMODE_MASK | WINCONx_BURSTLEN_MASK);
> > +
> > + reg |= WINCON0_BPPMODE_24BPP_888 |
> > + WINCONx_BURSTLEN_4WORD;
> > + bpp = 24;
> > + break;
> > + }
> > +
> > + fb_sd->streaming = 1;
> > + writel(reg, sfb->regs + WINCON(win->index));
> > +
> > + s3c_fb_set_osd(fb_sd->win, &fb_sd->curr_osd_win, bpp);
> > +
> > + writel(reg | WINCONx_ENLOCAL, sfb->regs + WINCON(win-
> >index));
> > +
> > + shadow_protect_win(win, 0);
> > +
> > + reg = readl(sfb->regs + WINCON(win->index));
> > + writel(reg | WINCONx_ENWIN, sfb->regs + WINCON(win-
> >index));
> > +
> > + if (sfb->variant.has_shadowcon) {
> > + data = readl(sfb->regs + SHADOWCON);
> > + data |= SHADOWCON_CHx_LOCAL_ENABLE(win->index);
> > + writel(data, sfb->regs + SHADOWCON);
> > + }
> > +
> > + } else if (en == 0) {
> > + if (!fb_sd->streaming)
> > + return 0;
>
> Same comment
>
> > +
> > + fb_sd->streaming = 0;
> > +
> > + /* need to be aligned with VSYNC interrupt */
> > + writel(wincon & ~WINCONx_ENLOCAL,
> > + sfb->regs + WINCON(win->index));
> > +
> > + /* restore OSD values from before we enabled local mode */
> > + bpp = win->fbinfo->var.bits_per_pixel;
> > + s3c_fb_set_osd(fb_sd->win, &fb_sd->default_osd_win, bpp);
> > +
> > + shadow_protect_win(win, 0);
> > +
> > + if (sfb->variant.has_shadowcon) {
> > + data = readl(sfb->regs + SHADOWCON);
> > + data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index);
> > + writel(data, sfb->regs + SHADOWCON);
> > + }
> > +
> > + reg = readl(sfb->regs + WINCON(win->index));
> > + writel(reg | WINCONx_ENWIN, sfb->regs + WINCON(win-
> >index));
> > + } else {
> > + return -EINVAL;
> > + }
> > +
> > + return ret;
> > +}
> > +
>
> --
> Maurus Cuelenaere
Regards,
--
Sylwester Nawrocki
> --
> To unsubscribe from this list: send the line "unsubscribe linux-
> samsung-soc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and platform definitions
2010-07-15 9:10 ` [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and platform definitions Sylwester Nawrocki
@ 2010-07-16 9:44 ` Kukjin Kim
2010-07-16 13:30 ` Sylwester Nawrocki
0 siblings, 1 reply; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16 9:44 UTC (permalink / raw)
To: linux-arm-kernel
Sylwester Nawrocki wrote:
>
> FIMC device is a camera interface embedded in S3C/S5P Samsung SOC series.
> It supports ITU-R BT.601/656 and MIPI-CSI2 standards, memory to memory
> operations, color conversion, resizing and rotation.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> arch/arm/plat-samsung/include/plat/fimc.h | 31 ++
> arch/arm/plat-samsung/include/plat/regs-fimc.h | 361
> ++++++++++++++++++++++++
> 2 files changed, 392 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/plat-samsung/include/plat/fimc.h
> create mode 100644 arch/arm/plat-samsung/include/plat/regs-fimc.h
>
> diff --git a/arch/arm/plat-samsung/include/plat/fimc.h b/arch/arm/plat-
> samsung/include/plat/fimc.h
> new file mode 100644
> index 0000000..be1e853
> --- /dev/null
> +++ b/arch/arm/plat-samsung/include/plat/fimc.h
> @@ -0,0 +1,31 @@
> +/* linux/arch/arm/plat-samsung/include/plat/fimc.h
> + *
> + * Platform header file for FIMC driver
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * Sylwester Nawrocki, <s.nawrocki@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef FIMC_H_
> +#define FIMC_H_
> +
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +
> +
2 empty lines...
> +#define FIMC_MAX_FIFO_TARGETS 1
> +#define FIMC_LCD_FIFO_TARGET 0
> +
> +struct s3c_fifo_link;
> +
> +struct samsung_plat_fimc {
> + struct s3c_fifo_link *fifo_targets[FIMC_MAX_FIFO_TARGETS];
> +};
> +
> +#endif /* FIMC_H_ */
> +
No need last empty line...
> diff --git a/arch/arm/plat-samsung/include/plat/regs-fimc.h
b/arch/arm/plat-
> samsung/include/plat/regs-fimc.h
> new file mode 100644
> index 0000000..6946a93
> --- /dev/null
> +++ b/arch/arm/plat-samsung/include/plat/regs-fimc.h
> @@ -0,0 +1,361 @@
> +/* arch/arm/plat-s5p/include/plat/regs-fimc.h
> + *
> + * Register definition file for Samsung Camera Interface (FIMC) driver
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef REGS_FIMC_H_
> +#define REGS_FIMC_H_
> +
> +#define S5P_CIOYSA(__x) (0x18 + (__x) * 4)
> +#define S5P_CIOCBSA(__x) (0x28 + (__x) * 4)
> +#define S5P_CIOCRSA(__x) (0x38 + (__x) * 4)
> +
> +/* Input source format */
> +#define S5P_CISRCFMT 0x00
> +/* Window offset */
> +#define S5P_CIWDOFST 0x04
> +/* Global control */
> +#define S5P_CIGCTRL 0x08
> +/* Window offset 2 */
> +#define S5P_CIWDOFST2 0x14
> +/* Output DMA Y 1st frame start address */
> +#define S5P_CIOYSA1 0x18
> +/* Output DMA Y 2nd frame start address */
> +#define S5P_CIOYSA2 0x1c
> +/* Output DMA Y 3rd frame start address */
> +#define S5P_CIOYSA3 0x20
> +/* Output DMA Y 4th frame start address */
> +#define S5P_CIOYSA4 0x24
> +/* Output DMA Cb 1st frame start address */
> +#define S5P_CIOCBSA1 0x28
> +/* Output DMA Cb 2nd frame start address */
> +#define S5P_CIOCBSA2 0x2c
> +/* Output DMA Cb 3rd frame start address */
> +#define S5P_CIOCBSA3 0x30
> +/* Output DMA Cb 4th frame start address */
> +#define S5P_CIOCBSA4 0x34
> +/* Output DMA Cr 1st frame start address */
> +#define S5P_CIOCRSA1 0x38
> +/* Output DMA Cr 2nd frame start address */
> +#define S5P_CIOCRSA2 0x3c
> +/* Output DMA Cr 3rd frame start address */
> +#define S5P_CIOCRSA3 0x40
> +/* Output DMA Cr 4th frame start address */
> +#define S5P_CIOCRSA4 0x44
> +/* Target image format */
> +#define S5P_CITRGFMT 0x48
> +/* Output DMA control */
> +#define S5P_CIOCTRL 0x4c
> +/* Pre-scaler control 1 */
> +#define S5P_CISCPRERATIO 0x50
> +/* Pre-scaler control 2 */
> +#define S5P_CISCPREDST 0x54
> +/* Main scaler control */
> +#define S5P_CISCCTRL 0x58
> +/* Target area */
> +#define S5P_CITAREA 0x5c
> +/* Status */
> +#define S5P_CISTATUS 0x64
> +/* Image capture enable command */
> +#define S5P_CIIMGCPT 0xc0
> +/* Capture sequence */
> +#define S5P_CICPTSEQ 0xc4
> +/* Image effects */
> +#define S5P_CIIMGEFF 0xd0
> +/* Y frame start address for input DMA */
> +#define S5P_CIIYSA0 0xd4
> +/* Cb frame start address for input DMA */
> +#define S5P_CIICBSA0 0xd8
> +/* Cr frame start address for input DMA */
> +#define S5P_CIICRSA0 0xdc
> +/* Real input DMA image size */
> +#define S5P_CIREAL_ISIZE 0xf8
> +/* Input DMA control */
> +#define S5P_MSCTRL 0xfc
> +/* Y frame start address for input DMA */
> +#define S5P_CIIYSA1 0x144
> +/* Cb frame start address for input DMA */
> +#define S5P_CIICBSA1 0x148
> +/* Cr frame start address for input DMA */
> +#define S5P_CIICRSA1 0x14c
> +/* Output DMA Y offset */
> +#define S5P_CIOYOFF 0x168
> +/* Output DMA CB offset */
> +#define S5P_CIOCBOFF 0x16c
> +/* Output DMA CR offset */
> +#define S5P_CIOCROFF 0x170
> +/* Input DMA Y offset */
> +#define S5P_CIIYOFF 0x174
> +/* Input DMA CB offset */
> +#define S5P_CIICBOFF 0x178
> +/* Input DMA CR offset */
> +#define S5P_CIICROFF 0x17c
> +/* Input DMA original image size */
> +#define S5P_ORGISIZE 0x180
> +/* Output DMA original image size */
> +#define S5P_ORGOSIZE 0x184
> +/* Real output DMA image size */
> +#define S5P_CIEXTEN 0x188
> +/* DMA parameter */
> +#define S5P_CIDMAPARAM 0x18c
> +/* MIPI CSI image format */
> +#define S5P_CSIIMGFMT 0x194
> +
> +
2 empty lines?
> +#define S5P_CISRCFMT_SOURCEHSIZE(x) ((x) << 16)
> +#define S5P_CISRCFMT_SOURCEVSIZE(x) ((x) << 0)
> +
> +#define S5P_CIWDOFST_WINHOROFST(x) ((x) << 16)
> +#define S5P_CIWDOFST_WINVEROFST(x) ((x) << 0)
> +
> +#define S5P_CIWDOFST2_WINHOROFST2(x) ((x) << 16)
> +#define S5P_CIWDOFST2_WINVEROFST2(x) ((x) << 0)
> +
> +#define S5P_CITRGFMT_TARGETHSIZE(x) ((x) << 16)
> +#define S5P_CITRGFMT_TARGETVSIZE(x) ((x) << 0)
> +
> +#define S5P_CISCPRERATIO_SHFACTOR(x) ((x) << 28)
> +#define S5P_CISCPRERATIO_PREHORRATIO(x) ((x) << 16)
> +#define S5P_CISCPRERATIO_PREVERRATIO(x) ((x) << 0)
> +
> +#define S5P_CISCPREDST_PREDSTWIDTH(x) ((x) << 16)
> +#define S5P_CISCPREDST_PREDSTHEIGHT(x) ((x) << 0)
> +
> +#define S5P_CISCCTRL_MAINHORRATIO(x) ((x) << 16)
> +#define S5P_CISCCTRL_MAINVERRATIO(x) ((x) << 0)
> +
> +#define S5P_CITAREA_TARGET_AREA(x) ((x) << 0)
> +
> +#define S5P_CIIMGEFF_PAT_CB(x) ((x) << 13)
> +#define S5P_CIIMGEFF_PAT_CR(x) ((x) << 0)
> +
> +#define S5P_CIREAL_ISIZE_HEIGHT(x) ((x) << 16)
> +#define S5P_CIREAL_ISIZE_WIDTH(x) ((x) << 0)
> +
> +#define S5P_MSCTRL_SUCCESSIVE_COUNT(x) ((x) << 24)
> +
> +#define S5P_CIOYOFF_VERTICAL(x) ((x) << 16)
> +#define S5P_CIOYOFF_HORIZONTAL(x) ((x) << 0)
> +
> +#define S5P_CIOCBOFF_VERTICAL(x) ((x) << 16)
> +#define S5P_CIOCBOFF_HORIZONTAL(x) ((x) << 0)
> +
> +#define S5P_CIOCROFF_VERTICAL(x) ((x) << 16)
> +#define S5P_CIOCROFF_HORIZONTAL(x) ((x) << 0)
> +
> +#define S5P_CIIYOFF_VERTICAL(x) ((x) << 16)
> +#define S5P_CIIYOFF_HORIZONTAL(x) ((x) << 0)
> +
> +#define S5P_CIICBOFF_VERTICAL(x) ((x) << 16)
> +#define S5P_CIICBOFF_HORIZONTAL(x) ((x) << 0)
> +
> +#define S5P_CIICROFF_VERTICAL(x) ((x) << 16)
> +#define S5P_CIICROFF_HORIZONTAL(x) ((x) << 0)
> +
> +#define S5P_ORGISIZE_VERTICAL(x) ((x) << 16)
> +#define S5P_ORGISIZE_HORIZONTAL(x) ((x) << 0)
> +
> +#define S5P_ORGOSIZE_VERTICAL(x) ((x) << 16)
> +#define S5P_ORGOSIZE_HORIZONTAL(x) ((x) << 0)
> +
> +
Same...2 empty lines...
And above definitions used same bit shift...((x) << 16) or ((x) << 0)...
Hmm...I'm thinking...whether there is any method to reduce similar codes...
> +/* Register's bit definitions */
> +
> +/* Source format register */
> +#define S5P_CISRCFMT_ITU601_8BIT (1 << 31)
> +#define S5P_CISRCFMT_ITU656_8BIT (0 << 31)
> +#define S5P_CISRCFMT_ITU601_16BIT (1 << 29)
> +#define S5P_CISRCFMT_ORDER422_YCBYCR (0 << 14)
> +#define S5P_CISRCFMT_ORDER422_YCRYCB (1 << 14)
> +#define S5P_CISRCFMT_ORDER422_CBYCRY (2 << 14)
> +#define S5P_CISRCFMT_ORDER422_CRYCBY (3 << 14)
> +/* ITU601 16bit only */
> +#define S5P_CISRCFMT_ORDER422_Y4CBCRCBCR (0 << 14)
> +/* ITU601 16bit only */
Same comments... ITU601 16bit only...
> +#define S5P_CISRCFMT_ORDER422_Y4CRCBCRCB (1 << 14)
> +
> +/* Window offset register */
> +#define S5P_CIWDOFST_WINOFSEN (1 << 31)
> +#define S5P_CIWDOFST_CLROVFIY (1 << 30)
> +#define S5P_CIWDOFST_CLROVRLB (1 << 29)
> +#define S5P_CIWDOFST_WINHOROFST_MASK (0x7ff << 16)
> +#define S5P_CIWDOFST_CLROVFICB (1 << 15)
> +#define S5P_CIWDOFST_CLROVFICR (1 << 14)
> +#define S5P_CIWDOFST_WINVEROFST_MASK (0xfff << 0)
> +
> +/* Global control register */
> +#define S5P_CIGCTRL_SWRST (1 << 31)
> +#define S5P_CIGCTRL_CAMRST_A (1 << 30)
> +#define S5P_CIGCTRL_SELCAM_ITU_B (0 << 29)
> +#define S5P_CIGCTRL_SELCAM_ITU_A (1 << 29)
> +#define S5P_CIGCTRL_SELCAM_ITU_MASK (1 << 29)
> +#define S5P_CIGCTRL_TESTPAT_NORMAL (0 << 27)
> +#define S5P_CIGCTRL_TESTPAT_COLOR_BAR (1 << 27)
> +#define S5P_CIGCTRL_TESTPAT_HOR_INC (2 << 27)
> +#define S5P_CIGCTRL_TESTPAT_VER_INC (3 << 27)
> +#define S5P_CIGCTRL_TESTPAT_MASK (3 << 27)
> +#define S5P_CIGCTRL_TESTPAT_SHIFT (27)
> +#define S5P_CIGCTRL_INVPOLPCLK (1 << 26)
> +#define S5P_CIGCTRL_INVPOLVSYNC (1 << 25)
> +#define S5P_CIGCTRL_INVPOLHREF (1 << 24)
> +#define S5P_CIGCTRL_IRQ_OVFEN (1 << 22)
> +#define S5P_CIGCTRL_HREF_MASK (1 << 21)
> +#define S5P_CIGCTRL_IRQ_EDGE (0 << 20)
> +#define S5P_CIGCTRL_IRQ_LEVEL (1 << 20)
> +#define S5P_CIGCTRL_IRQ_CLR (1 << 19)
> +#define S5P_CIGCTRL_IRQ_DISABLE (0 << 16)
> +#define S5P_CIGCTRL_IRQ_ENABLE (1 << 16)
> +#define S5P_CIGCTRL_SHDW_DISABLE (1 << 12)
> +#define S5P_CIGCTRL_SELCAM_MIPI_B (0 << 7)
> +#define S5P_CIGCTRL_SELCAM_MIPI_A (1 << 7)
> +#define S5P_CIGCTRL_SELCAM_MIPI_MASK (1 << 7)
> +#define S5P_CIGCTRL_CAMIF_SELWB (1 << 6)
> +#define S5P_CIGCTRL_INVPOLHSYNC (1 << 4)
> +#define S5P_CIGCTRL_SELCAM_ITU (0 << 3)
> +#define S5P_CIGCTRL_SELCAM_MIPI (1 << 3)
> +#define S5P_CIGCTRL_PROGRESSIVE (0 << 0)
> +#define S5P_CIGCTRL_INTERLACE (1 << 0)
> +
> +/* Window offset2 register */
> +#define S5P_CIWDOFST_WINHOROFST2_MASK (0xfff << 16)
> +#define S5P_CIWDOFST_WINVEROFST2_MASK (0xfff << 16)
> +
> +/* Target format register */
> +#define S5P_CITRGFMT_INROT90 (1 << 31)
> +#define S5P_CITRGFMT_OUTFORMAT_YCBCR420 (0 << 29)
> +#define S5P_CITRGFMT_OUTFORMAT_YCBCR422 (1 << 29)
> +#define S5P_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE (2 << 29)
> +#define S5P_CITRGFMT_OUTFORMAT_RGB (3 << 29)
> +#define S5P_CITRGFMT_OUT_FMT_MASK (3 << 29)
> +#define S5P_CITRGFMT_HSIZE_MASK (0xfff << 16)
> +#define S5P_CITRGFMT_FLIP_SHIFT (14)
> +#define S5P_CITRGFMT_FLIP_NORMAL (0 << 14)
> +#define S5P_CITRGFMT_FLIP_X_MIRROR (1 << 14)
> +#define S5P_CITRGFMT_FLIP_Y_MIRROR (2 << 14)
> +#define S5P_CITRGFMT_FLIP_180 (3 << 14)
> +#define S5P_CITRGFMT_FLIP_MASK (3 << 14)
> +#define S5P_CITRGFMT_OUTROT90 (1 << 13)
> +#define S5P_CITRGFMT_VSIZE_MASK (0xfff << 0)
> +
> +/* Output DMA control register */
> +#define S5P_CIOCTRL_ORDER422_MASK (3 << 0)
> +#define S5P_CIOCTRL_ORDER422_CRYCBY (0 << 0)
> +#define S5P_CIOCTRL_ORDER422_YCRYCB (1 << 0)
> +#define S5P_CIOCTRL_ORDER422_CBYCRY (2 << 0)
> +#define S5P_CIOCTRL_ORDER422_YCBYCR (3 << 0)
> +#define S5P_CIOCTRL_LASTIRQ_ENABLE (1 << 2)
> +#define S5P_CIOCTRL_YCBCR_3PLANE (0 << 3)
> +#define S5P_CIOCTRL_YCBCR_2PLANE (1 << 3)
> +#define S5P_CIOCTRL_YCBCR_PLANE_MASK (1 << 3)
> +#define S5P_CIOCTRL_ORDER2P_SHIFT (24)
> +#define S5P_CIOCTRL_ORDER2P_MASK (3 << 24)
> +#define S5P_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24)
> +
> +
2 empty lines...
> +/* Main scaler control register */
> +#define S5P_CISCCTRL_SCALERBYPASS (1 << 31)
> +#define S5P_CISCCTRL_SCALEUP_H (1 << 30)
> +#define S5P_CISCCTRL_SCALEUP_V (1 << 29)
> +#define S5P_CISCCTRL_CSCR2Y_NARROW (0 << 28)
> +#define S5P_CISCCTRL_CSCR2Y_WIDE (1 << 28)
> +#define S5P_CISCCTRL_CSCY2R_NARROW (0 << 27)
> +#define S5P_CISCCTRL_CSCY2R_WIDE (1 << 27)
> +#define S5P_CISCCTRL_LCDPATHEN_FIFO (1 << 26)
> +#define S5P_CISCCTRL_PROGRESSIVE (0 << 25)
> +#define S5P_CISCCTRL_INTERLACE (1 << 25)
> +#define S5P_CISCCTRL_SCALERSTART (1 << 15)
> +#define S5P_CISCCTRL_INRGB_FMT_RGB565 (0 << 13)
> +#define S5P_CISCCTRL_INRGB_FMT_RGB666 (1 << 13)
> +#define S5P_CISCCTRL_INRGB_FMT_RGB888 (2 << 13)
> +#define S5P_CISCCTRL_INRGB_FMT_MASK (3 << 13)
> +#define S5P_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11)
> +#define S5P_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11)
> +#define S5P_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11)
> +#define S5P_CISCCTRL_OUTRGB_FMT_MASK (3 << 11)
> +#define S5P_CISCCTRL_EXTRGB_NORMAL (0 << 10)
> +#define S5P_CISCCTRL_EXTRGB_EXTENSION (1 << 10)
> +#define S5P_CISCCTRL_ONE2ONE (1 << 9)
> +
> +/* Status register */
> +#define S5P_CISTATUS_OVFIY (1 << 31)
> +#define S5P_CISTATUS_OVFICB (1 << 30)
> +#define S5P_CISTATUS_OVFICR (1 << 29)
> +#define S5P_CISTATUS_VSYNC (1 << 28)
> +#define S5P_CISTATUS_WINOFSTEN (1 << 25)
> +#define S5P_CISTATUS_IMGCPTEN (1 << 22)
> +#define S5P_CISTATUS_IMGCPTENSC (1 << 21)
> +#define S5P_CISTATUS_VSYNC_A (1 << 20)
> +#define S5P_CISTATUS_VSYNC_B (1 << 19)
> +#define S5P_CISTATUS_OVRLB (1 << 18)
> +#define S5P_CISTATUS_FRAMEEND (1 << 17)
> +#define S5P_CISTATUS_LASTCAPTUREEND (1 << 16)
> +#define S5P_CISTATUS_VVALID_A (1 << 15)
> +#define S5P_CISTATUS_VVALID_B (1 << 14)
> +
> +/* Image capture enable register */
> +#define S5P_CIIMGCPT_IMGCPTEN (1 << 31)
> +#define S5P_CIIMGCPT_IMGCPTEN_SC (1 << 30)
> +#define S5P_CIIMGCPT_CPT_FREN_ENABLE (1 << 25)
> +#define S5P_CIIMGCPT_CPT_FRMOD_EN (0 << 18)
> +#define S5P_CIIMGCPT_CPT_FRMOD_CNT (1 << 18)
> +
> +/* Image effects register */
> +#define S5P_CIIMGEFF_IE_DISABLE (0 << 30)
> +#define S5P_CIIMGEFF_IE_ENABLE (1 << 30)
> +#define S5P_CIIMGEFF_IE_SC_BEFORE (0 << 29)
> +#define S5P_CIIMGEFF_IE_SC_AFTER (1 << 29)
> +#define S5P_CIIMGEFF_FIN_BYPASS (0 << 26)
> +#define S5P_CIIMGEFF_FIN_ARBITRARY (1 << 26)
> +#define S5P_CIIMGEFF_FIN_NEGATIVE (2 << 26)
> +#define S5P_CIIMGEFF_FIN_ARTFREEZE (3 << 26)
> +#define S5P_CIIMGEFF_FIN_EMBOSSING (4 << 26)
> +#define S5P_CIIMGEFF_FIN_SILHOUETTE (5 << 26)
> +#define S5P_CIIMGEFF_FIN_MASK (7 << 26)
> +#define S5P_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff <
> 0))
> +
> +/* Real input DMA size register */
> +#define S5P_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31)
> +#define S5P_CIREAL_ISIZE_ADDR_CH_DISABLE (1 << 30)
> +
> +/* Input DMA control register */
> +#define S5P_MSCTRL_IN_BURST_COUNT_MASK (3 << 24)
> +#define S5P_MSCTRL_2P_IN_ORDER_MASK (3 << 16)
> +#define S5P_MSCTRL_2P_IN_ORDER_SHIFT (16)
> +#define S5P_MSCTRL_C_INT_IN_3PLANE (0 << 15)
> +#define S5P_MSCTRL_C_INT_IN_2PLANE (1 << 15)
> +#define S5P_MSCTRL_C_INT_IN_MASK (1 << 15)
> +#define S5P_MSCTRL_FLIP_SHIFT (13)
> +#define S5P_MSCTRL_FLIP_MASK (3 << 13)
> +#define S5P_MSCTRL_FLIP_NORMAL (0 << 13)
> +#define S5P_MSCTRL_FLIP_X_MIRROR (1 << 13)
> +#define S5P_MSCTRL_FLIP_Y_MIRROR (2 << 13)
> +#define S5P_MSCTRL_FLIP_180 (3 << 13)
> +#define S5P_MSCTRL_ORDER422_SHIFT (4)
> +#define S5P_MSCTRL_ORDER422_CRYCBY (0 << 4)
> +#define S5P_MSCTRL_ORDER422_YCRYCB (1 << 4)
> +#define S5P_MSCTRL_ORDER422_CBYCRY (2 << 4)
> +#define S5P_MSCTRL_ORDER422_YCBYCR (3 << 4)
> +#define S5P_MSCTRL_ORDER422_MASK (3 << 4)
> +#define S5P_MSCTRL_INPUT_EXTCAM (0 << 3)
> +#define S5P_MSCTRL_INPUT_MEMORY (1 << 3)
> +#define S5P_MSCTRL_INPUT_MASK (1 << 3)
> +#define S5P_MSCTRL_INFORMAT_YCBCR420 (0 << 1)
> +#define S5P_MSCTRL_INFORMAT_YCBCR422 (1 << 1)
> +#define S5P_MSCTRL_INFORMAT_YCBCR422_1PLANE (2 << 1)
> +#define S5P_MSCTRL_INFORMAT_RGB (3 << 1)
> +#define S5P_MSCTRL_INFORMAT_MASK (3 << 1)
> +#define S5P_MSCTRL_ENVID (1 << 0)
> +
> +/* DMA parameter register */
> +#define S5P_CIDMAPARAM_R_MODE_64X32 (3 << 29)
> +#define S5P_CIDMAPARAM_W_MODE_LINEAR (0 << 13)
> +#define S5P_CIDMAPARAM_W_MODE_CONFTILE (1 << 13)
> +#define S5P_CIDMAPARAM_W_MODE_64X32 (3 << 13)
> +
> +#endif /* REGS_FIMC_H_ */
> --
I wonder...we really need above every definitions?
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 02/10 v2] ARM: Samsung: Add FIMC resource definition and FIMC driver platform helpers
2010-07-15 9:10 ` [PATCH 02/10 v2] ARM: Samsung: Add FIMC resource definition and FIMC driver platform helpers Sylwester Nawrocki
@ 2010-07-16 10:07 ` Kukjin Kim
2010-07-16 14:27 ` Sylwester Nawrocki
0 siblings, 1 reply; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16 10:07 UTC (permalink / raw)
To: linux-arm-kernel
Sylwester Nawrocki wrote:
>
> Add camera interface SoC resource definitions and setup code
> for FIMC/FB fifo links.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> arch/arm/mach-s5pc100/Kconfig | 15 ++++++
> arch/arm/mach-s5pc100/Makefile | 3 +
> arch/arm/mach-s5pc100/include/mach/map.h | 8 +++
> arch/arm/mach-s5pc100/setup-fimc0.c | 14 ++++++
> arch/arm/mach-s5pc100/setup-fimc1.c | 14 ++++++
> arch/arm/mach-s5pc100/setup-fimc2.c | 14 ++++++
> arch/arm/mach-s5pv210/Kconfig | 15 ++++++
> arch/arm/mach-s5pv210/Makefile | 3 +
> arch/arm/mach-s5pv210/cpu.c | 5 ++
> arch/arm/mach-s5pv210/include/mach/map.h | 8 +++
> arch/arm/mach-s5pv210/setup-fimc0.c | 14 ++++++
> arch/arm/mach-s5pv210/setup-fimc1.c | 14 ++++++
> arch/arm/mach-s5pv210/setup-fimc2.c | 14 ++++++
> arch/arm/plat-s5p/Kconfig | 16 +++++++
> arch/arm/plat-s5p/Makefile | 3 +
> arch/arm/plat-s5p/dev-fimc0.c | 56
> ++++++++++++++++++++++++
> arch/arm/plat-s5p/dev-fimc1.c | 55
> +++++++++++++++++++++++
> arch/arm/plat-s5p/dev-fimc2.c | 55
> +++++++++++++++++++++++
> arch/arm/plat-samsung/include/plat/fimc-core.h | 45 +++++++++++++++++++
> arch/arm/plat-samsung/include/plat/fimc.h | 12 +++++
> 20 files changed, 383 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/mach-s5pc100/setup-fimc0.c
> create mode 100644 arch/arm/mach-s5pc100/setup-fimc1.c
> create mode 100644 arch/arm/mach-s5pc100/setup-fimc2.c
> create mode 100644 arch/arm/mach-s5pv210/setup-fimc0.c
> create mode 100644 arch/arm/mach-s5pv210/setup-fimc1.c
> create mode 100644 arch/arm/mach-s5pv210/setup-fimc2.c
> create mode 100644 arch/arm/plat-s5p/dev-fimc0.c
> create mode 100644 arch/arm/plat-s5p/dev-fimc1.c
> create mode 100644 arch/arm/plat-s5p/dev-fimc2.c
> create mode 100644 arch/arm/plat-samsung/include/plat/fimc-core.h
>
> diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
> index d421f80..791270d 100644
> --- a/arch/arm/mach-s5pc100/Kconfig
> +++ b/arch/arm/mach-s5pc100/Kconfig
> @@ -36,6 +36,21 @@ config S5PC100_SETUP_SDHCI_GPIO
> help
> Common setup code for SDHCI gpio.
>
> +config S5PC100_SETUP_FIMC0
> + bool
> + help
> + Setup code for FIMC controller 0
> +
> +config S5PC100_SETUP_FIMC1
> + bool
> + help
> + Setup code for FIMC controller 1
> +
> +config S5PC100_SETUP_FIMC2
> + bool
> + help
> + Setup code for FIMC controller 2
> +
> config MACH_SMDKC100
> bool "SMDKC100"
> select CPU_S5PC100
> diff --git a/arch/arm/mach-s5pc100/Makefile
b/arch/arm/mach-s5pc100/Makefile
> index f2073bc..7b43337 100644
> --- a/arch/arm/mach-s5pc100/Makefile
> +++ b/arch/arm/mach-s5pc100/Makefile
> @@ -25,6 +25,9 @@ obj-$(CONFIG_S5PC100_SETUP_SDHCI_GPIO) += setup-
> sdhci-gpio.o
> # device support
> obj-y += dev-audio.o
> obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
> +obj-$(CONFIG_S5PC100_SETUP_FIMC0) += setup-fimc0.o
> +obj-$(CONFIG_S5PC100_SETUP_FIMC1) += setup-fimc1.o
> +obj-$(CONFIG_S5PC100_SETUP_FIMC2) += setup-fimc2.o
>
> # machine support
>
> diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-
> s5pc100/include/mach/map.h
> index c025064..a1c6f22 100644
> --- a/arch/arm/mach-s5pc100/include/mach/map.h
> +++ b/arch/arm/mach-s5pc100/include/mach/map.h
> @@ -112,6 +112,11 @@
> #define S5PC100_PA_SDRAM (0x30000000)
> #define S5P_PA_SDRAM S5PC100_PA_SDRAM
>
> +/* FIMC */
> +#define S5PC100_PA_FIMC0 (0xEE200000)
> +#define S5PC100_PA_FIMC1 (0xEE300000)
> +#define S5PC100_PA_FIMC2 (0xEE400000)
> +
> /* compatibiltiy defines. */
> #define S3C_PA_UART S5PC100_PA_UART
> #define S3C_PA_IIC S5PC100_PA_IIC0
> @@ -134,5 +139,8 @@
> #define S3C_PA_ONENAND S5PC100_PA_ONENAND
> #define S3C_PA_ONENAND_BUF S5PC100_PA_ONENAND_BUF
> #define S3C_SZ_ONENAND_BUF S5PC100_SZ_ONENAND_BUF
> +#define S5P_PA_FIMC0 S5PC100_PA_FIMC0
> +#define S5P_PA_FIMC1 S5PC100_PA_FIMC1
> +#define S5P_PA_FIMC2 S5PC100_PA_FIMC2
>
> #endif /* __ASM_ARCH_C100_MAP_H */
> diff --git a/arch/arm/mach-s5pc100/setup-fimc0.c
b/arch/arm/mach-s5pc100/setup-
> fimc0.c
> new file mode 100644
> index 0000000..dea33c2
> --- /dev/null
> +++ b/arch/arm/mach-s5pc100/setup-fimc0.c
> @@ -0,0 +1,14 @@
> +/* linux/arch/arm/mach-s5pc100/setup-fimc0.c
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * S5PC100 - setup for S5P FIMC device 0
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <plat/fimc.h>
> +
> +struct samsung_plat_fimc s5p_fimc0_default_data __initdata = {};
> diff --git a/arch/arm/mach-s5pc100/setup-fimc1.c
b/arch/arm/mach-s5pc100/setup-
> fimc1.c
> new file mode 100644
> index 0000000..1833377
> --- /dev/null
> +++ b/arch/arm/mach-s5pc100/setup-fimc1.c
> @@ -0,0 +1,14 @@
> +/* linux/arch/arm/mach-s5pc100/setup-fimc1.c
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * S5PC100 - setup for S5P FIMC device 1
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <plat/fimc.h>
> +
> +struct samsung_plat_fimc s5p_fimc1_default_data __initdata = {};
> diff --git a/arch/arm/mach-s5pc100/setup-fimc2.c
b/arch/arm/mach-s5pc100/setup-
> fimc2.c
> new file mode 100644
> index 0000000..746e0f0
> --- /dev/null
> +++ b/arch/arm/mach-s5pc100/setup-fimc2.c
> @@ -0,0 +1,14 @@
> +/* linux/arch/arm/mach-s5pc100/setup-fimc2.c
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * S5PC100 - setup for S5P FIMC device 2
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <plat/fimc.h>
> +
> +struct samsung_plat_fimc s5p_fimc2_default_data __initdata = {};
> diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
> index d876ff0..4bb5a85 100644
> --- a/arch/arm/mach-s5pv210/Kconfig
> +++ b/arch/arm/mach-s5pv210/Kconfig
> @@ -32,6 +32,21 @@ config S5PV210_SETUP_FB_24BPP
> help
> Common setup code for S5PV210 with an 24bpp RGB display helper.
>
> +config S5PV210_SETUP_FIMC0
> + bool
> + help
> + Setup code for FIMC controller 0
> +
> +config S5PV210_SETUP_FIMC1
> + bool
> + help
> + Setup code for FIMC controller 1
> +
> +config S5PV210_SETUP_FIMC2
> + bool
> + help
> + Setup code for FIMC controller 2
> +
> config S5PV210_SETUP_SDHCI
> bool
> select S5PV210_SETUP_SDHCI_GPIO
> diff --git a/arch/arm/mach-s5pv210/Makefile
b/arch/arm/mach-s5pv210/Makefile
> index 7b3a984..6eceeb8 100644
> --- a/arch/arm/mach-s5pv210/Makefile
> +++ b/arch/arm/mach-s5pv210/Makefile
> @@ -35,3 +35,6 @@ obj-$(CONFIG_S5PV210_SETUP_I2C1) += setup-i2c1.o
> obj-$(CONFIG_S5PV210_SETUP_I2C2) += setup-i2c2.o
> obj-$(CONFIG_S5PV210_SETUP_SDHCI) += setup-sdhci.o
> obj-$(CONFIG_S5PV210_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
> +obj-$(CONFIG_S5PV210_SETUP_FIMC0) += setup-fimc0.o
> +obj-$(CONFIG_S5PV210_SETUP_FIMC1) += setup-fimc1.o
> +obj-$(CONFIG_S5PV210_SETUP_FIMC2) += setup-fimc2.o
> diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
> index fc3801b..4133cae 100644
> --- a/arch/arm/mach-s5pv210/cpu.c
> +++ b/arch/arm/mach-s5pv210/cpu.c
> @@ -35,6 +35,7 @@
> #include <plat/iic-core.h>
> #include <plat/sdhci.h>
> #include <plat/fb-core.h>
> +#include <plat/fimc-core.h>
>
> /* Initial IO mappings */
>
> @@ -95,6 +96,10 @@ void __init s5pv210_map_io(void)
> s3c_i2c2_setname("s3c2440-i2c");
>
> s3c_fb_setname("s5pv210-fb");
> +
> + s3c_fimc_setname(0, "s5pv210-fimc");
> + s3c_fimc_setname(1, "s5pv210-fimc");
> + s3c_fimc_setname(2, "s5pv210-fimc");
> }
>
> void __init s5pv210_init_clocks(int xtal)
> diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-
> s5pv210/include/mach/map.h
> index e78bd47..9b8cf69 100644
> --- a/arch/arm/mach-s5pv210/include/mach/map.h
> +++ b/arch/arm/mach-s5pv210/include/mach/map.h
> @@ -96,6 +96,11 @@
>
> #define S5PV210_PA_ADC (0xE1700000)
>
> +/* FIMC */
> +#define S5PV210_PA_FIMC0 (0xFB200000)
> +#define S5PV210_PA_FIMC1 (0xFB300000)
> +#define S5PV210_PA_FIMC2 (0xFB400000)
> +
> /* compatibiltiy defines. */
> #define S3C_PA_UART S5PV210_PA_UART
> #define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0)
> @@ -111,5 +116,8 @@
> #define SAMSUNG_PA_ADC S5PV210_PA_ADC
> #define S3C_PA_USB_HSOTG S5PV210_PA_USB_HSOTG
> #define S3C_PA_USB_HSPHY S5PV210_PA_USB_HSPHY
> +#define S5P_PA_FIMC0 S5PV210_PA_FIMC0
> +#define S5P_PA_FIMC1 S5PV210_PA_FIMC1
> +#define S5P_PA_FIMC2 S5PV210_PA_FIMC2
>
> #endif /* __ASM_ARCH_MAP_H */
> diff --git a/arch/arm/mach-s5pv210/setup-fimc0.c
b/arch/arm/mach-s5pv210/setup-
> fimc0.c
> new file mode 100644
> index 0000000..0e5ef0a
> --- /dev/null
> +++ b/arch/arm/mach-s5pv210/setup-fimc0.c
> @@ -0,0 +1,14 @@
> +/* linux/arch/arm/mach-s5pv210/setup-fimc0.c
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * S5PV210 - setup for S5P FIMC device 0
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <plat/fimc.h>
> +
> +struct samsung_plat_fimc s5p_fimc0_default_data __initdata = {};
> diff --git a/arch/arm/mach-s5pv210/setup-fimc1.c
b/arch/arm/mach-s5pv210/setup-
> fimc1.c
> new file mode 100644
> index 0000000..80da0e7
> --- /dev/null
> +++ b/arch/arm/mach-s5pv210/setup-fimc1.c
> @@ -0,0 +1,14 @@
> +/* linux/arch/arm/mach-s5pv210/setup-fimc1.c
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * S5PV210 - setup for S5P FIMC device 1
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <plat/fimc.h>
> +
> +struct samsung_plat_fimc s5p_fimc1_default_data __initdata = {};
> diff --git a/arch/arm/mach-s5pv210/setup-fimc2.c
b/arch/arm/mach-s5pv210/setup-
> fimc2.c
> new file mode 100644
> index 0000000..bc6a27b
> --- /dev/null
> +++ b/arch/arm/mach-s5pv210/setup-fimc2.c
> @@ -0,0 +1,14 @@
> +/* linux/arch/arm/mach-s5pv210/setup-fimc2.c
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * S5PV210 - setup for S5P FIMC device 2
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <plat/fimc.h>
> +
> +struct samsung_plat_fimc s5p_fimc2_default_data __initdata = {};
> diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
> index 11d6a1b..38b60c7 100644
> --- a/arch/arm/plat-s5p/Kconfig
> +++ b/arch/arm/plat-s5p/Kconfig
> @@ -5,6 +5,22 @@
> #
> # Licensed under GPLv2
>
> +config S5P_DEV_FIMC0
> + bool
> + help
> + Compile in platform device definitions for FIMC controller 0
> +
> +config S5P_DEV_FIMC1
> + bool
> + help
> + Compile in platform device definitions for FIMC controller 1
> +
> +config S5P_DEV_FIMC2
> + bool
> + help
> + Compile in platform device definitions for FIMC controller 2
> +
> +
2 empty lines...
> config PLAT_S5P
> bool
> depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 ||
> ARCH_S5PV210)
> diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
> index b56b4d3..a7d3c35 100644
> --- a/arch/arm/plat-s5p/Makefile
> +++ b/arch/arm/plat-s5p/Makefile
> @@ -18,3 +18,6 @@ obj-y += clock.o
> obj-y += irq.o irq-gpioint.o
> obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o
>
> +obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o
> +obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o
> +obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o
> diff --git a/arch/arm/plat-s5p/dev-fimc0.c b/arch/arm/plat-s5p/dev-fimc0.c
> new file mode 100644
> index 0000000..cfa10f0
> --- /dev/null
> +++ b/arch/arm/plat-s5p/dev-fimc0.c
> @@ -0,0 +1,56 @@
> +/* linux/arch/arm/plat-s5p/dev-fimc0.c
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * Base S5P FIMC0 resource and device definitions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <linux/platform_device.h>
> +#include <mach/map.h>
> +#include <mach/irqs.h>
> +#include <plat/fimc.h>
> +#include <plat/devs.h>
> +#include <plat/cpu.h>
> +
> +
Same...2 empty lines...
> +static struct resource s5p_fimc_resource[] = {
> + [0] = {
> + .start = S5P_PA_FIMC0,
> + .end = S5P_PA_FIMC0 + SZ_1M - 1,
> + .flags = IORESOURCE_MEM,
> + },
> + [1] = {
> + .start = IRQ_FIMC0,
> + .end = IRQ_FIMC0,
> + .flags = IORESOURCE_IRQ,
> + },
> +};
> +
> +struct platform_device s5p_device_fimc0 = {
> + .name = "s5p-fimc",
> + .id = 0,
> + .num_resources = ARRAY_SIZE(s5p_fimc_resource),
> + .resource = s5p_fimc_resource,
> +};
> +
> +
2 empty lines...
> +void __init s5p_fimc0_set_platdata(struct samsung_plat_fimc *pd)
Actually, we can use Ben's 's3c_set_platdata' which can replace a number of
sites...
Please refer to below URL.
http://lists.infradead.org/pipermail/linux-arm-kernel/2010-May/016650.html
I think this method is better to us.
> +{
> + struct samsung_plat_fimc *npd;
> +
> + if (!pd)
> + pd = &s5p_fimc0_default_data;
> +
> + npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
> + if (!npd)
> + printk(KERN_ERR "%s: out of memory\n", __func__);
> +
> + s5p_device_fimc0.dev.platform_data = npd;
> +}
> +
No need last empty line
> diff --git a/arch/arm/plat-s5p/dev-fimc1.c b/arch/arm/plat-s5p/dev-fimc1.c
> new file mode 100644
> index 0000000..7178477
> --- /dev/null
> +++ b/arch/arm/plat-s5p/dev-fimc1.c
> @@ -0,0 +1,55 @@
> +/* linux/arch/arm/plat-s5p/dev-fimc1.c
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * Base S5P FIMC1 resource and device definitions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <linux/platform_device.h>
> +#include <mach/map.h>
> +#include <mach/irqs.h>
> +#include <plat/fimc.h>
> +#include <plat/devs.h>
> +#include <plat/cpu.h>
> +
> +
2 empty lines..
> +static struct resource s5p_fimc_resource[] = {
> + [0] = {
> + .start = S5P_PA_FIMC1,
> + .end = S5P_PA_FIMC1 + SZ_1M - 1,
> + .flags = IORESOURCE_MEM,
> + },
> + [1] = {
> + .start = IRQ_FIMC1,
> + .end = IRQ_FIMC1,
> + .flags = IORESOURCE_IRQ,
> + },
> +};
> +
> +struct platform_device s5p_device_fimc1 = {
> + .name = "s5p-fimc",
> + .id = 1,
> + .num_resources = ARRAY_SIZE(s5p_fimc_resource),
> + .resource = s5p_fimc_resource,
> +};
> +
> +void __init s5p_fimc1_set_platdata(struct samsung_plat_fimc *pd)
> +{
> + struct samsung_plat_fimc *npd;
> +
> + if (!pd)
> + pd = &s5p_fimc1_default_data;
> +
> + npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
> + if (!npd)
> + printk(KERN_ERR "%s: out of memory\n", __func__);
> +
> + s5p_device_fimc1.dev.platform_data = npd;
> +}
> +
No need last empty line...
> diff --git a/arch/arm/plat-s5p/dev-fimc2.c b/arch/arm/plat-s5p/dev-fimc2.c
> new file mode 100644
> index 0000000..fe1a6c0
> --- /dev/null
> +++ b/arch/arm/plat-s5p/dev-fimc2.c
> @@ -0,0 +1,55 @@
> +/* linux/arch/arm/plat-s5p/dev-fimc2.c
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * Base S5P FIMC2 resource and device definitions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <linux/platform_device.h>
> +#include <mach/map.h>
> +#include <mach/irqs.h>
> +#include <plat/fimc.h>
> +#include <plat/devs.h>
> +#include <plat/cpu.h>
> +
> +
Same...
> +static struct resource s5p_fimc_resource[] = {
> + [0] = {
> + .start = S5P_PA_FIMC2,
> + .end = S5P_PA_FIMC2 + SZ_1M - 1,
> + .flags = IORESOURCE_MEM,
> + },
> + [1] = {
> + .start = IRQ_FIMC2,
> + .end = IRQ_FIMC2,
> + .flags = IORESOURCE_IRQ,
> + },
> +};
> +
> +struct platform_device s5p_device_fimc2 = {
> + .name = "s5p-fimc",
> + .id = 2,
> + .num_resources = ARRAY_SIZE(s5p_fimc_resource),
> + .resource = s5p_fimc_resource,
> +};
> +
> +void __init s5p_fimc2_set_platdata(struct samsung_plat_fimc *pd)
> +{
> + struct samsung_plat_fimc *npd;
> +
> + if (!pd)
> + pd = &s5p_fimc2_default_data;
> +
> + npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
> + if (!npd)
> + printk(KERN_ERR "%s: out of memory\n", __func__);
> +
> + s5p_device_fimc2.dev.platform_data = npd;
> +}
> +
Same..
> diff --git a/arch/arm/plat-samsung/include/plat/fimc-core.h
b/arch/arm/plat-
> samsung/include/plat/fimc-core.h
> new file mode 100644
> index 0000000..a126bbd
> --- /dev/null
> +++ b/arch/arm/plat-samsung/include/plat/fimc-core.h
> @@ -0,0 +1,45 @@
> +/*
> + * arch/arm/plat-samsung/include/plat/fimc-core.h
> + *
> + * Copyright 2010 Samsung Electronics Co., Ltd.
> + * Sylwester Nawrocki <s.nawrocki@samsung.com>
> + *
> + * Samsung camera interface driver core functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#ifndef __ASM_PLAT_FIMC_CORE_H
> +#define __ASM_PLAT_FIMC_CORE_H __FILE__
> +
> +/*
> + * These functions are only for use with the core support code, such as
> + * the CPU-specific initialization code.
> + */
> +
> +#include <plat/fimc.h>
> +
> +/* Re-define device name to differentiate the subsystem in various SoCs.
*/
> +static inline void s3c_fimc_setname(int id, char *name)
> +{
> + switch(id) {
> +#ifdef CONFIG_S5P_DEV_FIMC0
> + case 0:
> + s5p_device_fimc0.name = name;
> + break;
> +#endif
> +#ifdef CONFIG_S5P_DEV_FIMC1
> + case 1:
> + s5p_device_fimc1.name = name;
> + break;
> +#endif
> +#ifdef CONFIG_S5P_DEV_FIMC2
> + case 2:
> + s5p_device_fimc2.name = name;
> + break;
> +#endif
> + }
> +}
> +
> +#endif /* __ASM_PLAT_FIMC_CORE_H */
> diff --git a/arch/arm/plat-samsung/include/plat/fimc.h b/arch/arm/plat-
> samsung/include/plat/fimc.h
> index be1e853..cf7d2fb 100644
> --- a/arch/arm/plat-samsung/include/plat/fimc.h
> +++ b/arch/arm/plat-samsung/include/plat/fimc.h
> @@ -27,5 +27,17 @@ struct samsung_plat_fimc {
> struct s3c_fifo_link *fifo_targets[FIMC_MAX_FIFO_TARGETS];
> };
>
> +extern struct platform_device s5p_device_fimc0;
> +extern struct platform_device s5p_device_fimc1;
> +extern struct platform_device s5p_device_fimc2;
> +
> +extern struct samsung_plat_fimc s5p_fimc0_default_data;
> +extern struct samsung_plat_fimc s5p_fimc1_default_data;
> +extern struct samsung_plat_fimc s5p_fimc2_default_data;
> +
> +extern void s5p_fimc0_set_platdata(struct samsung_plat_fimc *fimc);
> +extern void s5p_fimc1_set_platdata(struct samsung_plat_fimc *fimc);
> +extern void s5p_fimc2_set_platdata(struct samsung_plat_fimc *fimc);
> +
> #endif /* FIMC_H_ */
>
> --
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 04/10 v2] v4l: Add Samsung FIMC (video postprocessor) driver
2010-07-15 9:10 ` [PATCH 04/10 v2] v4l: Add Samsung FIMC (video postprocessor) driver Sylwester Nawrocki
@ 2010-07-16 11:39 ` Kukjin Kim
2010-07-16 16:33 ` Sylwester Nawrocki
0 siblings, 1 reply; 21+ messages in thread
From: Kukjin Kim @ 2010-07-16 11:39 UTC (permalink / raw)
To: linux-arm-kernel
Sylwester Nawrocki wrote:
>
Hi,
Samsung S.LSI hardly recommends DMA mode to implement the feature not FIFO
mode because of H/W limitation.
> This driver exports two video device nodes per each FIMC device,
> one for for memory to memory (color conversion, image resizing,
> flipping and rotation) operations and one for direct
> V4L2 output interface to framebuffer.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Reviewed-by: Pawel Osciak <p.osciak@samsung.com>
> Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
> drivers/media/video/Kconfig | 20 +
> drivers/media/video/Makefile | 1 +
> drivers/media/video/samsung/fimc/Makefile | 3 +
> drivers/media/video/samsung/fimc/fimc-core.c | 1664
> ++++++++++++++++++++++++++
> drivers/media/video/samsung/fimc/fimc-core.h | 541 +++++++++
> drivers/media/video/samsung/fimc/fimc-fifo.c | 814 +++++++++++++
> drivers/media/video/samsung/fimc/fimc-reg.c | 585 +++++++++
> include/linux/videodev2.h | 1 +
> 8 files changed, 3629 insertions(+), 0 deletions(-)
> create mode 100644 drivers/media/video/samsung/fimc/Makefile
> create mode 100644 drivers/media/video/samsung/fimc/fimc-core.c
> create mode 100644 drivers/media/video/samsung/fimc/fimc-core.h
> create mode 100644 drivers/media/video/samsung/fimc/fimc-fifo.c
> create mode 100644 drivers/media/video/samsung/fimc/fimc-reg.c
>
(snip)
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and platform definitions
2010-07-16 9:44 ` Kukjin Kim
@ 2010-07-16 13:30 ` Sylwester Nawrocki
2010-07-16 13:35 ` Maurus Cuelenaere
0 siblings, 1 reply; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-16 13:30 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
thank you for the review. Please se my comments below.
> -----Original Message-----
> From: Kukjin Kim [mailto:kgene.kim at samsung.com]
> Sent: Friday, July 16, 2010 11:45 AM
> To: 'Sylwester Nawrocki'; linux-samsung-soc at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org
> Cc: p.osciak at samsung.com; m.szyprowski at samsung.com;
> kyungmin.park at samsung.com; linux-media at vger.kernel.org
> Subject: RE: [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and
> platform definitions
>
> Sylwester Nawrocki wrote:
> >
> > FIMC device is a camera interface embedded in S3C/S5P Samsung SOC
> series.
> > It supports ITU-R BT.601/656 and MIPI-CSI2 standards, memory to
> memory
> > operations, color conversion, resizing and rotation.
> >
> > Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > ---
> > arch/arm/plat-samsung/include/plat/fimc.h | 31 ++
> > arch/arm/plat-samsung/include/plat/regs-fimc.h | 361
> > ++++++++++++++++++++++++
> > 2 files changed, 392 insertions(+), 0 deletions(-)
> > create mode 100644 arch/arm/plat-samsung/include/plat/fimc.h
> > create mode 100644 arch/arm/plat-samsung/include/plat/regs-fimc.h
> >
> > diff --git a/arch/arm/plat-samsung/include/plat/fimc.h
> b/arch/arm/plat-
> > samsung/include/plat/fimc.h
> > new file mode 100644
> > index 0000000..be1e853
> > --- /dev/null
> > +++ b/arch/arm/plat-samsung/include/plat/fimc.h
> > @@ -0,0 +1,31 @@
> > +/* linux/arch/arm/plat-samsung/include/plat/fimc.h
> > + *
> > + * Platform header file for FIMC driver
> > + *
> > + * Copyright (c) 2010 Samsung Electronics
> > + *
> > + * Sylwester Nawrocki, <s.nawrocki@samsung.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#ifndef FIMC_H_
> > +#define FIMC_H_
> > +
> > +#include <linux/device.h>
> > +#include <linux/platform_device.h>
> > +
> > +
>
> 2 empty lines...
I don't mind at all changing these to single line if it is
the adopted style, however I didn't file like so when looking
through the existing headers.
>
> > +#define FIMC_MAX_FIFO_TARGETS 1
> > +#define FIMC_LCD_FIFO_TARGET 0
> > +
> > +struct s3c_fifo_link;
> > +
> > +struct samsung_plat_fimc {
> > + struct s3c_fifo_link *fifo_targets[FIMC_MAX_FIFO_TARGETS];
> > +};
> > +
> > +#endif /* FIMC_H_ */
> > +
>
> No need last empty line...
C89 and C99 standard requires a new line character at the end of file.
The compiler should issue a warning when the new line character
at the end of file is missing, otherwise it is not compliant with
the above C standards.
So I would rather add a new line where it is missing rather than
removing it.
There is lots of header files already in arch/arm/plat-samsung where
there is even more than one empty line at the end of file.
>
> > diff --git a/arch/arm/plat-samsung/include/plat/regs-fimc.h
> b/arch/arm/plat-
> > samsung/include/plat/regs-fimc.h
> > new file mode 100644
> > index 0000000..6946a93
> > --- /dev/null
> > +++ b/arch/arm/plat-samsung/include/plat/regs-fimc.h
> > @@ -0,0 +1,361 @@
> > +/* arch/arm/plat-s5p/include/plat/regs-fimc.h
> > + *
> > + * Register definition file for Samsung Camera Interface (FIMC)
> driver
> > + *
> > + * Copyright (c) 2010 Samsung Electronics
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#ifndef REGS_FIMC_H_
> > +#define REGS_FIMC_H_
> > +
> > +#define S5P_CIOYSA(__x) (0x18 + (__x) * 4)
> > +#define S5P_CIOCBSA(__x) (0x28 + (__x) * 4)
> > +#define S5P_CIOCRSA(__x) (0x38 + (__x) * 4)
> > +
> > +/* Input source format */
> > +#define S5P_CISRCFMT 0x00
> > +/* Window offset */
> > +#define S5P_CIWDOFST 0x04
> > +/* Global control */
> > +#define S5P_CIGCTRL 0x08
> > +/* Window offset 2 */
> > +#define S5P_CIWDOFST2 0x14
> > +/* Output DMA Y 1st frame start address */
> > +#define S5P_CIOYSA1 0x18
> > +/* Output DMA Y 2nd frame start address */
> > +#define S5P_CIOYSA2 0x1c
> > +/* Output DMA Y 3rd frame start address */
> > +#define S5P_CIOYSA3 0x20
> > +/* Output DMA Y 4th frame start address */
> > +#define S5P_CIOYSA4 0x24
> > +/* Output DMA Cb 1st frame start address */
> > +#define S5P_CIOCBSA1 0x28
> > +/* Output DMA Cb 2nd frame start address */
> > +#define S5P_CIOCBSA2 0x2c
> > +/* Output DMA Cb 3rd frame start address */
> > +#define S5P_CIOCBSA3 0x30
> > +/* Output DMA Cb 4th frame start address */
> > +#define S5P_CIOCBSA4 0x34
> > +/* Output DMA Cr 1st frame start address */
> > +#define S5P_CIOCRSA1 0x38
> > +/* Output DMA Cr 2nd frame start address */
> > +#define S5P_CIOCRSA2 0x3c
> > +/* Output DMA Cr 3rd frame start address */
> > +#define S5P_CIOCRSA3 0x40
> > +/* Output DMA Cr 4th frame start address */
> > +#define S5P_CIOCRSA4 0x44
> > +/* Target image format */
> > +#define S5P_CITRGFMT 0x48
> > +/* Output DMA control */
> > +#define S5P_CIOCTRL 0x4c
> > +/* Pre-scaler control 1 */
> > +#define S5P_CISCPRERATIO 0x50
> > +/* Pre-scaler control 2 */
> > +#define S5P_CISCPREDST 0x54
> > +/* Main scaler control */
> > +#define S5P_CISCCTRL 0x58
> > +/* Target area */
> > +#define S5P_CITAREA 0x5c
> > +/* Status */
> > +#define S5P_CISTATUS 0x64
> > +/* Image capture enable command */
> > +#define S5P_CIIMGCPT 0xc0
> > +/* Capture sequence */
> > +#define S5P_CICPTSEQ 0xc4
> > +/* Image effects */
> > +#define S5P_CIIMGEFF 0xd0
> > +/* Y frame start address for input DMA */
> > +#define S5P_CIIYSA0 0xd4
> > +/* Cb frame start address for input DMA */
> > +#define S5P_CIICBSA0 0xd8
> > +/* Cr frame start address for input DMA */
> > +#define S5P_CIICRSA0 0xdc
> > +/* Real input DMA image size */
> > +#define S5P_CIREAL_ISIZE 0xf8
> > +/* Input DMA control */
> > +#define S5P_MSCTRL 0xfc
> > +/* Y frame start address for input DMA */
> > +#define S5P_CIIYSA1 0x144
> > +/* Cb frame start address for input DMA */
> > +#define S5P_CIICBSA1 0x148
> > +/* Cr frame start address for input DMA */
> > +#define S5P_CIICRSA1 0x14c
> > +/* Output DMA Y offset */
> > +#define S5P_CIOYOFF 0x168
> > +/* Output DMA CB offset */
> > +#define S5P_CIOCBOFF 0x16c
> > +/* Output DMA CR offset */
> > +#define S5P_CIOCROFF 0x170
> > +/* Input DMA Y offset */
> > +#define S5P_CIIYOFF 0x174
> > +/* Input DMA CB offset */
> > +#define S5P_CIICBOFF 0x178
> > +/* Input DMA CR offset */
> > +#define S5P_CIICROFF 0x17c
> > +/* Input DMA original image size */
> > +#define S5P_ORGISIZE 0x180
> > +/* Output DMA original image size */
> > +#define S5P_ORGOSIZE 0x184
> > +/* Real output DMA image size */
> > +#define S5P_CIEXTEN 0x188
> > +/* DMA parameter */
> > +#define S5P_CIDMAPARAM 0x18c
> > +/* MIPI CSI image format */
> > +#define S5P_CSIIMGFMT 0x194
> > +
> > +
>
> 2 empty lines?
>
> > +#define S5P_CISRCFMT_SOURCEHSIZE(x) ((x) << 16)
> > +#define S5P_CISRCFMT_SOURCEVSIZE(x) ((x) << 0)
> > +
> > +#define S5P_CIWDOFST_WINHOROFST(x) ((x) << 16)
> > +#define S5P_CIWDOFST_WINVEROFST(x) ((x) << 0)
> > +
> > +#define S5P_CIWDOFST2_WINHOROFST2(x) ((x) << 16)
> > +#define S5P_CIWDOFST2_WINVEROFST2(x) ((x) << 0)
> > +
> > +#define S5P_CITRGFMT_TARGETHSIZE(x) ((x) << 16)
> > +#define S5P_CITRGFMT_TARGETVSIZE(x) ((x) << 0)
> > +
> > +#define S5P_CISCPRERATIO_SHFACTOR(x) ((x) << 28)
> > +#define S5P_CISCPRERATIO_PREHORRATIO(x) ((x) << 16)
> > +#define S5P_CISCPRERATIO_PREVERRATIO(x) ((x) << 0)
> > +
> > +#define S5P_CISCPREDST_PREDSTWIDTH(x) ((x) << 16)
> > +#define S5P_CISCPREDST_PREDSTHEIGHT(x) ((x) << 0)
> > +
> > +#define S5P_CISCCTRL_MAINHORRATIO(x) ((x) << 16)
> > +#define S5P_CISCCTRL_MAINVERRATIO(x) ((x) << 0)
> > +
> > +#define S5P_CITAREA_TARGET_AREA(x) ((x) << 0)
> > +
> > +#define S5P_CIIMGEFF_PAT_CB(x) ((x) << 13)
> > +#define S5P_CIIMGEFF_PAT_CR(x) ((x) << 0)
> > +
> > +#define S5P_CIREAL_ISIZE_HEIGHT(x) ((x) << 16)
> > +#define S5P_CIREAL_ISIZE_WIDTH(x) ((x) << 0)
> > +
> > +#define S5P_MSCTRL_SUCCESSIVE_COUNT(x) ((x) << 24)
> > +
> > +#define S5P_CIOYOFF_VERTICAL(x) ((x) << 16)
> > +#define S5P_CIOYOFF_HORIZONTAL(x) ((x) << 0)
> > +
> > +#define S5P_CIOCBOFF_VERTICAL(x) ((x) << 16)
> > +#define S5P_CIOCBOFF_HORIZONTAL(x) ((x) << 0)
> > +
> > +#define S5P_CIOCROFF_VERTICAL(x) ((x) << 16)
> > +#define S5P_CIOCROFF_HORIZONTAL(x) ((x) << 0)
> > +
> > +#define S5P_CIIYOFF_VERTICAL(x) ((x) << 16)
> > +#define S5P_CIIYOFF_HORIZONTAL(x) ((x) << 0)
> > +
> > +#define S5P_CIICBOFF_VERTICAL(x) ((x) << 16)
> > +#define S5P_CIICBOFF_HORIZONTAL(x) ((x) << 0)
> > +
> > +#define S5P_CIICROFF_VERTICAL(x) ((x) << 16)
> > +#define S5P_CIICROFF_HORIZONTAL(x) ((x) << 0)
> > +
> > +#define S5P_ORGISIZE_VERTICAL(x) ((x) << 16)
> > +#define S5P_ORGISIZE_HORIZONTAL(x) ((x) << 0)
> > +
> > +#define S5P_ORGOSIZE_VERTICAL(x) ((x) << 16)
> > +#define S5P_ORGOSIZE_HORIZONTAL(x) ((x) << 0)
> > +
> > +
>
> Same...2 empty lines...
>
> And above definitions used same bit shift...((x) << 16) or ((x) <<
> 0)...
> Hmm...I'm thinking...whether there is any method to reduce similar
> codes...
OK, I will just define 2 generic macros for these DMA offsets
and possibly other two for the sizes. However when the shifts are
changed in the future SoC versions we will have to go back to
separate definitions per each register and modify the driver again.
>
> > +/* Register's bit definitions */
> > +
> > +/* Source format register */
> > +#define S5P_CISRCFMT_ITU601_8BIT (1 << 31)
> > +#define S5P_CISRCFMT_ITU656_8BIT (0 << 31)
> > +#define S5P_CISRCFMT_ITU601_16BIT (1 << 29)
> > +#define S5P_CISRCFMT_ORDER422_YCBYCR (0 << 14)
> > +#define S5P_CISRCFMT_ORDER422_YCRYCB (1 << 14)
> > +#define S5P_CISRCFMT_ORDER422_CBYCRY (2 << 14)
> > +#define S5P_CISRCFMT_ORDER422_CRYCBY (3 << 14)
> > +/* ITU601 16bit only */
> > +#define S5P_CISRCFMT_ORDER422_Y4CBCRCBCR (0 << 14)
> > +/* ITU601 16bit only */
>
> Same comments... ITU601 16bit only...
>
> > +#define S5P_CISRCFMT_ORDER422_Y4CRCBCRCB (1 << 14)
> > +
> > +/* Window offset register */
> > +#define S5P_CIWDOFST_WINOFSEN (1 << 31)
> > +#define S5P_CIWDOFST_CLROVFIY (1 << 30)
> > +#define S5P_CIWDOFST_CLROVRLB (1 << 29)
> > +#define S5P_CIWDOFST_WINHOROFST_MASK (0x7ff << 16)
> > +#define S5P_CIWDOFST_CLROVFICB (1 << 15)
> > +#define S5P_CIWDOFST_CLROVFICR (1 << 14)
> > +#define S5P_CIWDOFST_WINVEROFST_MASK (0xfff << 0)
> > +
> > +/* Global control register */
> > +#define S5P_CIGCTRL_SWRST (1 << 31)
> > +#define S5P_CIGCTRL_CAMRST_A (1 << 30)
> > +#define S5P_CIGCTRL_SELCAM_ITU_B (0 << 29)
> > +#define S5P_CIGCTRL_SELCAM_ITU_A (1 << 29)
> > +#define S5P_CIGCTRL_SELCAM_ITU_MASK (1 << 29)
> > +#define S5P_CIGCTRL_TESTPAT_NORMAL (0 << 27)
> > +#define S5P_CIGCTRL_TESTPAT_COLOR_BAR (1 << 27)
> > +#define S5P_CIGCTRL_TESTPAT_HOR_INC (2 << 27)
> > +#define S5P_CIGCTRL_TESTPAT_VER_INC (3 << 27)
> > +#define S5P_CIGCTRL_TESTPAT_MASK (3 << 27)
> > +#define S5P_CIGCTRL_TESTPAT_SHIFT (27)
> > +#define S5P_CIGCTRL_INVPOLPCLK (1 << 26)
> > +#define S5P_CIGCTRL_INVPOLVSYNC (1 << 25)
> > +#define S5P_CIGCTRL_INVPOLHREF (1 << 24)
> > +#define S5P_CIGCTRL_IRQ_OVFEN (1 << 22)
> > +#define S5P_CIGCTRL_HREF_MASK (1 << 21)
> > +#define S5P_CIGCTRL_IRQ_EDGE (0 << 20)
> > +#define S5P_CIGCTRL_IRQ_LEVEL (1 << 20)
> > +#define S5P_CIGCTRL_IRQ_CLR (1 << 19)
> > +#define S5P_CIGCTRL_IRQ_DISABLE (0 << 16)
> > +#define S5P_CIGCTRL_IRQ_ENABLE (1 << 16)
> > +#define S5P_CIGCTRL_SHDW_DISABLE (1 << 12)
> > +#define S5P_CIGCTRL_SELCAM_MIPI_B (0 << 7)
> > +#define S5P_CIGCTRL_SELCAM_MIPI_A (1 << 7)
> > +#define S5P_CIGCTRL_SELCAM_MIPI_MASK (1 << 7)
> > +#define S5P_CIGCTRL_CAMIF_SELWB (1 << 6)
> > +#define S5P_CIGCTRL_INVPOLHSYNC (1 << 4)
> > +#define S5P_CIGCTRL_SELCAM_ITU (0 << 3)
> > +#define S5P_CIGCTRL_SELCAM_MIPI (1 << 3)
> > +#define S5P_CIGCTRL_PROGRESSIVE (0 << 0)
> > +#define S5P_CIGCTRL_INTERLACE (1 << 0)
> > +
> > +/* Window offset2 register */
> > +#define S5P_CIWDOFST_WINHOROFST2_MASK (0xfff << 16)
> > +#define S5P_CIWDOFST_WINVEROFST2_MASK (0xfff << 16)
> > +
> > +/* Target format register */
> > +#define S5P_CITRGFMT_INROT90 (1 << 31)
> > +#define S5P_CITRGFMT_OUTFORMAT_YCBCR420 (0 << 29)
> > +#define S5P_CITRGFMT_OUTFORMAT_YCBCR422 (1 << 29)
> > +#define S5P_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE (2 << 29)
> > +#define S5P_CITRGFMT_OUTFORMAT_RGB (3 << 29)
> > +#define S5P_CITRGFMT_OUT_FMT_MASK (3 << 29)
> > +#define S5P_CITRGFMT_HSIZE_MASK (0xfff << 16)
> > +#define S5P_CITRGFMT_FLIP_SHIFT (14)
> > +#define S5P_CITRGFMT_FLIP_NORMAL (0 << 14)
> > +#define S5P_CITRGFMT_FLIP_X_MIRROR (1 << 14)
> > +#define S5P_CITRGFMT_FLIP_Y_MIRROR (2 << 14)
> > +#define S5P_CITRGFMT_FLIP_180 (3 << 14)
> > +#define S5P_CITRGFMT_FLIP_MASK (3 << 14)
> > +#define S5P_CITRGFMT_OUTROT90 (1 << 13)
> > +#define S5P_CITRGFMT_VSIZE_MASK (0xfff << 0)
> > +
> > +/* Output DMA control register */
> > +#define S5P_CIOCTRL_ORDER422_MASK (3 << 0)
> > +#define S5P_CIOCTRL_ORDER422_CRYCBY (0 << 0)
> > +#define S5P_CIOCTRL_ORDER422_YCRYCB (1 << 0)
> > +#define S5P_CIOCTRL_ORDER422_CBYCRY (2 << 0)
> > +#define S5P_CIOCTRL_ORDER422_YCBYCR (3 << 0)
> > +#define S5P_CIOCTRL_LASTIRQ_ENABLE (1 << 2)
> > +#define S5P_CIOCTRL_YCBCR_3PLANE (0 << 3)
> > +#define S5P_CIOCTRL_YCBCR_2PLANE (1 << 3)
> > +#define S5P_CIOCTRL_YCBCR_PLANE_MASK (1 << 3)
> > +#define S5P_CIOCTRL_ORDER2P_SHIFT (24)
> > +#define S5P_CIOCTRL_ORDER2P_MASK (3 << 24)
> > +#define S5P_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24)
> > +
> > +
>
> 2 empty lines...
>
> > +/* Main scaler control register */
> > +#define S5P_CISCCTRL_SCALERBYPASS (1 << 31)
> > +#define S5P_CISCCTRL_SCALEUP_H (1 << 30)
> > +#define S5P_CISCCTRL_SCALEUP_V (1 << 29)
> > +#define S5P_CISCCTRL_CSCR2Y_NARROW (0 << 28)
> > +#define S5P_CISCCTRL_CSCR2Y_WIDE (1 << 28)
> > +#define S5P_CISCCTRL_CSCY2R_NARROW (0 << 27)
> > +#define S5P_CISCCTRL_CSCY2R_WIDE (1 << 27)
> > +#define S5P_CISCCTRL_LCDPATHEN_FIFO (1 << 26)
> > +#define S5P_CISCCTRL_PROGRESSIVE (0 << 25)
> > +#define S5P_CISCCTRL_INTERLACE (1 << 25)
> > +#define S5P_CISCCTRL_SCALERSTART (1 << 15)
> > +#define S5P_CISCCTRL_INRGB_FMT_RGB565 (0 << 13)
> > +#define S5P_CISCCTRL_INRGB_FMT_RGB666 (1 << 13)
> > +#define S5P_CISCCTRL_INRGB_FMT_RGB888 (2 << 13)
> > +#define S5P_CISCCTRL_INRGB_FMT_MASK (3 << 13)
> > +#define S5P_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11)
> > +#define S5P_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11)
> > +#define S5P_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11)
> > +#define S5P_CISCCTRL_OUTRGB_FMT_MASK (3 << 11)
> > +#define S5P_CISCCTRL_EXTRGB_NORMAL (0 << 10)
> > +#define S5P_CISCCTRL_EXTRGB_EXTENSION (1 << 10)
> > +#define S5P_CISCCTRL_ONE2ONE (1 << 9)
> > +
> > +/* Status register */
> > +#define S5P_CISTATUS_OVFIY (1 << 31)
> > +#define S5P_CISTATUS_OVFICB (1 << 30)
> > +#define S5P_CISTATUS_OVFICR (1 << 29)
> > +#define S5P_CISTATUS_VSYNC (1 << 28)
> > +#define S5P_CISTATUS_WINOFSTEN (1 << 25)
> > +#define S5P_CISTATUS_IMGCPTEN (1 << 22)
> > +#define S5P_CISTATUS_IMGCPTENSC (1 << 21)
> > +#define S5P_CISTATUS_VSYNC_A (1 << 20)
> > +#define S5P_CISTATUS_VSYNC_B (1 << 19)
> > +#define S5P_CISTATUS_OVRLB (1 << 18)
> > +#define S5P_CISTATUS_FRAMEEND (1 << 17)
> > +#define S5P_CISTATUS_LASTCAPTUREEND (1 << 16)
> > +#define S5P_CISTATUS_VVALID_A (1 << 15)
> > +#define S5P_CISTATUS_VVALID_B (1 << 14)
> > +
> > +/* Image capture enable register */
> > +#define S5P_CIIMGCPT_IMGCPTEN (1 << 31)
> > +#define S5P_CIIMGCPT_IMGCPTEN_SC (1 << 30)
> > +#define S5P_CIIMGCPT_CPT_FREN_ENABLE (1 << 25)
> > +#define S5P_CIIMGCPT_CPT_FRMOD_EN (0 << 18)
> > +#define S5P_CIIMGCPT_CPT_FRMOD_CNT (1 << 18)
> > +
> > +/* Image effects register */
> > +#define S5P_CIIMGEFF_IE_DISABLE (0 << 30)
> > +#define S5P_CIIMGEFF_IE_ENABLE (1 << 30)
> > +#define S5P_CIIMGEFF_IE_SC_BEFORE (0 << 29)
> > +#define S5P_CIIMGEFF_IE_SC_AFTER (1 << 29)
> > +#define S5P_CIIMGEFF_FIN_BYPASS (0 << 26)
> > +#define S5P_CIIMGEFF_FIN_ARBITRARY (1 << 26)
> > +#define S5P_CIIMGEFF_FIN_NEGATIVE (2 << 26)
> > +#define S5P_CIIMGEFF_FIN_ARTFREEZE (3 << 26)
> > +#define S5P_CIIMGEFF_FIN_EMBOSSING (4 << 26)
> > +#define S5P_CIIMGEFF_FIN_SILHOUETTE (5 << 26)
> > +#define S5P_CIIMGEFF_FIN_MASK (7 << 26)
> > +#define S5P_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff <
> > 0))
> > +
> > +/* Real input DMA size register */
> > +#define S5P_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31)
> > +#define S5P_CIREAL_ISIZE_ADDR_CH_DISABLE (1 << 30)
> > +
> > +/* Input DMA control register */
> > +#define S5P_MSCTRL_IN_BURST_COUNT_MASK (3 << 24)
> > +#define S5P_MSCTRL_2P_IN_ORDER_MASK (3 << 16)
> > +#define S5P_MSCTRL_2P_IN_ORDER_SHIFT (16)
> > +#define S5P_MSCTRL_C_INT_IN_3PLANE (0 << 15)
> > +#define S5P_MSCTRL_C_INT_IN_2PLANE (1 << 15)
> > +#define S5P_MSCTRL_C_INT_IN_MASK (1 << 15)
> > +#define S5P_MSCTRL_FLIP_SHIFT (13)
> > +#define S5P_MSCTRL_FLIP_MASK (3 << 13)
> > +#define S5P_MSCTRL_FLIP_NORMAL (0 << 13)
> > +#define S5P_MSCTRL_FLIP_X_MIRROR (1 << 13)
> > +#define S5P_MSCTRL_FLIP_Y_MIRROR (2 << 13)
> > +#define S5P_MSCTRL_FLIP_180 (3 << 13)
> > +#define S5P_MSCTRL_ORDER422_SHIFT (4)
> > +#define S5P_MSCTRL_ORDER422_CRYCBY (0 << 4)
> > +#define S5P_MSCTRL_ORDER422_YCRYCB (1 << 4)
> > +#define S5P_MSCTRL_ORDER422_CBYCRY (2 << 4)
> > +#define S5P_MSCTRL_ORDER422_YCBYCR (3 << 4)
> > +#define S5P_MSCTRL_ORDER422_MASK (3 << 4)
> > +#define S5P_MSCTRL_INPUT_EXTCAM (0 << 3)
> > +#define S5P_MSCTRL_INPUT_MEMORY (1 << 3)
> > +#define S5P_MSCTRL_INPUT_MASK (1 << 3)
> > +#define S5P_MSCTRL_INFORMAT_YCBCR420 (0 << 1)
> > +#define S5P_MSCTRL_INFORMAT_YCBCR422 (1 << 1)
> > +#define S5P_MSCTRL_INFORMAT_YCBCR422_1PLANE (2 << 1)
> > +#define S5P_MSCTRL_INFORMAT_RGB (3 << 1)
> > +#define S5P_MSCTRL_INFORMAT_MASK (3 << 1)
> > +#define S5P_MSCTRL_ENVID (1 << 0)
> > +
> > +/* DMA parameter register */
> > +#define S5P_CIDMAPARAM_R_MODE_64X32 (3 << 29)
> > +#define S5P_CIDMAPARAM_W_MODE_LINEAR (0 << 13)
> > +#define S5P_CIDMAPARAM_W_MODE_CONFTILE (1 << 13)
> > +#define S5P_CIDMAPARAM_W_MODE_64X32 (3 << 13)
> > +
> > +#endif /* REGS_FIMC_H_ */
> > --
> I wonder...we really need above every definitions?
I think I could get rid of some of them. But I was not sure
whether it is better to define all available bit fields at once
or rather only those used by the current driver, and then
re-submit what is missing.
Anyway I will try to remove as many as possible statements that
define a single bit position with 1 and 0.
>
> Thanks.
>
> Best regards,
> Kgene.
> --
> Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
> SW Solution Development Team, Samsung Electronics Co., Ltd.
Kind regards,
Sylwester
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and platform definitions
2010-07-16 13:30 ` Sylwester Nawrocki
@ 2010-07-16 13:35 ` Maurus Cuelenaere
2010-07-16 14:47 ` Sylwester Nawrocki
0 siblings, 1 reply; 21+ messages in thread
From: Maurus Cuelenaere @ 2010-07-16 13:35 UTC (permalink / raw)
To: linux-arm-kernel
Op 16-07-10 15:30, Sylwester Nawrocki schreef:
> Hi,
>
> thank you for the review. Please se my comments below.
>
>> -----Original Message-----
>> From: Kukjin Kim [mailto:kgene.kim at samsung.com]
>> Sent: Friday, July 16, 2010 11:45 AM
>> To: 'Sylwester Nawrocki'; linux-samsung-soc at vger.kernel.org; linux-arm-
>> kernel at lists.infradead.org
>> Cc: p.osciak at samsung.com; m.szyprowski at samsung.com;
>> kyungmin.park at samsung.com; linux-media at vger.kernel.org
>> Subject: RE: [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and
>> platform definitions
>>
>> Sylwester Nawrocki wrote:
>>> FIMC device is a camera interface embedded in S3C/S5P Samsung SOC
>> series.
>>> It supports ITU-R BT.601/656 and MIPI-CSI2 standards, memory to
>> memory
>>> operations, color conversion, resizing and rotation.
>>>
>>> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
>>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>>> ---
>>> arch/arm/plat-samsung/include/plat/fimc.h | 31 ++
>>> arch/arm/plat-samsung/include/plat/regs-fimc.h | 361
>>> ++++++++++++++++++++++++
>>> 2 files changed, 392 insertions(+), 0 deletions(-)
>>> create mode 100644 arch/arm/plat-samsung/include/plat/fimc.h
>>> create mode 100644 arch/arm/plat-samsung/include/plat/regs-fimc.h
>>>
>>> diff --git a/arch/arm/plat-samsung/include/plat/fimc.h
>> b/arch/arm/plat-
>>> samsung/include/plat/fimc.h
>>> new file mode 100644
>>> index 0000000..be1e853
>>> --- /dev/null
>>> +++ b/arch/arm/plat-samsung/include/plat/fimc.h
>>> @@ -0,0 +1,31 @@
>>> +/* linux/arch/arm/plat-samsung/include/plat/fimc.h
>>> + *
>>> + * Platform header file for FIMC driver
>>> + *
>>> + * Copyright (c) 2010 Samsung Electronics
>>> + *
>>> + * Sylwester Nawrocki, <s.nawrocki@samsung.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or
>> modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + */
>>> +
>>> +#ifndef FIMC_H_
>>> +#define FIMC_H_
>>> +
>>> +#include <linux/device.h>
>>> +#include <linux/platform_device.h>
>>> +
>>> +
>> 2 empty lines...
> I don't mind at all changing these to single line if it is
> the adopted style, however I didn't file like so when looking
> through the existing headers.
>
>>> +#define FIMC_MAX_FIFO_TARGETS 1
>>> +#define FIMC_LCD_FIFO_TARGET 0
>>> +
>>> +struct s3c_fifo_link;
>>> +
>>> +struct samsung_plat_fimc {
>>> + struct s3c_fifo_link *fifo_targets[FIMC_MAX_FIFO_TARGETS];
>>> +};
>>> +
>>> +#endif /* FIMC_H_ */
>>> +
>> No need last empty line...
> C89 and C99 standard requires a new line character at the end of file.
> The compiler should issue a warning when the new line character
> at the end of file is missing, otherwise it is not compliant with
> the above C standards.
> So I would rather add a new line where it is missing rather than
> removing it.
> There is lots of header files already in arch/arm/plat-samsung where
> there is even more than one empty line at the end of file.
AFAIK there *already is* an empty line, git just omits it in diffs.
Try removing the last line with your editor and see what git diff gives, it'll
show "\ No newline at end of file".
--
Maurus Cuelenaere
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 02/10 v2] ARM: Samsung: Add FIMC resource definition and FIMC driver platform helpers
2010-07-16 10:07 ` Kukjin Kim
@ 2010-07-16 14:27 ` Sylwester Nawrocki
0 siblings, 0 replies; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-16 14:27 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
> -----Original Message-----
> From: Kukjin Kim [mailto:kgene.kim at samsung.com]
> Sent: Friday, July 16, 2010 12:08 PM
> To: 'Sylwester Nawrocki'; linux-samsung-soc at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org
> Cc: p.osciak at samsung.com; m.szyprowski at samsung.com;
> kyungmin.park at samsung.com
> Subject: RE: [PATCH 02/10 v2] ARM: Samsung: Add FIMC resource
> definition and FIMC driver platform helpers
>
> Sylwester Nawrocki wrote:
> >
> > Add camera interface SoC resource definitions and setup code
> > for FIMC/FB fifo links.
> >
> > Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > ---
> > arch/arm/mach-s5pc100/Kconfig | 15 ++++++
> > arch/arm/mach-s5pc100/Makefile | 3 +
> > arch/arm/mach-s5pc100/include/mach/map.h | 8 +++
> > arch/arm/mach-s5pc100/setup-fimc0.c | 14 ++++++
> > arch/arm/mach-s5pc100/setup-fimc1.c | 14 ++++++
> > arch/arm/mach-s5pc100/setup-fimc2.c | 14 ++++++
> > arch/arm/mach-s5pv210/Kconfig | 15 ++++++
> > arch/arm/mach-s5pv210/Makefile | 3 +
> > arch/arm/mach-s5pv210/cpu.c | 5 ++
> > arch/arm/mach-s5pv210/include/mach/map.h | 8 +++
> > arch/arm/mach-s5pv210/setup-fimc0.c | 14 ++++++
> > arch/arm/mach-s5pv210/setup-fimc1.c | 14 ++++++
> > arch/arm/mach-s5pv210/setup-fimc2.c | 14 ++++++
> > arch/arm/plat-s5p/Kconfig | 16 +++++++
> > arch/arm/plat-s5p/Makefile | 3 +
> > arch/arm/plat-s5p/dev-fimc0.c | 56
> > ++++++++++++++++++++++++
> > arch/arm/plat-s5p/dev-fimc1.c | 55
> > +++++++++++++++++++++++
> > arch/arm/plat-s5p/dev-fimc2.c | 55
> > +++++++++++++++++++++++
> > arch/arm/plat-samsung/include/plat/fimc-core.h | 45
> +++++++++++++++++++
> > arch/arm/plat-samsung/include/plat/fimc.h | 12 +++++
> > 20 files changed, 383 insertions(+), 0 deletions(-)
> > create mode 100644 arch/arm/mach-s5pc100/setup-fimc0.c
> > create mode 100644 arch/arm/mach-s5pc100/setup-fimc1.c
> > create mode 100644 arch/arm/mach-s5pc100/setup-fimc2.c
> > create mode 100644 arch/arm/mach-s5pv210/setup-fimc0.c
> > create mode 100644 arch/arm/mach-s5pv210/setup-fimc1.c
> > create mode 100644 arch/arm/mach-s5pv210/setup-fimc2.c
> > create mode 100644 arch/arm/plat-s5p/dev-fimc0.c
> > create mode 100644 arch/arm/plat-s5p/dev-fimc1.c
> > create mode 100644 arch/arm/plat-s5p/dev-fimc2.c
> > create mode 100644 arch/arm/plat-samsung/include/plat/fimc-core.h
> >
<snip>
> > +config S5P_DEV_FIMC2
> > + bool
> > + help
> > + Compile in platform device definitions for FIMC controller 2
> > +
> > +
>
> 2 empty lines...
OK, will try to pay more attention to these.
>
> > config PLAT_S5P
> > bool
> > depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PC100 ||
> > ARCH_S5PV210)
> > diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
> > index b56b4d3..a7d3c35 100644
> > --- a/arch/arm/plat-s5p/Makefile
> > +++ b/arch/arm/plat-s5p/Makefile
> > @@ -18,3 +18,6 @@ obj-y += clock.o
> > obj-y += irq.o irq-gpioint.o
> > obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o
> >
> > +obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o
> > +obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o
> > +obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o
> > diff --git a/arch/arm/plat-s5p/dev-fimc0.c b/arch/arm/plat-s5p/dev-
> fimc0.c
> > new file mode 100644
> > index 0000000..cfa10f0
> > --- /dev/null
> > +++ b/arch/arm/plat-s5p/dev-fimc0.c
> > @@ -0,0 +1,56 @@
> > +/* linux/arch/arm/plat-s5p/dev-fimc0.c
> > + *
> > + * Copyright (c) 2010 Samsung Electronics
> > + *
> > + * Base S5P FIMC0 resource and device definitions
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/string.h>
> > +#include <linux/platform_device.h>
> > +#include <mach/map.h>
> > +#include <mach/irqs.h>
> > +#include <plat/fimc.h>
> > +#include <plat/devs.h>
> > +#include <plat/cpu.h>
> > +
> > +
>
> Same...2 empty lines...
Please see my comment to previous patch.
>
> > +static struct resource s5p_fimc_resource[] = {
> > + [0] = {
> > + .start = S5P_PA_FIMC0,
> > + .end = S5P_PA_FIMC0 + SZ_1M - 1,
> > + .flags = IORESOURCE_MEM,
> > + },
> > + [1] = {
> > + .start = IRQ_FIMC0,
> > + .end = IRQ_FIMC0,
> > + .flags = IORESOURCE_IRQ,
> > + },
> > +};
> > +
> > +struct platform_device s5p_device_fimc0 = {
> > + .name = "s5p-fimc",
> > + .id = 0,
> > + .num_resources = ARRAY_SIZE(s5p_fimc_resource),
> > + .resource = s5p_fimc_resource,
> > +};
> > +
> > +
>
> 2 empty lines...
>
> > +void __init s5p_fimc0_set_platdata(struct samsung_plat_fimc *pd)
>
> Actually, we can use Ben's 's3c_set_platdata' which can replace a
> number of
> sites...
>
> Please refer to below URL.
> http://lists.infradead.org/pipermail/linux-arm-kernel/2010-
> May/016650.html
>
> I think this method is better to us.
Thank you for pointing this out. I expected such changes, but I wanted
to move on with the development so I have done that similar to the other
devices.
I will rework this part too.
>
> > +{
> > + struct samsung_plat_fimc *npd;
> > +
> > + if (!pd)
> > + pd = &s5p_fimc0_default_data;
> > +
> > + npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
> > + if (!npd)
> > + printk(KERN_ERR "%s: out of memory\n", __func__);
> > +
> > + s5p_device_fimc0.dev.platform_data = npd;
> > +}
> > +
>
> No need last empty line
Right, I will clean this up in the next patch version.
>
> > diff --git a/arch/arm/plat-s5p/dev-fimc1.c b/arch/arm/plat-s5p/dev-
> fimc1.c
> > new file mode 100644
> > index 0000000..7178477
> > --- /dev/null
> > +++ b/arch/arm/plat-s5p/dev-fimc1.c
> > @@ -0,0 +1,55 @@
> > +/* linux/arch/arm/plat-s5p/dev-fimc1.c
> > + *
> > + * Copyright (c) 2010 Samsung Electronics
> > + *
> > + * Base S5P FIMC1 resource and device definitions
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/string.h>
> > +#include <linux/platform_device.h>
> > +#include <mach/map.h>
> > +#include <mach/irqs.h>
> > +#include <plat/fimc.h>
> > +#include <plat/devs.h>
> > +#include <plat/cpu.h>
> > +
> > +
> 2 empty lines..
>
> > +static struct resource s5p_fimc_resource[] = {
> > + [0] = {
> > + .start = S5P_PA_FIMC1,
> > + .end = S5P_PA_FIMC1 + SZ_1M - 1,
> > + .flags = IORESOURCE_MEM,
> > + },
> > + [1] = {
> > + .start = IRQ_FIMC1,
> > + .end = IRQ_FIMC1,
> > + .flags = IORESOURCE_IRQ,
> > + },
> > +};
> > +
> > +struct platform_device s5p_device_fimc1 = {
> > + .name = "s5p-fimc",
> > + .id = 1,
> > + .num_resources = ARRAY_SIZE(s5p_fimc_resource),
> > + .resource = s5p_fimc_resource,
> > +};
> > +
> > +void __init s5p_fimc1_set_platdata(struct samsung_plat_fimc *pd)
> > +{
> > + struct samsung_plat_fimc *npd;
> > +
> > + if (!pd)
> > + pd = &s5p_fimc1_default_data;
> > +
> > + npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
> > + if (!npd)
> > + printk(KERN_ERR "%s: out of memory\n", __func__);
> > +
> > + s5p_device_fimc1.dev.platform_data = npd;
> > +}
> > +
>
> No need last empty line...
>
> > diff --git a/arch/arm/plat-s5p/dev-fimc2.c b/arch/arm/plat-s5p/dev-
> fimc2.c
> > new file mode 100644
> > index 0000000..fe1a6c0
> > --- /dev/null
> > +++ b/arch/arm/plat-s5p/dev-fimc2.c
> > @@ -0,0 +1,55 @@
> > +/* linux/arch/arm/plat-s5p/dev-fimc2.c
> > + *
> > + * Copyright (c) 2010 Samsung Electronics
> > + *
> > + * Base S5P FIMC2 resource and device definitions
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/string.h>
> > +#include <linux/platform_device.h>
> > +#include <mach/map.h>
> > +#include <mach/irqs.h>
> > +#include <plat/fimc.h>
> > +#include <plat/devs.h>
> > +#include <plat/cpu.h>
> > +
> > +
>
> Same...
>
> > +static struct resource s5p_fimc_resource[] = {
> > + [0] = {
> > + .start = S5P_PA_FIMC2,
> > + .end = S5P_PA_FIMC2 + SZ_1M - 1,
> > + .flags = IORESOURCE_MEM,
> > + },
> > + [1] = {
> > + .start = IRQ_FIMC2,
> > + .end = IRQ_FIMC2,
> > + .flags = IORESOURCE_IRQ,
> > + },
> > +};
> > +
> > +struct platform_device s5p_device_fimc2 = {
> > + .name = "s5p-fimc",
> > + .id = 2,
> > + .num_resources = ARRAY_SIZE(s5p_fimc_resource),
> > + .resource = s5p_fimc_resource,
> > +};
> > +
> > +void __init s5p_fimc2_set_platdata(struct samsung_plat_fimc *pd)
> > +{
> > + struct samsung_plat_fimc *npd;
> > +
> > + if (!pd)
> > + pd = &s5p_fimc2_default_data;
> > +
> > + npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
> > + if (!npd)
> > + printk(KERN_ERR "%s: out of memory\n", __func__);
> > +
> > + s5p_device_fimc2.dev.platform_data = npd;
> > +}
> > +
>
> Same..
>
<snip>
>
>
> Thanks.
>
> Best regards,
> Kgene.
> --
> Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
> SW Solution Development Team, Samsung Electronics Co., Ltd.
Regards,
Sylwester
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and platform definitions
2010-07-16 13:35 ` Maurus Cuelenaere
@ 2010-07-16 14:47 ` Sylwester Nawrocki
0 siblings, 0 replies; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-16 14:47 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Maurus Cuelenaere [mailto:mcuelenaere at gmail.com]
> Sent: Friday, July 16, 2010 3:36 PM
> To: Sylwester Nawrocki
> Cc: 'Kukjin Kim'; Pawel Osciak; Marek Szyprowski;
> kyungmin.park at samsung.com; linux-media at vger.kernel.org; linux-samsung-
> soc at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and
> platform definitions
>
> Op 16-07-10 15:30, Sylwester Nawrocki schreef:
> > Hi,
> >
> > thank you for the review. Please se my comments below.
> >
> >> -----Original Message-----
> >> From: Kukjin Kim [mailto:kgene.kim at samsung.com]
> >> Sent: Friday, July 16, 2010 11:45 AM
> >> To: 'Sylwester Nawrocki'; linux-samsung-soc at vger.kernel.org; linux-
> arm-
> >> kernel at lists.infradead.org
> >> Cc: p.osciak at samsung.com; m.szyprowski at samsung.com;
> >> kyungmin.park at samsung.com; linux-media at vger.kernel.org
> >> Subject: RE: [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and
> >> platform definitions
> >>
<snip>
> >>> +
> >>> +struct samsung_plat_fimc {
> >>> + struct s3c_fifo_link *fifo_targets[FIMC_MAX_FIFO_TARGETS];
> >>> +};
> >>> +
> >>> +#endif /* FIMC_H_ */
> >>> +
> >> No need last empty line...
> > C89 and C99 standard requires a new line character at the end of
> file.
> > The compiler should issue a warning when the new line character
> > at the end of file is missing, otherwise it is not compliant with
> > the above C standards.
> > So I would rather add a new line where it is missing rather than
> > removing it.
> > There is lots of header files already in arch/arm/plat-samsung where
> > there is even more than one empty line at the end of file.
>
> AFAIK there *already is* an empty line, git just omits it in diffs.
> Try removing the last line with your editor and see what git diff
> gives, it'll
> show "\ No newline at end of file".
Indeed, I just had two new-line characters with single empty line..
>
> --
> Maurus Cuelenaere
Thanks,
Sylwester
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 04/10 v2] v4l: Add Samsung FIMC (video postprocessor) driver
2010-07-16 11:39 ` Kukjin Kim
@ 2010-07-16 16:33 ` Sylwester Nawrocki
0 siblings, 0 replies; 21+ messages in thread
From: Sylwester Nawrocki @ 2010-07-16 16:33 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kukjin Kim [mailto:kgene.kim at samsung.com]
> Sent: Friday, July 16, 2010 1:39 PM
> To: 'Sylwester Nawrocki'; linux-samsung-soc at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org
> Cc: p.osciak at samsung.com; m.szyprowski at samsung.com;
> kyungmin.park at samsung.com; linux-media at vger.kernel.org
> Subject: RE: [PATCH 04/10 v2] v4l: Add Samsung FIMC (video
> postprocessor) driver
>
> Sylwester Nawrocki wrote:
> >
> Hi,
>
> Samsung S.LSI hardly recommends DMA mode to implement the feature not
> FIFO
> mode because of H/W limitation.
Does the hardware issue occur in all SoCs or only some specific versions
are affected?
So far we were successful with S5PC110 EVT0, however we could not make
it work on S5PV210 (EVT1). That said I have created an option in the FIMC
variant definition (samsung_fimc_variant::fifo_capable) so that
the V4L2 video node for FIMC FIFO operation mode is registered only
for selected SoC variants.
>
> > This driver exports two video device nodes per each FIMC device,
> > one for for memory to memory (color conversion, image resizing,
> > flipping and rotation) operations and one for direct
> > V4L2 output interface to framebuffer.
> >
> > Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > Reviewed-by: Pawel Osciak <p.osciak@samsung.com>
> > Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com>
> > ---
> > drivers/media/video/Kconfig | 20 +
> > drivers/media/video/Makefile | 1 +
> > drivers/media/video/samsung/fimc/Makefile | 3 +
> > drivers/media/video/samsung/fimc/fimc-core.c | 1664
> > ++++++++++++++++++++++++++
> > drivers/media/video/samsung/fimc/fimc-core.h | 541 +++++++++
> > drivers/media/video/samsung/fimc/fimc-fifo.c | 814 +++++++++++++
> > drivers/media/video/samsung/fimc/fimc-reg.c | 585 +++++++++
> > include/linux/videodev2.h | 1 +
> > 8 files changed, 3629 insertions(+), 0 deletions(-)
> > create mode 100644 drivers/media/video/samsung/fimc/Makefile
> > create mode 100644 drivers/media/video/samsung/fimc/fimc-core.c
> > create mode 100644 drivers/media/video/samsung/fimc/fimc-core.h
> > create mode 100644 drivers/media/video/samsung/fimc/fimc-fifo.c
> > create mode 100644 drivers/media/video/samsung/fimc/fimc-reg.c
> >
>
> (snip)
>
> Thanks.
>
> Best regards,
> Kgene.
> --
> Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
> SW Solution Development Team, Samsung Electronics Co., Ltd.
Best regards,
--
Sylwester Nawrocki
Samsung Poland R&D Center
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2010-07-16 16:33 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-15 9:10 [PATCH v2] Samsung S5P SoC camera interface driver Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 01/10 v2] ARM: Samsung: Add FIMC register and platform definitions Sylwester Nawrocki
2010-07-16 9:44 ` Kukjin Kim
2010-07-16 13:30 ` Sylwester Nawrocki
2010-07-16 13:35 ` Maurus Cuelenaere
2010-07-16 14:47 ` Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 02/10 v2] ARM: Samsung: Add FIMC resource definition and FIMC driver platform helpers Sylwester Nawrocki
2010-07-16 10:07 ` Kukjin Kim
2010-07-16 14:27 ` Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 03/10 v2] ARM: Samsung: Add platform definitions for local FIMC/FIMD fifo path Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 04/10 v2] v4l: Add Samsung FIMC (video postprocessor) driver Sylwester Nawrocki
2010-07-16 11:39 ` Kukjin Kim
2010-07-16 16:33 ` Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 05/10 v2] s3c-fb: Add v4l2 subdevice to support framebuffer local fifo input path Sylwester Nawrocki
2010-07-15 10:32 ` Maurus Cuelenaere
2010-07-15 11:18 ` Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 06/10 v2] ARM: S5PV210: Add fifo link definitions for FIMC and framebuffer Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 07/10 v2] ARM: S5PV210: add common Aquila & GONI code Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 08/10 v2] ARM: S5PV210: enable FIMC on Aquila Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 09/10 v2] ARM: s5pv210: enable FIMC on Goni Sylwester Nawrocki
2010-07-15 9:10 ` [PATCH 10/10 v2] ARM: S5PC100: enable FIMC on SMDKC100 Sylwester Nawrocki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).