linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v12 00/12] Exynos5 IS driver
@ 2013-11-05 12:13 Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 01/12] [media] exynos5-fimc-is: Add Exynos5 FIMC-IS device tree bindings documentation Arun Kumar K
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

The patch series adds support for exynos5 fimc-is driver and a
new sensor s5k4e5. The media driver part is omitted form this series
as it is already applied.

Changes from v11
----------------
- Addressed review comments from Sakari Ailus
http://www.mail-archive.com/linux-media@vger.kernel.org/msg68134.html

Changes from v10
---------------
- Addressed DT binding review comments from Mark Rutland
https://www.mail-archive.com/linux-media@vger.kernel.org/msg67806.html
https://www.mail-archive.com/linux-media@vger.kernel.org/msg67808.html

Changes from v9
---------------
- Addressed review comments from Hans and Sylwester
http://www.mail-archive.com/linux-media@vger.kernel.org/msg67102.html
http://www.mail-archive.com/linux-media@vger.kernel.org/msg67624.html
http://www.mail-archive.com/linux-media@vger.kernel.org/msg67623.html
- Skipped already applied media driver

Changes from v8
---------------
- Moved i2c-isp device nodes into the fimc-is node as suggested
  by Sylwester
- Addressed comments given by Sylwester and Philipp Zabel

Changes from v7
---------------
- Addressed few DT related review comments from Sylwester
  http://www.mail-archive.com/linux-media@vger.kernel.org/msg66403.html
- Few fixes added after some regression testing

Changes from v6
---------------
- Addressed DT binding doc review comments from Sylwester
  http://www.mail-archive.com/linux-media@vger.kernel.org/msg65771.html
  http://www.mail-archive.com/linux-media@vger.kernel.org/msg65772.html

Changes from v5
---------------
- Addressed review comments from Sylwester
  http://www.mail-archive.com/linux-media@vger.kernel.org/msg65578.html
  http://www.mail-archive.com/linux-media@vger.kernel.org/msg65605.html

Changes from v4
---------------
- Addressed all review comments from Sylwester
- Added separate PMU node as suggested by Stephen Warren
- Added phandle based discovery of subdevs instead of node name

Changes from v3
---------------
- Dropped the RFC tag
- Addressed all review comments from Sylwester and Sachin
- Removed clock provider for media dev
- Added s5k4e5 sensor devicetree binding doc

Changes from v2
---------------
- Added exynos5 media device driver from Shaik to this series
- Added ISP pipeline support in media device driver
- Based on Sylwester's latest exynos4-is development
- Asynchronos registration of sensor subdevs
- Made independent IS-sensor support
- Add s5k4e5 sensor driver
- Addressed review comments from Sylwester, Hans, Andrzej, Sachin

Changes from v1
---------------
- Addressed all review comments from Sylwester
- Made sensor subdevs as independent i2c devices
- Lots of cleanup
- Debugfs support added
- Removed PMU global register access


Arun Kumar K (12):
  [media] exynos5-fimc-is: Add Exynos5 FIMC-IS device tree bindings
    documentation
  [media] exynos5-fimc-is: Add driver core files
  [media] exynos5-fimc-is: Add common driver header files
  [media] exynos5-fimc-is: Add register definition and context header
  [media] exynos5-fimc-is: Add isp subdev
  [media] exynos5-fimc-is: Add scaler subdev
  [media] exynos5-fimc-is: Add sensor interface
  [media] exynos5-fimc-is: Add the hardware pipeline control
  [media] exynos5-fimc-is: Add the hardware interface module
  [media] exynos5-is: Add Kconfig and Makefile
  V4L: Add DT binding doc for s5k4e5 image sensor
  V4L: Add s5k4e5 sensor driver

 .../devicetree/bindings/media/exynos5-fimc-is.txt  |  113 ++
 .../devicetree/bindings/media/samsung-s5k4e5.txt   |   45 +
 drivers/media/i2c/Kconfig                          |    8 +
 drivers/media/i2c/Makefile                         |    1 +
 drivers/media/i2c/s5k4e5.c                         |  344 ++++
 drivers/media/platform/Kconfig                     |    1 +
 drivers/media/platform/Makefile                    |    1 +
 drivers/media/platform/exynos5-is/Kconfig          |   20 +
 drivers/media/platform/exynos5-is/Makefile         |    7 +
 drivers/media/platform/exynos5-is/fimc-is-cmd.h    |  187 +++
 drivers/media/platform/exynos5-is/fimc-is-core.c   |  387 +++++
 drivers/media/platform/exynos5-is/fimc-is-core.h   |  117 ++
 drivers/media/platform/exynos5-is/fimc-is-err.h    |  257 +++
 .../media/platform/exynos5-is/fimc-is-interface.c  |  810 ++++++++++
 .../media/platform/exynos5-is/fimc-is-interface.h  |  124 ++
 drivers/media/platform/exynos5-is/fimc-is-isp.c    |  534 ++++++
 drivers/media/platform/exynos5-is/fimc-is-isp.h    |   90 ++
 .../media/platform/exynos5-is/fimc-is-metadata.h   |  767 +++++++++
 drivers/media/platform/exynos5-is/fimc-is-param.h  | 1159 +++++++++++++
 .../media/platform/exynos5-is/fimc-is-pipeline.c   | 1699 ++++++++++++++++++++
 .../media/platform/exynos5-is/fimc-is-pipeline.h   |  129 ++
 drivers/media/platform/exynos5-is/fimc-is-regs.h   |  105 ++
 drivers/media/platform/exynos5-is/fimc-is-scaler.c |  476 ++++++
 drivers/media/platform/exynos5-is/fimc-is-scaler.h |  106 ++
 drivers/media/platform/exynos5-is/fimc-is-sensor.c |   45 +
 drivers/media/platform/exynos5-is/fimc-is-sensor.h |   65 +
 drivers/media/platform/exynos5-is/fimc-is.h        |  160 ++
 27 files changed, 7757 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/exynos5-fimc-is.txt
 create mode 100644 Documentation/devicetree/bindings/media/samsung-s5k4e5.txt
 create mode 100644 drivers/media/i2c/s5k4e5.c
 create mode 100644 drivers/media/platform/exynos5-is/Kconfig
 create mode 100644 drivers/media/platform/exynos5-is/Makefile
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-cmd.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-core.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-core.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-err.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-interface.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-interface.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-isp.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-isp.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-metadata.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-param.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-pipeline.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-pipeline.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-regs.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-scaler.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-scaler.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-sensor.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-sensor.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is.h

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v12 01/12] [media] exynos5-fimc-is: Add Exynos5 FIMC-IS device tree bindings documentation
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 02/12] [media] exynos5-fimc-is: Add driver core files Arun Kumar K
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

The patch adds the DT binding documentation for Samsung
Exynos5 SoC series imaging subsystem (FIMC-IS).

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
---
 .../devicetree/bindings/media/exynos5-fimc-is.txt  |  113 ++++++++++++++++++++
 1 file changed, 113 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/exynos5-fimc-is.txt

diff --git a/Documentation/devicetree/bindings/media/exynos5-fimc-is.txt b/Documentation/devicetree/bindings/media/exynos5-fimc-is.txt
new file mode 100644
index 0000000..658d4a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/exynos5-fimc-is.txt
@@ -0,0 +1,113 @@
+Samsung EXYNOS5 SoC series Imaging Subsystem (FIMC-IS)
+------------------------------------------------------
+
+The camera subsystem on Samsung Exynos5 SoC has some changes relative
+to previous SoC versions. Exynos5 has almost similar MIPI-CSIS and
+FIMC-LITE IPs but has a much improved version of FIMC-IS which can
+handle sensor controls and camera post-processing operations. The
+Exynos5 FIMC-IS has a dedicated ARM Cortex A5 processor, many
+post-processing blocks (ISP, DRC, FD, ODC, DIS, 3DNR) and two
+dedicated scalers (SCC and SCP).
+
+fimc-is node
+------------
+
+Required properties:
+
+- compatible        : should contain "samsung,exynos5250-fimc-is"
+- reg               : physical base address and size of the memory mapped
+                      registers
+- interrupts        : interrupt-specifier for the fimc-is interrupt
+- clocks            : list of clock specifiers, corresponding to entries in
+                      clock-names property
+- clock-names       : must contain "isp", "mcu_isp", "isp_div0", "isp_div1",
+                      "isp_divmpwm", "mcu_isp_div0", "mcu_isp_div1" entries,
+                      matching entries in the clocks property
+- samsung,pmu       : phandle to the Power Management Unit (PMU) node
+
+i2c-isp (ISP I2C bus controller) nodes
+--------------------------------------
+The i2c-isp nodes should be children of the fimc-is node.
+
+Required properties:
+
+- compatible	: must contain "samsung,exynos4212-i2c-isp" for Exynos4212,
+		  Exynos4412 and Exynos5250 SoCs
+- reg		: physical base address and length of the registers set
+- clocks	: should contain gate clock specifier for this controller
+- clock-names	: should contain "i2c_isp" for the gate clock
+- pinctrl-0	: phandle of the pinctrl node for the i2c isp
+- pinctrl-names : must contain "default"
+
+ranges, #address-cells, and #size-cells should be present as appropriate.
+
+Device tree nodes of the image sensors controlled directly by the FIMC-IS
+firmware must be child nodes of their corresponding ISP I2C bus controller node.
+The data link of these image sensors must be specified using the common video
+interfaces bindings, defined in video-interfaces.txt.
+
+Example:
+
+	fimc_is: fimc-is@13000000 {
+		compatible = "samsung,exynos5250-fimc-is";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0x13000000 0x200000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <19 1>;
+		clocks = <&clock 346>, <&clock 347>, <&clock 512>,
+			<&clock 513>, <&clock 514>, <&clock 515>,
+			<&clock 516>;
+		clock-names = "isp", "mcu_isp", "isp_div0", "isp_div1",
+				"isp_divmpwm", "mcu_isp_div0",
+				"mcu_isp_div1";
+		samsung,pmu = <&pmu>;
+
+		i2c0_isp: i2c-isp@13130000 {
+			compatible = "samsung,exynos4212-i2c-isp";
+			reg = <0x13130000 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&clock 352>;
+			clock-names = "i2c_isp";
+			pinctrl-0 = <&cam_i2c0_bus>;
+			pinctrl-names = "default";
+		};
+
+		i2c1_isp: i2c-isp@13140000 {
+			compatible = "samsung,exynos4212-i2c-isp";
+			reg = <0x13140000 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&clock 353>;
+			clock-names = "i2c_isp";
+			pinctrl-0 = <&cam_i2c1_bus>;
+			pinctrl-names = "default";
+		};
+	};
+
+In the board specific file the sensor nodes can be provided. For the sensor
+node documentation for s5k4e5, please refer to samsung-s5k4e5.txt
+
+	fimc-is@13000000 {
+		status = "okay";
+
+		i2c-isp@13130000 {
+			s5k4e5@20 {
+				compatible = "samsung,s5k4e5";
+				reg = <0x20>;
+				reset-gpios = <&gpx1 2 1>;
+				clock-frequency = <24000000>;
+				clocks = <&clock 129>;
+				clock-names = "extclk";
+				svdda-supply = <&vdd>;
+				svddio-supply = <&vdd>;
+				port {
+					is_s5k4e5_ep: endpoint {
+						remote-endpoint = <&csis0_ep>;
+					};
+				};
+			};
+		};
+	};
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 02/12] [media] exynos5-fimc-is: Add driver core files
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 01/12] [media] exynos5-fimc-is: Add Exynos5 FIMC-IS device tree bindings documentation Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 03/12] [media] exynos5-fimc-is: Add common driver header files Arun Kumar K
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

This driver is for the FIMC-IS IP available in Samsung Exynos5
SoC onwards. This patch adds the core files for the new driver.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Kilyeon Im <kilyeon.im@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/media/platform/exynos5-is/fimc-is-core.c |  386 ++++++++++++++++++++++
 drivers/media/platform/exynos5-is/fimc-is-core.h |  117 +++++++
 2 files changed, 503 insertions(+)
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-core.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-core.h

diff --git a/drivers/media/platform/exynos5-is/fimc-is-core.c b/drivers/media/platform/exynos5-is/fimc-is-core.c
new file mode 100644
index 0000000..136e3c1
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-core.c
@@ -0,0 +1,386 @@
+/*
+ * Samsung EXYNOS5 FIMC-IS (Imaging Subsystem) driver
+*
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Arun Kumar K <arun.kk@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/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-of.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "fimc-is.h"
+#include "fimc-is-i2c.h"
+
+#define CLK_MCU_ISP_DIV0_FREQ	(200 * 1000000)
+#define CLK_MCU_ISP_DIV1_FREQ	(100 * 1000000)
+#define CLK_ISP_DIV0_FREQ	(134 * 1000000)
+#define CLK_ISP_DIV1_FREQ	(68 * 1000000)
+#define CLK_ISP_DIVMPWM_FREQ	(34 * 1000000)
+
+static const char * const fimc_is_clock_name[] = {
+	[IS_CLK_ISP]		= "isp",
+	[IS_CLK_MCU_ISP]	= "mcu_isp",
+	[IS_CLK_ISP_DIV0]	= "isp_div0",
+	[IS_CLK_ISP_DIV1]	= "isp_div1",
+	[IS_CLK_ISP_DIVMPWM]	= "isp_divmpwm",
+	[IS_CLK_MCU_ISP_DIV0]	= "mcu_isp_div0",
+	[IS_CLK_MCU_ISP_DIV1]	= "mcu_isp_div1",
+};
+
+static void fimc_is_put_clocks(struct fimc_is *is)
+{
+	int i;
+
+	for (i = 0; i < IS_CLK_MAX_NUM; i++) {
+		if (IS_ERR(is->clock[i]))
+			continue;
+		clk_unprepare(is->clock[i]);
+		clk_put(is->clock[i]);
+		is->clock[i] = ERR_PTR(-EINVAL);
+	}
+}
+
+static int fimc_is_get_clocks(struct fimc_is *is)
+{
+	struct device *dev = &is->pdev->dev;
+	int i, ret;
+
+	for (i = 0; i < IS_CLK_MAX_NUM; i++) {
+		is->clock[i] = clk_get(dev, fimc_is_clock_name[i]);
+		if (IS_ERR(is->clock[i]))
+			goto err;
+		ret = clk_prepare(is->clock[i]);
+		if (ret < 0) {
+			clk_put(is->clock[i]);
+			is->clock[i] = ERR_PTR(-EINVAL);
+			goto err;
+		}
+	}
+	return 0;
+err:
+	fimc_is_put_clocks(is);
+	dev_err(dev, "Failed to get clock: %s\n", fimc_is_clock_name[i]);
+	return -ENXIO;
+}
+
+static int fimc_is_configure_clocks(struct fimc_is *is)
+{
+	int i, ret;
+
+	for (i = 0; i < IS_CLK_MAX_NUM; i++)
+		is->clock[i] = ERR_PTR(-EINVAL);
+
+	ret = fimc_is_get_clocks(is);
+	if (ret)
+		return ret;
+
+	/* Set rates */
+	ret = clk_set_rate(is->clock[IS_CLK_MCU_ISP_DIV0],
+			CLK_MCU_ISP_DIV0_FREQ);
+	if (ret)
+		return ret;
+	ret = clk_set_rate(is->clock[IS_CLK_MCU_ISP_DIV1],
+			CLK_MCU_ISP_DIV1_FREQ);
+	if (ret)
+		return ret;
+	ret = clk_set_rate(is->clock[IS_CLK_ISP_DIV0], CLK_ISP_DIV0_FREQ);
+	if (ret)
+		return ret;
+	ret = clk_set_rate(is->clock[IS_CLK_ISP_DIV1], CLK_ISP_DIV1_FREQ);
+	if (ret)
+		return ret;
+	return clk_set_rate(is->clock[IS_CLK_ISP_DIVMPWM],
+			CLK_ISP_DIVMPWM_FREQ);
+}
+
+static void fimc_is_pipelines_destroy(struct fimc_is *is)
+{
+	int i;
+
+	for (i = 0; i < is->drvdata->num_instances; i++)
+		fimc_is_pipeline_destroy(&is->pipeline[i]);
+}
+
+static int fimc_is_parse_sensor_config(struct fimc_is *is, unsigned int index,
+						struct device_node *node)
+{
+	struct fimc_is_sensor *sensor = &is->sensor[index];
+	u32 tmp = 0;
+	int ret;
+
+	sensor->drvdata = exynos5_is_sensor_get_drvdata(node);
+	if (!sensor->drvdata) {
+		dev_err(&is->pdev->dev, "no driver data found for: %s\n",
+							 node->full_name);
+		return -EINVAL;
+	}
+
+	node = v4l2_of_get_next_endpoint(node, NULL);
+	if (!node)
+		return -ENXIO;
+
+	node = v4l2_of_get_remote_port(node);
+	if (!node)
+		return -ENXIO;
+
+	/* Use MIPI-CSIS channel id to determine the ISP I2C bus index. */
+	ret = of_property_read_u32(node, "reg", &tmp);
+	if (ret < 0) {
+		dev_err(&is->pdev->dev, "reg property not found at: %s\n",
+							 node->full_name);
+		return ret;
+	}
+
+	sensor->i2c_bus = tmp - FIMC_INPUT_MIPI_CSI2_0;
+	return 0;
+}
+
+static int fimc_is_parse_sensor(struct fimc_is *is)
+{
+	struct device_node *i2c_bus, *child;
+	int ret, index = 0;
+
+	for_each_compatible_node(i2c_bus, NULL, FIMC_IS_I2C_COMPATIBLE) {
+		for_each_available_child_of_node(i2c_bus, child) {
+			ret = fimc_is_parse_sensor_config(is, index, child);
+
+			if (ret < 0 || index >= FIMC_IS_NUM_SENSORS) {
+				of_node_put(child);
+				return ret;
+			}
+			index++;
+		}
+	}
+	return 0;
+}
+
+static struct fimc_is_drvdata exynos5250_drvdata = {
+	.num_instances	= 1,
+	.fw_name	= "exynos5_fimc_is_fw.bin",
+};
+
+static const struct of_device_id exynos5_fimc_is_match[] = {
+	{
+		.compatible = "samsung,exynos5250-fimc-is",
+		.data = &exynos5250_drvdata,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos5_fimc_is_match);
+
+static void *fimc_is_get_drvdata(struct platform_device *pdev)
+{
+	struct fimc_is_drvdata *driver_data = NULL;
+	const struct of_device_id *match;
+
+	match = of_match_node(exynos5_fimc_is_match,
+			pdev->dev.of_node);
+	if (match)
+		driver_data = (struct fimc_is_drvdata *)match->data;
+	return driver_data;
+}
+
+static int fimc_is_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct fimc_is *is;
+	void __iomem *regs;
+	struct device_node *node;
+	int irq, ret;
+	int i;
+
+	dev_dbg(dev, "FIMC-IS Probe Enter\n");
+
+	if (!dev->of_node)
+		return -ENODEV;
+
+	is = devm_kzalloc(&pdev->dev, sizeof(*is), GFP_KERNEL);
+	if (!is)
+		return -ENOMEM;
+
+	is->pdev = pdev;
+
+	is->drvdata = fimc_is_get_drvdata(pdev);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	/* Get the PMU base */
+	node = of_parse_phandle(dev->of_node, "samsung,pmu", 0);
+	if (!node)
+		return -ENODEV;
+	is->pmu_regs = of_iomap(node, 0);
+	if (!is->pmu_regs)
+		return -ENOMEM;
+
+	irq = irq_of_parse_and_map(dev->of_node, 0);
+	if (!irq) {
+		dev_err(dev, "Failed to get IRQ\n");
+		return irq;
+	}
+
+	ret = fimc_is_configure_clocks(is);
+	if (ret < 0) {
+		dev_err(dev, "clocks configuration failed\n");
+		goto err_clk;
+	}
+
+	platform_set_drvdata(pdev, is);
+	pm_runtime_enable(dev);
+
+	is->alloc_ctx = vb2_dma_contig_init_ctx(dev);
+	if (IS_ERR(is->alloc_ctx)) {
+		ret = PTR_ERR(is->alloc_ctx);
+		goto err_vb;
+	}
+
+	/* Get IS-sensor contexts */
+	ret = fimc_is_parse_sensor(is);
+	if (ret < 0)
+		goto err_vb;
+
+	/* Initialize FIMC Pipeline */
+	for (i = 0; i < is->drvdata->num_instances; i++) {
+		ret = fimc_is_pipeline_init(&is->pipeline[i], i, is);
+		if (ret < 0)
+			goto err_sd;
+	}
+
+	/* Initialize FIMC Interface */
+	ret = fimc_is_interface_init(&is->interface, regs, irq);
+	if (ret < 0)
+		goto err_sd;
+
+	/* Probe the peripheral devices  */
+	ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+	if (ret < 0)
+		goto err_sd;
+
+	dev_dbg(dev, "FIMC-IS registered successfully\n");
+
+	return 0;
+
+err_sd:
+	fimc_is_pipelines_destroy(is);
+err_vb:
+	vb2_dma_contig_cleanup_ctx(is->alloc_ctx);
+err_clk:
+	fimc_is_put_clocks(is);
+
+	return ret;
+}
+
+int fimc_is_clk_enable(struct fimc_is *is)
+{
+	int ret;
+
+	ret = clk_enable(is->clock[IS_CLK_ISP]);
+	if (ret)
+		return ret;
+	ret = clk_enable(is->clock[IS_CLK_MCU_ISP]);
+	if (ret)
+		clk_disable(is->clock[IS_CLK_ISP]);
+	return ret;
+}
+
+void fimc_is_clk_disable(struct fimc_is *is)
+{
+	clk_disable(is->clock[IS_CLK_ISP]);
+	clk_disable(is->clock[IS_CLK_MCU_ISP]);
+}
+
+static int fimc_is_pm_resume(struct device *dev)
+{
+	struct fimc_is *is = dev_get_drvdata(dev);
+	int ret;
+
+	ret = fimc_is_clk_enable(is);
+	if (ret < 0) {
+		dev_err(dev, "Could not enable clocks\n");
+		return ret;
+	}
+	return 0;
+}
+
+static int fimc_is_pm_suspend(struct device *dev)
+{
+	struct fimc_is *is = dev_get_drvdata(dev);
+
+	fimc_is_clk_disable(is);
+	return 0;
+}
+
+static int fimc_is_runtime_resume(struct device *dev)
+{
+	return fimc_is_pm_resume(dev);
+}
+
+static int fimc_is_runtime_suspend(struct device *dev)
+{
+	return fimc_is_pm_suspend(dev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int fimc_is_resume(struct device *dev)
+{
+	/* TODO */
+	return 0;
+}
+
+static int fimc_is_suspend(struct device *dev)
+{
+	/* TODO */
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static int fimc_is_remove(struct platform_device *pdev)
+{
+	struct fimc_is *is = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	fimc_is_pipelines_destroy(is);
+	vb2_dma_contig_cleanup_ctx(is->alloc_ctx);
+	fimc_is_put_clocks(is);
+	return 0;
+}
+
+static const struct dev_pm_ops fimc_is_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(fimc_is_suspend, fimc_is_resume)
+	SET_RUNTIME_PM_OPS(fimc_is_runtime_suspend, fimc_is_runtime_resume,
+			   NULL)
+};
+
+static struct platform_driver fimc_is_driver = {
+	.probe		= fimc_is_probe,
+	.remove		= fimc_is_remove,
+	.driver = {
+		.name	= FIMC_IS_DRV_NAME,
+		.owner	= THIS_MODULE,
+		.pm	= &fimc_is_pm_ops,
+		.of_match_table = exynos5_fimc_is_match,
+	}
+};
+module_platform_driver(fimc_is_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Arun Kumar K <arun.kk@samsung.com>");
+MODULE_DESCRIPTION("Samsung Exynos5 (FIMC-IS) Imaging Subsystem driver");
diff --git a/drivers/media/platform/exynos5-is/fimc-is-core.h b/drivers/media/platform/exynos5-is/fimc-is-core.h
new file mode 100644
index 0000000..ef80ed9
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-core.h
@@ -0,0 +1,117 @@
+/*
+ * Samsung EXYNOS5 FIMC-IS (Imaging Subsystem) driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *  Arun Kumar K <arun.kk@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_IS_CORE_H_
+#define FIMC_IS_CORE_H_
+
+#include <linux/clk.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/media-entity.h>
+#include <media/s5p_fimc.h>
+#include <media/videobuf2-core.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+
+#define FIMC_IS_DRV_NAME		"exynos5-fimc-is"
+
+#define FIMC_IS_COMMAND_TIMEOUT		(10 * HZ)
+#define FIMC_IS_STARTUP_TIMEOUT		(3 * HZ)
+#define FIMC_IS_SHUTDOWN_TIMEOUT	(10 * HZ)
+
+#define FW_SHARED_OFFSET		(0x8c0000)
+#define DEBUG_CNT			(500 * 1024)
+#define DEBUG_OFFSET			(0x840000)
+#define DEBUGCTL_OFFSET			(0x8bd000)
+#define DEBUG_FCOUNT			(0x8c64c0)
+
+#define FIMC_IS_MAX_INSTANCES		1
+
+#define FIMC_IS_NUM_SENSORS		2
+#define FIMC_IS_NUM_PIPELINES		1
+
+#define FIMC_IS_MAX_PLANES		3
+#define FIMC_IS_NUM_SCALERS		2
+
+enum fimc_is_clks {
+	IS_CLK_ISP,
+	IS_CLK_MCU_ISP,
+	IS_CLK_ISP_DIV0,
+	IS_CLK_ISP_DIV1,
+	IS_CLK_ISP_DIVMPWM,
+	IS_CLK_MCU_ISP_DIV0,
+	IS_CLK_MCU_ISP_DIV1,
+	IS_CLK_MAX_NUM
+};
+
+/* Video capture states */
+enum fimc_is_video_state {
+	STATE_INIT,
+	STATE_BUFS_ALLOCATED,
+	STATE_RUNNING,
+};
+
+enum fimc_is_scaler_id {
+	SCALER_SCC,
+	SCALER_SCP
+};
+
+enum fimc_is_sensor_pos {
+	SENSOR_CAM0,
+	SENSOR_CAM1
+};
+
+struct fimc_is_buf {
+	struct vb2_buffer vb;
+	struct list_head list;
+	unsigned int paddr[FIMC_IS_MAX_PLANES];
+};
+
+struct fimc_is_memory {
+	/* physical base address */
+	dma_addr_t paddr;
+	/* virtual base address */
+	void *vaddr;
+	/* total length */
+	unsigned int size;
+};
+
+struct fimc_is_meminfo {
+	struct fimc_is_memory	fw;
+	struct fimc_is_memory	shot;
+	struct fimc_is_memory	region;
+	struct fimc_is_memory	shared;
+};
+
+struct fimc_is_drvdata {
+	unsigned int	num_instances;
+	char		*fw_name;
+};
+
+/**
+ * struct fimc_is_fmt - the driver's internal color format data
+ * @name: format description
+ * @fourcc: the fourcc code for this format
+ * @depth: number of bytes per pixel
+ * @num_planes: number of planes for this color format
+ */
+struct fimc_is_fmt {
+	char		*name;
+	unsigned int	fourcc;
+	unsigned int	depth[FIMC_IS_MAX_PLANES];
+	unsigned int	num_planes;
+};
+
+#endif
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 03/12] [media] exynos5-fimc-is: Add common driver header files
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 01/12] [media] exynos5-fimc-is: Add Exynos5 FIMC-IS device tree bindings documentation Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 02/12] [media] exynos5-fimc-is: Add driver core files Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 04/12] [media] exynos5-fimc-is: Add register definition and context header Arun Kumar K
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

This patch adds all the common header files used by the fimc-is
driver. It includes the commands for interfacing with the firmware
and error codes from IS firmware, metadata and command parameter
definitions.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Kilyeon Im <kilyeon.im@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/media/platform/exynos5-is/fimc-is-cmd.h    |  187 ++++
 drivers/media/platform/exynos5-is/fimc-is-err.h    |  257 +++++
 .../media/platform/exynos5-is/fimc-is-metadata.h   |  767 +++++++++++++
 drivers/media/platform/exynos5-is/fimc-is-param.h  | 1159 ++++++++++++++++++++
 4 files changed, 2370 insertions(+)
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-cmd.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-err.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-metadata.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-param.h

diff --git a/drivers/media/platform/exynos5-is/fimc-is-cmd.h b/drivers/media/platform/exynos5-is/fimc-is-cmd.h
new file mode 100644
index 0000000..6250280
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-cmd.h
@@ -0,0 +1,187 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd
+ * Kil-yeon Lim <kilyeon.im@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_IS_CMD_H
+#define FIMC_IS_CMD_H
+
+#define IS_COMMAND_VER 122 /* IS COMMAND VERSION 1.22 */
+
+enum is_cmd {
+	/* HOST -> IS */
+	HIC_PREVIEW_STILL = 0x1,
+	HIC_PREVIEW_VIDEO,
+	HIC_CAPTURE_STILL,
+	HIC_CAPTURE_VIDEO,
+	HIC_PROCESS_START,
+	HIC_PROCESS_STOP,
+	HIC_STREAM_ON,
+	HIC_STREAM_OFF,
+	HIC_SHOT,
+	HIC_GET_STATIC_METADATA,
+	HIC_SET_CAM_CONTROL,
+	HIC_GET_CAM_CONTROL,
+	HIC_SET_PARAMETER,
+	HIC_GET_PARAMETER,
+	HIC_SET_A5_MEM_ACCESS,
+	RESERVED2,
+	HIC_GET_STATUS,
+	/* SENSOR PART*/
+	HIC_OPEN_SENSOR,
+	HIC_CLOSE_SENSOR,
+	HIC_SIMMIAN_INIT,
+	HIC_SIMMIAN_WRITE,
+	HIC_SIMMIAN_READ,
+	HIC_POWER_DOWN,
+	HIC_GET_SET_FILE_ADDR,
+	HIC_LOAD_SET_FILE,
+	HIC_MSG_CONFIG,
+	HIC_MSG_TEST,
+	/* IS -> HOST */
+	IHC_GET_SENSOR_NUMBER = 0x1000,
+	/* Parameter1 : Address of space to copy a setfile */
+	/* Parameter2 : Space szie */
+	IHC_SET_SHOT_MARK,
+	/* PARAM1 : a frame number */
+	/* PARAM2 : confidence level(smile 0~100) */
+	/* PARMA3 : confidence level(blink 0~100) */
+	IHC_SET_FACE_MARK,
+	/* PARAM1 : coordinate count */
+	/* PARAM2 : coordinate buffer address */
+	IHC_FRAME_DONE,
+	/* PARAM1 : frame start number */
+	/* PARAM2 : frame count */
+	IHC_AA_DONE,
+	IHC_NOT_READY,
+	IHC_FLASH_READY
+};
+
+enum is_reply {
+	ISR_DONE	= 0x2000,
+	ISR_NDONE
+};
+
+enum is_scenario_id {
+	ISS_PREVIEW_STILL,
+	ISS_PREVIEW_VIDEO,
+	ISS_CAPTURE_STILL,
+	ISS_CAPTURE_VIDEO,
+	ISS_END
+};
+
+enum is_subscenario_id {
+	ISS_SUB_SCENARIO_STILL,
+	ISS_SUB_SCENARIO_VIDEO,
+	ISS_SUB_SCENARIO_SCENE1,
+	ISS_SUB_SCENARIO_SCENE2,
+	ISS_SUB_SCENARIO_SCENE3,
+	ISS_SUB_END
+};
+
+struct is_setfile_header_element {
+	u32 binary_addr;
+	u32 binary_size;
+};
+
+struct is_setfile_header {
+	struct is_setfile_header_element isp[ISS_END];
+	struct is_setfile_header_element drc[ISS_END];
+	struct is_setfile_header_element fd[ISS_END];
+};
+
+struct is_common_reg {
+	u32 hicmd;
+	u32 hic_sensorid;
+	u32 hic_param[4];
+
+	u32 reserved1[3];
+
+	u32 ihcmd_iflag;
+	u32 ihcmd;
+	u32 ihc_sensorid;
+	u32 ihc_param[4];
+
+	u32 reserved2[3];
+
+	u32 isp_bayer_iflag;
+	u32 isp_bayer_sensor_id;
+	u32 isp_bayer_param[2];
+
+	u32 reserved3[4];
+
+	u32 scc_iflag;
+	u32 scc_sensor_id;
+	u32 scc_param[3];
+
+	u32 reserved4[3];
+
+	u32 dnr_iflag;
+	u32 dnr_sensor_id;
+	u32 dnr_param[2];
+
+	u32 reserved5[4];
+
+	u32 scp_iflag;
+	u32 scp_sensor_id;
+	u32 scp_param[3];
+
+	u32 reserved6[1];
+
+	u32 isp_yuv_iflag;
+	u32 isp_yuv_sensor_id;
+	u32 isp_yuv_param[2];
+
+	u32 reserved7[1];
+
+	u32 shot_iflag;
+	u32 shot_sensor_id;
+	u32 shot_param[2];
+
+	u32 reserved8[1];
+
+	u32 meta_iflag;
+	u32 meta_sensor_id;
+	u32 meta_param1;
+
+	u32 reserved9[1];
+
+	u32 fcount;
+};
+
+struct is_mcuctl_reg {
+	u32 mcuctl;
+	u32 bboar;
+
+	u32 intgr0;
+	u32 intcr0;
+	u32 intmr0;
+	u32 intsr0;
+	u32 intmsr0;
+
+	u32 intgr1;
+	u32 intcr1;
+	u32 intmr1;
+	u32 intsr1;
+	u32 intmsr1;
+
+	u32 intcr2;
+	u32 intmr2;
+	u32 intsr2;
+	u32 intmsr2;
+
+	u32 gpoctrl;
+	u32 cpoenctlr;
+	u32 gpictlr;
+
+	u32 pad[0xD];
+
+	struct is_common_reg common_reg;
+};
+#endif
diff --git a/drivers/media/platform/exynos5-is/fimc-is-err.h b/drivers/media/platform/exynos5-is/fimc-is-err.h
new file mode 100644
index 0000000..e19eced
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-err.h
@@ -0,0 +1,257 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd
+ * Arun Kumar K <arun.kk@samsung.com>
+ * Kil-yeon Lim <kilyeon.im@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_IS_ERR_H
+#define FIMC_IS_ERR_H
+
+#define IS_ERROR_VER 012 /* IS ERROR VERSION 0.07 */
+
+/* IS error enum */
+enum is_error {
+
+	IS_ERROR_SUCCESS = 0,
+
+	/* General 1 ~ 100 */
+	IS_ERROR_INVALID_COMMAND = 1,
+	IS_ERROR_REQUEST_FAIL,
+	IS_ERROR_INVALID_SCENARIO,
+	IS_ERROR_INVALID_SENSORID,
+	IS_ERROR_INVALID_MODE_CHANGE,
+	IS_ERROR_INVALID_MAGIC_NUMBER,
+	IS_ERROR_INVALID_SETFILE_HDR,
+	IS_ERROR_ISP_SETFILE_VERSION_MISMATCH,
+	IS_ERROR_ISP_SETFILE_REVISION_MISMATCH,
+	IS_ERROR_BUSY,
+	IS_ERROR_SET_PARAMETER,
+	IS_ERROR_INVALID_PATH,
+	IS_ERROR_OPEN_SENSOR_FAIL,
+	IS_ERROR_ENTRY_MSG_THREAD_DOWN,
+	IS_ERROR_ISP_FRAME_END_NOT_DONE,
+	IS_ERROR_DRC_FRAME_END_NOT_DONE,
+	IS_ERROR_SCALERC_FRAME_END_NOT_DONE,
+	IS_ERROR_ODC_FRAME_END_NOT_DONE,
+	IS_ERROR_DIS_FRAME_END_NOT_DONE,
+	IS_ERROR_TDNR_FRAME_END_NOT_DONE,
+	IS_ERROR_SCALERP_FRAME_END_NOT_DONE,
+	IS_ERROR_WAIT_STREAM_OFF_NOT_DONE,
+	IS_ERROR_NO_MSG_IS_RECEIVED,
+	IS_ERROR_SENSOR_MSG_FAIL,
+	IS_ERROR_ISP_MSG_FAIL,
+	IS_ERROR_DRC_MSG_FAIL,
+	IS_ERROR_SCALERC_MSG_FAIL,
+	IS_ERROR_ODC_MSG_FAIL,
+	IS_ERROR_DIS_MSG_FAIL,
+	IS_ERROR_TDNR_MSG_FAIL,
+	IS_ERROR_SCALERP_MSG_FAIL,
+	IS_ERROR_LHFD_MSG_FAIL,
+	IS_ERROR_INTERNAL_STOP,
+	IS_ERROR_UNKNOWN,
+	IS_ERROR_TIME_OUT_FLAG,
+
+	/* Sensor 100 ~ 200 */
+	IS_ERROR_SENSOR_PWRDN_FAIL = 100,
+	IS_ERROR_SENSOR_STREAM_ON_FAIL,
+	IS_ERROR_SENSOR_STREAM_OFF_FAIL,
+
+	/* ISP 200 ~ 300 */
+	IS_ERROR_ISP_PWRDN_FAIL = 200,
+	IS_ERROR_ISP_MULTIPLE_INPUT,
+	IS_ERROR_ISP_ABSENT_INPUT,
+	IS_ERROR_ISP_ABSENT_OUTPUT,
+	IS_ERROR_ISP_NONADJACENT_OUTPUT,
+	IS_ERROR_ISP_FORMAT_MISMATCH,
+	IS_ERROR_ISP_WIDTH_MISMATCH,
+	IS_ERROR_ISP_HEIGHT_MISMATCH,
+	IS_ERROR_ISP_BITWIDTH_MISMATCH,
+	IS_ERROR_ISP_FRAME_END_TIME_OUT,
+
+	/* DRC 300 ~ 400 */
+	IS_ERROR_DRC_PWRDN_FAIL = 300,
+	IS_ERROR_DRC_MULTIPLE_INPUT,
+	IS_ERROR_DRC_ABSENT_INPUT,
+	IS_ERROR_DRC_NONADJACENT_INTPUT,
+	IS_ERROR_DRC_ABSENT_OUTPUT,
+	IS_ERROR_DRC_NONADJACENT_OUTPUT,
+	IS_ERROR_DRC_FORMAT_MISMATCH,
+	IS_ERROR_DRC_WIDTH_MISMATCH,
+	IS_ERROR_DRC_HEIGHT_MISMATCH,
+	IS_ERROR_DRC_BITWIDTH_MISMATCH,
+	IS_ERROR_DRC_FRAME_END_TIME_OUT,
+
+	/*SCALERC(400~500)*/
+	IS_ERROR_SCALERC_PWRDN_FAIL = 400,
+
+	/*ODC(500~600)*/
+	IS_ERROR_ODC_PWRDN_FAIL = 500,
+
+	/*DIS(600~700)*/
+	IS_ERROR_DIS_PWRDN_FAIL = 600,
+
+	/*TDNR(700~800)*/
+	IS_ERROR_TDNR_PWRDN_FAIL = 700,
+
+	/*SCALERP(800~900)*/
+	IS_ERROR_SCALERP_PWRDN_FAIL = 800,
+
+	/*FD(900~1000)*/
+	IS_ERROR_FD_PWRDN_FAIL = 900,
+	IS_ERROR_FD_MULTIPLE_INPUT,
+	IS_ERROR_FD_ABSENT_INPUT,
+	IS_ERROR_FD_NONADJACENT_INPUT,
+	IS_ERROR_LHFD_FRAME_END_TIME_OUT,
+};
+
+/* Set parameter error enum */
+enum error {
+	/* Common error (0~99) */
+	ERROR_COMMON_NONE		= 0,
+	ERROR_COMMON_CMD		= 1,	/* Invalid command*/
+	ERROR_COMMON_PARAMETER		= 2,	/* Invalid parameter*/
+	/* setfile is not loaded before adjusting */
+	ERROR_COMMON_SETFILE_LOAD	= 3,
+	/* setfile is not Adjusted before runnng. */
+	ERROR_COMMON_SETFILE_ADJUST	= 4,
+	/* index of setfile is not valid. */
+	ERROR_COMMON_SETFILE_INDEX = 5,
+	/* Input path can be changed in ready state(stop) */
+	ERROR_COMMON_INPUT_PATH		= 6,
+	/* IP can not start if input path is not set */
+	ERROR_COMMON_INPUT_INIT		= 7,
+	/* Output path can be changed in ready state(stop) */
+	ERROR_COMMON_OUTPUT_PATH	= 8,
+	/* IP can not start if output path is not set */
+	ERROR_COMMON_OUTPUT_INIT	= 9,
+
+	ERROR_CONTROL_NONE		= ERROR_COMMON_NONE,
+	ERROR_CONTROL_BYPASS		= 11,	/* Enable or Disable */
+	ERROR_CONTROL_BUF		= 12,	/* invalid buffer info */
+
+	ERROR_OTF_INPUT_NONE		= ERROR_COMMON_NONE,
+	/* invalid command */
+	ERROR_OTF_INPUT_CMD		= 21,
+	/* invalid format  (DRC: YUV444, FD: YUV444, 422, 420) */
+	ERROR_OTF_INPUT_FORMAT		= 22,
+	/* invalid width (DRC: 128~8192, FD: 32~8190) */
+	ERROR_OTF_INPUT_WIDTH		= 23,
+	/* invalid height (DRC: 64~8192, FD: 16~8190) */
+	ERROR_OTF_INPUT_HEIGHT		= 24,
+	/* invalid bit-width (DRC: 8~12bits, FD: 8bit) */
+	ERROR_OTF_INPUT_BIT_WIDTH	= 25,
+	/* invalid frame time for ISP */
+	ERROR_OTF_INPUT_USER_FRAMETILE = 26,
+
+	ERROR_DMA_INPUT_NONE		= ERROR_COMMON_NONE,
+	/* invalid width (DRC: 128~8192, FD: 32~8190) */
+	ERROR_DMA_INPUT_WIDTH		= 31,
+	/* invalid height (DRC: 64~8192, FD: 16~8190) */
+	ERROR_DMA_INPUT_HEIGHT		= 32,
+	/* invalid format (DRC: YUV444 or YUV422, FD: YUV444, 422, 420) */
+	ERROR_DMA_INPUT_FORMAT		= 33,
+	/* invalid bit-width (DRC: 8~12bit, FD: 8bit) */
+	ERROR_DMA_INPUT_BIT_WIDTH	= 34,
+	/* invalid order(DRC: YYCbCrorYCbYCr, FD:NO,YYCbCr,YCbYCr,CbCr,CrCb) */
+	ERROR_DMA_INPUT_ORDER		= 35,
+	/* invalid palne (DRC: 3, FD: 1, 2, 3) */
+	ERROR_DMA_INPUT_PLANE		= 36,
+
+	ERROR_OTF_OUTPUT_NONE		= ERROR_COMMON_NONE,
+	/* invalid width (DRC: 128~8192) */
+	ERROR_OTF_OUTPUT_WIDTH		= 41,
+	/* invalid height (DRC: 64~8192) */
+	ERROR_OTF_OUTPUT_HEIGHT		= 42,
+	/* invalid format (DRC: YUV444) */
+	ERROR_OTF_OUTPUT_FORMAT		= 43,
+	/* invalid bit-width (DRC: 8~12bits) */
+	ERROR_OTF_OUTPUT_BIT_WIDTH	= 44,
+	/* invalid crop size (ODC: left>2, right>10) */
+	ERROR_OTF_OUTPUT_CROP		= 45,
+
+	ERROR_DMA_OUTPUT_NONE		= ERROR_COMMON_NONE,
+	ERROR_DMA_OUTPUT_WIDTH		= 51,	/* invalid width */
+	ERROR_DMA_OUTPUT_HEIGHT		= 52,	/* invalid height */
+	ERROR_DMA_OUTPUT_FORMAT		= 53,	/* invalid format */
+	ERROR_DMA_OUTPUT_BIT_WIDTH	= 54,	/* invalid bit-width */
+	ERROR_DMA_OUTPUT_PLANE		= 55,	/* invalid plane */
+	ERROR_DMA_OUTPUT_ORDER		= 56,	/* invalid order */
+	ERROR_DMA_OUTPUT_BUF		= 57,	/* invalid buffer info */
+
+	ERROR_GLOBAL_SHOTMODE_NONE	= ERROR_COMMON_NONE,
+
+	/* SENSOR Error(100~199) */
+	ERROR_SENSOR_NONE		= ERROR_COMMON_NONE,
+	ERROR_SENSOR_I2C_FAIL		= 101,
+	ERROR_SENSOR_INVALID_FRAMERATE,
+	ERROR_SENSOR_INVALID_EXPOSURETIME,
+	ERROR_SENSOR_INVALID_SIZE,
+	ERROR_SENSOR_ACTURATOR_INIT_FAIL,
+	ERROR_SENSOR_INVALID_AF_POS,
+	ERROR_SENSOR_UNSUPPORT_FUNC,
+	ERROR_SENSOR_UNSUPPORT_PERI,
+	ERROR_SENSOR_UNSUPPORT_AF,
+	ERROR_SENSOR_FLASH_FAIL,
+	ERROR_SENSOR_START_FAIL,
+	ERROR_SENSOR_STOP_FAIL,
+
+	/* ISP Error (200~299) */
+	ERROR_ISP_AF_NONE		= ERROR_COMMON_NONE,
+	ERROR_ISP_AF_BUSY		= 201,
+	ERROR_ISP_AF_INVALID_COMMAND	= 202,
+	ERROR_ISP_AF_INVALID_MODE	= 203,
+	ERROR_ISP_FLASH_NONE		= ERROR_COMMON_NONE,
+	ERROR_ISP_AWB_NONE		= ERROR_COMMON_NONE,
+	ERROR_ISP_IMAGE_EFFECT_NONE	= ERROR_COMMON_NONE,
+	ERROR_ISP_IMAGE_EFFECT_INVALID	= 231,
+	ERROR_ISP_ISO_NONE		= ERROR_COMMON_NONE,
+	ERROR_ISP_ADJUST_NONE		= ERROR_COMMON_NONE,
+	ERROR_ISP_METERING_NONE		= ERROR_COMMON_NONE,
+	ERROR_ISP_AFC_NONE		= ERROR_COMMON_NONE,
+
+	/* DRC Error (300~399) */
+
+	/* FD Error  (400~499) */
+	ERROR_FD_NONE					= ERROR_COMMON_NONE,
+	/* Invalid max number (1~16) */
+	ERROR_FD_CONFIG_MAX_NUMBER_STATE		= 401,
+	ERROR_FD_CONFIG_MAX_NUMBER_INVALID		= 402,
+	ERROR_FD_CONFIG_YAW_ANGLE_STATE			= 403,
+	ERROR_FD_CONFIG_YAW_ANGLE_INVALID		= 404,
+	ERROR_FD_CONFIG_ROLL_ANGLE_STATE		= 405,
+	ERROR_FD_CONFIG_ROLL_ANGLE_INVALID		= 406,
+	ERROR_FD_CONFIG_SMILE_MODE_INVALID		= 407,
+	ERROR_FD_CONFIG_BLINK_MODE_INVALID		= 408,
+	ERROR_FD_CONFIG_EYES_DETECT_INVALID		= 409,
+	ERROR_FD_CONFIG_MOUTH_DETECT_INVALID		= 410,
+	ERROR_FD_CONFIG_ORIENTATION_STATE		= 411,
+	ERROR_FD_CONFIG_ORIENTATION_INVALID		= 412,
+	ERROR_FD_CONFIG_ORIENTATION_VALUE_INVALID	= 413,
+	/* PARAM_FdResultStr can be only applied
+	 * in ready-state or stream off */
+	ERROR_FD_RESULT				= 414,
+	/* PARAM_FdModeStr can be only applied
+	 * in ready-state or stream off */
+	ERROR_FD_MODE					= 415,
+
+	/*SCALER ERR(500~599)*/
+	ERROR_SCALER_NONE			= ERROR_COMMON_NONE,
+	ERROR_SCALER_DMA_OUTSEL			= 501,
+	ERROR_SCALER_H_RATIO			= 502,
+	ERROR_SCALER_V_RATIO			= 503,
+	ERROR_SCALER_FRAME_BUFFER_SEQ		= 504,
+
+	ERROR_SCALER_IMAGE_EFFECT		= 510,
+
+	ERROR_SCALER_ROTATE			= 520,
+	ERROR_SCALER_FLIP			= 521,
+
+};
+
+#endif
diff --git a/drivers/media/platform/exynos5-is/fimc-is-metadata.h b/drivers/media/platform/exynos5-is/fimc-is-metadata.h
new file mode 100644
index 0000000..02367c4
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-metadata.h
@@ -0,0 +1,767 @@
+/*
+ * Samsung EXYNOS5 FIMC-IS (Imaging Subsystem) driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Kil-yeon Lim <kilyeon.im@samsung.com>
+ * Arun Kumar K <arun.kk@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_IS_METADATA_H_
+#define FIMC_IS_METADATA_H_
+
+struct rational {
+	uint32_t num;
+	uint32_t den;
+};
+
+#define CAMERA2_MAX_AVAILABLE_MODE	21
+#define CAMERA2_MAX_FACES		16
+
+/*
+ * Controls/dynamic metadata
+ */
+
+enum metadata_mode {
+	METADATA_MODE_NONE,
+	METADATA_MODE_FULL
+};
+
+struct camera2_request_ctl {
+	uint32_t		id;
+	enum metadata_mode	metadatamode;
+	uint8_t			outputstreams[16];
+	uint32_t		framecount;
+};
+
+struct camera2_request_dm {
+	uint32_t		id;
+	enum metadata_mode	metadatamode;
+	uint32_t		framecount;
+};
+
+
+
+enum optical_stabilization_mode {
+	OPTICAL_STABILIZATION_MODE_OFF,
+	OPTICAL_STABILIZATION_MODE_ON
+};
+
+enum lens_facing {
+	LENS_FACING_BACK,
+	LENS_FACING_FRONT
+};
+
+struct camera2_lens_ctl {
+	uint32_t				focus_distance;
+	float					aperture;
+	float					focal_length;
+	float					filter_density;
+	enum optical_stabilization_mode		optical_stabilization_mode;
+};
+
+struct camera2_lens_dm {
+	uint32_t				focus_distance;
+	float					aperture;
+	float					focal_length;
+	float					filter_density;
+	enum optical_stabilization_mode		optical_stabilization_mode;
+	float					focus_range[2];
+};
+
+struct camera2_lens_sm {
+	float				minimum_focus_distance;
+	float				hyper_focal_distance;
+	float				available_focal_length[2];
+	float				available_apertures;
+	/* assuming 1 aperture */
+	float				available_filter_densities;
+	/* assuming 1 ND filter value */
+	enum optical_stabilization_mode	available_optical_stabilization;
+	/* assuming 1 */
+	uint32_t			shading_map_size;
+	float				shading_map[3][40][30];
+	uint32_t			geometric_correction_map_size;
+	float				geometric_correction_map[2][3][40][30];
+	enum lens_facing		facing;
+	float				position[2];
+};
+
+enum sensor_colorfilter_arrangement {
+	SENSOR_COLORFILTER_ARRANGEMENT_RGGB,
+	SENSOR_COLORFILTER_ARRANGEMENT_GRBG,
+	SENSOR_COLORFILTER_ARRANGEMENT_GBRG,
+	SENSOR_COLORFILTER_ARRANGEMENT_BGGR,
+	SENSOR_COLORFILTER_ARRANGEMENT_RGB
+};
+
+enum sensor_ref_illuminant {
+	SENSOR_ILLUMINANT_DAYLIGHT = 1,
+	SENSOR_ILLUMINANT_FLUORESCENT = 2,
+	SENSOR_ILLUMINANT_TUNGSTEN = 3,
+	SENSOR_ILLUMINANT_FLASH = 4,
+	SENSOR_ILLUMINANT_FINE_WEATHER = 9,
+	SENSOR_ILLUMINANT_CLOUDY_WEATHER = 10,
+	SENSOR_ILLUMINANT_SHADE = 11,
+	SENSOR_ILLUMINANT_DAYLIGHT_FLUORESCENT = 12,
+	SENSOR_ILLUMINANT_DAY_WHITE_FLUORESCENT = 13,
+	SENSOR_ILLUMINANT_COOL_WHITE_FLUORESCENT = 14,
+	SENSOR_ILLUMINANT_WHITE_FLUORESCENT = 15,
+	SENSOR_ILLUMINANT_STANDARD_A = 17,
+	SENSOR_ILLUMINANT_STANDARD_B = 18,
+	SENSOR_ILLUMINANT_STANDARD_C = 19,
+	SENSOR_ILLUMINANT_D55 = 20,
+	SENSOR_ILLUMINANT_D65 = 21,
+	SENSOR_ILLUMINANT_D75 = 22,
+	SENSOR_ILLUMINANT_D50 = 23,
+	SENSOR_ILLUMINANT_ISO_STUDIO_TUNGSTEN = 24
+};
+
+struct camera2_sensor_ctl {
+	/* unit : nano */
+	uint64_t	exposure_time;
+	/* unit : nano(It's min frame duration */
+	uint64_t	frame_duration;
+	/* unit : percent(need to change ISO value?) */
+	uint32_t	sensitivity;
+};
+
+struct camera2_sensor_dm {
+	uint64_t	exposure_time;
+	uint64_t	frame_duration;
+	uint32_t	sensitivity;
+	uint64_t	timestamp;
+};
+
+struct camera2_sensor_sm {
+	uint32_t	exposure_time_range[2];
+	uint32_t	max_frame_duration;
+	/* list of available sensitivities. */
+	uint32_t	available_sensitivities[10];
+	enum sensor_colorfilter_arrangement colorfilter_arrangement;
+	float		physical_size[2];
+	uint32_t	pixel_array_size[2];
+	uint32_t	active_array_size[4];
+	uint32_t	white_level;
+	uint32_t	black_level_pattern[4];
+	struct rational	color_transform1[9];
+	struct rational	color_transform2[9];
+	enum sensor_ref_illuminant	reference_illuminant1;
+	enum sensor_ref_illuminant	reference_illuminant2;
+	struct rational	forward_matrix1[9];
+	struct rational	forward_matrix2[9];
+	struct rational	calibration_transform1[9];
+	struct rational	calibration_transform2[9];
+	struct rational	base_gain_factor;
+	uint32_t	max_analog_sensitivity;
+	float		noise_model_coefficients[2];
+	uint32_t	orientation;
+};
+
+
+
+enum flash_mode {
+	CAM2_FLASH_MODE_OFF = 1,
+	CAM2_FLASH_MODE_SINGLE,
+	CAM2_FLASH_MODE_TORCH,
+	CAM2_FLASH_MODE_BEST
+};
+
+struct camera2_flash_ctl {
+	enum flash_mode		flash_mode;
+	uint32_t		firing_power;
+	uint64_t		firing_time;
+};
+
+struct camera2_flash_dm {
+	enum flash_mode		flash_mode;
+	/* 10 is max power */
+	uint32_t		firing_power;
+	/* unit : microseconds */
+	uint64_t		firing_time;
+	/* 1 : stable, 0 : unstable */
+	uint32_t		firing_stable;
+	/* 1 : success, 0 : fail */
+	uint32_t		decision;
+};
+
+struct camera2_flash_sm {
+	uint32_t	available;
+	uint64_t	charge_duration;
+};
+
+enum processing_mode {
+	PROCESSING_MODE_OFF = 1,
+	PROCESSING_MODE_FAST,
+	PROCESSING_MODE_HIGH_QUALITY
+};
+
+
+struct camera2_hotpixel_ctl {
+	enum processing_mode	mode;
+};
+
+struct camera2_hotpixel_dm {
+	enum processing_mode	mode;
+};
+
+struct camera2_demosaic_ctl {
+	enum processing_mode	mode;
+};
+
+struct camera2_demosaic_dm {
+	enum processing_mode	mode;
+};
+
+struct camera2_noise_reduction_ctl {
+	enum processing_mode	mode;
+	uint32_t		strength;
+};
+
+struct camera2_noise_reduction_dm {
+	enum processing_mode	mode;
+	uint32_t		strength;
+};
+
+struct camera2_shading_ctl {
+	enum processing_mode	mode;
+};
+
+struct camera2_shading_dm {
+	enum processing_mode	mode;
+};
+
+struct camera2_geometric_ctl {
+	enum processing_mode	mode;
+};
+
+struct camera2_geometric_dm {
+	enum processing_mode	mode;
+};
+
+enum color_correction_mode {
+	COLOR_CORRECTION_MODE_FAST = 1,
+	COLOR_CORRECTION_MODE_HIGH_QUALITY,
+	COLOR_CORRECTION_MODE_TRANSFORM_MATRIX,
+	COLOR_CORRECTION_MODE_EFFECT_MONO,
+	COLOR_CORRECTION_MODE_EFFECT_NEGATIVE,
+	COLOR_CORRECTION_MODE_EFFECT_SOLARIZE,
+	COLOR_CORRECTION_MODE_EFFECT_SEPIA,
+	COLOR_CORRECTION_MODE_EFFECT_POSTERIZE,
+	COLOR_CORRECTION_MODE_EFFECT_WHITEBOARD,
+	COLOR_CORRECTION_MODE_EFFECT_BLACKBOARD,
+	COLOR_CORRECTION_MODE_EFFECT_AQUA
+};
+
+
+struct camera2_color_correction_ctl {
+	enum color_correction_mode	mode;
+	float				transform[9];
+	uint32_t			hue;
+	uint32_t			saturation;
+	uint32_t			brightness;
+};
+
+struct camera2_color_correction_dm {
+	enum color_correction_mode	mode;
+	float				transform[9];
+	uint32_t			hue;
+	uint32_t			saturation;
+	uint32_t			brightness;
+};
+
+struct camera2_color_correction_sm {
+	/* assuming 10 supported modes */
+	uint8_t			available_modes[CAMERA2_MAX_AVAILABLE_MODE];
+	uint32_t		hue_range[2];
+	uint32_t		saturation_range[2];
+	uint32_t		brightness_range[2];
+};
+
+enum tonemap_mode {
+	TONEMAP_MODE_FAST = 1,
+	TONEMAP_MODE_HIGH_QUALITY,
+	TONEMAP_MODE_CONTRAST_CURVE
+};
+
+struct camera2_tonemap_ctl {
+	enum tonemap_mode		mode;
+	/* assuming maxCurvePoints = 64 */
+	float				curve_red[64];
+	float				curve_green[64];
+	float				curve_blue[64];
+};
+
+struct camera2_tonemap_dm {
+	enum tonemap_mode		mode;
+	/* assuming maxCurvePoints = 64 */
+	float				curve_red[64];
+	float				curve_green[64];
+	float				curve_blue[64];
+};
+
+struct camera2_tonemap_sm {
+	uint32_t	max_curve_points;
+};
+
+struct camera2_edge_ctl {
+	enum processing_mode	mode;
+	uint32_t		strength;
+};
+
+struct camera2_edge_dm {
+	enum processing_mode	mode;
+	uint32_t		strength;
+};
+
+enum scaler_formats {
+	SCALER_FORMAT_BAYER_RAW,
+	SCALER_FORMAT_YV12,
+	SCALER_FORMAT_NV21,
+	SCALER_FORMAT_JPEG,
+	SCALER_FORMAT_UNKNOWN
+};
+
+struct camera2_scaler_ctl {
+	uint32_t	crop_region[3];
+};
+
+struct camera2_scaler_dm {
+	uint32_t	crop_region[3];
+};
+
+struct camera2_scaler_sm {
+	enum scaler_formats available_formats[4];
+	/* assuming # of availableFormats = 4 */
+	uint32_t	available_raw_sizes;
+	uint64_t	available_raw_min_durations;
+	/* needs check */
+	uint32_t	available_processed_sizes[8];
+	uint64_t	available_processed_min_durations[8];
+	uint32_t	available_jpeg_sizes[8][2];
+	uint64_t	available_jpeg_min_durations[8];
+	uint32_t	available_max_digital_zoom[8];
+};
+
+struct camera2_jpeg_ctl {
+	uint32_t	quality;
+	uint32_t	thumbnail_size[2];
+	uint32_t	thumbnail_quality;
+	double		gps_coordinates[3];
+	uint32_t	gps_processing_method;
+	uint64_t	gps_timestamp;
+	uint32_t	orientation;
+};
+
+struct camera2_jpeg_dm {
+	uint32_t	quality;
+	uint32_t	thumbnail_size[2];
+	uint32_t	thumbnail_quality;
+	double		gps_coordinates[3];
+	uint32_t	gps_processing_method;
+	uint64_t	gps_timestamp;
+	uint32_t	orientation;
+};
+
+struct camera2_jpeg_sm {
+	uint32_t	available_thumbnail_sizes[8][2];
+	uint32_t	maxsize;
+	/* assuming supported size=8 */
+};
+
+enum face_detect_mode {
+	FACEDETECT_MODE_OFF = 1,
+	FACEDETECT_MODE_SIMPLE,
+	FACEDETECT_MODE_FULL
+};
+
+enum stats_mode {
+	STATS_MODE_OFF = 1,
+	STATS_MODE_ON
+};
+
+struct camera2_stats_ctl {
+	enum face_detect_mode	face_detect_mode;
+	enum stats_mode		histogram_mode;
+	enum stats_mode		sharpness_map_mode;
+};
+
+
+struct camera2_stats_dm {
+	enum face_detect_mode	face_detect_mode;
+	uint32_t		face_rectangles[CAMERA2_MAX_FACES][4];
+	uint8_t			face_scores[CAMERA2_MAX_FACES];
+	uint32_t		face_landmarks[CAMERA2_MAX_FACES][6];
+	uint32_t		face_ids[CAMERA2_MAX_FACES];
+	enum stats_mode		histogram_mode;
+	uint32_t		histogram[3 * 256];
+	enum stats_mode		sharpness_map_mode;
+};
+
+
+struct camera2_stats_sm {
+	uint8_t		available_face_detect_modes[CAMERA2_MAX_AVAILABLE_MODE];
+	/* assuming supported modes = 3 */
+	uint32_t	max_face_count;
+	uint32_t	histogram_bucket_count;
+	uint32_t	max_histogram_count;
+	uint32_t	sharpness_map_size[2];
+	uint32_t	max_sharpness_map_value;
+};
+
+enum aa_capture_intent {
+	AA_CAPTURE_INTENT_CUSTOM = 0,
+	AA_CAPTURE_INTENT_PREVIEW,
+	AA_CAPTURE_INTENT_STILL_CAPTURE,
+	AA_CAPTURE_INTENT_VIDEO_RECORD,
+	AA_CAPTURE_INTENT_VIDEO_SNAPSHOT,
+	AA_CAPTURE_INTENT_ZERO_SHUTTER_LAG
+};
+
+enum aa_mode {
+	AA_CONTROL_OFF = 1,
+	AA_CONTROL_AUTO,
+	AA_CONTROL_USE_SCENE_MODE
+};
+
+enum aa_scene_mode {
+	AA_SCENE_MODE_UNSUPPORTED = 1,
+	AA_SCENE_MODE_FACE_PRIORITY,
+	AA_SCENE_MODE_ACTION,
+	AA_SCENE_MODE_PORTRAIT,
+	AA_SCENE_MODE_LANDSCAPE,
+	AA_SCENE_MODE_NIGHT,
+	AA_SCENE_MODE_NIGHT_PORTRAIT,
+	AA_SCENE_MODE_THEATRE,
+	AA_SCENE_MODE_BEACH,
+	AA_SCENE_MODE_SNOW,
+	AA_SCENE_MODE_SUNSET,
+	AA_SCENE_MODE_STEADYPHOTO,
+	AA_SCENE_MODE_FIREWORKS,
+	AA_SCENE_MODE_SPORTS,
+	AA_SCENE_MODE_PARTY,
+	AA_SCENE_MODE_CANDLELIGHT,
+	AA_SCENE_MODE_BARCODE,
+	AA_SCENE_MODE_NIGHT_CAPTURE
+};
+
+enum aa_effect_mode {
+	AA_EFFECT_OFF = 1,
+	AA_EFFECT_MONO,
+	AA_EFFECT_NEGATIVE,
+	AA_EFFECT_SOLARIZE,
+	AA_EFFECT_SEPIA,
+	AA_EFFECT_POSTERIZE,
+	AA_EFFECT_WHITEBOARD,
+	AA_EFFECT_BLACKBOARD,
+	AA_EFFECT_AQUA
+};
+
+enum aa_aemode {
+	AA_AEMODE_OFF = 1,
+	AA_AEMODE_LOCKED,
+	AA_AEMODE_ON,
+	AA_AEMODE_ON_AUTO_FLASH,
+	AA_AEMODE_ON_ALWAYS_FLASH,
+	AA_AEMODE_ON_AUTO_FLASH_REDEYE
+};
+
+enum aa_ae_flashmode {
+	/* all flash control stop */
+	AA_FLASHMODE_OFF = 1,
+	/* internal 3A can control flash */
+	AA_FLASHMODE_ON,
+	/* internal 3A can do auto flash algorithm */
+	AA_FLASHMODE_AUTO,
+	/* internal 3A can fire flash by auto result */
+	AA_FLASHMODE_CAPTURE,
+	/* internal 3A can control flash forced */
+	AA_FLASHMODE_ON_ALWAYS
+
+};
+
+enum aa_ae_antibanding_mode {
+	AA_AE_ANTIBANDING_OFF = 1,
+	AA_AE_ANTIBANDING_50HZ,
+	AA_AE_ANTIBANDING_60HZ,
+	AA_AE_ANTIBANDING_AUTO
+};
+
+enum aa_awbmode {
+	AA_AWBMODE_OFF = 1,
+	AA_AWBMODE_LOCKED,
+	AA_AWBMODE_WB_AUTO,
+	AA_AWBMODE_WB_INCANDESCENT,
+	AA_AWBMODE_WB_FLUORESCENT,
+	AA_AWBMODE_WB_WARM_FLUORESCENT,
+	AA_AWBMODE_WB_DAYLIGHT,
+	AA_AWBMODE_WB_CLOUDY_DAYLIGHT,
+	AA_AWBMODE_WB_TWILIGHT,
+	AA_AWBMODE_WB_SHADE
+};
+
+enum aa_afmode {
+	AA_AFMODE_OFF = 1,
+	AA_AFMODE_AUTO,
+	AA_AFMODE_MACRO,
+	AA_AFMODE_CONTINUOUS_VIDEO,
+	AA_AFMODE_CONTINUOUS_PICTURE,
+	AA_AFMODE_EDOF
+};
+
+enum aa_afstate {
+	AA_AFSTATE_INACTIVE = 1,
+	AA_AFSTATE_PASSIVE_SCAN,
+	AA_AFSTATE_ACTIVE_SCAN,
+	AA_AFSTATE_AF_ACQUIRED_FOCUS,
+	AA_AFSTATE_AF_FAILED_FOCUS
+};
+
+enum ae_state {
+	AE_STATE_INACTIVE = 1,
+	AE_STATE_SEARCHING,
+	AE_STATE_CONVERGED,
+	AE_STATE_LOCKED,
+	AE_STATE_FLASH_REQUIRED,
+	AE_STATE_PRECAPTURE
+};
+
+enum awb_state {
+	AWB_STATE_INACTIVE = 1,
+	AWB_STATE_SEARCHING,
+	AWB_STATE_CONVERGED,
+	AWB_STATE_LOCKED
+};
+
+enum aa_isomode {
+	AA_ISOMODE_AUTO = 1,
+	AA_ISOMODE_MANUAL,
+};
+
+struct camera2_aa_ctl {
+	enum aa_capture_intent		capture_intent;
+	enum aa_mode			mode;
+	enum aa_scene_mode		scene_mode;
+	uint32_t			video_stabilization_mode;
+	enum aa_aemode			ae_mode;
+	uint32_t			ae_regions[5];
+	/* 5 per region(x1,y1,x2,y2,weight). Currently assuming 1 region. */
+	int32_t				ae_exp_compensation;
+	uint32_t			ae_target_fps_range[2];
+	enum aa_ae_antibanding_mode	ae_anti_banding_mode;
+	enum aa_ae_flashmode		ae_flash_mode;
+	enum aa_awbmode			awb_mode;
+	uint32_t			awb_regions[5];
+	/* 5 per region(x1,y1,x2,y2,weight). Currently assuming 1 region. */
+	enum aa_afmode			af_mode;
+	uint32_t			af_regions[5];
+	/* 5 per region(x1,y1,x2,y2,weight). Currently assuming 1 region. */
+	uint32_t			af_trigger;
+	enum aa_isomode			iso_mode;
+	uint32_t			iso_value;
+
+};
+
+struct camera2_aa_dm {
+	enum aa_mode				mode;
+	enum aa_effect_mode			effect_mode;
+	enum aa_scene_mode			scene_mode;
+	uint32_t				video_stabilization_mode;
+	enum aa_aemode				ae_mode;
+	uint32_t				ae_regions[5];
+	/* 5 per region(x1,y1,x2,y2,weight). Currently assuming 1 region. */
+	enum ae_state				ae_state;
+	enum aa_ae_flashmode			ae_flash_mode;
+	enum aa_awbmode				awb_mode;
+	uint32_t				awb_regions[5];
+	enum awb_state				awb_state;
+	/* 5 per region(x1,y1,x2,y2,weight). Currently assuming 1 region. */
+	enum aa_afmode				af_mode;
+	uint32_t				af_regions[5];
+	/* 5 per region(x1,y1,x2,y2,weight). Currently assuming 1 region */
+	enum aa_afstate				af_state;
+	enum aa_isomode				iso_mode;
+	uint32_t				iso_value;
+};
+
+struct camera2_aa_sm {
+	uint8_t	available_scene_modes[CAMERA2_MAX_AVAILABLE_MODE];
+	uint8_t	available_effects[CAMERA2_MAX_AVAILABLE_MODE];
+	/* Assuming # of available scene modes = 10 */
+	uint32_t max_regions;
+	uint8_t ae_available_modes[CAMERA2_MAX_AVAILABLE_MODE];
+	/* Assuming # of available ae modes = 8 */
+	struct rational	ae_compensation_step;
+	int32_t	ae_compensation_range[2];
+	uint32_t ae_available_target_fps_ranges[CAMERA2_MAX_AVAILABLE_MODE][2];
+	uint8_t	 ae_available_antibanding_modes[CAMERA2_MAX_AVAILABLE_MODE];
+	uint8_t	awb_available_modes[CAMERA2_MAX_AVAILABLE_MODE];
+	/* Assuming # of awbAvailableModes = 10 */
+	uint8_t	af_available_modes[CAMERA2_MAX_AVAILABLE_MODE];
+	/* Assuming # of afAvailableModes = 4 */
+	uint8_t	available_video_stabilization_modes[4];
+	/* Assuming # of availableVideoStabilizationModes = 4 */
+	uint32_t iso_range[2];
+};
+
+struct camera2_lens_usm {
+	/* Frame delay between sending command and applying frame data */
+	uint32_t	focus_distance_frame_delay;
+};
+
+struct camera2_sensor_usm {
+	/* Frame delay between sending command and applying frame data */
+	uint32_t	exposure_time_frame_delay;
+	uint32_t	frame_duration_frame_delay;
+	uint32_t	sensitivity_frame_delay;
+};
+
+struct camera2_flash_usm {
+	/* Frame delay between sending command and applying frame data */
+	uint32_t	flash_mode_frame_delay;
+	uint32_t	firing_power_frame_delay;
+	uint64_t	firing_time_frame_delay;
+};
+
+struct camera2_ctl {
+	struct camera2_request_ctl		request;
+	struct camera2_lens_ctl			lens;
+	struct camera2_sensor_ctl		sensor;
+	struct camera2_flash_ctl		flash;
+	struct camera2_hotpixel_ctl		hotpixel;
+	struct camera2_demosaic_ctl		demosaic;
+	struct camera2_noise_reduction_ctl	noise;
+	struct camera2_shading_ctl		shading;
+	struct camera2_geometric_ctl		geometric;
+	struct camera2_color_correction_ctl	color;
+	struct camera2_tonemap_ctl		tonemap;
+	struct camera2_edge_ctl			edge;
+	struct camera2_scaler_ctl		scaler;
+	struct camera2_jpeg_ctl			jpeg;
+	struct camera2_stats_ctl		stats;
+	struct camera2_aa_ctl			aa;
+};
+
+struct camera2_dm {
+	struct camera2_request_dm		request;
+	struct camera2_lens_dm			lens;
+	struct camera2_sensor_dm		sensor;
+	struct camera2_flash_dm			flash;
+	struct camera2_hotpixel_dm		hotpixel;
+	struct camera2_demosaic_dm		demosaic;
+	struct camera2_noise_reduction_dm	noise;
+	struct camera2_shading_dm		shading;
+	struct camera2_geometric_dm		geometric;
+	struct camera2_color_correction_dm	color;
+	struct camera2_tonemap_dm		tonemap;
+	struct camera2_edge_dm			edge;
+	struct camera2_scaler_dm		scaler;
+	struct camera2_jpeg_dm			jpeg;
+	struct camera2_stats_dm			stats;
+	struct camera2_aa_dm			aa;
+};
+
+struct camera2_sm {
+	struct camera2_lens_sm			lens;
+	struct camera2_sensor_sm		sensor;
+	struct camera2_flash_sm			flash;
+	struct camera2_color_correction_sm	color;
+	struct camera2_tonemap_sm		tonemap;
+	struct camera2_scaler_sm		scaler;
+	struct camera2_jpeg_sm			jpeg;
+	struct camera2_stats_sm			stats;
+	struct camera2_aa_sm			aa;
+
+	/* User-defined(ispfw specific) static metadata. */
+	struct camera2_lens_usm			lensud;
+	struct camera2_sensor_usm		sensor_ud;
+	struct camera2_flash_usm		flash_ud;
+};
+
+/*
+ * User-defined control for lens.
+ */
+struct camera2_lens_uctl {
+	struct camera2_lens_ctl ctl;
+
+	/* It depends by af algorithm(normally 255 or 1023) */
+	uint32_t        max_pos;
+	/* Some actuator support slew rate control. */
+	uint32_t        slew_rate;
+};
+
+/*
+ * User-defined metadata for lens.
+ */
+struct camera2_lens_udm {
+	/* It depends by af algorithm(normally 255 or 1023) */
+	uint32_t        max_pos;
+	/* Some actuator support slew rate control. */
+	uint32_t        slew_rate;
+};
+
+/*
+ * User-defined control for sensor.
+ */
+struct camera2_sensor_uctl {
+	struct camera2_sensor_ctl ctl;
+	/* Dynamic frame duration.
+	 * This feature is decided to max. value between
+	 * 'sensor.exposureTime'+alpha and 'sensor.frameDuration'.
+	 */
+	uint64_t        dynamic_frame_duration;
+};
+
+struct camera2_scaler_uctl {
+	/* Target address for next frame.
+	 * [0] invalid address, stop
+	 * [others] valid address
+	 */
+	uint32_t scc_target_address[4];
+	uint32_t scp_target_address[4];
+};
+
+struct camera2_flash_uctl {
+	struct camera2_flash_ctl ctl;
+};
+
+struct camera2_uctl {
+	/* Set sensor, lens, flash control for next frame.
+	 * This flag can be combined.
+	 * [0 bit] lens
+	 * [1 bit] sensor
+	 * [2 bit] flash
+	 */
+	uint32_t u_update_bitmap;
+
+	/* For debugging */
+	uint32_t u_frame_number;
+
+	/* isp fw specific control (user-defined) of lens. */
+	struct camera2_lens_uctl	lens_ud;
+	/* isp fw specific control (user-defined) of sensor. */
+	struct camera2_sensor_uctl	sensor_ud;
+	/* isp fw specific control (user-defined) of flash. */
+	struct camera2_flash_uctl	flash_ud;
+
+	struct camera2_scaler_uctl	scaler_ud;
+};
+
+struct camera2_udm {
+	struct camera2_lens_udm		lens;
+};
+
+struct camera2_shot {
+	/* standard area */
+	struct camera2_ctl	ctl;
+	struct camera2_dm	dm;
+	/* user defined area */
+	struct camera2_uctl	uctl;
+	struct camera2_udm	udm;
+	/* magic : 23456789 */
+	uint32_t		magicnumber;
+};
+#endif
diff --git a/drivers/media/platform/exynos5-is/fimc-is-param.h b/drivers/media/platform/exynos5-is/fimc-is-param.h
new file mode 100644
index 0000000..015cc13
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-param.h
@@ -0,0 +1,1159 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd
+ * Kil-yeon Lim <kilyeon.im@samsung.com>
+ * Arun Kumar K <arun.kk@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_IS_PARAM_H
+#define FIMC_IS_PARAM_H
+
+#define MAGIC_NUMBER 0x01020304
+
+#define PARAMETER_MAX_SIZE    128  /* in bytes */
+#define PARAMETER_MAX_MEMBER  (PARAMETER_MAX_SIZE / 4)
+
+enum is_param_set_bit {
+	PARAM_GLOBAL_SHOTMODE = 0,
+	PARAM_SENSOR_CONTROL,
+	PARAM_SENSOR_OTF_INPUT,
+	PARAM_SENSOR_OTF_OUTPUT,
+	PARAM_SENSOR_FRAME_RATE,
+	PARAM_SENSOR_DMA_OUTPUT,
+	PARAM_BUFFER_CONTROL,
+	PARAM_BUFFER_OTF_INPUT,
+	PARAM_BUFFER_OTF_OUTPUT,
+	PARAM_ISP_CONTROL,
+	PARAM_ISP_OTF_INPUT = 10,
+	PARAM_ISP_DMA1_INPUT,
+	PARAM_ISP_DMA2_INPUT,
+	PARAM_ISP_AA,
+	PARAM_ISP_FLASH,
+	PARAM_ISP_AWB,
+	PARAM_ISP_IMAGE_EFFECT,
+	PARAM_ISP_ISO,
+	PARAM_ISP_ADJUST,
+	PARAM_ISP_METERING,
+	PARAM_ISP_AFC = 20,
+	PARAM_ISP_OTF_OUTPUT,
+	PARAM_ISP_DMA1_OUTPUT,
+	PARAM_ISP_DMA2_OUTPUT,
+	PARAM_DRC_CONTROL,
+	PARAM_DRC_OTF_INPUT,
+	PARAM_DRC_DMA_INPUT,
+	PARAM_DRC_OTF_OUTPUT,
+	PARAM_SCALERC_CONTROL,
+	PARAM_SCALERC_OTF_INPUT,
+	PARAM_SCALERC_IMAGE_EFFECT = 30,
+	PARAM_SCALERC_INPUT_CROP,
+	PARAM_SCALERC_OUTPUT_CROP,
+	PARAM_SCALERC_OTF_OUTPUT,
+	PARAM_SCALERC_DMA_OUTPUT = 34,
+	PARAM_ODC_CONTROL,
+	PARAM_ODC_OTF_INPUT,
+	PARAM_ODC_OTF_OUTPUT,
+	PARAM_DIS_CONTROL,
+	PARAM_DIS_OTF_INPUT,
+	PARAM_DIS_OTF_OUTPUT = 40,
+	PARAM_TDNR_CONTROL,
+	PARAM_TDNR_OTF_INPUT,
+	PARAM_TDNR_1ST_FRAME,
+	PARAM_TDNR_OTF_OUTPUT,
+	PARAM_TDNR_DMA_OUTPUT,
+	PARAM_SCALERP_CONTROL,
+	PARAM_SCALERP_OTF_INPUT,
+	PARAM_SCALERP_IMAGE_EFFECT,
+	PARAM_SCALERP_INPUT_CROP,
+	PARAM_SCALERP_OUTPUT_CROP = 50,
+	PARAM_SCALERP_ROTATION,
+	PARAM_SCALERP_FLIP,
+	PARAM_SCALERP_OTF_OUTPUT,
+	PARAM_SCALERP_DMA_OUTPUT,
+	PARAM_FD_CONTROL,
+	PARAM_FD_OTF_INPUT,
+	PARAM_FD_DMA_INPUT,
+	PARAM_FD_CONFIG = 58,
+	PARAM_END,
+};
+
+/* ----------------------  Input  ----------------------------------- */
+enum control_command {
+	CONTROL_COMMAND_STOP	= 0,
+	CONTROL_COMMAND_START	= 1,
+	CONTROL_COMMAND_TEST	= 2
+};
+
+enum bypass_command {
+	CONTROL_BYPASS_DISABLE		= 0,
+	CONTROL_BYPASS_ENABLE		= 1
+};
+
+enum control_error {
+	CONTROL_ERROR_NONE		= 0
+};
+
+enum otf_input_command {
+	OTF_INPUT_COMMAND_DISABLE	= 0,
+	OTF_INPUT_COMMAND_ENABLE	= 1
+};
+
+enum otf_input_format {
+	OTF_INPUT_FORMAT_BAYER		= 0, /* 1 Channel */
+	OTF_INPUT_FORMAT_YUV444		= 1, /* 3 Channel */
+	OTF_INPUT_FORMAT_YUV422		= 2, /* 3 Channel */
+	OTF_INPUT_FORMAT_YUV420		= 3, /* 3 Channel */
+	OTF_INPUT_FORMAT_STRGEN_COLORBAR_BAYER = 10,
+	OTF_INPUT_FORMAT_BAYER_DMA	= 11,
+};
+
+enum otf_input_bitwidth {
+	OTF_INPUT_BIT_WIDTH_14BIT	= 14,
+	OTF_INPUT_BIT_WIDTH_12BIT	= 12,
+	OTF_INPUT_BIT_WIDTH_11BIT	= 11,
+	OTF_INPUT_BIT_WIDTH_10BIT	= 10,
+	OTF_INPUT_BIT_WIDTH_9BIT	= 9,
+	OTF_INPUT_BIT_WIDTH_8BIT	= 8
+};
+
+enum otf_input_order {
+	OTF_INPUT_ORDER_BAYER_GR_BG	= 0,
+	OTF_INPUT_ORDER_BAYER_RG_GB	= 1,
+	OTF_INPUT_ORDER_BAYER_BG_GR	= 2,
+	OTF_INPUT_ORDER_BAYER_GB_RG	= 3
+};
+
+enum otf_intput_error {
+	OTF_INPUT_ERROR_NONE		= 0 /* Input setting is done */
+};
+
+enum dma_input_command {
+	DMA_INPUT_COMMAND_DISABLE	= 0,
+	DMA_INPUT_COMMAND_ENABLE	= 1,
+	DMA_INPUT_COMMAND_BUF_MNGR	= 2,
+	DMA_INPUT_COMMAND_RUN_SINGLE	= 3,
+};
+
+enum dma_inut_format {
+	DMA_INPUT_FORMAT_BAYER		= 0,
+	DMA_INPUT_FORMAT_YUV444		= 1,
+	DMA_INPUT_FORMAT_YUV422		= 2,
+	DMA_INPUT_FORMAT_YUV420		= 3,
+};
+
+enum dma_input_bitwidth {
+	DMA_INPUT_BIT_WIDTH_14BIT	= 14,
+	DMA_INPUT_BIT_WIDTH_12BIT	= 12,
+	DMA_INPUT_BIT_WIDTH_11BIT	= 11,
+	DMA_INPUT_BIT_WIDTH_10BIT	= 10,
+	DMA_INPUT_BIT_WIDTH_9BIT	= 9,
+	DMA_INPUT_BIT_WIDTH_8BIT	= 8
+};
+
+enum dma_input_order {
+	DMA_INPUT_ORDER_NONE	= 0,
+	DMA_INPUT_ORDER_CBCR	= 1,
+	DMA_INPUT_ORDER_CRCB	= 2,
+	DMA_INPUT_ORDER_YCBCR	= 3,
+	DMA_INPUT_ORDER_YYCBCR	= 4,
+	DMA_INPUT_ORDER_YCBYCR	= 5,
+	DMA_INPUT_ORDER_YCRYCB	= 6,
+	DMA_INPUT_ORDER_CBYCRY	= 7,
+	DMA_INPUT_ORDER_CRYCBY	= 8,
+	DMA_INPUT_ORDER_GR_BG	= 9
+};
+
+enum dma_input_error {
+	DMA_INPUT_ERROR_NONE	= 0 /*  DMA input setting is done */
+};
+
+/* ----------------------  Output  ----------------------------------- */
+enum otf_output_crop {
+	OTF_OUTPUT_CROP_DISABLE		= 0,
+	OTF_OUTPUT_CROP_ENABLE		= 1
+};
+
+enum otf_output_command {
+	OTF_OUTPUT_COMMAND_DISABLE	= 0,
+	OTF_OUTPUT_COMMAND_ENABLE	= 1
+};
+
+enum orf_output_format {
+	OTF_OUTPUT_FORMAT_YUV444	= 1,
+	OTF_OUTPUT_FORMAT_YUV422	= 2,
+	OTF_OUTPUT_FORMAT_YUV420	= 3,
+	OTF_OUTPUT_FORMAT_RGB		= 4
+};
+
+enum otf_output_bitwidth {
+	OTF_OUTPUT_BIT_WIDTH_14BIT	= 14,
+	OTF_OUTPUT_BIT_WIDTH_12BIT	= 12,
+	OTF_OUTPUT_BIT_WIDTH_11BIT	= 11,
+	OTF_OUTPUT_BIT_WIDTH_10BIT	= 10,
+	OTF_OUTPUT_BIT_WIDTH_9BIT	= 9,
+	OTF_OUTPUT_BIT_WIDTH_8BIT	= 8
+};
+
+enum otf_output_order {
+	OTF_OUTPUT_ORDER_BAYER_GR_BG	= 0,
+};
+
+enum otf_output_error {
+	OTF_OUTPUT_ERROR_NONE = 0 /* Output Setting is done */
+};
+
+enum dma_output_command {
+	DMA_OUTPUT_COMMAND_DISABLE	= 0,
+	DMA_OUTPUT_COMMAND_ENABLE	= 1,
+	DMA_OUTPUT_COMMAND_BUF_MNGR	= 2,
+	DMA_OUTPUT_UPDATE_MASK_BITS	= 3
+};
+
+enum dma_output_format {
+	DMA_OUTPUT_FORMAT_BAYER		= 0,
+	DMA_OUTPUT_FORMAT_YUV444	= 1,
+	DMA_OUTPUT_FORMAT_YUV422	= 2,
+	DMA_OUTPUT_FORMAT_YUV420	= 3,
+	DMA_OUTPUT_FORMAT_RGB		= 4
+};
+
+enum dma_output_bitwidth {
+	DMA_OUTPUT_BIT_WIDTH_14BIT	= 14,
+	DMA_OUTPUT_BIT_WIDTH_12BIT	= 12,
+	DMA_OUTPUT_BIT_WIDTH_11BIT	= 11,
+	DMA_OUTPUT_BIT_WIDTH_10BIT	= 10,
+	DMA_OUTPUT_BIT_WIDTH_9BIT	= 9,
+	DMA_OUTPUT_BIT_WIDTH_8BIT	= 8
+};
+
+enum dma_output_order {
+	DMA_OUTPUT_ORDER_NONE		= 0,
+	DMA_OUTPUT_ORDER_CBCR		= 1,
+	DMA_OUTPUT_ORDER_CRCB		= 2,
+	DMA_OUTPUT_ORDER_YYCBCR		= 3,
+	DMA_OUTPUT_ORDER_YCBYCR		= 4,
+	DMA_OUTPUT_ORDER_YCRYCB		= 5,
+	DMA_OUTPUT_ORDER_CBYCRY		= 6,
+	DMA_OUTPUT_ORDER_CRYCBY		= 7,
+	DMA_OUTPUT_ORDER_YCBCR		= 8,
+	DMA_OUTPUT_ORDER_CRYCB		= 9,
+	DMA_OUTPUT_ORDER_CRCBY		= 10,
+	DMA_OUTPUT_ORDER_CBYCR		= 11,
+	DMA_OUTPUT_ORDER_YCRCB		= 12,
+	DMA_OUTPUT_ORDER_CBCRY		= 13,
+	DMA_OUTPUT_ORDER_BGR		= 14,
+	DMA_OUTPUT_ORDER_GB_BG		= 15
+};
+
+enum dma_output_notify_dma_done {
+	DMA_OUTPUT_NOTIFY_DMA_DONE_DISABLE	= 0,
+	DMA_OUTPUT_NOTIFY_DMA_DONE_ENBABLE	= 1,
+};
+
+enum dma_output_error {
+	DMA_OUTPUT_ERROR_NONE		= 0 /* DMA output setting is done */
+};
+
+/* ----------------------  Global  ----------------------------------- */
+enum global_shotmode_error {
+	GLOBAL_SHOTMODE_ERROR_NONE	= 0 /* shot-mode setting is done */
+};
+
+/* -------------------------  AA  ------------------------------------ */
+enum isp_lock_command {
+	ISP_AA_COMMAND_START	= 0,
+	ISP_AA_COMMAND_STOP	= 1
+};
+
+enum isp_lock_target {
+	ISP_AA_TARGET_AF	= 1,
+	ISP_AA_TARGET_AE	= 2,
+	ISP_AA_TARGET_AWB	= 4
+};
+
+enum isp_af_mode {
+	ISP_AF_MANUAL = 0,
+	ISP_AF_SINGLE,
+	ISP_AF_CONTINUOUS,
+	ISP_AF_REGION,
+	ISP_AF_SLEEP,
+	ISP_AF_INIT,
+	ISP_AF_SET_CENTER_WINDOW,
+	ISP_AF_SET_TOUCH_WINDOW,
+	ISP_AF_SET_FACE_WINDOW
+};
+
+enum isp_af_scene {
+	ISP_AF_SCENE_NORMAL		= 0,
+	ISP_AF_SCENE_MACRO		= 1
+};
+
+enum isp_af_touch {
+	ISP_AF_TOUCH_DISABLE = 0,
+	ISP_AF_TOUCH_ENABLE
+};
+
+enum isp_af_face {
+	ISP_AF_FACE_DISABLE = 0,
+	ISP_AF_FACE_ENABLE
+};
+
+enum isp_af_reponse {
+	ISP_AF_RESPONSE_PREVIEW = 0,
+	ISP_AF_RESPONSE_MOVIE
+};
+
+enum isp_af_sleep {
+	ISP_AF_SLEEP_OFF		= 0,
+	ISP_AF_SLEEP_ON			= 1
+};
+
+enum isp_af_continuous {
+	ISP_AF_CONTINUOUS_DISABLE	= 0,
+	ISP_AF_CONTINUOUS_ENABLE	= 1
+};
+
+enum isp_af_error {
+	ISP_AF_ERROR_NONE		= 0, /* AF mode change is done */
+	ISP_AF_EROOR_NO_LOCK_DONE	= 1  /* AF lock is done */
+};
+
+/* -------------------------  Flash  ------------------------------------- */
+enum isp_flash_command {
+	ISP_FLASH_COMMAND_DISABLE	= 0,
+	ISP_FLASH_COMMAND_MANUALON	= 1, /* (forced flash) */
+	ISP_FLASH_COMMAND_AUTO		= 2,
+	ISP_FLASH_COMMAND_TORCH		= 3,   /* 3 sec */
+	ISP_FLASH_COMMAND_FLASH_ON	= 4,
+	ISP_FLASH_COMMAND_CAPTURE	= 5,
+	ISP_FLASH_COMMAND_TRIGGER	= 6,
+	ISP_FLASH_COMMAND_CALIBRATION	= 7
+};
+
+enum isp_flash_redeye {
+	ISP_FLASH_REDEYE_DISABLE	= 0,
+	ISP_FLASH_REDEYE_ENABLE		= 1
+};
+
+enum isp_flash_error {
+	ISP_FLASH_ERROR_NONE		= 0 /* Flash setting is done */
+};
+
+/* --------------------------  AWB  ------------------------------------ */
+enum isp_awb_command {
+	ISP_AWB_COMMAND_AUTO		= 0,
+	ISP_AWB_COMMAND_ILLUMINATION	= 1,
+	ISP_AWB_COMMAND_MANUAL	= 2
+};
+
+enum isp_awb_illumination {
+	ISP_AWB_ILLUMINATION_DAYLIGHT		= 0,
+	ISP_AWB_ILLUMINATION_CLOUDY		= 1,
+	ISP_AWB_ILLUMINATION_TUNGSTEN		= 2,
+	ISP_AWB_ILLUMINATION_FLUORESCENT	= 3
+};
+
+enum isp_awb_error {
+	ISP_AWB_ERROR_NONE		= 0 /* AWB setting is done */
+};
+
+/* --------------------------  Effect  ----------------------------------- */
+enum isp_imageeffect_command {
+	ISP_IMAGE_EFFECT_DISABLE		= 0,
+	ISP_IMAGE_EFFECT_MONOCHROME		= 1,
+	ISP_IMAGE_EFFECT_NEGATIVE_MONO		= 2,
+	ISP_IMAGE_EFFECT_NEGATIVE_COLOR		= 3,
+	ISP_IMAGE_EFFECT_SEPIA			= 4,
+	ISP_IMAGE_EFFECT_AQUA			= 5,
+	ISP_IMAGE_EFFECT_EMBOSS			= 6,
+	ISP_IMAGE_EFFECT_EMBOSS_MONO		= 7,
+	ISP_IMAGE_EFFECT_SKETCH			= 8,
+	ISP_IMAGE_EFFECT_RED_YELLOW_POINT	= 9,
+	ISP_IMAGE_EFFECT_GREEN_POINT		= 10,
+	ISP_IMAGE_EFFECT_BLUE_POINT		= 11,
+	ISP_IMAGE_EFFECT_MAGENTA_POINT		= 12,
+	ISP_IMAGE_EFFECT_WARM_VINTAGE		= 13,
+	ISP_IMAGE_EFFECT_COLD_VINTAGE		= 14,
+	ISP_IMAGE_EFFECT_POSTERIZE		= 15,
+	ISP_IMAGE_EFFECT_SOLARIZE		= 16,
+	ISP_IMAGE_EFFECT_WASHED			= 17,
+	ISP_IMAGE_EFFECT_CCM			= 18,
+};
+
+enum isp_imageeffect_error {
+	ISP_IMAGE_EFFECT_ERROR_NONE	= 0 /* Image effect setting is done */
+};
+
+/* ---------------------------  ISO  ------------------------------------ */
+enum isp_iso_command {
+	ISP_ISO_COMMAND_AUTO		= 0,
+	ISP_ISO_COMMAND_MANUAL		= 1
+};
+
+enum iso_error {
+	ISP_ISO_ERROR_NONE		= 0 /* ISO setting is done */
+};
+
+/* --------------------------  Adjust  ----------------------------------- */
+enum iso_adjust_command {
+	ISP_ADJUST_COMMAND_AUTO			= 0,
+	ISP_ADJUST_COMMAND_MANUAL_CONTRAST	= (1 << 0),
+	ISP_ADJUST_COMMAND_MANUAL_SATURATION	= (1 << 1),
+	ISP_ADJUST_COMMAND_MANUAL_SHARPNESS	= (1 << 2),
+	ISP_ADJUST_COMMAND_MANUAL_EXPOSURE	= (1 << 3),
+	ISP_ADJUST_COMMAND_MANUAL_BRIGHTNESS	= (1 << 4),
+	ISP_ADJUST_COMMAND_MANUAL_HUE		= (1 << 5),
+	ISP_ADJUST_COMMAND_MANUAL_HOTPIXEL	= (1 << 6),
+	ISP_ADJUST_COMMAND_MANUAL_NOISEREDUCTION = (1 << 7),
+	ISP_ADJUST_COMMAND_MANUAL_SHADING	= (1 << 8),
+	ISP_ADJUST_COMMAND_MANUAL_GAMMA		= (1 << 9),
+	ISP_ADJUST_COMMAND_MANUAL_EDGEENHANCEMENT = (1 << 10),
+	ISP_ADJUST_COMMAND_MANUAL_SCENE		= (1 << 11),
+	ISP_ADJUST_COMMAND_MANUAL_FRAMETIME	= (1 << 12),
+	ISP_ADJUST_COMMAND_MANUAL_ALL		= 0x1fff
+};
+
+enum isp_adjust_scene_index {
+	ISP_ADJUST_SCENE_NORMAL			= 0,
+	ISP_ADJUST_SCENE_NIGHT_PREVIEW		= 1,
+	ISP_ADJUST_SCENE_NIGHT_CAPTURE		= 2
+};
+
+
+enum isp_adjust_error {
+	ISP_ADJUST_ERROR_NONE		= 0 /* Adjust setting is done */
+};
+
+/* -------------------------  Metering  ---------------------------------- */
+enum isp_metering_command {
+	ISP_METERING_COMMAND_AVERAGE		= 0,
+	ISP_METERING_COMMAND_SPOT		= 1,
+	ISP_METERING_COMMAND_MATRIX		= 2,
+	ISP_METERING_COMMAND_CENTER		= 3,
+	ISP_METERING_COMMAND_EXPOSURE_MODE	= (1 << 8)
+};
+
+enum isp_exposure_mode {
+	ISP_EXPOSUREMODE_OFF		= 1,
+	ISP_EXPOSUREMODE_AUTO		= 2
+};
+
+enum isp_metering_error {
+	ISP_METERING_ERROR_NONE	= 0 /* Metering setting is done */
+};
+
+/* --------------------------  AFC  ----------------------------------- */
+enum isp_afc_command {
+	ISP_AFC_COMMAND_DISABLE		= 0,
+	ISP_AFC_COMMAND_AUTO		= 1,
+	ISP_AFC_COMMAND_MANUAL		= 2
+};
+
+enum isp_afc_manual {
+	ISP_AFC_MANUAL_50HZ		= 50,
+	ISP_AFC_MANUAL_60HZ		= 60
+};
+
+enum isp_afc_error {
+	ISP_AFC_ERROR_NONE	= 0 /* AFC setting is done */
+};
+
+enum isp_scene_command {
+	ISP_SCENE_NONE		= 0,
+	ISP_SCENE_PORTRAIT	= 1,
+	ISP_SCENE_LANDSCAPE     = 2,
+	ISP_SCENE_SPORTS        = 3,
+	ISP_SCENE_PARTYINDOOR	= 4,
+	ISP_SCENE_BEACHSNOW	= 5,
+	ISP_SCENE_SUNSET	= 6,
+	ISP_SCENE_DAWN		= 7,
+	ISP_SCENE_FALL		= 8,
+	ISP_SCENE_NIGHT		= 9,
+	ISP_SCENE_AGAINSTLIGHTWLIGHT	= 10,
+	ISP_SCENE_AGAINSTLIGHTWOLIGHT	= 11,
+	ISP_SCENE_FIRE			= 12,
+	ISP_SCENE_TEXT			= 13,
+	ISP_SCENE_CANDLE		= 14
+};
+
+/* --------------------------  Scaler  --------------------------------- */
+enum scaler_imageeffect_command {
+	SCALER_IMAGE_EFFECT_COMMNAD_DISABLE	= 0,
+	SCALER_IMAGE_EFFECT_COMMNAD_SEPIA_CB	= 1,
+	SCALER_IMAGE_EFFECT_COMMAND_SEPIA_CR	= 2,
+	SCALER_IMAGE_EFFECT_COMMAND_NEGATIVE	= 3,
+	SCALER_IMAGE_EFFECT_COMMAND_ARTFREEZE	= 4,
+	SCALER_IMAGE_EFFECT_COMMAND_EMBOSSING	= 5,
+	SCALER_IMAGE_EFFECT_COMMAND_SILHOUETTE	= 6
+};
+
+enum scaler_imageeffect_error {
+	SCALER_IMAGE_EFFECT_ERROR_NONE		= 0
+};
+
+enum scaler_crop_command {
+	SCALER_CROP_COMMAND_DISABLE		= 0,
+	SCALER_CROP_COMMAND_ENABLE		= 1
+};
+
+enum scaler_crop_error {
+	SCALER_CROP_ERROR_NONE			= 0 /* crop setting is done */
+};
+
+enum scaler_scaling_command {
+	SCALER_SCALING_COMMNAD_DISABLE		= 0,
+	SCALER_SCALING_COMMAND_UP		= 1,
+	SCALER_SCALING_COMMAND_DOWN		= 2
+};
+
+enum scaler_scaling_error {
+	SCALER_SCALING_ERROR_NONE		= 0
+};
+
+enum scaler_rotation_command {
+	SCALER_ROTATION_COMMAND_DISABLE		= 0,
+	SCALER_ROTATION_COMMAND_CLOCKWISE90	= 1
+};
+
+enum scaler_rotation_error {
+	SCALER_ROTATION_ERROR_NONE		= 0
+};
+
+enum scaler_flip_command {
+	SCALER_FLIP_COMMAND_NORMAL		= 0,
+	SCALER_FLIP_COMMAND_X_MIRROR		= 1,
+	SCALER_FLIP_COMMAND_Y_MIRROR		= 2,
+	SCALER_FLIP_COMMAND_XY_MIRROR		= 3 /* (180 rotation) */
+};
+
+enum scaler_flip_error {
+	SCALER_FLIP_ERROR_NONE			= 0 /* flip setting is done */
+};
+
+/* --------------------------  3DNR  ----------------------------------- */
+enum tdnr_1st_frame_command {
+	TDNR_1ST_FRAME_COMMAND_NOPROCESSING	= 0,
+	TDNR_1ST_FRAME_COMMAND_2DNR		= 1
+};
+
+enum tdnr_1st_frame_error {
+	TDNR_1ST_FRAME_ERROR_NONE		= 0
+};
+
+/* ----------------------------  FD  ------------------------------------- */
+enum fd_config_command {
+	FD_CONFIG_COMMAND_MAXIMUM_NUMBER	= 0x1,
+	FD_CONFIG_COMMAND_ROLL_ANGLE		= 0x2,
+	FD_CONFIG_COMMAND_YAW_ANGLE		= 0x4,
+	FD_CONFIG_COMMAND_SMILE_MODE		= 0x8,
+	FD_CONFIG_COMMAND_BLINK_MODE		= 0x10,
+	FD_CONFIG_COMMAND_EYES_DETECT		= 0x20,
+	FD_CONFIG_COMMAND_MOUTH_DETECT		= 0x40,
+	FD_CONFIG_COMMAND_ORIENTATION		= 0x80,
+	FD_CONFIG_COMMAND_ORIENTATION_VALUE	= 0x100
+};
+
+enum fd_config_roll_angle {
+	FD_CONFIG_ROLL_ANGLE_BASIC		= 0,
+	FD_CONFIG_ROLL_ANGLE_PRECISE_BASIC	= 1,
+	FD_CONFIG_ROLL_ANGLE_SIDES		= 2,
+	FD_CONFIG_ROLL_ANGLE_PRECISE_SIDES	= 3,
+	FD_CONFIG_ROLL_ANGLE_FULL		= 4,
+	FD_CONFIG_ROLL_ANGLE_PRECISE_FULL	= 5,
+};
+
+enum fd_config_yaw_angle {
+	FD_CONFIG_YAW_ANGLE_0			= 0,
+	FD_CONFIG_YAW_ANGLE_45			= 1,
+	FD_CONFIG_YAW_ANGLE_90			= 2,
+	FD_CONFIG_YAW_ANGLE_45_90		= 3,
+};
+
+enum fd_config_smile_mode {
+	FD_CONFIG_SMILE_MODE_DISABLE		= 0,
+	FD_CONFIG_SMILE_MODE_ENABLE		= 1
+};
+
+enum fd_config_blink_mode {
+	FD_CONFIG_BLINK_MODE_DISABLE		= 0,
+	FD_CONFIG_BLINK_MODE_ENABLE		= 1
+};
+
+enum fd_config_eye_result {
+	FD_CONFIG_EYES_DETECT_DISABLE		= 0,
+	FD_CONFIG_EYES_DETECT_ENABLE		= 1
+};
+
+enum fd_config_mouth_result {
+	FD_CONFIG_MOUTH_DETECT_DISABLE		= 0,
+	FD_CONFIG_MOUTH_DETECT_ENABLE		= 1
+};
+
+enum fd_config_orientation {
+	FD_CONFIG_ORIENTATION_DISABLE		= 0,
+	FD_CONFIG_ORIENTATION_ENABLE		= 1
+};
+
+struct param_control {
+	u32 cmd;
+	u32 bypass;
+	u32 buffer_address;
+	u32 buffer_number;
+	/* 0: continuous, 1: single */
+	u32 run_mode;
+	u32 reserved[PARAMETER_MAX_MEMBER - 6];
+	u32 err;
+};
+
+struct param_otf_input {
+	u32 cmd;
+	u32 width;
+	u32 height;
+	u32 format;
+	u32 bitwidth;
+	u32 order;
+	u32 crop_offset_x;
+	u32 crop_offset_y;
+	u32 crop_width;
+	u32 crop_height;
+	u32 frametime_min;
+	u32 frametime_max;
+	u32 reserved[PARAMETER_MAX_MEMBER - 13];
+	u32 err;
+};
+
+struct param_dma_input {
+	u32 cmd;
+	u32 width;
+	u32 height;
+	u32 format;
+	u32 bitwidth;
+	u32 plane;
+	u32 order;
+	u32 buffer_number;
+	u32 buffer_address;
+	u32 bayer_crop_offset_x;
+	u32 bayer_crop_offset_y;
+	u32 bayer_crop_width;
+	u32 bayer_crop_height;
+	u32 dma_crop_offset_x;
+	u32 dma_crop_offset_y;
+	u32 dma_crop_width;
+	u32 dma_crop_height;
+	u32 user_min_frametime;
+	u32 user_max_frametime;
+	u32 wide_frame_gap;
+	u32 frame_gap;
+	u32 line_gap;
+	u32 reserved[PARAMETER_MAX_MEMBER - 23];
+	u32 err;
+};
+
+struct param_otf_output {
+	u32 cmd;
+	u32 width;
+	u32 height;
+	u32 format;
+	u32 bitwidth;
+	u32 order;
+	u32 crop_offset_x;
+	u32 crop_offset_y;
+	u32 reserved[PARAMETER_MAX_MEMBER - 9];
+	u32 err;
+};
+
+struct param_dma_output {
+	u32 cmd;
+	u32 width;
+	u32 height;
+	u32 format;
+	u32 bitwidth;
+	u32 plane;
+	u32 order;
+	u32 buffer_number;
+	u32 buffer_address;
+	u32 notify_dma_done;
+	u32 dma_out_mask;
+	u32 reserved[PARAMETER_MAX_MEMBER - 12];
+	u32 err;
+};
+
+struct param_global_shotmode {
+	u32 cmd;
+	u32 skip_frames;
+	u32 reserved[PARAMETER_MAX_MEMBER - 3];
+	u32 err;
+};
+
+struct param_sensor_framerate {
+	u32 frame_rate;
+	u32 reserved[PARAMETER_MAX_MEMBER - 2];
+	u32 err;
+};
+
+struct param_isp_aa {
+	u32 cmd;
+	u32 target;
+	u32 mode;
+	u32 scene;
+	u32 af_touch;
+	u32 af_face;
+	u32 af_response;
+	u32 sleep;
+	u32 touch_x;
+	u32 touch_y;
+	u32 manual_af_setting;
+	/* 0: Legacy, 1: Camera 2.0 */
+	u32 cam_api2p0;
+	/*
+	 * For android.control.afRegions in Camera 2.0,
+	 * Resolution based on YUV output size
+	 */
+	u32 af_region_left;
+	u32 af_region_top;
+	u32 af_region_right;
+	u32 af_region_bottom;
+	u32 reserved[PARAMETER_MAX_MEMBER - 17];
+	u32 err;
+};
+
+struct param_isp_flash {
+	u32 cmd;
+	u32 redeye;
+	u32 flash_intensity;
+	u32 reserved[PARAMETER_MAX_MEMBER - 4];
+	u32 err;
+};
+
+struct param_isp_awb {
+	u32 cmd;
+	u32 illumination;
+	u32 reserved[PARAMETER_MAX_MEMBER - 3];
+	u32 err;
+};
+
+struct param_isp_imageeffect {
+	u32 cmd;
+	u32 reserved[PARAMETER_MAX_MEMBER - 2];
+	u32 err;
+};
+
+struct param_isp_iso {
+	u32 cmd;
+	u32 value;
+	u32 reserved[PARAMETER_MAX_MEMBER - 3];
+	u32 err;
+};
+
+struct param_isp_adjust {
+	u32 cmd;
+	s32 contrast;
+	s32 saturation;
+	s32 sharpness;
+	s32 exposure;
+	s32 brightness;
+	s32 hue;
+	/* 0 or 1 */
+	u32 hotpixel_enable;
+	/* -127 ~ 127 */
+	s32 noise_reduction_strength;
+	/* 0 or 1 */
+	u32 shading_correction_enable;
+	/* 0 or 1 */
+	u32 user_gamma_enable;
+	/* -127 ~ 127 */
+	s32 edge_enhancement_strength;
+	u32 user_scene_mode;
+	u32 min_frametime;
+	u32 max_frametime;
+	u32 reserved[PARAMETER_MAX_MEMBER - 16];
+	u32 err;
+};
+
+struct param_isp_metering {
+	u32 cmd;
+	u32 win_pos_x;
+	u32 win_pos_y;
+	u32 win_width;
+	u32 win_height;
+	u32 exposure_mode;
+	/* 0: Legacy, 1: Camera 2.0 */
+	u32 cam_api2p0;
+	u32 reserved[PARAMETER_MAX_MEMBER - 8];
+	u32 err;
+};
+
+struct param_isp_afc {
+	u32 cmd;
+	u32 manual;
+	u32 reserved[PARAMETER_MAX_MEMBER - 3];
+	u32 err;
+};
+
+struct param_scaler_imageeffect {
+	u32 cmd;
+	u32 reserved[PARAMETER_MAX_MEMBER - 2];
+	u32 err;
+};
+
+struct param_scaler_input_crop {
+	u32  cmd;
+	u32  pos_x;
+	u32  pos_y;
+	u32  crop_width;
+	u32  crop_height;
+	u32  in_width;
+	u32  in_height;
+	u32  out_width;
+	u32  out_height;
+	u32  reserved[PARAMETER_MAX_MEMBER - 10];
+	u32  err;
+};
+
+struct param_scaler_output_crop {
+	u32  cmd;
+	u32  pos_x;
+	u32  pos_y;
+	u32  crop_width;
+	u32  crop_height;
+	u32  format;
+	u32  reserved[PARAMETER_MAX_MEMBER - 7];
+	u32  err;
+};
+
+struct param_scaler_rotation {
+	u32 cmd;
+	u32 reserved[PARAMETER_MAX_MEMBER - 2];
+	u32 err;
+};
+
+struct param_scaler_flip {
+	u32 cmd;
+	u32 reserved[PARAMETER_MAX_MEMBER - 2];
+	u32 err;
+};
+
+struct param_3dnr_1stframe {
+	u32 cmd;
+	u32 reserved[PARAMETER_MAX_MEMBER - 2];
+	u32 err;
+};
+
+struct param_fd_config {
+	u32 cmd;
+	u32 max_number;
+	u32 roll_angle;
+	u32 yaw_angle;
+	s32 smile_mode;
+	s32 blink_mode;
+	u32 eye_detect;
+	u32 mouth_detect;
+	u32 orientation;
+	u32 orientation_value;
+	u32 reserved[PARAMETER_MAX_MEMBER - 11];
+	u32 err;
+};
+
+struct global_param {
+	struct param_global_shotmode shotmode;
+};
+
+struct sensor_param {
+	struct param_control		control;
+	struct param_otf_input		otf_input;
+	struct param_otf_output		otf_output;
+	struct param_sensor_framerate	frame_rate;
+	struct param_dma_output		dma_output;
+};
+
+struct buffer_param {
+	struct param_control	control;
+	struct param_otf_input	otf_input;
+	struct param_otf_output	otf_output;
+};
+
+struct isp_param {
+	struct param_control		control;
+	struct param_otf_input		otf_input;
+	struct param_dma_input		dma1_input;
+	struct param_dma_input		dma2_input;
+	struct param_isp_aa		aa;
+	struct param_isp_flash		flash;
+	struct param_isp_awb		awb;
+	struct param_isp_imageeffect	effect;
+	struct param_isp_iso		iso;
+	struct param_isp_adjust		adjust;
+	struct param_isp_metering	metering;
+	struct param_isp_afc		afc;
+	struct param_otf_output		otf_output;
+	struct param_dma_output		dma1_output;
+	struct param_dma_output		dma2_output;
+};
+
+struct drc_param {
+	struct param_control		control;
+	struct param_otf_input		otf_input;
+	struct param_dma_input		dma_input;
+	struct param_otf_output		otf_output;
+};
+
+struct scalerc_param {
+	struct param_control		control;
+	struct param_otf_input		otf_input;
+	struct param_scaler_imageeffect	effect;
+	struct param_scaler_input_crop	input_crop;
+	struct param_scaler_output_crop	 output_crop;
+	struct param_otf_output		otf_output;
+	struct param_dma_output		dma_output;
+};
+
+struct odc_param {
+	struct param_control		control;
+	struct param_otf_input		otf_input;
+	struct param_otf_output		otf_output;
+};
+
+struct dis_param {
+	struct param_control		control;
+	struct param_otf_input		otf_input;
+	struct param_otf_output		otf_output;
+};
+
+struct tdnr_param {
+	struct param_control		control;
+	struct param_otf_input		otf_input;
+	struct param_3dnr_1stframe	frame;
+	struct param_otf_output		otf_output;
+	struct param_dma_output		dma_output;
+};
+
+struct scalerp_param {
+	struct param_control			control;
+	struct param_otf_input			otf_input;
+	struct param_scaler_imageeffect		effect;
+	struct param_scaler_input_crop		input_crop;
+	struct param_scaler_output_crop		output_crop;
+	struct param_scaler_rotation		rotation;
+	struct param_scaler_flip		flip;
+	struct param_otf_output			otf_output;
+	struct param_dma_output			dma_output;
+};
+
+struct fd_param {
+	struct param_control		control;
+	struct param_otf_input		otf_input;
+	struct param_dma_input		dma_input;
+	struct param_fd_config		config;
+};
+
+struct is_param_region {
+	struct global_param	global;
+	struct sensor_param	sensor;
+	struct buffer_param	buf;
+	struct isp_param	isp;
+	struct drc_param	drc;
+	struct scalerc_param	scalerc;
+	struct odc_param	odc;
+	struct dis_param	dis;
+	struct tdnr_param	tdnr;
+	struct scalerp_param	scalerp;
+	struct fd_param		fd;
+};
+
+#define	NUMBER_OF_GAMMA_CURVE_POINTS	32
+
+struct is_sensor_tune {
+	u32 exposure;
+	u32 analog_gain;
+	u32 frame_rate;
+	u32 actuator_pos;
+};
+
+struct is_tune_gammacurve {
+	u32 num_pts_x[NUMBER_OF_GAMMA_CURVE_POINTS];
+	u32 num_pts_y_r[NUMBER_OF_GAMMA_CURVE_POINTS];
+	u32 num_pts_y_g[NUMBER_OF_GAMMA_CURVE_POINTS];
+	u32 num_pts_y_b[NUMBER_OF_GAMMA_CURVE_POINTS];
+};
+
+struct is_isp_tune {
+	/* Brightness level: range 0~100, default: 7 */
+	u32 brightness_level;
+	/* Contrast level: range -127~127, default: 0 */
+	s32 contrast_level;
+	/* Saturation level: range -127~127, default: 0 */
+	s32 saturation_level;
+	s32 gamma_level;
+	struct is_tune_gammacurve gamma_curve[4];
+	/* Hue: range -127~127, default: 0 */
+	s32 hue;
+	/* Sharpness blur: range -127~127, default: 0 */
+	s32 sharpness_blur;
+	/* Despeckle: range -127~127, default: 0 */
+	s32 despeckle;
+	/* Edge color supression: range -127~127, default: 0 */
+	s32 edge_color_supression;
+	/* Noise reduction: range -127~127, default: 0 */
+	s32 noise_reduction;
+};
+
+struct is_tune_region {
+	struct is_sensor_tune sensor_tune;
+	struct is_isp_tune isp_tune;
+};
+
+struct rational_t {
+	u32 num;
+	u32 den;
+};
+
+struct srational_t {
+	s32 num;
+	s32 den;
+};
+
+#define FLASH_FIRED_SHIFT	0
+#define FLASH_NOT_FIRED		0
+#define FLASH_FIRED		1
+
+#define FLASH_STROBE_SHIFT				1
+#define FLASH_STROBE_NO_DETECTION			0
+#define FLASH_STROBE_RESERVED				1
+#define FLASH_STROBE_RETURN_LIGHT_NOT_DETECTED		2
+#define FLASH_STROBE_RETURN_LIGHT_DETECTED		3
+
+#define FLASH_MODE_SHIFT			3
+#define FLASH_MODE_UNKNOWN			0
+#define FLASH_MODE_COMPULSORY_FLASH_FIRING	1
+#define FLASH_MODE_COMPULSORY_FLASH_SUPPRESSION	2
+#define FLASH_MODE_AUTO_MODE			3
+
+#define FLASH_FUNCTION_SHIFT		5
+#define FLASH_FUNCTION_PRESENT		0
+#define FLASH_FUNCTION_NONE		1
+
+#define FLASH_RED_EYE_SHIFT		6
+#define FLASH_RED_EYE_DISABLED		0
+#define FLASH_RED_EYE_SUPPORTED		1
+
+struct exif_attribute {
+	struct rational_t exposure_time;
+	struct srational_t shutter_speed;
+	u32 iso_speed_rating;
+	u32 flash;
+	struct srational_t brightness;
+};
+
+struct is_frame_header {
+	u32 valid;
+	u32 bad_mark;
+	u32 captured;
+	u32 frame_number;
+	struct exif_attribute	exif;
+};
+
+struct is_face_marker {
+	u32 frame_number;
+	struct v4l2_rect face;
+	struct v4l2_rect left_eye;
+	struct v4l2_rect right_eye;
+	struct v4l2_rect mouth;
+	u32 roll_angle;
+	u32 yaw_angle;
+	u32 confidence;
+	u32 stracked;
+	u32 tracked_faceid;
+	u32 smile_level;
+	u32 blink_level;
+};
+
+#define MAX_FRAME_COUNT		8
+#define MAX_FRAME_COUNT_PREVIEW	4
+#define MAX_FRAME_COUNT_CAPTURE	1
+#define MAX_FACE_COUNT		16
+
+#define MAX_SHARED_COUNT	500
+
+struct is_region {
+	struct is_param_region	parameter;
+	struct is_tune_region	tune;
+	struct is_frame_header	header[MAX_FRAME_COUNT];
+	struct is_face_marker	face[MAX_FACE_COUNT];
+	u32			shared[MAX_SHARED_COUNT];
+};
+
+struct is_time_measure_us {
+	u32 min_time_us;
+	u32 max_time_us;
+	u32 avrg_time_us;
+	u32 current_time_us;
+};
+
+struct is_debug_frame_descriptor {
+	u32 sensor_frame_time;
+	u32 sensor_exposure_time;
+	u32 sensor_analog_gain;
+	u32 req_lei;
+};
+
+#define MAX_FRAMEDESCRIPTOR_CONTEXT_NUM	(30 * 20)	/* 600 frame */
+#define MAX_VERSION_DISPLAY_BUF		(32)
+
+struct is_share_region {
+	u32 frame_time;
+	u32 exposure_time;
+	u32 analog_gain;
+
+	u32 r_gain;
+	u32 g_gain;
+	u32 b_gain;
+
+	u32 af_position;
+	u32 af_status;
+	u32 af_scene_type;
+
+	u32 frame_descp_onoff_control;
+	u32 frame_descp_update_done;
+	u32 frame_descp_idx;
+	u32 frame_descp_max_idx;
+
+	struct is_debug_frame_descriptor
+		dbg_frame_descp_ctx[MAX_FRAMEDESCRIPTOR_CONTEXT_NUM];
+
+	u32 chip_id;
+	u32 chip_rev_no;
+	u8 ispfw_version_no[MAX_VERSION_DISPLAY_BUF];
+	u8 ispfw_version_date[MAX_VERSION_DISPLAY_BUF];
+	u8 sirc_sdk_version_no[MAX_VERSION_DISPLAY_BUF];
+	u8 sirc_sdk_revsion_no[MAX_VERSION_DISPLAY_BUF];
+	u8 sirc_sdk_version_date[MAX_VERSION_DISPLAY_BUF];
+
+	/* measure timing */
+	struct is_time_measure_us	isp_sdk_time;
+};
+
+struct is_debug_control {
+	u32 write_point;	/* 0~500KB boundary */
+	u32 assert_flag;	/* 0:Not Invoked, 1:Invoked */
+	u32 pabort_flag;	/* 0:Not Invoked, 1:Invoked */
+	u32 dabort_flag;	/* 0:Not Invoked, 1:Invoked */
+	u32 pd_ready_flag;	/* 0:Normal, 1:EnterIdle(Ready to power down) */
+	u32 isp_frame_err;	/* Frame Error Counters */
+	u32 drc_frame_err;
+	u32 scc_frame_err;
+	u32 odc_frame_err;
+	u32 dis_frame_err;
+	u32 tdnr_frame_err;
+	u32 scp_frame_err;
+	u32 fd_frame_err;
+	u32 isp_frame_drop;	/* Frame Drop Counters */
+	u32 drc_frame_drop;
+	u32 dis_frame_drop;
+	u32 uifdframedrop;
+};
+
+#endif
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 04/12] [media] exynos5-fimc-is: Add register definition and context header
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
                   ` (2 preceding siblings ...)
  2013-11-05 12:13 ` [PATCH v12 03/12] [media] exynos5-fimc-is: Add common driver header files Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 05/12] [media] exynos5-fimc-is: Add isp subdev Arun Kumar K
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

This patch adds the register definition file for the fimc-is driver
and also the header file containing the main context for the driver.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Kilyeon Im <kilyeon.im@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/media/platform/exynos5-is/fimc-is-regs.h |  105 ++++++++++++++
 drivers/media/platform/exynos5-is/fimc-is.h      |  160 ++++++++++++++++++++++
 2 files changed, 265 insertions(+)
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-regs.h
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is.h

diff --git a/drivers/media/platform/exynos5-is/fimc-is-regs.h b/drivers/media/platform/exynos5-is/fimc-is-regs.h
new file mode 100644
index 0000000..06aa466
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-regs.h
@@ -0,0 +1,105 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd
+ * Arun Kumar K <arun.kk@samsung.com>
+ * Kil-yeon Lim <kilyeon.im@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_IS_REGS_H
+#define FIMC_IS_REGS_H
+
+/* WDT_ISP register */
+#define WDT			0x00170000
+/* MCUCTL register */
+#define MCUCTL			0x00180000
+/* MCU Controller Register */
+#define MCUCTLR				(MCUCTL+0x00)
+#define MCUCTLR_AXI_ISPX_AWCACHE(x)	((x) << 16)
+#define MCUCTLR_AXI_ISPX_ARCACHE(x)	((x) << 12)
+#define MCUCTLR_MSWRST			(1 << 0)
+/* Boot Base OFfset Address Register */
+#define BBOAR				(MCUCTL+0x04)
+#define BBOAR_BBOA(x)			((x) << 0)
+
+/* Interrupt Generation Register 0 from Host CPU to VIC */
+#define INTGR0				(MCUCTL+0x08)
+#define INTGR0_INTGC(n)			(1 << ((n) + 16))
+#define INTGR0_INTGD(n)			(1 << (n))
+
+/* Interrupt Clear Register 0 from Host CPU to VIC */
+#define INTCR0				(MCUCTL+0x0c)
+#define INTCR0_INTCC(n)			(1 << ((n) + 16))
+#define INTCR0_INTCD(n)			(1 << (n))
+
+/* Interrupt Mask Register 0 from Host CPU to VIC */
+#define INTMR0				(MCUCTL+0x10)
+#define INTMR0_INTMC(n)			(1 << ((n) + 16))
+#define INTMR0_INTMD(n)			(1 << (n))
+
+/* Interrupt Status Register 0 from Host CPU to VIC */
+#define INTSR0				(MCUCTL+0x14)
+#define INTSR0_GET_INTSD(n, x)		(((x) >> (n)) & 0x1)
+#define INTSR0_GET_INTSC(n, x)		(((x) >> ((n) + 16)) & 0x1)
+
+/* Interrupt Mask Status Register 0 from Host CPU to VIC */
+#define INTMSR0				(MCUCTL+0x18)
+#define INTMSR0_GET_INTMSD(n, x)	(((x) >> (n)) & 0x1)
+#define INTMSR0_GET_INTMSC(n, x)	(((x) >> ((n) + 16)) & 0x1)
+
+/* Interrupt Generation Register 1 from ISP CPU to Host IC */
+#define INTGR1				(MCUCTL+0x1c)
+#define INTGR1_INTGC(n)			(1 << (n))
+
+/* Interrupt Clear Register 1 from ISP CPU to Host IC */
+#define INTCR1				(MCUCTL+0x20)
+#define INTCR1_INTCC(n)			(1 << (n))
+
+/* Interrupt Mask Register 1 from ISP CPU to Host IC */
+#define INTMR1				(MCUCTL+0x24)
+#define INTMR1_INTMC(n)			(1 << (n))
+
+/* Interrupt Status Register 1 from ISP CPU to Host IC */
+#define INTSR1				(MCUCTL+0x28)
+/* Interrupt Mask Status Register 1 from ISP CPU to Host IC */
+#define INTMSR1				(MCUCTL+0x2c)
+/* Interrupt Clear Register 2 from ISP BLK's interrupts to Host IC */
+#define INTCR2				(MCUCTL+0x30)
+#define INTCR2_INTCC(n)			(1 << (n))
+
+/* Interrupt Mask Register 2 from ISP BLK's interrupts to Host IC */
+#define INTMR2				(MCUCTL+0x34)
+#define INTMR2_INTMCIS(n)		(1 << (n))
+
+/* Interrupt Status Register 2 from ISP BLK's interrupts to Host IC */
+#define INTSR2				(MCUCTL+0x38)
+/* Interrupt Mask Status Register 2 from ISP BLK's interrupts to Host IC */
+#define INTMSR2				(MCUCTL+0x3c)
+/* General Purpose Output Control Register (0~17) */
+#define GPOCTLR				(MCUCTL+0x40)
+#define GPOCTLR_GPOG(n, x)		((x) << (n))
+
+/* General Purpose Pad Output Enable Register (0~17) */
+#define GPOENCTLR			(MCUCTL+0x44)
+#define GPOENCTLR_GPOEN0(n, x)		((x) << (n))
+
+/* General Purpose Input Control Register (0~17) */
+#define GPICTLR				(MCUCTL+0x48)
+
+/* IS Shared Registers between ISP CPU and HOST CPU */
+#define ISSR(n)			(MCUCTL + 0x80 + (n))
+
+/* PMU for FIMC-IS*/
+#define PMUREG_CMU_RESET_ISP_SYS_PWR_REG	0x1584
+#define PMUREG_ISP_ARM_CONFIGURATION		0x2280
+#define PMUREG_ISP_ARM_STATUS			0x2284
+#define PMUREG_ISP_ARM_OPTION			0x2288
+#define PMUREG_ISP_LOW_POWER_OFF		0x0004
+#define PMUREG_ISP_CONFIGURATION		0x4020
+#define PMUREG_ISP_STATUS			0x4024
+
+#endif
diff --git a/drivers/media/platform/exynos5-is/fimc-is.h b/drivers/media/platform/exynos5-is/fimc-is.h
new file mode 100644
index 0000000..136f367
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is.h
@@ -0,0 +1,160 @@
+/*
+ * Samsung EXYNOS5 FIMC-IS (Imaging Subsystem) driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *  Arun Kumar K <arun.kk@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_IS_H_
+#define FIMC_IS_H_
+
+#include "fimc-is-err.h"
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-pipeline.h"
+#include "fimc-is-interface.h"
+
+#define fimc_interface_to_is(p) container_of(p, struct fimc_is, interface)
+#define fimc_sensor_to_is(p) container_of(p, struct fimc_is, sensor)
+
+/*
+ * Macros used by media dev to get the subdev and vfd
+ * is - driver data from pdev
+ * pid - pipeline index
+ */
+#define fimc_is_isp_get_sd(is, pid) (&is->pipeline[pid].isp.subdev)
+#define fimc_is_isp_get_vfd(is, pid) (&is->pipeline[pid].isp.vfd)
+#define fimc_is_scc_get_sd(is, pid) \
+	(&is->pipeline[pid].scaler[SCALER_SCC].subdev)
+#define fimc_is_scc_get_vfd(is, pid) \
+	(&is->pipeline[pid].scaler[SCALER_SCC].vfd)
+#define fimc_is_scp_get_sd(is, pid) \
+	(&is->pipeline[pid].scaler[SCALER_SCP].subdev)
+#define fimc_is_scp_get_vfd(is, pid) \
+	(&is->pipeline[pid].scaler[SCALER_SCP].vfd)
+/*
+ * is - driver data from pdev
+ * sid - sensor index
+ */
+#define fimc_is_sensor_get_sd(is, sid) (&is->sensor[sid].subdev)
+
+
+/**
+ * struct fimc_is - fimc-is driver private data
+ * @pdev: pointer to FIMC-IS platform device
+ * @pdata: platform data for FIMC-IS
+ * @alloc_ctx: videobuf2 memory allocator context
+ * @clock: FIMC-IS clocks
+ * @pmu_regs: PMU reg base address
+ * @num_pipelines: number of pipelines opened
+ * @minfo: internal memory organization info
+ * @drvdata: fimc-is driver data
+ * @sensor: FIMC-IS sensor context
+ * @pipeline: hardware pipeline context
+ * @interface: hardware interface context
+ */
+struct fimc_is {
+	struct platform_device		*pdev;
+
+	struct vb2_alloc_ctx		*alloc_ctx;
+	struct clk			*clock[IS_CLK_MAX_NUM];
+	void __iomem			*pmu_regs;
+	unsigned int			num_pipelines;
+
+	struct fimc_is_meminfo		minfo;
+
+	struct fimc_is_drvdata		*drvdata;
+	struct fimc_is_sensor		sensor[FIMC_IS_NUM_SENSORS];
+	struct fimc_is_pipeline		pipeline[FIMC_IS_NUM_PIPELINES];
+	struct fimc_is_interface	interface;
+};
+
+/* Queue operations for ISP */
+static inline void fimc_is_isp_wait_queue_add(struct fimc_is_isp *isp,
+		struct fimc_is_buf *buf)
+{
+	list_add_tail(&buf->list, &isp->wait_queue);
+	isp->wait_queue_cnt++;
+}
+
+static inline struct fimc_is_buf *fimc_is_isp_wait_queue_get(
+		struct fimc_is_isp *isp)
+{
+	struct fimc_is_buf *buf;
+	buf = list_entry(isp->wait_queue.next,
+			struct fimc_is_buf, list);
+	list_del(&buf->list);
+	isp->wait_queue_cnt--;
+	return buf;
+}
+
+static inline void fimc_is_isp_run_queue_add(struct fimc_is_isp *isp,
+		struct fimc_is_buf *buf)
+{
+	list_add_tail(&buf->list, &isp->run_queue);
+	isp->run_queue_cnt++;
+}
+
+static inline struct fimc_is_buf *fimc_is_isp_run_queue_get(
+		struct fimc_is_isp *isp)
+{
+	struct fimc_is_buf *buf;
+	buf = list_entry(isp->run_queue.next,
+			struct fimc_is_buf, list);
+	list_del(&buf->list);
+	isp->run_queue_cnt--;
+	return buf;
+}
+
+/* Queue operations for SCALER */
+static inline void fimc_is_scaler_wait_queue_add(struct fimc_is_scaler *scp,
+		struct fimc_is_buf *buf)
+{
+	list_add_tail(&buf->list, &scp->wait_queue);
+	scp->wait_queue_cnt++;
+}
+
+static inline struct fimc_is_buf *fimc_is_scaler_wait_queue_get(
+		struct fimc_is_scaler *scp)
+{
+	struct fimc_is_buf *buf;
+	buf = list_entry(scp->wait_queue.next,
+			struct fimc_is_buf, list);
+	list_del(&buf->list);
+	scp->wait_queue_cnt--;
+	return buf;
+}
+
+static inline void fimc_is_scaler_run_queue_add(struct fimc_is_scaler *scp,
+		struct fimc_is_buf *buf)
+{
+	list_add_tail(&buf->list, &scp->run_queue);
+	scp->run_queue_cnt++;
+}
+
+static inline struct fimc_is_buf *fimc_is_scaler_run_queue_get(
+		struct fimc_is_scaler *scp)
+{
+	struct fimc_is_buf *buf;
+	buf = list_entry(scp->run_queue.next,
+			struct fimc_is_buf, list);
+	list_del(&buf->list);
+	scp->run_queue_cnt--;
+	return buf;
+}
+
+static inline void pmu_is_write(u32 v, struct fimc_is *is, unsigned int offset)
+{
+	writel(v, is->pmu_regs + offset);
+}
+
+static inline u32 pmu_is_read(struct fimc_is *is, unsigned int offset)
+{
+	return readl(is->pmu_regs + offset);
+}
+
+#endif
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 05/12] [media] exynos5-fimc-is: Add isp subdev
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
                   ` (3 preceding siblings ...)
  2013-11-05 12:13 ` [PATCH v12 04/12] [media] exynos5-fimc-is: Add register definition and context header Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 06/12] [media] exynos5-fimc-is: Add scaler subdev Arun Kumar K
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

fimc-is driver takes video data input from the ISP video node
which is added in this patch. This node accepts Bayer input
buffers which is given from the IS sensors.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Kilyeon Im <kilyeon.im@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/media/platform/exynos5-is/fimc-is-isp.c |  534 +++++++++++++++++++++++
 drivers/media/platform/exynos5-is/fimc-is-isp.h |   90 ++++
 2 files changed, 624 insertions(+)
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-isp.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-isp.h

diff --git a/drivers/media/platform/exynos5-is/fimc-is-isp.c b/drivers/media/platform/exynos5-is/fimc-is-isp.c
new file mode 100644
index 0000000..7bd603f
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-isp.c
@@ -0,0 +1,534 @@
+/*
+ * Samsung EXYNOS5250 FIMC-IS (Imaging Subsystem) driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *  Arun Kumar K <arun.kk@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 <media/v4l2-ioctl.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "fimc-is.h"
+
+#define ISP_DRV_NAME "fimc-is-isp"
+
+static const struct fimc_is_fmt formats[] = {
+	{
+		.name           = "Bayer GR-BG 8bits",
+		.fourcc         = V4L2_PIX_FMT_SGRBG8,
+		.depth		= { 8 },
+		.num_planes     = 1,
+	},
+	{
+		.name           = "Bayer GR-BG 10bits",
+		.fourcc         = V4L2_PIX_FMT_SGRBG10,
+		.depth		= { 16 },
+		.num_planes     = 1,
+	},
+	{
+		.name           = "Bayer GR-BG 12bits",
+		.fourcc         = V4L2_PIX_FMT_SGRBG12,
+		.depth		= { 16 },
+		.num_planes     = 1,
+	},
+};
+#define NUM_FORMATS ARRAY_SIZE(formats)
+
+static const struct fimc_is_fmt *find_format(struct v4l2_format *f)
+{
+	unsigned int i;
+
+	for (i = 0; i < NUM_FORMATS; i++)
+		if (formats[i].fourcc == f->fmt.pix_mp.pixelformat)
+			return &formats[i];
+	return NULL;
+}
+
+static int isp_video_output_start_streaming(struct vb2_queue *vq,
+					unsigned int count)
+{
+	struct fimc_is_isp *isp = vb2_get_drv_priv(vq);
+
+	set_bit(STATE_RUNNING, &isp->output_state);
+	return 0;
+}
+
+static int isp_video_output_stop_streaming(struct vb2_queue *vq)
+{
+	struct fimc_is_isp *isp = vb2_get_drv_priv(vq);
+	struct fimc_is_buf *buf;
+
+	/* Release unused buffers */
+	while (!list_empty(&isp->wait_queue)) {
+		buf = fimc_is_isp_wait_queue_get(isp);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+	while (!list_empty(&isp->run_queue)) {
+		buf = fimc_is_isp_run_queue_get(isp);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+
+	clear_bit(STATE_RUNNING, &isp->output_state);
+	return 0;
+}
+
+static int isp_video_output_queue_setup(struct vb2_queue *vq,
+			const struct v4l2_format *pfmt,
+			unsigned int *num_buffers, unsigned int *num_planes,
+			unsigned int sizes[], void *allocators[])
+{
+	struct fimc_is_isp *isp = vb2_get_drv_priv(vq);
+	const struct fimc_is_fmt *fmt = isp->fmt;
+	unsigned int wh, i;
+
+	if (!fmt)
+		return -EINVAL;
+
+	*num_planes = fmt->num_planes;
+	wh = isp->width * isp->height;
+
+	for (i = 0; i < *num_planes; i++) {
+		allocators[i] = isp->alloc_ctx;
+		sizes[i] = (wh * fmt->depth[i]) / 8;
+	}
+	return 0;
+}
+
+static int isp_video_output_buffer_init(struct vb2_buffer *vb)
+{
+	struct fimc_is_buf *buf = container_of(vb, struct fimc_is_buf, vb);
+
+	buf->paddr[0] = vb2_dma_contig_plane_dma_addr(vb, 0);
+	return 0;
+}
+
+static int isp_video_output_buffer_prepare(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct fimc_is_isp *isp = vb2_get_drv_priv(vq);
+	unsigned long size;
+
+	size = (isp->width * isp->height * isp->fmt->depth[0]) / 8;
+	if (vb2_plane_size(vb, 0) < size) {
+		v4l2_err(&isp->subdev, "User buffer too small (%ld < %ld)\n",
+			 vb2_plane_size(vb, 0), size);
+		return -EINVAL;
+	}
+	vb2_set_plane_payload(vb, 0, size);
+
+	return 0;
+}
+
+static void isp_video_output_buffer_queue(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct fimc_is_isp *isp = vb2_get_drv_priv(vq);
+	struct fimc_is_buf *buf = container_of(vb, struct fimc_is_buf, vb);
+
+	fimc_is_pipeline_buf_lock(isp->pipeline);
+	fimc_is_isp_wait_queue_add(isp, buf);
+	fimc_is_pipeline_buf_unlock(isp->pipeline);
+
+	/* Call shot command */
+	fimc_is_pipeline_shot_safe(isp->pipeline);
+}
+
+static const struct vb2_ops isp_video_output_qops = {
+	.queue_setup	 = isp_video_output_queue_setup,
+	.buf_init	 = isp_video_output_buffer_init,
+	.buf_prepare	 = isp_video_output_buffer_prepare,
+	.buf_queue	 = isp_video_output_buffer_queue,
+	.wait_prepare	 = vb2_ops_wait_prepare,
+	.wait_finish	 = vb2_ops_wait_finish,
+	.start_streaming = isp_video_output_start_streaming,
+	.stop_streaming	 = isp_video_output_stop_streaming,
+};
+
+static const struct v4l2_file_operations isp_video_output_fops = {
+	.owner		= THIS_MODULE,
+	.open		= v4l2_fh_open,
+	.release	= vb2_fop_release,
+	.poll		= vb2_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= vb2_fop_mmap,
+};
+
+/*
+ * Video node ioctl operations
+ */
+static int isp_querycap_output(struct file *file, void *priv,
+					struct v4l2_capability *cap)
+{
+	strncpy(cap->driver, ISP_DRV_NAME, sizeof(cap->driver) - 1);
+	strncpy(cap->card, ISP_DRV_NAME, sizeof(cap->card) - 1);
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+			ISP_DRV_NAME);
+	cap->device_caps = V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int isp_enum_fmt_mplane(struct file *file, void *priv,
+				     struct v4l2_fmtdesc *f)
+{
+	const struct fimc_is_fmt *fmt;
+
+	if (f->index >= NUM_FORMATS)
+		return -EINVAL;
+
+	fmt = &formats[f->index];
+	strlcpy(f->description, fmt->name, sizeof(f->description));
+	f->pixelformat = fmt->fourcc;
+
+	return 0;
+}
+
+static int isp_g_fmt_mplane(struct file *file, void *fh,
+				  struct v4l2_format *f)
+{
+	struct fimc_is_isp *isp = video_drvdata(file);
+	struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
+	struct v4l2_plane_pix_format *plane_fmt = &pixm->plane_fmt[0];
+	const struct fimc_is_fmt *fmt = isp->fmt;
+
+	plane_fmt->bytesperline = (isp->width * fmt->depth[0]) / 8;
+	plane_fmt->sizeimage = plane_fmt->bytesperline * isp->height;
+	memset(plane_fmt->reserved, 0, sizeof(plane_fmt->reserved));
+
+	pixm->num_planes = fmt->num_planes;
+	pixm->pixelformat = fmt->fourcc;
+	pixm->width = isp->width;
+	pixm->height = isp->height;
+	pixm->field = V4L2_FIELD_NONE;
+	pixm->colorspace = V4L2_COLORSPACE_JPEG;
+	memset(pixm->reserved, 0, sizeof(pixm->reserved));
+
+	return 0;
+}
+
+static int isp_try_fmt_mplane(struct file *file, void *fh,
+		struct v4l2_format *f)
+{
+	const struct fimc_is_fmt *fmt;
+	struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
+	struct v4l2_plane_pix_format *plane_fmt = &pixm->plane_fmt[0];
+
+	fmt = find_format(f);
+	if (!fmt)
+		fmt = (struct fimc_is_fmt *) &formats[0];
+
+	v4l_bound_align_image(&pixm->width,
+			ISP_MIN_WIDTH + SENSOR_WIDTH_PADDING,
+			ISP_MAX_WIDTH + SENSOR_WIDTH_PADDING, 0,
+			&pixm->height,
+			ISP_MIN_HEIGHT + SENSOR_HEIGHT_PADDING,
+			ISP_MAX_HEIGHT + SENSOR_HEIGHT_PADDING, 0,
+			0);
+
+	plane_fmt->bytesperline = (pixm->width * fmt->depth[0]) / 8;
+	plane_fmt->sizeimage = (pixm->width * pixm->height *
+				fmt->depth[0]) / 8;
+	memset(plane_fmt->reserved, 0, sizeof(plane_fmt->reserved));
+
+	pixm->num_planes = fmt->num_planes;
+	pixm->pixelformat = fmt->fourcc;
+	pixm->colorspace = V4L2_COLORSPACE_JPEG;
+	pixm->field = V4L2_FIELD_NONE;
+	memset(pixm->reserved, 0, sizeof(pixm->reserved));
+
+	return 0;
+}
+
+static int isp_s_fmt_mplane(struct file *file, void *priv,
+		struct v4l2_format *f)
+{
+	struct fimc_is_isp *isp = video_drvdata(file);
+	const struct fimc_is_fmt *fmt;
+	struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
+	int ret;
+
+	ret = isp_try_fmt_mplane(file, priv, f);
+	if (ret)
+		return ret;
+
+	/* Get format type */
+	fmt = find_format(f);
+	if (!fmt) {
+		fmt = &formats[0];
+		pixm->pixelformat = fmt->fourcc;
+		pixm->num_planes = fmt->num_planes;
+	}
+
+	isp->fmt = fmt;
+	isp->width = pixm->width;
+	isp->height = pixm->height;
+	isp->size_image = pixm->plane_fmt[0].sizeimage;
+	set_bit(STATE_INIT, &isp->output_state);
+	return 0;
+}
+
+static int isp_reqbufs(struct file *file, void *priv,
+		struct v4l2_requestbuffers *reqbufs)
+{
+	struct fimc_is_isp *isp = video_drvdata(file);
+	int ret;
+
+	reqbufs->count = max_t(u32, FIMC_IS_ISP_REQ_BUFS_MIN, reqbufs->count);
+	ret = vb2_reqbufs(&isp->vbq, reqbufs);
+	if (ret) {
+		v4l2_err(&isp->subdev, "vb2 req buffers failed\n");
+		return ret;
+	}
+
+	if (reqbufs->count < FIMC_IS_ISP_REQ_BUFS_MIN) {
+		reqbufs->count = 0;
+		vb2_reqbufs(&isp->vbq, reqbufs);
+		return -ENOMEM;
+	}
+	set_bit(STATE_BUFS_ALLOCATED, &isp->output_state);
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops isp_video_output_ioctl_ops = {
+	.vidioc_querycap		= isp_querycap_output,
+	.vidioc_enum_fmt_vid_out_mplane	= isp_enum_fmt_mplane,
+	.vidioc_try_fmt_vid_out_mplane	= isp_try_fmt_mplane,
+	.vidioc_s_fmt_vid_out_mplane	= isp_s_fmt_mplane,
+	.vidioc_g_fmt_vid_out_mplane	= isp_g_fmt_mplane,
+	.vidioc_reqbufs			= isp_reqbufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
+};
+
+static int isp_subdev_registered(struct v4l2_subdev *sd)
+{
+	struct fimc_is_isp *isp = v4l2_get_subdevdata(sd);
+	struct vb2_queue *q = &isp->vbq;
+	struct video_device *vfd = &isp->vfd;
+	int ret;
+
+	mutex_init(&isp->video_lock);
+
+	memset(vfd, 0, sizeof(*vfd));
+	snprintf(vfd->name, sizeof(vfd->name), "fimc-is-isp.output");
+
+	vfd->fops = &isp_video_output_fops;
+	vfd->ioctl_ops = &isp_video_output_ioctl_ops;
+	vfd->v4l2_dev = sd->v4l2_dev;
+	vfd->release = video_device_release_empty;
+	vfd->lock = &isp->video_lock;
+	vfd->queue = q;
+	vfd->vfl_dir = VFL_DIR_TX;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+
+	memset(q, 0, sizeof(*q));
+	q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	q->io_modes = VB2_MMAP | VB2_DMABUF;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->ops = &isp_video_output_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct fimc_is_buf);
+	q->drv_priv = isp;
+
+	ret = vb2_queue_init(q);
+	if (ret < 0)
+		return ret;
+
+	isp->vd_pad.flags = MEDIA_PAD_FL_SINK;
+	ret = media_entity_init(&vfd->entity, 1, &isp->vd_pad, 0);
+	if (ret < 0)
+		return ret;
+
+	video_set_drvdata(vfd, isp);
+
+	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		media_entity_cleanup(&vfd->entity);
+		return ret;
+	}
+
+	v4l2_info(sd->v4l2_dev, "Registered %s as /dev/%s\n",
+		  vfd->name, video_device_node_name(vfd));
+	return 0;
+}
+
+static void isp_subdev_unregistered(struct v4l2_subdev *sd)
+{
+	struct fimc_is_isp *isp = v4l2_get_subdevdata(sd);
+
+	if (isp && video_is_registered(&isp->vfd))
+		video_unregister_device(&isp->vfd);
+}
+
+static const struct v4l2_subdev_internal_ops isp_subdev_internal_ops = {
+	.registered = isp_subdev_registered,
+	.unregistered = isp_subdev_unregistered,
+};
+
+static struct fimc_is_sensor *fimc_is_get_sensor(struct fimc_is *is,
+		int sensor_id)
+{
+	int i;
+
+	for (i = 0; i < FIMC_IS_NUM_SENSORS; i++) {
+		if (is->sensor[i].drvdata->id == sensor_id)
+			return &is->sensor[i];
+	}
+	return NULL;
+}
+
+static int isp_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct fimc_is_isp *isp = v4l2_get_subdevdata(sd);
+	struct fimc_is *is = isp->pipeline->is;
+	struct v4l2_subdev *sensor_sd = isp->sensor_sd;
+	struct fimc_is_sensor *sensor;
+	const struct sensor_drv_data *sdata;
+	int ret;
+
+	if (!sensor_sd)
+		return -EINVAL;
+
+	if (on) {
+		ret = pm_runtime_get_sync(&is->pdev->dev);
+		if (ret < 0)
+			return ret;
+
+		sdata = exynos5_is_sensor_get_drvdata(sensor_sd->dev->of_node);
+		sensor = fimc_is_get_sensor(is, sdata->id);
+
+		ret = fimc_is_pipeline_open(isp->pipeline, sensor);
+		if (ret)
+			v4l2_err(&isp->subdev, "Pipeline open failed\n");
+	} else {
+		ret = fimc_is_pipeline_close(isp->pipeline);
+		if (ret)
+			v4l2_err(&isp->subdev, "Pipeline close failed\n");
+		pm_runtime_put_sync(&is->pdev->dev);
+	}
+
+	return ret;
+}
+
+static struct v4l2_subdev_core_ops isp_core_ops = {
+	.s_power = isp_s_power,
+};
+
+static int isp_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct fimc_is_isp *isp = v4l2_get_subdevdata(sd);
+	struct fimc_is *is = isp->pipeline->is;
+	struct v4l2_subdev *sensor_sd = isp->sensor_sd;
+	struct v4l2_subdev_format fmt;
+	const struct sensor_drv_data *sdata;
+	struct fimc_is_sensor *sensor;
+	int ret;
+
+	if (!sensor_sd)
+		return -EINVAL;
+
+	if (enable) {
+		sdata = exynos5_is_sensor_get_drvdata(sensor_sd->dev->of_node);
+		sensor = fimc_is_get_sensor(is, sdata->id);
+		/* Retrieve the sensor format */
+		fmt.pad = 0;
+		fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		ret = v4l2_subdev_call(sensor_sd, pad, get_fmt, NULL, &fmt);
+		if (ret)
+			return ret;
+
+		sensor->width = fmt.format.width - SENSOR_WIDTH_PADDING;
+		sensor->height = fmt.format.height - SENSOR_HEIGHT_PADDING;
+		sensor->pixel_width = fmt.format.width;
+		sensor->pixel_height = fmt.format.height;
+
+		/* Check sensor resolution match */
+		if ((sensor->pixel_width != isp->width) ||
+			(sensor->pixel_height != isp->height)) {
+			v4l2_err(sd, "Resolution mismatch\n");
+			return -EPIPE;
+		}
+
+		ret = fimc_is_pipeline_start(isp->pipeline, 1);
+		if (ret)
+			v4l2_err(sd, "Pipeline start failed.\n");
+	} else {
+		ret = fimc_is_pipeline_stop(isp->pipeline, 1);
+		if (ret)
+			v4l2_err(sd, "Pipeline stop failed.\n");
+	}
+
+	return ret;
+}
+
+static const struct v4l2_subdev_video_ops isp_video_ops = {
+	.s_stream       = isp_s_stream,
+};
+
+static struct v4l2_subdev_ops isp_subdev_ops = {
+	.core = &isp_core_ops,
+	.video = &isp_video_ops,
+};
+
+int fimc_is_isp_subdev_create(struct fimc_is_isp *isp,
+		struct vb2_alloc_ctx *alloc_ctx,
+		struct fimc_is_pipeline *pipeline)
+{
+	struct v4l2_ctrl_handler *handler = &isp->ctrl_handler;
+	struct v4l2_subdev *sd = &isp->subdev;
+	int ret;
+
+	isp->alloc_ctx = alloc_ctx;
+	isp->pipeline = pipeline;
+	isp->fmt = &formats[1];
+	INIT_LIST_HEAD(&isp->wait_queue);
+	INIT_LIST_HEAD(&isp->run_queue);
+	isp->width = ISP_DEF_WIDTH;
+	isp->height = ISP_DEF_HEIGHT;
+
+	v4l2_subdev_init(sd, &isp_subdev_ops);
+	sd->owner = THIS_MODULE;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(sd->name, sizeof(sd->name), ISP_DRV_NAME);
+
+	isp->subdev_pads[ISP_SD_PAD_SINK_DMA].flags = MEDIA_PAD_FL_SINK;
+	isp->subdev_pads[ISP_SD_PAD_SINK_OTF].flags = MEDIA_PAD_FL_SINK;
+	isp->subdev_pads[ISP_SD_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&sd->entity, ISP_SD_PADS_NUM,
+			isp->subdev_pads, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = v4l2_ctrl_handler_init(handler, 1);
+	if (handler->error)
+		goto err_ctrl;
+
+	sd->ctrl_handler = handler;
+	sd->internal_ops = &isp_subdev_internal_ops;
+	v4l2_set_subdevdata(sd, isp);
+
+	return 0;
+
+err_ctrl:
+	media_entity_cleanup(&sd->entity);
+	v4l2_ctrl_handler_free(handler);
+	return ret;
+}
+
+void fimc_is_isp_subdev_destroy(struct fimc_is_isp *isp)
+{
+	struct v4l2_subdev *sd = &isp->subdev;
+
+	v4l2_device_unregister_subdev(sd);
+	media_entity_cleanup(&sd->entity);
+	v4l2_ctrl_handler_free(&isp->ctrl_handler);
+	v4l2_set_subdevdata(sd, NULL);
+}
+
diff --git a/drivers/media/platform/exynos5-is/fimc-is-isp.h b/drivers/media/platform/exynos5-is/fimc-is-isp.h
new file mode 100644
index 0000000..fdb6d86
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-isp.h
@@ -0,0 +1,90 @@
+/*
+ * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ *  Arun Kumar K <arun.kk@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_IS_ISP_H_
+#define FIMC_IS_ISP_H_
+
+#include "fimc-is-core.h"
+#include "fimc-is-pipeline.h"
+
+#define FIMC_IS_ISP_REQ_BUFS_MIN	2
+
+#define ISP_SD_PAD_SINK_DMA	0
+#define ISP_SD_PAD_SINK_OTF	1
+#define ISP_SD_PAD_SRC		2
+#define ISP_SD_PADS_NUM		3
+
+#define ISP_DEF_WIDTH		1296
+#define ISP_DEF_HEIGHT		732
+
+#define ISP_MAX_WIDTH		4808
+#define ISP_MAX_HEIGHT		3356
+#define ISP_MIN_WIDTH		32
+#define ISP_MIN_HEIGHT		32
+
+#define ISP_MAX_BUFS		2
+
+/**
+ * struct fimc_is_isp - ISP context
+ * @vfd: video device node
+ * @fh: v4l2 file handle
+ * @alloc_ctx: videobuf2 memory allocator context
+ * @subdev: fimc-is-isp subdev
+ * @vd_pad: media pad for the output video node
+ * @subdev_pads: the subdev media pads
+ * @ctrl_handler: v4l2 control handler
+ * @video_lock: video lock mutex
+ * @sensor_sd: sensor subdev used with this isp instance
+ * @pipeline: pipeline instance for this isp context
+ * @vbq: vb2 buffers queue for ISP output video node
+ * @wait_queue: list holding buffers waiting to be queued to HW
+ * @wait_queue_cnt: wait queue number of buffers
+ * @run_queue: list holding buffers queued to HW
+ * @run_queue_cnt: run queue number of buffers
+ * @output_bufs: isp output buffers array
+ * @out_buf_cnt: number of output buffers in use
+ * @fmt: output plane format for isp
+ * @width: user configured input width
+ * @height: user configured input height
+ * @size_image: image size in bytes
+ * @output_state: state of the output video node operations
+ */
+struct fimc_is_isp {
+	struct video_device		vfd;
+	struct v4l2_fh			fh;
+	struct vb2_alloc_ctx		*alloc_ctx;
+	struct v4l2_subdev		subdev;
+	struct media_pad		vd_pad;
+	struct media_pad		subdev_pads[ISP_SD_PADS_NUM];
+	struct v4l2_ctrl_handler	ctrl_handler;
+	struct mutex			video_lock;
+
+	struct v4l2_subdev		*sensor_sd;
+	struct fimc_is_pipeline		*pipeline;
+
+	struct vb2_queue		vbq;
+	struct list_head		wait_queue;
+	unsigned int			wait_queue_cnt;
+	struct list_head		run_queue;
+	unsigned int			run_queue_cnt;
+
+	const struct fimc_is_fmt	*fmt;
+	unsigned int			width;
+	unsigned int			height;
+	unsigned int			size_image;
+	unsigned long			output_state;
+};
+
+int fimc_is_isp_subdev_create(struct fimc_is_isp *isp,
+		struct vb2_alloc_ctx *alloc_ctx,
+		struct fimc_is_pipeline *pipeline);
+void fimc_is_isp_subdev_destroy(struct fimc_is_isp *isp);
+
+#endif /* FIMC_IS_ISP_H_ */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 06/12] [media] exynos5-fimc-is: Add scaler subdev
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
                   ` (4 preceding siblings ...)
  2013-11-05 12:13 ` [PATCH v12 05/12] [media] exynos5-fimc-is: Add isp subdev Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 07/12] [media] exynos5-fimc-is: Add sensor interface Arun Kumar K
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

FIMC-IS has two hardware scalers named as scaler-codec and
scaler-preview. This patch adds the common code handling the
video nodes and subdevs of both the scalers.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Kilyeon Im <kilyeon.im@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/media/platform/exynos5-is/fimc-is-scaler.c |  476 ++++++++++++++++++++
 drivers/media/platform/exynos5-is/fimc-is-scaler.h |  106 +++++
 2 files changed, 582 insertions(+)
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-scaler.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-scaler.h

diff --git a/drivers/media/platform/exynos5-is/fimc-is-scaler.c b/drivers/media/platform/exynos5-is/fimc-is-scaler.c
new file mode 100644
index 0000000..029eb8b
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-scaler.c
@@ -0,0 +1,476 @@
+/*
+ * Samsung EXYNOS5250 FIMC-IS (Imaging Subsystem) driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *  Arun Kumar K <arun.kk@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 <media/v4l2-ioctl.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "fimc-is.h"
+
+#define IS_SCALER_DRV_NAME "fimc-is-scaler"
+
+static const struct fimc_is_fmt formats[] = {
+	{
+		.name           = "YUV 4:2:0 3p MultiPlanar",
+		.fourcc         = V4L2_PIX_FMT_YUV420M,
+		.depth		= {8, 2, 2},
+		.num_planes     = 3,
+	},
+	{
+		.name           = "YUV 4:2:0 2p MultiPlanar",
+		.fourcc         = V4L2_PIX_FMT_NV12M,
+		.depth		= {8, 4},
+		.num_planes     = 2,
+	},
+	{
+		.name           = "YUV 4:2:2 1p MultiPlanar",
+		.fourcc         = V4L2_PIX_FMT_NV16,
+		.depth		= {16},
+		.num_planes     = 1,
+	},
+};
+#define NUM_FORMATS ARRAY_SIZE(formats)
+
+static const struct fimc_is_fmt *find_format(struct v4l2_format *f)
+{
+	unsigned int i;
+
+	for (i = 0; i < NUM_FORMATS; i++) {
+		if (formats[i].fourcc == f->fmt.pix_mp.pixelformat)
+			return &formats[i];
+	}
+	return NULL;
+}
+
+static int scaler_video_capture_start_streaming(struct vb2_queue *vq,
+					unsigned int count)
+{
+	struct fimc_is_scaler *ctx = vb2_get_drv_priv(vq);
+	int ret;
+
+	ret = fimc_is_pipeline_scaler_start(ctx->pipeline,
+			ctx->scaler_id,
+			vq->num_buffers,
+			ctx->fmt->num_planes);
+	if (ret) {
+		v4l2_err(&ctx->subdev, "Scaler start failed.\n");
+		return -EINVAL;
+	}
+
+	set_bit(STATE_RUNNING, &ctx->capture_state);
+	return 0;
+}
+
+static int scaler_video_capture_stop_streaming(struct vb2_queue *vq)
+{
+	struct fimc_is_scaler *ctx = vb2_get_drv_priv(vq);
+	struct fimc_is_buf *buf;
+	int ret;
+
+	ret = fimc_is_pipeline_scaler_stop(ctx->pipeline, ctx->scaler_id);
+	if (ret)
+		v4l2_info(&ctx->subdev, "Scaler already stopped.\n");
+
+	/* Release un-used buffers */
+	while (!list_empty(&ctx->wait_queue)) {
+		buf = fimc_is_scaler_wait_queue_get(ctx);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+	while (!list_empty(&ctx->run_queue)) {
+		buf = fimc_is_scaler_run_queue_get(ctx);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+
+	clear_bit(STATE_RUNNING, &ctx->capture_state);
+	return 0;
+}
+
+static int scaler_video_capture_queue_setup(struct vb2_queue *vq,
+			const struct v4l2_format *pfmt,
+			unsigned int *num_buffers, unsigned int *num_planes,
+			unsigned int sizes[], void *allocators[])
+{
+	struct fimc_is_scaler *ctx = vb2_get_drv_priv(vq);
+	const struct fimc_is_fmt *fmt = ctx->fmt;
+	unsigned int wh;
+	int i;
+
+	if (!fmt)
+		return -EINVAL;
+
+	*num_planes = fmt->num_planes;
+	wh = ctx->width * ctx->height;
+
+	for (i = 0; i < *num_planes; i++) {
+		allocators[i] = ctx->alloc_ctx;
+		sizes[i] = (wh * fmt->depth[i]) / 8;
+	}
+	return 0;
+}
+
+static int scaler_video_capture_buffer_init(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct fimc_is_scaler *ctx = vb2_get_drv_priv(vq);
+	struct fimc_is_buf *buf = container_of(vb, struct fimc_is_buf, vb);
+	const struct fimc_is_fmt *fmt;
+	int i;
+
+	fmt = ctx->fmt;
+	for (i = 0; i < fmt->num_planes; i++)
+		buf->paddr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
+
+	return 0;
+}
+
+static int scaler_video_capture_buffer_prepare(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct fimc_is_scaler *ctx = vb2_get_drv_priv(vq);
+	int i;
+
+	for (i = 0; i < ctx->fmt->num_planes; i++) {
+		unsigned long size = (ctx->width * ctx->height *
+					ctx->fmt->depth[i]) / 8;
+
+		if (vb2_plane_size(vb, i) < size) {
+			v4l2_err(&ctx->subdev,
+				 "User buffer too small (%ld < %ld)\n",
+				 vb2_plane_size(vb, i), size);
+			return -EINVAL;
+		}
+		vb2_set_plane_payload(vb, i, size);
+	}
+
+	return 0;
+}
+
+static void scaler_video_capture_buffer_queue(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct fimc_is_scaler *ctx = vb2_get_drv_priv(vq);
+	struct fimc_is_buf *buf = container_of(vb, struct fimc_is_buf, vb);
+
+	/* Add buffer to the wait queue */
+	fimc_is_pipeline_buf_lock(ctx->pipeline);
+	fimc_is_scaler_wait_queue_add(ctx, buf);
+	fimc_is_pipeline_buf_unlock(ctx->pipeline);
+}
+
+static const struct vb2_ops scaler_video_capture_qops = {
+	.queue_setup		= scaler_video_capture_queue_setup,
+	.buf_init		= scaler_video_capture_buffer_init,
+	.buf_prepare		= scaler_video_capture_buffer_prepare,
+	.buf_queue		= scaler_video_capture_buffer_queue,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
+	.start_streaming	= scaler_video_capture_start_streaming,
+	.stop_streaming		= scaler_video_capture_stop_streaming,
+};
+
+static const struct v4l2_file_operations scaler_video_capture_fops = {
+	.owner		= THIS_MODULE,
+	.open		= v4l2_fh_open,
+	.release	= vb2_fop_release,
+	.poll		= vb2_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= vb2_fop_mmap,
+};
+
+/*
+ * Video node ioctl operations
+ */
+static int scaler_querycap_capture(struct file *file, void *priv,
+					struct v4l2_capability *cap)
+{
+	struct fimc_is_scaler *ctx = video_drvdata(file);
+	char *name = (ctx->scaler_id == SCALER_SCC) ?
+				"fimc-is-scc" : "fimc-is-scp";
+
+	strncpy(cap->driver, name, sizeof(cap->driver) - 1);
+	strncpy(cap->card, name, sizeof(cap->card) - 1);
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+			name);
+	cap->device_caps = V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int scaler_enum_fmt_mplane(struct file *file, void *priv,
+				     struct v4l2_fmtdesc *f)
+{
+	const struct fimc_is_fmt *fmt;
+
+	if (f->index >= NUM_FORMATS)
+		return -EINVAL;
+
+	fmt = &formats[f->index];
+	strlcpy(f->description, fmt->name, sizeof(f->description));
+	f->pixelformat = fmt->fourcc;
+	return 0;
+}
+
+static int scaler_g_fmt_mplane(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct fimc_is_scaler *ctx = video_drvdata(file);
+	struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
+	const struct fimc_is_fmt *fmt = ctx->fmt;
+	int i;
+
+	for (i = 0; i < fmt->num_planes; i++) {
+		struct v4l2_plane_pix_format *plane_fmt = &pixm->plane_fmt[i];
+		plane_fmt->bytesperline = (ctx->width * fmt->depth[i]) / 8;
+		plane_fmt->sizeimage = plane_fmt->bytesperline * ctx->height;
+		memset(plane_fmt->reserved, 0, sizeof(plane_fmt->reserved));
+	}
+
+	pixm->num_planes = fmt->num_planes;
+	pixm->pixelformat = fmt->fourcc;
+	pixm->width = ctx->width;
+	pixm->height = ctx->height;
+	pixm->field = V4L2_FIELD_NONE;
+	pixm->colorspace = V4L2_COLORSPACE_JPEG;
+	memset(pixm->reserved, 0, sizeof(pixm->reserved));
+
+	return 0;
+}
+
+static int scaler_try_fmt_mplane(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	const struct fimc_is_fmt *fmt;
+	struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
+	u32 i;
+
+	fmt = find_format(f);
+	if (!fmt)
+		fmt = &formats[0];
+
+	v4l_bound_align_image(&pixm->width, SCALER_MIN_WIDTH,
+			SCALER_MAX_WIDTH, 0,
+			&pixm->height, SCALER_MIN_HEIGHT,
+			SCALER_MAX_HEIGHT, 0, 0);
+
+	for (i = 0; i < fmt->num_planes; i++) {
+		struct v4l2_plane_pix_format *plane_fmt = &pixm->plane_fmt[i];
+
+		plane_fmt->bytesperline = (pixm->width * fmt->depth[i]) / 8;
+		plane_fmt->sizeimage = (pixm->width * pixm->height *
+					fmt->depth[i]) / 8;
+		memset(plane_fmt->reserved, 0, sizeof(plane_fmt->reserved));
+	}
+	pixm->num_planes = fmt->num_planes;
+	pixm->pixelformat = fmt->fourcc;
+	pixm->colorspace = V4L2_COLORSPACE_JPEG;
+	pixm->field = V4L2_FIELD_NONE;
+	memset(pixm->reserved, 0, sizeof(pixm->reserved));
+
+	return 0;
+}
+
+static int scaler_s_fmt_mplane(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct fimc_is_scaler *ctx = video_drvdata(file);
+	const struct fimc_is_fmt *fmt;
+	struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
+	int ret;
+
+	ret = scaler_try_fmt_mplane(file, priv, f);
+	if (ret)
+		return ret;
+
+	/* Get format type */
+	fmt = find_format(f);
+	if (!fmt) {
+		fmt = &formats[0];
+		pixm->pixelformat = fmt->fourcc;
+		pixm->num_planes = fmt->num_planes;
+	}
+
+	/* Save values to context */
+	ctx->fmt = fmt;
+	ctx->width = pixm->width;
+	ctx->height = pixm->height;
+	set_bit(STATE_INIT, &ctx->capture_state);
+	return 0;
+}
+
+static int scaler_reqbufs(struct file *file, void *priv,
+		struct v4l2_requestbuffers *reqbufs)
+{
+	struct fimc_is_scaler *ctx = video_drvdata(file);
+	int ret;
+
+	reqbufs->count = max_t(u32, FIMC_IS_SCALER_REQ_BUFS_MIN,
+			reqbufs->count);
+	ret = vb2_reqbufs(&ctx->vbq, reqbufs);
+	if (ret) {
+		v4l2_err(&ctx->subdev, "vb2 req buffers failed\n");
+		return ret;
+	}
+
+	if (reqbufs->count < FIMC_IS_SCALER_REQ_BUFS_MIN) {
+		reqbufs->count = 0;
+		vb2_reqbufs(&ctx->vbq, reqbufs);
+		return -ENOMEM;
+	}
+	set_bit(STATE_BUFS_ALLOCATED, &ctx->capture_state);
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops scaler_video_capture_ioctl_ops = {
+	.vidioc_querycap		= scaler_querycap_capture,
+	.vidioc_enum_fmt_vid_cap_mplane	= scaler_enum_fmt_mplane,
+	.vidioc_try_fmt_vid_cap_mplane	= scaler_try_fmt_mplane,
+	.vidioc_s_fmt_vid_cap_mplane	= scaler_s_fmt_mplane,
+	.vidioc_g_fmt_vid_cap_mplane	= scaler_g_fmt_mplane,
+	.vidioc_reqbufs			= scaler_reqbufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_expbuf			= vb2_ioctl_expbuf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
+};
+
+static int scaler_subdev_registered(struct v4l2_subdev *sd)
+{
+	struct fimc_is_scaler *ctx = v4l2_get_subdevdata(sd);
+	struct vb2_queue *q = &ctx->vbq;
+	struct video_device *vfd = &ctx->vfd;
+	int ret;
+
+	mutex_init(&ctx->video_lock);
+
+	memset(vfd, 0, sizeof(*vfd));
+	if (ctx->scaler_id == SCALER_SCC)
+		snprintf(vfd->name, sizeof(vfd->name), "fimc-is-scaler.codec");
+	else
+		snprintf(vfd->name, sizeof(vfd->name),
+				"fimc-is-scaler.preview");
+
+	vfd->fops = &scaler_video_capture_fops;
+	vfd->ioctl_ops = &scaler_video_capture_ioctl_ops;
+	vfd->v4l2_dev = sd->v4l2_dev;
+	vfd->release = video_device_release_empty;
+	vfd->lock = &ctx->video_lock;
+	vfd->queue = q;
+	vfd->vfl_dir = VFL_DIR_RX;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+
+	memset(q, 0, sizeof(*q));
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	q->io_modes = VB2_MMAP | VB2_DMABUF;
+	q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->ops = &scaler_video_capture_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct fimc_is_buf);
+	q->drv_priv = ctx;
+
+	ret = vb2_queue_init(q);
+	if (ret < 0)
+		return ret;
+
+	ctx->vd_pad.flags = MEDIA_PAD_FL_SINK;
+	ret = media_entity_init(&vfd->entity, 1, &ctx->vd_pad, 0);
+	if (ret < 0)
+		return ret;
+
+	video_set_drvdata(vfd, ctx);
+
+	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		media_entity_cleanup(&vfd->entity);
+		return ret;
+	}
+
+	v4l2_info(sd->v4l2_dev, "Registered %s as /dev/%s\n",
+		  vfd->name, video_device_node_name(vfd));
+	return 0;
+}
+
+static void scaler_subdev_unregistered(struct v4l2_subdev *sd)
+{
+	struct fimc_is_scaler *ctx = v4l2_get_subdevdata(sd);
+
+	if (ctx && video_is_registered(&ctx->vfd))
+		video_unregister_device(&ctx->vfd);
+}
+
+static const struct v4l2_subdev_internal_ops scaler_subdev_internal_ops = {
+	.registered = scaler_subdev_registered,
+	.unregistered = scaler_subdev_unregistered,
+};
+
+static struct v4l2_subdev_ops scaler_subdev_ops;
+
+int fimc_is_scaler_subdev_create(struct fimc_is_scaler *ctx,
+		enum fimc_is_scaler_id scaler_id,
+		struct vb2_alloc_ctx *alloc_ctx,
+		struct fimc_is_pipeline *pipeline)
+{
+	struct v4l2_ctrl_handler *handler = &ctx->ctrl_handler;
+	struct v4l2_subdev *sd = &ctx->subdev;
+	int ret;
+
+	ctx->scaler_id = scaler_id;
+	ctx->alloc_ctx = alloc_ctx;
+	ctx->pipeline = pipeline;
+	ctx->fmt = &formats[0];
+	ctx->width = SCALER_DEF_WIDTH;
+	ctx->height = SCALER_DEF_HEIGHT;
+	init_waitqueue_head(&ctx->event_q);
+	INIT_LIST_HEAD(&ctx->wait_queue);
+	INIT_LIST_HEAD(&ctx->run_queue);
+
+	/* Initialize scaler subdev */
+	v4l2_subdev_init(sd, &scaler_subdev_ops);
+	sd->owner = THIS_MODULE;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	if (scaler_id == SCALER_SCC)
+		snprintf(sd->name, sizeof(sd->name), "fimc-is-scc");
+	else
+		snprintf(sd->name, sizeof(sd->name), "fimc-is-scp");
+
+	ctx->subdev_pads[SCALER_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	ctx->subdev_pads[SCALER_SD_PAD_SRC_FIFO].flags = MEDIA_PAD_FL_SOURCE;
+	ctx->subdev_pads[SCALER_SD_PAD_SRC_DMA].flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&sd->entity, ISP_SD_PADS_NUM,
+			ctx->subdev_pads, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = v4l2_ctrl_handler_init(handler, 1);
+	if (handler->error)
+		goto err_ctrl;
+
+	sd->ctrl_handler = handler;
+	sd->internal_ops = &scaler_subdev_internal_ops;
+	v4l2_set_subdevdata(sd, ctx);
+
+	return 0;
+err_ctrl:
+	media_entity_cleanup(&sd->entity);
+	v4l2_ctrl_handler_free(handler);
+	return ret;
+}
+
+void fimc_is_scaler_subdev_destroy(struct fimc_is_scaler *ctx)
+{
+	struct v4l2_subdev *sd = &ctx->subdev;
+
+	v4l2_device_unregister_subdev(sd);
+	media_entity_cleanup(&sd->entity);
+	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+	v4l2_set_subdevdata(sd, NULL);
+}
+
diff --git a/drivers/media/platform/exynos5-is/fimc-is-scaler.h b/drivers/media/platform/exynos5-is/fimc-is-scaler.h
new file mode 100644
index 0000000..97a9d0d
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-scaler.h
@@ -0,0 +1,106 @@
+/*
+ * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *  Arun Kumar K <arun.kk@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_IS_SCALER_H_
+#define FIMC_IS_SCALER_H_
+
+#include <linux/sizes.h>
+#include <linux/io.h>
+#include <linux/irqreturn.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/media-entity.h>
+#include <media/videobuf2-core.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mediabus.h>
+#include <media/s5p_fimc.h>
+
+#include "fimc-is-core.h"
+
+#define SCALER_SD_PAD_SINK	0
+#define SCALER_SD_PAD_SRC_FIFO	1
+#define SCALER_SD_PAD_SRC_DMA	2
+#define SCALER_SD_PADS_NUM	3
+
+#define SCALER_MAX_BUFS		32
+#define SCALER_MAX_PLANES	3
+
+#define FIMC_IS_SCALER_REQ_BUFS_MIN	2
+
+#define SCALER_DEF_WIDTH	1280
+#define SCALER_DEF_HEIGHT	720
+#define SCALER_MAX_WIDTH	4808
+#define SCALER_MAX_HEIGHT	3356
+#define SCALER_MIN_WIDTH	32
+#define SCALER_MIN_HEIGHT	32
+
+/**
+ * struct fimc_is_scaler - fimc-is scaler structure
+ * @vfd: video device node
+ * @fh: v4l2 file handle
+ * @alloc_ctx: videobuf2 memory allocator context
+ * @subdev: fimc-is-scaler subdev
+ * @vd_pad: media pad for the output video node
+ * @subdev_pads: the subdev media pads
+ * @ctrl_handler: v4l2 control handler
+ * @video_lock: video lock mutex
+ * @event_q: notifies scaler events
+ * @pipeline: pipeline instance for this scaler context
+ * @scaler_id: distinguishes scaler preview or scaler codec
+ * @vbq: vb2 buffers queue for ISP output video node
+ * @wait_queue: list holding buffers waiting to be queued to HW
+ * @wait_queue_cnt: wait queue number of buffers
+ * @run_queue: list holding buffers queued to HW
+ * @run_queue_cnt: run queue number of buffers
+ * @capture_bufs: scaler capture buffers array
+ * @fmt: capture plane format for scaler
+ * @width: user configured output width
+ * @height: user configured output height
+ * @capture_state: state of the capture video node operations
+ */
+struct fimc_is_scaler {
+	struct video_device		vfd;
+	struct v4l2_fh			fh;
+	struct vb2_alloc_ctx		*alloc_ctx;
+	struct v4l2_subdev		subdev;
+	struct media_pad		vd_pad;
+	struct media_pad		subdev_pads[SCALER_SD_PADS_NUM];
+	struct v4l2_mbus_framefmt	subdev_fmt;
+	struct v4l2_ctrl_handler	ctrl_handler;
+
+	struct mutex		video_lock;
+	wait_queue_head_t	event_q;
+
+	struct fimc_is_pipeline	*pipeline;
+	enum fimc_is_scaler_id	scaler_id;
+
+	struct vb2_queue	vbq;
+	struct list_head	wait_queue;
+	unsigned int		wait_queue_cnt;
+	struct list_head	run_queue;
+	unsigned int		run_queue_cnt;
+
+	const struct fimc_is_fmt *fmt;
+	unsigned int		width;
+	unsigned int		height;
+	unsigned long		capture_state;
+};
+
+int fimc_is_scaler_subdev_create(struct fimc_is_scaler *ctx,
+		enum fimc_is_scaler_id scaler_id,
+		struct vb2_alloc_ctx *alloc_ctx,
+		struct fimc_is_pipeline *pipeline);
+void fimc_is_scaler_subdev_destroy(struct fimc_is_scaler *scaler);
+
+#endif /* FIMC_IS_SCALER_H_ */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 07/12] [media] exynos5-fimc-is: Add sensor interface
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
                   ` (5 preceding siblings ...)
  2013-11-05 12:13 ` [PATCH v12 06/12] [media] exynos5-fimc-is: Add scaler subdev Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 08/12] [media] exynos5-fimc-is: Add the hardware pipeline control Arun Kumar K
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

Some sensors to be used with fimc-is are exclusively controlled
by the fimc-is firmware. This minimal sensor driver provides
the required info for the firmware to configure the sensors
sitting on I2C bus.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/media/platform/exynos5-is/fimc-is-sensor.c |   45 ++++++++++++++
 drivers/media/platform/exynos5-is/fimc-is-sensor.h |   65 ++++++++++++++++++++
 2 files changed, 110 insertions(+)
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-sensor.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-sensor.h

diff --git a/drivers/media/platform/exynos5-is/fimc-is-sensor.c b/drivers/media/platform/exynos5-is/fimc-is-sensor.c
new file mode 100644
index 0000000..475f1c3
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-sensor.c
@@ -0,0 +1,45 @@
+/*
+ * Samsung EXYNOS5250 FIMC-IS (Imaging Subsystem) driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Arun Kumar K <arun.kk@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 "fimc-is-sensor.h"
+
+static const struct sensor_drv_data s5k6a3_drvdata = {
+	.id		= FIMC_IS_SENSOR_ID_S5K6A3,
+	.open_timeout	= S5K6A3_OPEN_TIMEOUT,
+	.setfile_name	= "exynos5_s5k6a3_setfile.bin",
+};
+
+static const struct sensor_drv_data s5k4e5_drvdata = {
+	.id		= FIMC_IS_SENSOR_ID_S5K4E5,
+	.open_timeout	= S5K4E5_OPEN_TIMEOUT,
+	.setfile_name	= "exynos5_s5k4e5_setfile.bin",
+};
+
+static const struct of_device_id fimc_is_sensor_of_ids[] = {
+	{
+		.compatible	= "samsung,s5k6a3",
+		.data		= &s5k6a3_drvdata,
+	},
+	{
+		.compatible	= "samsung,s5k4e5",
+		.data		= &s5k4e5_drvdata,
+	},
+	{  }
+};
+
+const struct sensor_drv_data *exynos5_is_sensor_get_drvdata(
+			struct device_node *node)
+{
+	const struct of_device_id *of_id;
+
+	of_id = of_match_node(fimc_is_sensor_of_ids, node);
+	return of_id ? of_id->data : NULL;
+}
diff --git a/drivers/media/platform/exynos5-is/fimc-is-sensor.h b/drivers/media/platform/exynos5-is/fimc-is-sensor.h
new file mode 100644
index 0000000..0ba5733
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-sensor.h
@@ -0,0 +1,65 @@
+/*
+ * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Arun Kumar K <arun.kk@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_IS_SENSOR_H_
+#define FIMC_IS_SENSOR_H_
+
+#include <linux/of.h>
+#include <linux/types.h>
+
+#define S5K6A3_OPEN_TIMEOUT		2000 /* ms */
+#define S5K6A3_SENSOR_WIDTH		1392
+#define S5K6A3_SENSOR_HEIGHT		1392
+
+#define S5K4E5_OPEN_TIMEOUT		2000 /* ms */
+#define S5K4E5_SENSOR_WIDTH		2560
+#define S5K4E5_SENSOR_HEIGHT		1920
+
+#define SENSOR_WIDTH_PADDING		16
+#define SENSOR_HEIGHT_PADDING		10
+
+enum fimc_is_sensor_id {
+	FIMC_IS_SENSOR_ID_S5K3H2 = 1,
+	FIMC_IS_SENSOR_ID_S5K6A3,
+	FIMC_IS_SENSOR_ID_S5K4E5,
+	FIMC_IS_SENSOR_ID_S5K3H7,
+	FIMC_IS_SENSOR_ID_CUSTOM,
+	FIMC_IS_SENSOR_ID_END
+};
+
+struct sensor_drv_data {
+	enum fimc_is_sensor_id id;
+	/* sensor open timeout in ms */
+	unsigned short open_timeout;
+	char *setfile_name;
+};
+
+/**
+ * struct fimc_is_sensor - fimc-is sensor data structure
+ * @drvdata: a pointer to the sensor's parameters data structure
+ * @i2c_bus: ISP I2C bus index (0...1)
+ * @width: sensor active width
+ * @height: sensor active height
+ * @pixel_width: sensor effective pixel width (width + padding)
+ * @pixel_height: sensor effective pixel height (height + padding)
+ */
+struct fimc_is_sensor {
+	const struct sensor_drv_data *drvdata;
+	unsigned int i2c_bus;
+	unsigned int width;
+	unsigned int height;
+	unsigned int pixel_width;
+	unsigned int pixel_height;
+};
+
+const struct sensor_drv_data *exynos5_is_sensor_get_drvdata(
+			struct device_node *node);
+
+#endif /* FIMC_IS_SENSOR_H_ */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 08/12] [media] exynos5-fimc-is: Add the hardware pipeline control
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
                   ` (6 preceding siblings ...)
  2013-11-05 12:13 ` [PATCH v12 07/12] [media] exynos5-fimc-is: Add sensor interface Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 09/12] [media] exynos5-fimc-is: Add the hardware interface module Arun Kumar K
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

This patch adds the crucial hardware pipeline control for the
fimc-is driver. All the subdev nodes will call this pipeline
interfaces to reach the hardware. Responsibilities of this module
involves configuring and maintaining the hardware pipeline involving
multiple sub-ips like ISP, DRC, Scalers, ODC, 3DNR, FD etc.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Kilyeon Im <kilyeon.im@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 .../media/platform/exynos5-is/fimc-is-pipeline.c   | 1699 ++++++++++++++++++++
 .../media/platform/exynos5-is/fimc-is-pipeline.h   |  129 ++
 2 files changed, 1828 insertions(+)
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-pipeline.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-pipeline.h

diff --git a/drivers/media/platform/exynos5-is/fimc-is-pipeline.c b/drivers/media/platform/exynos5-is/fimc-is-pipeline.c
new file mode 100644
index 0000000..25eaf24
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-pipeline.c
@@ -0,0 +1,1699 @@
+/*
+ * Samsung EXYNOS5 FIMC-IS (Imaging Subsystem) driver
+*
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Arun Kumar K <arun.kk@samsung.com>
+ * Kil-yeon Lim <kilyeon.im@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 "fimc-is.h"
+#include "fimc-is-pipeline.h"
+#include "fimc-is-metadata.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-cmd.h"
+#include <media/videobuf2-dma-contig.h>
+#include <linux/delay.h>
+
+/* Default setting values */
+#define DEFAULT_PREVIEW_STILL_WIDTH		1280
+#define DEFAULT_PREVIEW_STILL_HEIGHT		720
+#define DEFAULT_CAPTURE_VIDEO_WIDTH		1920
+#define DEFAULT_CAPTURE_VIDEO_HEIGHT		1080
+#define DEFAULT_CAPTURE_STILL_WIDTH		2560
+#define DEFAULT_CAPTURE_STILL_HEIGHT		1920
+#define DEFAULT_CAPTURE_STILL_CROP_WIDTH	2560
+#define DEFAULT_CAPTURE_STILL_CROP_HEIGHT	1440
+#define DEFAULT_PREVIEW_VIDEO_WIDTH		640
+#define DEFAULT_PREVIEW_VIDEO_HEIGHT		480
+
+/* Init params for pipeline devices */
+static const struct sensor_param init_sensor_param = {
+	.frame_rate = {
+		.frame_rate = 30,
+	},
+};
+
+static const struct isp_param init_isp_param = {
+	.control = {
+		.cmd = CONTROL_COMMAND_START,
+		.bypass = CONTROL_BYPASS_DISABLE,
+	},
+	.otf_input = {
+		.cmd = OTF_INPUT_COMMAND_DISABLE,
+		.width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
+		.format = OTF_INPUT_FORMAT_BAYER,
+		.bitwidth = OTF_INPUT_BIT_WIDTH_10BIT,
+		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
+		.frametime_max = 33333,
+	},
+	.dma1_input = {
+		.cmd = DMA_INPUT_COMMAND_DISABLE,
+	},
+	.dma2_input = {
+		.cmd = DMA_INPUT_COMMAND_DISABLE,
+	},
+	.aa = {
+		.cmd = ISP_AA_COMMAND_START,
+	},
+	.flash = {
+		.cmd = ISP_FLASH_COMMAND_DISABLE,
+		.redeye = ISP_FLASH_REDEYE_DISABLE,
+	},
+	.awb = {
+		.cmd = ISP_AWB_COMMAND_AUTO,
+	},
+	.effect = {
+		.cmd = ISP_IMAGE_EFFECT_DISABLE,
+	},
+	.iso = {
+		.cmd = ISP_ISO_COMMAND_AUTO,
+	},
+	.adjust = {
+		.cmd = ISP_ADJUST_COMMAND_AUTO,
+	},
+	.metering = {
+		.cmd = ISP_METERING_COMMAND_CENTER,
+		.win_width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.win_height = DEFAULT_CAPTURE_STILL_HEIGHT,
+	},
+	.afc = {
+		.cmd = ISP_AFC_COMMAND_AUTO,
+	},
+	.otf_output = {
+		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
+		.format = OTF_OUTPUT_FORMAT_YUV444,
+		.bitwidth = OTF_OUTPUT_BIT_WIDTH_12BIT,
+		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+	},
+	.dma1_output = {
+		.cmd = DMA_OUTPUT_COMMAND_DISABLE,
+		.width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
+		.format = DMA_INPUT_FORMAT_YUV444,
+		.bitwidth = DMA_INPUT_BIT_WIDTH_8BIT,
+		.plane = 1,
+		.order = DMA_INPUT_ORDER_YCBCR,
+	},
+	.dma2_output = {
+		.cmd = DMA_OUTPUT_COMMAND_DISABLE,
+		.width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
+		.format = DMA_OUTPUT_FORMAT_BAYER,
+		.bitwidth = DMA_OUTPUT_BIT_WIDTH_12BIT,
+		.plane = 1,
+		.order = DMA_OUTPUT_ORDER_GB_BG,
+		.dma_out_mask = 0xffffffff,
+	},
+};
+
+static const struct drc_param init_drc_param = {
+	.control = {
+		.cmd = CONTROL_COMMAND_START,
+		.bypass = CONTROL_BYPASS_ENABLE,
+	},
+	.otf_input = {
+		.cmd = OTF_INPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
+		.format = OTF_INPUT_FORMAT_YUV444,
+		.bitwidth = OTF_INPUT_BIT_WIDTH_12BIT,
+		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
+	},
+	.dma_input = {
+		.cmd = DMA_INPUT_COMMAND_DISABLE,
+		.width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
+		.format = DMA_INPUT_FORMAT_YUV444,
+		.bitwidth = DMA_INPUT_BIT_WIDTH_8BIT,
+		.plane = 1,
+		.order = DMA_INPUT_ORDER_YCBCR,
+	},
+	.otf_output = {
+		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
+		.format = OTF_OUTPUT_FORMAT_YUV444,
+		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+	},
+};
+
+static const struct scalerc_param init_scalerc_param = {
+	.control = {
+		.cmd = CONTROL_COMMAND_START,
+		.bypass = CONTROL_BYPASS_ENABLE,
+	},
+	.otf_input = {
+		.cmd = OTF_INPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
+		.format = OTF_INPUT_FORMAT_YUV444,
+		.bitwidth = OTF_INPUT_BIT_WIDTH_12BIT,
+		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
+	},
+	.input_crop = {
+		.cmd = OTF_INPUT_COMMAND_ENABLE,
+		.crop_width = DEFAULT_CAPTURE_STILL_CROP_WIDTH,
+		.crop_height = DEFAULT_CAPTURE_STILL_CROP_HEIGHT,
+		.in_width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.in_height = DEFAULT_CAPTURE_STILL_HEIGHT,
+		.out_width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.out_height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+	},
+	.output_crop = {
+		.cmd = SCALER_CROP_COMMAND_DISABLE,
+		.crop_width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.crop_height = DEFAULT_CAPTURE_STILL_HEIGHT,
+		.format = DMA_OUTPUT_FORMAT_YUV420,
+	},
+	.otf_output = {
+		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+		.format = OTF_OUTPUT_FORMAT_YUV444,
+		.bitwidth = OTF_OUTPUT_BIT_WIDTH_8BIT,
+		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+	},
+	.dma_output = {
+		.cmd = DMA_OUTPUT_COMMAND_DISABLE,
+		.width = DEFAULT_CAPTURE_STILL_WIDTH,
+		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
+		.format = DMA_OUTPUT_FORMAT_YUV420,
+		.bitwidth = DMA_OUTPUT_BIT_WIDTH_8BIT,
+		.plane = 3,
+		.order = DMA_OUTPUT_ORDER_NONE,
+		.dma_out_mask = 0xffff,
+	},
+};
+
+static const struct odc_param init_odc_param = {
+	.control = {
+		.cmd = CONTROL_COMMAND_START,
+		.bypass = CONTROL_BYPASS_ENABLE,
+		.err = CONTROL_ERROR_NONE,
+	},
+	.otf_input = {
+		.cmd = OTF_INPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+		.format = OTF_INPUT_FORMAT_YUV444,
+		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
+	},
+	.otf_output = {
+		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+		.format = OTF_OUTPUT_FORMAT_YUV422,
+		.bitwidth = OTF_OUTPUT_BIT_WIDTH_8BIT,
+		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+	},
+};
+
+static const struct dis_param init_dis_param = {
+	.control = {
+		.cmd = CONTROL_COMMAND_START,
+		.bypass = CONTROL_BYPASS_ENABLE,
+	},
+	.otf_input = {
+		.cmd = OTF_INPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+		.format = OTF_INPUT_FORMAT_YUV422,
+		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
+	},
+	.otf_output = {
+		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+		.format = OTF_OUTPUT_FORMAT_YUV422,
+		.bitwidth = OTF_OUTPUT_BIT_WIDTH_8BIT,
+		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+	},
+};
+static const struct tdnr_param init_tdnr_param = {
+	.control = {
+		.cmd = CONTROL_COMMAND_START,
+		.bypass = CONTROL_BYPASS_ENABLE,
+	},
+	.otf_input = {
+		.cmd = OTF_INPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+		.format = OTF_INPUT_FORMAT_YUV422,
+		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
+	},
+	.otf_output = {
+		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+		.format = OTF_OUTPUT_FORMAT_YUV444,
+		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+	},
+	.dma_output = {
+		.cmd = DMA_OUTPUT_COMMAND_DISABLE,
+		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+		.format = DMA_OUTPUT_FORMAT_YUV420,
+		.bitwidth = DMA_OUTPUT_BIT_WIDTH_8BIT,
+		.plane = 2,
+		.order = DMA_OUTPUT_ORDER_CBCR,
+		.dma_out_mask = 0xffff,
+	},
+};
+
+static const struct scalerp_param init_scalerp_param = {
+	.control = {
+		.cmd = CONTROL_COMMAND_START,
+		.bypass = CONTROL_BYPASS_ENABLE,
+	},
+	.otf_input = {
+		.cmd = OTF_INPUT_COMMAND_ENABLE,
+		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+		.format = OTF_INPUT_FORMAT_YUV444,
+		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
+	},
+	.input_crop = {
+		.cmd = OTF_INPUT_COMMAND_ENABLE,
+		.crop_width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.crop_height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+		.in_width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+		.in_height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+		.out_width = DEFAULT_PREVIEW_STILL_WIDTH,
+		.out_height = DEFAULT_PREVIEW_STILL_HEIGHT,
+	},
+	.output_crop = {
+		.cmd = SCALER_CROP_COMMAND_DISABLE,
+		.crop_width = DEFAULT_PREVIEW_STILL_WIDTH,
+		.crop_height = DEFAULT_PREVIEW_STILL_HEIGHT,
+		.format = OTF_OUTPUT_FORMAT_YUV420,
+	},
+	.otf_output = {
+		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
+		.width = DEFAULT_PREVIEW_STILL_WIDTH,
+		.height = DEFAULT_PREVIEW_STILL_HEIGHT,
+		.format = OTF_INPUT_FORMAT_YUV444,
+		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+	},
+	.dma_output = {
+		.cmd = DMA_OUTPUT_COMMAND_DISABLE,
+		.width = DEFAULT_PREVIEW_STILL_WIDTH,
+		.height = DEFAULT_PREVIEW_STILL_HEIGHT,
+		.format = OTF_OUTPUT_FORMAT_YUV420,
+		.bitwidth = DMA_OUTPUT_BIT_WIDTH_8BIT,
+		.plane = 3,
+		.order = DMA_OUTPUT_ORDER_NONE,
+		.dma_out_mask = 0xffff,
+	},
+};
+
+static const struct fd_param init_fd_param = {
+	.control = {
+		.cmd = CONTROL_COMMAND_STOP,
+		.bypass = CONTROL_BYPASS_DISABLE,
+	},
+	.otf_input = {
+		.cmd = OTF_INPUT_COMMAND_ENABLE,
+		.width = DEFAULT_PREVIEW_STILL_WIDTH,
+		.height = DEFAULT_PREVIEW_STILL_HEIGHT,
+		.format = OTF_INPUT_FORMAT_YUV444,
+		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
+	},
+	.dma_input = {
+		.cmd = DMA_INPUT_COMMAND_DISABLE,
+	},
+	.config = {
+		.cmd = FD_CONFIG_COMMAND_MAXIMUM_NUMBER |
+			FD_CONFIG_COMMAND_ROLL_ANGLE |
+			FD_CONFIG_COMMAND_YAW_ANGLE |
+			FD_CONFIG_COMMAND_SMILE_MODE |
+			FD_CONFIG_COMMAND_BLINK_MODE |
+			FD_CONFIG_COMMAND_EYES_DETECT |
+			FD_CONFIG_COMMAND_MOUTH_DETECT |
+			FD_CONFIG_COMMAND_ORIENTATION |
+			FD_CONFIG_COMMAND_ORIENTATION_VALUE,
+		.max_number = CAMERA2_MAX_FACES,
+		.roll_angle = FD_CONFIG_ROLL_ANGLE_FULL,
+		.yaw_angle = FD_CONFIG_YAW_ANGLE_45_90,
+		.smile_mode = FD_CONFIG_SMILE_MODE_DISABLE,
+		.blink_mode = FD_CONFIG_BLINK_MODE_DISABLE,
+		.eye_detect = FD_CONFIG_EYES_DETECT_ENABLE,
+		.mouth_detect = FD_CONFIG_MOUTH_DETECT_DISABLE,
+		.orientation = FD_CONFIG_ORIENTATION_DISABLE,
+	},
+};
+
+static int fimc_is_pipeline_create_subdevs(struct fimc_is_pipeline *pipeline)
+{
+	struct fimc_is *is = pipeline->is;
+	int ret;
+
+	/* ISP */
+	ret = fimc_is_isp_subdev_create(&pipeline->isp,
+			is->alloc_ctx, pipeline);
+	if (ret)
+		return ret;
+
+	/* SCC scaler */
+	ret = fimc_is_scaler_subdev_create(&pipeline->scaler[SCALER_SCC],
+			SCALER_SCC, is->alloc_ctx, pipeline);
+	if (ret)
+		return ret;
+
+	/* SCP scaler */
+	ret = fimc_is_scaler_subdev_create(&pipeline->scaler[SCALER_SCP],
+			SCALER_SCP, is->alloc_ctx, pipeline);
+	if (ret)
+		return ret;
+
+	return ret;
+}
+
+static int fimc_is_pipeline_unregister_subdevs(struct fimc_is_pipeline *p)
+{
+	fimc_is_isp_subdev_destroy(&p->isp);
+	fimc_is_scaler_subdev_destroy(&p->scaler[SCALER_SCC]);
+	fimc_is_scaler_subdev_destroy(&p->scaler[SCALER_SCP]);
+
+	return 0;
+}
+
+int fimc_is_pipeline_init(struct fimc_is_pipeline *pipeline,
+			unsigned int instance, void *is_ctx)
+{
+	struct fimc_is *is = is_ctx;
+	unsigned int i;
+	int ret;
+
+	if (test_bit(PIPELINE_INIT, &pipeline->state))
+		return -EINVAL;
+
+	/* Initialize context variables */
+	pipeline->instance = instance;
+	pipeline->is = is;
+	pipeline->dev = &is->pdev->dev;
+	pipeline->minfo = &is->minfo;
+	pipeline->state = 0;
+	pipeline->force_down = false;
+	for (i = 0; i < FIMC_IS_NUM_COMPS; i++)
+		pipeline->comp_state[i] = 0;
+
+	spin_lock_init(&pipeline->slock_buf);
+	init_waitqueue_head(&pipeline->wait_q);
+	mutex_init(&pipeline->pipe_lock);
+	mutex_init(&pipeline->pipe_scl_lock);
+
+	ret = fimc_is_pipeline_create_subdevs(pipeline);
+	if (ret) {
+		dev_err(pipeline->dev, "Subdev creation failed\n");
+		return -EINVAL;
+	}
+
+	set_bit(PIPELINE_INIT, &pipeline->state);
+	return 0;
+}
+
+int fimc_is_pipeline_destroy(struct fimc_is_pipeline *pipeline)
+{
+	if (!pipeline)
+		return -EINVAL;
+
+	if (!test_bit(PIPELINE_INIT, &pipeline->state))
+		return -EINVAL;
+	return fimc_is_pipeline_unregister_subdevs(pipeline);
+}
+
+static int fimc_is_pipeline_initmem(struct fimc_is_pipeline *pipeline)
+{
+	struct fimc_is_meminfo *minfo = pipeline->minfo;
+	unsigned int offset;
+
+	/* Allocate fw memory */
+	minfo->fw.vaddr = dma_alloc_coherent(pipeline->dev,
+			FIMC_IS_A5_MEM_SIZE + FIMC_IS_A5_SEN_SIZE,
+			&minfo->fw.paddr, GFP_KERNEL);
+	if (minfo->fw.vaddr == NULL)
+		return -ENOMEM;
+	minfo->fw.size = FIMC_IS_A5_MEM_SIZE + FIMC_IS_A5_SEN_SIZE;
+
+	/* FW memory should be 64MB aligned */
+	if ((u32)minfo->fw.paddr & FIMC_IS_FW_BASE_MASK) {
+		dev_err(pipeline->dev, "FW memory not 64MB aligned\n");
+		dma_free_coherent(pipeline->dev, minfo->fw.size,
+				minfo->fw.vaddr,
+				minfo->fw.paddr);
+		return -EIO;
+	}
+
+	/* Assigning memory regions */
+	offset = FIMC_IS_A5_MEM_SIZE - FIMC_IS_REGION_SIZE;
+	minfo->region.paddr = minfo->fw.paddr + offset;
+	minfo->region.vaddr = minfo->fw.vaddr + offset;
+	pipeline->is_region = (struct is_region *)minfo->region.vaddr;
+
+	minfo->shared.paddr = minfo->fw.paddr +
+		(unsigned int)((void *)&pipeline->is_region->shared[0] -
+		 minfo->fw.vaddr);
+	minfo->shared.vaddr = minfo->fw.vaddr +
+		(unsigned int)((void *)&pipeline->is_region->shared[0] -
+		 minfo->fw.vaddr);
+
+	/* Allocate shot buffer */
+	minfo->shot.vaddr = dma_alloc_coherent(pipeline->dev,
+			sizeof(struct camera2_shot),
+			&minfo->shot.paddr, GFP_KERNEL);
+	if (minfo->shot.vaddr == NULL) {
+		dma_free_coherent(pipeline->dev, minfo->fw.size,
+				minfo->fw.vaddr,
+				minfo->fw.paddr);
+		return -ENOMEM;
+	}
+	minfo->shot.size = sizeof(struct camera2_shot);
+
+	return 0;
+}
+
+static void fimc_is_pipeline_freemem(struct fimc_is_pipeline *pipeline)
+{
+	struct fimc_is_meminfo *minfo = pipeline->minfo;
+	if (minfo->fw.vaddr)
+		dma_free_coherent(pipeline->dev, minfo->fw.size,
+				minfo->fw.vaddr,
+				minfo->fw.paddr);
+	if (minfo->shot.vaddr)
+		dma_free_coherent(pipeline->dev, minfo->shot.size,
+				minfo->shot.vaddr,
+				minfo->shot.paddr);
+}
+
+static int fimc_is_pipeline_load_firmware(struct fimc_is_pipeline *pipeline)
+{
+	const struct firmware *fw_blob;
+	struct fimc_is *is = pipeline->is;
+	int ret;
+
+	ret = request_firmware(&fw_blob, is->drvdata->fw_name, &is->pdev->dev);
+	if (ret) {
+		dev_err(pipeline->dev, "Firmware file not found\n");
+		return -EINVAL;
+	}
+	if (fw_blob->size > FIMC_IS_A5_MEM_SIZE + FIMC_IS_A5_SEN_SIZE) {
+		dev_err(pipeline->dev, "Firmware file too big\n");
+		release_firmware(fw_blob);
+		return -ENOMEM;
+	}
+
+	memcpy(pipeline->minfo->fw.vaddr, fw_blob->data, fw_blob->size);
+	wmb();
+	release_firmware(fw_blob);
+
+	return 0;
+}
+
+static void fimc_is_pipeline_forcedown(struct fimc_is_pipeline *pipeline,
+		bool on)
+{
+	struct fimc_is *is = pipeline->is;
+	if (on) {
+		pmu_is_write(0x0, is, PMUREG_ISP_ARM_OPTION);
+		pmu_is_write(0x1cf82000, is, PMUREG_ISP_LOW_POWER_OFF);
+		pipeline->force_down = true;
+	} else {
+		pmu_is_write(0xffffffff, is, PMUREG_ISP_ARM_OPTION);
+		pmu_is_write(0x8, is, PMUREG_ISP_LOW_POWER_OFF);
+		pipeline->force_down = false;
+	}
+}
+
+static int fimc_is_pipeline_wait_timeout(struct fimc_is_pipeline *pipeline,
+					int on)
+{
+	struct fimc_is *is = pipeline->is;
+	u32 timeout = FIMC_IS_A5_TIMEOUT;
+
+	while ((pmu_is_read(is, PMUREG_ISP_ARM_STATUS) & 0x1) != on) {
+		if (timeout == 0)
+			return -ETIME;
+		timeout--;
+		udelay(1);
+	}
+	return 0;
+}
+
+static int fimc_is_pipeline_power(struct fimc_is_pipeline *pipeline, int on)
+{
+	int ret = 0;
+	struct fimc_is *is = pipeline->is;
+	struct device *dev = &is->pdev->dev;
+
+	if (on) {
+		/* force poweroff setting */
+		if (pipeline->force_down)
+			fimc_is_pipeline_forcedown(pipeline, false);
+
+		/* FIMC-IS local power enable */
+		ret = pm_runtime_get_sync(dev);
+		if (ret)
+			return ret;
+
+		/* A5 start address setting */
+		writel(pipeline->minfo->fw.paddr, is->interface.regs + BBOAR);
+
+		/* A5 power on*/
+		pmu_is_write(0x1, is, PMUREG_ISP_ARM_CONFIGURATION);
+
+		/* enable A5 */
+		pmu_is_write(0x00018000, is, PMUREG_ISP_ARM_OPTION);
+		ret = fimc_is_pipeline_wait_timeout(pipeline, on);
+		if (ret)
+			dev_err(pipeline->dev, "A5 power on failed\n");
+	} else {
+		/* disable A5 */
+		pmu_is_write(0x10000, is, PMUREG_ISP_ARM_OPTION);
+
+		/* A5 power off*/
+		pmu_is_write(0x0, is, PMUREG_ISP_ARM_CONFIGURATION);
+
+		/* Check A5 power off status register */
+		ret = fimc_is_pipeline_wait_timeout(pipeline, on);
+		if (ret) {
+			dev_err(pipeline->dev, "A5 power off failed\n");
+			fimc_is_pipeline_forcedown(pipeline, true);
+		}
+
+		pmu_is_write(0x0, is, PMUREG_CMU_RESET_ISP_SYS_PWR_REG);
+
+		/* FIMC-IS local power down */
+		pm_runtime_put_sync(dev);
+	}
+
+	return ret;
+}
+
+static int fimc_is_pipeline_load_setfile(struct fimc_is_pipeline *pipeline,
+		unsigned int setfile_addr,
+		unsigned char *setfile_name)
+{
+	struct fimc_is *is = pipeline->is;
+	const struct firmware *fw_blob;
+	int ret;
+
+	ret = request_firmware(&fw_blob, setfile_name, &is->pdev->dev);
+	if (ret) {
+		dev_err(pipeline->dev, "Setfile %s not found\n", setfile_name);
+		return ret;
+	}
+
+	memcpy(pipeline->minfo->fw.vaddr + setfile_addr,
+			fw_blob->data, fw_blob->size);
+	wmb();
+	release_firmware(fw_blob);
+
+	return 0;
+}
+
+static int fimc_is_pipeline_setfile(struct fimc_is_pipeline *pipeline)
+{
+	struct fimc_is *is = pipeline->is;
+	struct fimc_is_sensor *sensor = pipeline->sensor;
+	int ret;
+	unsigned int setfile_addr;
+
+	/* Get setfile addr from HW */
+	ret = fimc_is_itf_get_setfile_addr(&is->interface,
+			pipeline->instance, &setfile_addr);
+	if (ret) {
+		dev_err(pipeline->dev, "Get setfile addr failed\n");
+		return ret;
+	}
+
+	if (!sensor->drvdata->setfile_name)
+		return -EINVAL;
+
+	/* Load setfile */
+	ret = fimc_is_pipeline_load_setfile(pipeline, setfile_addr,
+			sensor->drvdata->setfile_name);
+	if (ret) {
+		dev_err(pipeline->dev, "Load setfile failed\n");
+		return ret;
+	}
+
+	/* Send HW command */
+	ret = fimc_is_itf_load_setfile(&is->interface, pipeline->instance);
+	if (ret) {
+		dev_err(pipeline->dev, "HW Load setfile failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int fimc_is_pipeline_isp_setparams(struct fimc_is_pipeline *pipeline,
+		unsigned int enable)
+{
+	struct isp_param *isp_param = &pipeline->is_region->parameter.isp;
+	struct fimc_is *is = pipeline->is;
+	unsigned long index[2] = {0};
+	unsigned int sensor_width, sensor_height, scc_width, scc_height;
+	unsigned int crop_x, crop_y, isp_width, isp_height;
+	unsigned int sensor_ratio, output_ratio;
+	int ret;
+
+	/* Crop calculation */
+	sensor_width = pipeline->sensor->width;
+	sensor_height = pipeline->sensor->height;
+	scc_width = pipeline->scaler[SCALER_SCC].width;
+	scc_height = pipeline->scaler[SCALER_SCC].height;
+	isp_width = sensor_width;
+	isp_height = sensor_height;
+	crop_x = crop_y = 0;
+
+	sensor_ratio = sensor_width * 1000 / sensor_height;
+	output_ratio = scc_width * 1000 / scc_height;
+
+	if (sensor_ratio == output_ratio) {
+		isp_width = sensor_width;
+		isp_height = sensor_height;
+	} else if (sensor_ratio < output_ratio) {
+		isp_height = (sensor_width * scc_height) / scc_width;
+		isp_height = ALIGN(isp_height, 2);
+		crop_y = ((sensor_height - isp_height) >> 1) & ~1U;
+	} else {
+		isp_width = (sensor_height * scc_width) / scc_height;
+		isp_width = ALIGN(isp_width, 4);
+		crop_x =  ((sensor_width - isp_width) >> 1) & ~1U;
+	}
+	pipeline->isp_width = isp_width;
+	pipeline->isp_height = isp_height;
+
+	isp_param->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE;
+	isp_param->otf_output.width = pipeline->sensor->width;
+	isp_param->otf_output.height = pipeline->sensor->height;
+	isp_param->otf_output.format = OTF_OUTPUT_FORMAT_YUV444;
+	isp_param->otf_output.bitwidth = OTF_OUTPUT_BIT_WIDTH_12BIT;
+	isp_param->otf_output.order = OTF_INPUT_ORDER_BAYER_GR_BG;
+	__set_bit(PARAM_ISP_OTF_OUTPUT, index);
+
+	isp_param->dma1_output.cmd = DMA_OUTPUT_COMMAND_DISABLE;
+	__set_bit(PARAM_ISP_DMA1_OUTPUT, index);
+
+	isp_param->dma2_output.cmd = DMA_OUTPUT_COMMAND_DISABLE;
+	__set_bit(PARAM_ISP_DMA2_OUTPUT, index);
+
+	if (enable)
+		isp_param->control.bypass = CONTROL_BYPASS_DISABLE;
+	else
+		isp_param->control.bypass = CONTROL_BYPASS_ENABLE;
+	isp_param->control.cmd = CONTROL_COMMAND_START;
+	isp_param->control.run_mode = 1;
+	__set_bit(PARAM_ISP_CONTROL, index);
+
+	isp_param->dma1_input.cmd = DMA_INPUT_COMMAND_BUF_MNGR;
+	isp_param->dma1_input.width = sensor_width;
+	isp_param->dma1_input.height = sensor_height;
+	isp_param->dma1_input.dma_crop_offset_x = crop_x;
+	isp_param->dma1_input.dma_crop_offset_y = crop_y;
+	isp_param->dma1_input.dma_crop_width = isp_width;
+	isp_param->dma1_input.dma_crop_height = isp_height;
+	isp_param->dma1_input.bayer_crop_offset_x = 0;
+	isp_param->dma1_input.bayer_crop_offset_y = 0;
+	isp_param->dma1_input.bayer_crop_width = 0;
+	isp_param->dma1_input.bayer_crop_height = 0;
+	isp_param->dma1_input.user_min_frametime = 0;
+	isp_param->dma1_input.user_max_frametime = 66666;
+	isp_param->dma1_input.wide_frame_gap = 1;
+	isp_param->dma1_input.frame_gap = 4096;
+	isp_param->dma1_input.line_gap = 45;
+	isp_param->dma1_input.order = DMA_INPUT_ORDER_GR_BG;
+	isp_param->dma1_input.plane = 1;
+	isp_param->dma1_input.buffer_number = 1;
+	isp_param->dma1_input.buffer_address = 0;
+	isp_param->dma1_input.reserved[1] = 0;
+	isp_param->dma1_input.reserved[2] = 0;
+	if (pipeline->isp.fmt->fourcc == V4L2_PIX_FMT_SGRBG8)
+		isp_param->dma1_input.bitwidth = DMA_INPUT_BIT_WIDTH_8BIT;
+	else if (pipeline->isp.fmt->fourcc == V4L2_PIX_FMT_SGRBG10)
+		isp_param->dma1_input.bitwidth = DMA_INPUT_BIT_WIDTH_10BIT;
+	else
+		isp_param->dma1_input.bitwidth = DMA_INPUT_BIT_WIDTH_12BIT;
+	__set_bit(PARAM_ISP_DMA1_INPUT, index);
+
+	wmb();
+	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
+			index[0], index[1]);
+	if (ret) {
+		dev_err(pipeline->dev, "%s failed\n", __func__);
+		return -EINVAL;
+	}
+
+	set_bit(COMP_ENABLE, &pipeline->comp_state[IS_ISP]);
+
+	return 0;
+}
+
+static int fimc_is_pipeline_drc_setparams(struct fimc_is_pipeline *pipeline,
+		unsigned int enable)
+{
+	struct drc_param *drc_param = &pipeline->is_region->parameter.drc;
+	struct fimc_is *is = pipeline->is;
+	int ret;
+	unsigned long index[2] = {0};
+
+	if (enable)
+		drc_param->control.bypass = CONTROL_BYPASS_DISABLE;
+	else
+		drc_param->control.bypass = CONTROL_BYPASS_ENABLE;
+	__set_bit(PARAM_DRC_CONTROL, index);
+
+	drc_param->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE;
+	drc_param->otf_input.width = pipeline->isp_width;
+	drc_param->otf_input.height = pipeline->isp_height;
+	__set_bit(PARAM_DRC_OTF_INPUT, index);
+
+	drc_param->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE;
+	drc_param->otf_output.width = pipeline->isp_width;
+	drc_param->otf_output.height = pipeline->isp_height;
+	__set_bit(PARAM_DRC_OTF_OUTPUT, index);
+
+	wmb();
+	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
+			index[0], index[1]);
+	if (ret) {
+		dev_err(pipeline->dev, "%s failed\n", __func__);
+		return -EINVAL;
+	}
+	if (enable)
+		set_bit(COMP_ENABLE, &pipeline->comp_state[IS_DRC]);
+	else
+		clear_bit(COMP_ENABLE, &pipeline->comp_state[IS_DRC]);
+
+	return 0;
+}
+
+static int fimc_is_pipeline_scc_setparams(struct fimc_is_pipeline *pipeline,
+		unsigned int enable)
+{
+	struct scalerc_param *scc_param =
+		&pipeline->is_region->parameter.scalerc;
+	struct fimc_is *is = pipeline->is;
+	int ret;
+	unsigned long index[2] = {0};
+	unsigned int scc_width, scc_height;
+
+	scc_width = pipeline->scaler[SCALER_SCC].width;
+	scc_height = pipeline->scaler[SCALER_SCC].height;
+
+	if (enable)
+		scc_param->control.bypass = CONTROL_BYPASS_DISABLE;
+	else
+		scc_param->control.bypass = CONTROL_BYPASS_ENABLE;
+	__set_bit(PARAM_SCALERC_CONTROL, index);
+
+	scc_param->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE;
+	scc_param->otf_input.width = pipeline->isp_width;
+	scc_param->otf_input.height = pipeline->isp_height;
+	__set_bit(PARAM_SCALERC_OTF_INPUT, index);
+
+	/* SCC OUTPUT */
+	scc_param->input_crop.cmd = SCALER_CROP_COMMAND_ENABLE;
+	scc_param->input_crop.pos_x = 0;
+	scc_param->input_crop.pos_y = 0;
+	scc_param->input_crop.crop_width = pipeline->isp_width;
+	scc_param->input_crop.crop_height = pipeline->isp_height;
+	scc_param->input_crop.in_width = pipeline->isp_width;
+	scc_param->input_crop.in_height = pipeline->isp_height;
+	scc_param->input_crop.out_width = scc_width;
+	scc_param->input_crop.out_height = scc_height;
+	__set_bit(PARAM_SCALERC_INPUT_CROP, index);
+
+	scc_param->output_crop.cmd = SCALER_CROP_COMMAND_DISABLE;
+	scc_param->output_crop.pos_x = 0;
+	scc_param->output_crop.pos_y = 0;
+	scc_param->output_crop.crop_width = scc_width;
+	scc_param->output_crop.crop_height = scc_height;
+	__set_bit(PARAM_SCALERC_OUTPUT_CROP, index);
+
+	scc_param->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE;
+	scc_param->otf_output.width = scc_width;
+	scc_param->otf_output.height = scc_height;
+	__set_bit(PARAM_SCALERC_OTF_OUTPUT, index);
+
+	wmb();
+	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
+			index[0], index[1]);
+	if (ret) {
+		dev_err(pipeline->dev, "%s failed\n", __func__);
+		return -EINVAL;
+	}
+	set_bit(COMP_ENABLE, &pipeline->comp_state[IS_SCC]);
+	return 0;
+}
+
+static int fimc_is_pipeline_odc_setparams(struct fimc_is_pipeline *pipeline,
+		unsigned int enable)
+{
+	struct odc_param *odc_param = &pipeline->is_region->parameter.odc;
+	struct fimc_is *is = pipeline->is;
+	int ret;
+	unsigned long index[2] = {0};
+	unsigned int scc_width, scc_height;
+
+	scc_width = pipeline->scaler[SCALER_SCC].width;
+	scc_height = pipeline->scaler[SCALER_SCC].height;
+
+	if (enable)
+		odc_param->control.bypass = CONTROL_BYPASS_DISABLE;
+	else
+		odc_param->control.bypass = CONTROL_BYPASS_ENABLE;
+	__set_bit(PARAM_ODC_CONTROL, index);
+
+	odc_param->otf_input.width = scc_width;
+	odc_param->otf_input.height = scc_height;
+	__set_bit(PARAM_ODC_OTF_INPUT, index);
+
+	odc_param->otf_output.width = scc_width;
+	odc_param->otf_output.height = scc_height;
+	__set_bit(PARAM_ODC_OTF_OUTPUT, index);
+
+	wmb();
+	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
+			index[0], index[1]);
+	if (ret) {
+		dev_err(pipeline->dev, "%s failed\n", __func__);
+		return -EINVAL;
+	}
+	if (enable)
+		set_bit(COMP_ENABLE, &pipeline->comp_state[IS_ODC]);
+	else
+		clear_bit(COMP_ENABLE, &pipeline->comp_state[IS_ODC]);
+
+	return 0;
+}
+
+static int fimc_is_pipeline_dis_setparams(struct fimc_is_pipeline *pipeline,
+		unsigned int enable)
+{
+	struct dis_param *dis_param = &pipeline->is_region->parameter.dis;
+	struct fimc_is *is = pipeline->is;
+	int ret;
+	unsigned long index[2] = {0};
+	unsigned int scc_width, scc_height;
+
+	scc_width = pipeline->scaler[SCALER_SCC].width;
+	scc_height = pipeline->scaler[SCALER_SCC].height;
+
+	if (enable)
+		dis_param->control.bypass = CONTROL_BYPASS_DISABLE;
+	else
+		dis_param->control.bypass = CONTROL_BYPASS_ENABLE;
+	__set_bit(PARAM_DIS_CONTROL, index);
+
+	/* DIS INPUT */
+	dis_param->otf_input.width = scc_width;
+	dis_param->otf_input.height = scc_height;
+	__set_bit(PARAM_DIS_OTF_INPUT, index);
+
+	/* DIS OUTPUT */
+	dis_param->otf_output.width = scc_width;
+	dis_param->otf_output.height = scc_height;
+	__set_bit(PARAM_DIS_OTF_OUTPUT, index);
+
+	wmb();
+	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
+			index[0], index[1]);
+	if (ret) {
+		dev_err(pipeline->dev, "%s failed\n", __func__);
+		return -EINVAL;
+	}
+	if (enable)
+		set_bit(COMP_ENABLE, &pipeline->comp_state[IS_DIS]);
+	else
+		clear_bit(COMP_ENABLE, &pipeline->comp_state[IS_DIS]);
+
+	return 0;
+}
+
+static int fimc_is_pipeline_3dnr_setparams(struct fimc_is_pipeline *pipeline,
+		unsigned int enable)
+{
+	struct tdnr_param *tdnr_param = &pipeline->is_region->parameter.tdnr;
+	struct fimc_is *is = pipeline->is;
+	int ret;
+	unsigned long index[2] = {0};
+	unsigned int scc_width, scc_height;
+
+	scc_width = pipeline->scaler[SCALER_SCC].width;
+	scc_height = pipeline->scaler[SCALER_SCC].height;
+
+	if (enable)
+		tdnr_param->control.bypass = CONTROL_BYPASS_DISABLE;
+	else
+		tdnr_param->control.bypass = CONTROL_BYPASS_ENABLE;
+	__set_bit(PARAM_TDNR_CONTROL, index);
+
+	tdnr_param->otf_input.width = scc_width;
+	tdnr_param->otf_input.height = scc_height;
+	__set_bit(PARAM_TDNR_OTF_INPUT, index);
+
+	tdnr_param->dma_output.width = scc_width;
+	tdnr_param->dma_output.height = scc_height;
+	__set_bit(PARAM_TDNR_DMA_OUTPUT, index);
+
+	tdnr_param->otf_output.width = scc_width;
+	tdnr_param->otf_output.height = scc_height;
+	__set_bit(PARAM_TDNR_OTF_OUTPUT, index);
+
+	wmb();
+	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
+			index[0], index[1]);
+	if (ret) {
+		dev_err(pipeline->dev, "%s failed\n", __func__);
+		return -EINVAL;
+	}
+	if (enable)
+		set_bit(COMP_ENABLE, &pipeline->comp_state[IS_TDNR]);
+	else
+		clear_bit(COMP_ENABLE, &pipeline->comp_state[IS_TDNR]);
+
+	return 0;
+}
+
+static int fimc_is_pipeline_scp_setparams(struct fimc_is_pipeline *pipeline,
+		unsigned int enable)
+{
+	struct scalerp_param *scp_param =
+		&pipeline->is_region->parameter.scalerp;
+	struct fimc_is *is = pipeline->is;
+	int ret;
+	unsigned long index[2] = {0};
+	unsigned int scc_width, scc_height;
+	unsigned int scp_width, scp_height;
+
+	scc_width = pipeline->scaler[SCALER_SCC].width;
+	scc_height = pipeline->scaler[SCALER_SCC].height;
+	scp_width = pipeline->scaler[SCALER_SCP].width;
+	scp_height = pipeline->scaler[SCALER_SCP].height;
+
+	if (enable)
+		scp_param->control.bypass = CONTROL_BYPASS_DISABLE;
+	else
+		scp_param->control.bypass = CONTROL_BYPASS_ENABLE;
+	__set_bit(PARAM_SCALERP_CONTROL, index);
+
+	/* SCP Input */
+	scp_param->otf_input.width = scc_width;
+	scp_param->otf_input.height = scc_height;
+	__set_bit(PARAM_SCALERP_OTF_INPUT, index);
+
+	/* SCP Output */
+	scp_param->input_crop.cmd = SCALER_CROP_COMMAND_ENABLE;
+	scp_param->input_crop.pos_x = 0;
+	scp_param->input_crop.pos_y = 0;
+	scp_param->input_crop.crop_width = scc_width;
+	scp_param->input_crop.crop_height = scc_height;
+	scp_param->input_crop.in_width = scc_width;
+	scp_param->input_crop.in_height = scc_height;
+	scp_param->input_crop.out_width = scp_width;
+	scp_param->input_crop.out_height = scp_height;
+	__set_bit(PARAM_SCALERP_INPUT_CROP, index);
+
+	scp_param->output_crop.cmd = SCALER_CROP_COMMAND_DISABLE;
+	__set_bit(PARAM_SCALERP_OUTPUT_CROP, index);
+
+	scp_param->otf_output.width = scp_width;
+	scp_param->otf_output.height = scp_height;
+	__set_bit(PARAM_SCALERP_OTF_OUTPUT, index);
+
+	wmb();
+	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
+			index[0], index[1]);
+	if (ret) {
+		dev_err(pipeline->dev, "%s failed\n", __func__);
+		return -EINVAL;
+	}
+	set_bit(COMP_ENABLE, &pipeline->comp_state[IS_SCP]);
+
+	return 0;
+}
+
+static int fimc_is_pipeline_fd_setparams(struct fimc_is_pipeline *pipeline,
+		unsigned int enable)
+{
+	struct fd_param *fd_param = &pipeline->is_region->parameter.fd;
+	struct fimc_is *is = pipeline->is;
+	int ret;
+	unsigned long index[2] = {0};
+
+	if (enable)
+		fd_param->control.bypass = CONTROL_BYPASS_DISABLE;
+	else
+		fd_param->control.bypass = CONTROL_BYPASS_ENABLE;
+	__set_bit(PARAM_FD_CONTROL, index);
+
+	fd_param->otf_input.width = pipeline->scaler[SCALER_SCP].width;
+	fd_param->otf_input.height = pipeline->scaler[SCALER_SCP].height;
+	__set_bit(PARAM_FD_OTF_INPUT, index);
+
+	wmb();
+	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
+			index[0], index[1]);
+	if (ret) {
+		dev_err(pipeline->dev, "%s failed\n", __func__);
+		return -EINVAL;
+	}
+	if (enable)
+		set_bit(COMP_ENABLE, &pipeline->comp_state[IS_FD]);
+	else
+		clear_bit(COMP_ENABLE, &pipeline->comp_state[IS_FD]);
+
+	return 0;
+}
+
+void fimc_is_pipeline_buf_lock(struct fimc_is_pipeline *pipeline)
+{
+	spin_lock_irqsave(&pipeline->slock_buf, pipeline->slock_flags);
+}
+
+void fimc_is_pipeline_buf_unlock(struct fimc_is_pipeline *pipeline)
+{
+	spin_unlock_irqrestore(&pipeline->slock_buf, pipeline->slock_flags);
+}
+
+int fimc_is_pipeline_setparams(struct fimc_is_pipeline *pipeline)
+{
+	int ret;
+
+	/* Enabling basic components in pipeline */
+	ret = fimc_is_pipeline_isp_setparams(pipeline, true);
+	if (!ret)
+		ret = fimc_is_pipeline_drc_setparams(pipeline, false);
+	if (!ret)
+		ret = fimc_is_pipeline_scc_setparams(pipeline, true);
+	if (!ret)
+		ret = fimc_is_pipeline_odc_setparams(pipeline, false);
+	if (!ret)
+		ret = fimc_is_pipeline_dis_setparams(pipeline, false);
+	if (!ret)
+		ret = fimc_is_pipeline_3dnr_setparams(pipeline, false);
+	if (!ret)
+		ret = fimc_is_pipeline_scp_setparams(pipeline, true);
+	if (!ret)
+		ret = fimc_is_pipeline_fd_setparams(pipeline, false);
+	if (ret)
+		dev_err(pipeline->dev, "Pipeline setparam failed\n");
+
+	return ret;
+}
+
+int fimc_is_pipeline_scaler_start(struct fimc_is_pipeline *pipeline,
+		enum fimc_is_scaler_id scaler_id,
+		unsigned int num_bufs,
+		unsigned int num_planes)
+{
+	struct fimc_is *is = pipeline->is;
+	struct scalerp_param *scp_param =
+		&pipeline->is_region->parameter.scalerp;
+	struct scalerc_param *scc_param =
+		&pipeline->is_region->parameter.scalerc;
+	struct param_dma_output *dma_output;
+	const struct fimc_is_fmt *fmt;
+	unsigned int region_index;
+	unsigned long *comp_state;
+	int ret;
+	unsigned int pipe_start_flag = 0;
+	unsigned int i, buf_mask = 0;
+	unsigned long index[2] = {0};
+	enum fimc_is_scaler_id id;
+
+	if (!test_bit(PIPELINE_OPEN, &pipeline->state)) {
+		dev_err(pipeline->dev, "Pipeline not opened.\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&pipeline->pipe_scl_lock);
+
+	if (test_bit(PIPELINE_START, &pipeline->state)) {
+		/*
+		 * Pipeline is started.
+		 * Stop it now to set params and start again
+		 */
+		ret = fimc_is_pipeline_stop(pipeline, 0);
+		if (ret) {
+			dev_err(pipeline->dev, "Not able to stop pipeline\n");
+			goto exit;
+		}
+		pipe_start_flag = 1;
+	}
+
+	if (scaler_id == SCALER_SCC) {
+		dma_output = &scc_param->dma_output;
+		region_index = FIMC_IS_SCC_REGION_INDEX;
+		comp_state = &pipeline->comp_state[IS_SCC];
+		id = SCALER_SCC;
+		__set_bit(PARAM_SCALERC_DMA_OUTPUT, index);
+	} else {
+		dma_output = &scp_param->dma_output;
+		comp_state = &pipeline->comp_state[IS_SCP];
+		region_index = FIMC_IS_SCP_REGION_INDEX;
+		id = SCALER_SCP;
+		__set_bit(PARAM_SCALERP_DMA_OUTPUT, index);
+	}
+
+	for (i = 0; i < num_bufs; i++)
+		buf_mask |= BIT(i);
+
+	fmt = pipeline->scaler[id].fmt;
+	dma_output->cmd = DMA_OUTPUT_COMMAND_ENABLE;
+	dma_output->dma_out_mask = buf_mask;
+	dma_output->buffer_number = num_bufs;
+	dma_output->plane = num_planes;
+	dma_output->width = pipeline->scaler[id].width;
+	dma_output->height = pipeline->scaler[id].height;
+	if ((fmt->fourcc == V4L2_PIX_FMT_YUV420M) ||
+			(fmt->fourcc == V4L2_PIX_FMT_NV12M))
+		dma_output->format = DMA_OUTPUT_FORMAT_YUV420;
+	else if (fmt->fourcc == V4L2_PIX_FMT_NV16)
+		dma_output->format = DMA_OUTPUT_FORMAT_YUV422;
+
+	dma_output->buffer_address = pipeline->minfo->shared.paddr +
+				region_index * sizeof(unsigned int);
+	__set_bit(PARAM_SCALERC_DMA_OUTPUT, index);
+
+	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
+			index[0], index[1]);
+	if (ret)
+		dev_err(pipeline->dev, "fimc_is_itf_set_param is fail\n");
+	else
+		set_bit(COMP_START, comp_state);
+
+	if (pipe_start_flag) {
+		ret = fimc_is_pipeline_start(pipeline, 0);
+		if (ret)
+			dev_err(pipeline->dev,
+				"Not able to start pipeline back\n");
+	}
+exit:
+	mutex_unlock(&pipeline->pipe_scl_lock);
+	return ret;
+}
+
+int fimc_is_pipeline_scaler_stop(struct fimc_is_pipeline *pipeline,
+		enum fimc_is_scaler_id scaler_id)
+{
+	struct fimc_is *is = pipeline->is;
+	struct scalerp_param *scp_param =
+		&pipeline->is_region->parameter.scalerp;
+	struct scalerc_param *scc_param =
+		&pipeline->is_region->parameter.scalerc;
+	struct param_dma_output *dma_output;
+	unsigned int pipe_start_flag = 0;
+	unsigned long index[2] = {0};
+	unsigned long *comp_state;
+	int ret;
+
+	if (!test_bit(PIPELINE_OPEN, &pipeline->state))
+		return -EINVAL;
+
+	mutex_lock(&pipeline->pipe_scl_lock);
+
+	if (test_bit(PIPELINE_START, &pipeline->state)) {
+		/*
+		 * Pipeline is started.
+		 * Stop it now to set params and start again
+		 */
+		ret = fimc_is_pipeline_stop(pipeline, 0);
+		if (ret) {
+			dev_err(pipeline->dev, "Not able to stop pipeline\n");
+			goto exit;
+		}
+		pipe_start_flag = 1;
+	}
+
+	comp_state = (scaler_id == SCALER_SCC) ?
+		&pipeline->comp_state[IS_SCC] : &pipeline->comp_state[IS_SCP];
+
+	if (!test_bit(COMP_START, comp_state)) {
+		ret = 0;
+		goto exit;
+	}
+
+	if (scaler_id == SCALER_SCC) {
+		dma_output = &scc_param->dma_output;
+		__set_bit(PARAM_SCALERC_DMA_OUTPUT, index);
+	} else {
+		dma_output = &scp_param->dma_output;
+		__set_bit(PARAM_SCALERP_DMA_OUTPUT, index);
+	}
+	dma_output->cmd = DMA_OUTPUT_COMMAND_DISABLE;
+
+	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
+			index[0], index[1]);
+	if (ret)
+		dev_err(pipeline->dev, "fimc_is_itf_set_param is fail\n");
+	else
+		clear_bit(COMP_START, comp_state);
+
+	if (pipe_start_flag) {
+		ret = fimc_is_pipeline_start(pipeline, 0);
+		if (ret)
+			dev_err(pipeline->dev,
+				"Not able to start pipeline back\n");
+	}
+exit:
+	mutex_unlock(&pipeline->pipe_scl_lock);
+	return ret;
+}
+
+void fimc_is_pipeline_config_shot(struct fimc_is_pipeline *pipeline)
+{
+	struct camera2_shot *shot =
+		(struct camera2_shot *)pipeline->minfo->shot.vaddr;
+
+	shot->magicnumber = FIMC_IS_MAGIC_NUMBER;
+
+	shot->ctl.aa.mode = AA_CONTROL_AUTO;
+	shot->ctl.aa.ae_mode = AA_AEMODE_ON;
+}
+
+int fimc_is_pipeline_shot_safe(struct fimc_is_pipeline *pipeline)
+{
+	int ret;
+	mutex_lock(&pipeline->pipe_lock);
+	ret = fimc_is_pipeline_shot(pipeline);
+	mutex_unlock(&pipeline->pipe_lock);
+	return ret;
+}
+
+int fimc_is_pipeline_shot(struct fimc_is_pipeline *pipeline)
+{
+	struct fimc_is *is = pipeline->is;
+	int ret;
+	unsigned int rcount, i;
+	struct camera2_shot *shot = pipeline->minfo->shot.vaddr;
+	struct fimc_is_buf *scc_buf, *scp_buf, *bayer_buf;
+
+	if (!test_bit(PIPELINE_START, &pipeline->state))
+		return -EINVAL;
+
+	if (test_bit(PIPELINE_RUN, &pipeline->state))
+		return -EBUSY;
+
+	fimc_is_pipeline_buf_lock(pipeline);
+
+	if (list_empty(&pipeline->isp.wait_queue)) {
+		/* No more bayer buffers */
+		wake_up(&pipeline->wait_q);
+		fimc_is_pipeline_buf_unlock(pipeline);
+		return 0;
+	}
+
+	set_bit(PIPELINE_RUN, &pipeline->state);
+
+	/* Get bayer input buffer */
+	bayer_buf = fimc_is_isp_wait_queue_get(&pipeline->isp);
+	if (!bayer_buf) {
+		fimc_is_pipeline_buf_unlock(pipeline);
+		goto err_exit;
+	}
+	fimc_is_isp_run_queue_add(&pipeline->isp, bayer_buf);
+
+	/* Get SCC buffer */
+	if (test_bit(COMP_START, &pipeline->comp_state[IS_SCC]) &&
+		!list_empty(&pipeline->scaler[SCALER_SCC].wait_queue)) {
+		scc_buf = fimc_is_scaler_wait_queue_get(
+				&pipeline->scaler[SCALER_SCC]);
+		if (scc_buf) {
+			fimc_is_scaler_run_queue_add(
+					&pipeline->scaler[SCALER_SCC],
+					scc_buf);
+			for (i = 0; i < 3; i++)
+				shot->uctl.scaler_ud.scc_target_address[i] =
+							scc_buf->paddr[i];
+			set_bit(COMP_RUN, &pipeline->comp_state[IS_SCC]);
+		}
+	} else {
+		dev_dbg(pipeline->dev, "No SCC buffer available\n");
+		for (i = 0; i < 3; i++)
+			shot->uctl.scaler_ud.scc_target_address[i] = 0;
+	}
+
+	/* Get SCP buffer */
+	if (test_bit(COMP_START, &pipeline->comp_state[IS_SCP]) &&
+		!list_empty(&pipeline->scaler[SCALER_SCP].wait_queue)) {
+		scp_buf = fimc_is_scaler_wait_queue_get(
+				&pipeline->scaler[SCALER_SCP]);
+		if (scp_buf) {
+			fimc_is_scaler_run_queue_add(
+					&pipeline->scaler[SCALER_SCP],
+					scp_buf);
+			for (i = 0; i < 3; i++)
+				shot->uctl.scaler_ud.scp_target_address[i] =
+							scp_buf->paddr[i];
+			set_bit(COMP_RUN, &pipeline->comp_state[IS_SCP]);
+		}
+	} else {
+		dev_dbg(pipeline->dev, "No SCP buffer available\n");
+		for (i = 0; i < 3; i++)
+			shot->uctl.scaler_ud.scp_target_address[i] = 0;
+	}
+	fimc_is_pipeline_buf_unlock(pipeline);
+
+	/* Send shot command */
+	pipeline->fcount++;
+	rcount = pipeline->fcount;
+	shot->ctl.request.framecount = pipeline->fcount;
+	dev_dbg(pipeline->dev,
+		"Shot command fcount : %d, Bayer addr : 0x%08x\n",
+		pipeline->fcount, bayer_buf->paddr[0]);
+	ret = fimc_is_itf_shot_nblk(&is->interface, pipeline->instance,
+			bayer_buf->paddr[0],
+			pipeline->minfo->shot.paddr,
+			pipeline->fcount,
+			rcount);
+	if (ret) {
+		dev_err(pipeline->dev, "Shot command failed\n");
+		goto err_exit;
+	}
+	return 0;
+
+err_exit:
+	clear_bit(PIPELINE_RUN, &pipeline->state);
+	clear_bit(COMP_RUN, &pipeline->comp_state[IS_SCC]);
+	clear_bit(COMP_RUN, &pipeline->comp_state[IS_SCP]);
+	return -EINVAL;
+}
+
+int fimc_is_pipeline_start(struct fimc_is_pipeline *pipeline, int streamon)
+{
+	int ret = 0;
+	struct fimc_is *is = pipeline->is;
+
+	/* Check if open or not */
+	if (!test_bit(PIPELINE_OPEN, &pipeline->state)) {
+		dev_err(pipeline->dev, "Pipeline not open\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&pipeline->pipe_lock);
+
+	/* Check if already started */
+	if (test_bit(PIPELINE_START, &pipeline->state))
+		goto err_exit;
+
+	/* Set pipeline component params */
+	ret = fimc_is_pipeline_setparams(pipeline);
+	if (ret) {
+		dev_err(pipeline->dev, "Set params failed\n");
+		goto err_exit;
+	}
+
+	/* Send preview still command */
+	ret = fimc_is_itf_preview_still(&is->interface, pipeline->instance);
+	if (ret) {
+		dev_err(pipeline->dev, "Preview still failed\n");
+		goto err_exit;
+	}
+
+	/* Confiture shot memory to A5 */
+	ret = fimc_is_itf_cfg_mem(&is->interface, pipeline->instance,
+			pipeline->minfo->shot.paddr,
+			sizeof(struct camera2_shot));
+	if (ret) {
+		dev_err(pipeline->dev, "Config A5 mem failed\n");
+		goto err_exit;
+	}
+
+	/* Set shot params */
+	fimc_is_pipeline_config_shot(pipeline);
+
+	/* Process ON command */
+	ret = fimc_is_itf_process_on(&is->interface, pipeline->instance);
+	if (ret) {
+		dev_err(pipeline->dev, "Process on failed\n");
+		goto err_exit;
+	}
+
+	/* Stream ON */
+	if (streamon) {
+		ret = fimc_is_itf_stream_on(&is->interface, pipeline->instance);
+		if (ret) {
+			dev_err(pipeline->dev, "Stream On failed\n");
+			goto err_exit;
+		}
+	}
+
+	/* Set state to START */
+	set_bit(PIPELINE_START, &pipeline->state);
+
+	mutex_unlock(&pipeline->pipe_lock);
+	return 0;
+
+err_exit:
+	mutex_unlock(&pipeline->pipe_lock);
+	return ret;
+}
+
+int fimc_is_pipeline_stop(struct fimc_is_pipeline *pipeline, int streamoff)
+{
+	int ret;
+	struct fimc_is *is = pipeline->is;
+
+	mutex_lock(&pipeline->pipe_lock);
+
+	/* Check if started */
+	if (!test_bit(PIPELINE_OPEN, &pipeline->state) ||
+		!test_bit(PIPELINE_START, &pipeline->state)) {
+		ret = -EINVAL;
+		goto err_exit;
+	}
+
+	/* Wait if any operation is in progress */
+	ret = wait_event_timeout(pipeline->wait_q,
+			!test_bit(PIPELINE_RUN, &pipeline->state),
+			FIMC_IS_COMMAND_TIMEOUT);
+	if (!ret) {
+		dev_err(pipeline->dev, "Pipeline timeout");
+		ret = -EBUSY;
+		goto err_exit;
+	}
+
+	/* Wait for scaler operations if any to complete */
+	ret = wait_event_timeout(pipeline->scaler[SCALER_SCC].event_q,
+			!test_bit(COMP_RUN, &pipeline->comp_state[IS_SCC]),
+			FIMC_IS_COMMAND_TIMEOUT);
+	if (!ret) {
+		dev_err(pipeline->dev, "SCC timeout");
+		ret = -EBUSY;
+		goto err_exit;
+	}
+	ret = wait_event_timeout(pipeline->scaler[SCALER_SCP].event_q,
+			!test_bit(COMP_RUN, &pipeline->comp_state[IS_SCP]),
+			FIMC_IS_COMMAND_TIMEOUT);
+	if (!ret) {
+		dev_err(pipeline->dev, "SCP timeout");
+		ret = -EBUSY;
+		goto err_exit;
+	}
+
+	if (streamoff) {
+		/* Stream OFF */
+		ret = fimc_is_itf_stream_off(&is->interface,
+					pipeline->instance);
+		if (ret) {
+			dev_err(pipeline->dev, "Stream Off failed\n");
+			ret = -EINVAL;
+			goto err_exit;
+		}
+	}
+
+	/* Process OFF */
+	ret = fimc_is_itf_process_off(&is->interface, pipeline->instance);
+	if (ret) {
+		dev_err(pipeline->dev, "Process off failed\n");
+		ret = -EINVAL;
+		goto err_exit;
+	}
+
+	/* Clear state */
+	clear_bit(PIPELINE_START, &pipeline->state);
+
+err_exit:
+	mutex_unlock(&pipeline->pipe_lock);
+	return ret;
+}
+
+int fimc_is_pipeline_open(struct fimc_is_pipeline *pipeline,
+			struct fimc_is_sensor *sensor)
+{
+	struct fimc_is *is = pipeline->is;
+	struct is_region *region;
+	unsigned long index[2] = {0};
+	int ret;
+
+	if (!sensor)
+		return -EINVAL;
+
+	mutex_lock(&pipeline->pipe_lock);
+
+	if (test_bit(PIPELINE_OPEN, &pipeline->state)) {
+		dev_err(pipeline->dev, "Pipeline already open\n");
+		ret = -EINVAL;
+		goto err_exit;
+	}
+
+	pipeline->fcount = 0;
+	pipeline->sensor = sensor;
+
+	if (is->num_pipelines == 0) {
+		/* Init memory */
+		ret = fimc_is_pipeline_initmem(pipeline);
+		if (ret) {
+			dev_err(pipeline->dev, "Pipeline memory init failed\n");
+			goto err_exit;
+		}
+
+		/* Load firmware */
+		ret = fimc_is_pipeline_load_firmware(pipeline);
+		if (ret) {
+			dev_err(pipeline->dev, "Firmware load failed\n");
+			goto err_fw;
+		}
+
+		/* Power ON */
+		ret = fimc_is_pipeline_power(pipeline, 1);
+		if (ret) {
+			dev_err(pipeline->dev, "A5 power on failed\n");
+			goto err_fw;
+		}
+
+		/* Wait for FW Init to complete */
+		ret = fimc_is_itf_wait_init_state(&is->interface);
+		if (ret) {
+			dev_err(pipeline->dev, "FW init failed\n");
+			goto err_fw;
+		}
+	}
+
+	/* Open Sensor */
+	region = pipeline->is_region;
+	ret = fimc_is_itf_open_sensor(&is->interface,
+			pipeline->instance,
+			sensor->drvdata->id,
+			sensor->i2c_bus,
+			pipeline->minfo->shared.paddr);
+	if (ret) {
+		dev_err(pipeline->dev, "Open sensor failed\n");
+		goto err_exit;
+	}
+
+	/* Load setfile */
+	ret = fimc_is_pipeline_setfile(pipeline);
+	if (ret)
+		goto err_exit;
+
+	/* Stream off */
+	ret = fimc_is_itf_stream_off(&is->interface, pipeline->instance);
+	if (ret)
+		goto err_exit;
+
+	/* Process off */
+	ret = fimc_is_itf_process_off(&is->interface, pipeline->instance);
+	if (ret)
+		goto err_exit;
+
+	if (is->num_pipelines == 0) {
+		/* Copy init params to FW region */
+		memset(&region->parameter, 0x0, sizeof(struct is_param_region));
+
+		region->parameter.sensor = init_sensor_param;
+		region->parameter.isp = init_isp_param;
+		region->parameter.drc = init_drc_param;
+		region->parameter.scalerc = init_scalerc_param;
+		region->parameter.odc = init_odc_param;
+		region->parameter.dis = init_dis_param;
+		region->parameter.tdnr = init_tdnr_param;
+		region->parameter.scalerp = init_scalerp_param;
+		region->parameter.fd = init_fd_param;
+		wmb();
+
+		/* Set all init params to FW */
+		index[0] = 0xffffffff;
+		index[1] = 0xffffffff;
+		ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
+				index[0], index[1]);
+		if (ret) {
+			dev_err(pipeline->dev, "%s failed\n", __func__);
+			return -EINVAL;
+		}
+	}
+
+	/* Set state to OPEN */
+	set_bit(PIPELINE_OPEN, &pipeline->state);
+	is->num_pipelines++;
+
+	mutex_unlock(&pipeline->pipe_lock);
+	return 0;
+
+err_fw:
+	fimc_is_pipeline_freemem(pipeline);
+err_exit:
+	mutex_unlock(&pipeline->pipe_lock);
+	return ret;
+}
+
+int fimc_is_pipeline_close(struct fimc_is_pipeline *pipeline)
+{
+	int ret;
+	struct fimc_is *is = pipeline->is;
+
+	mutex_lock(&pipeline->pipe_lock);
+
+	if (!test_bit(PIPELINE_OPEN, &pipeline->state)) {
+		dev_err(pipeline->dev, "Pipeline not opened\n");
+		ret = -EINVAL;
+		goto err_exit;
+	}
+
+	if (test_bit(PIPELINE_START, &pipeline->state)) {
+		dev_err(pipeline->dev, "Cannot close pipeline when its started\n");
+		ret = -EINVAL;
+		goto err_exit;
+	}
+
+	is->num_pipelines--;
+	if (is->num_pipelines == 0) {
+		/* FW power off command */
+		ret = fimc_is_itf_power_down(&is->interface,
+					pipeline->instance);
+		if (ret)
+			dev_err(pipeline->dev, "FW power down error\n");
+
+		/* Pipeline power off*/
+		fimc_is_pipeline_power(pipeline, 0);
+
+		/* Free memory */
+		fimc_is_pipeline_freemem(pipeline);
+	}
+
+	clear_bit(PIPELINE_OPEN, &pipeline->state);
+	mutex_unlock(&pipeline->pipe_lock);
+	return 0;
+
+err_exit:
+	mutex_unlock(&pipeline->pipe_lock);
+	return ret;
+}
diff --git a/drivers/media/platform/exynos5-is/fimc-is-pipeline.h b/drivers/media/platform/exynos5-is/fimc-is-pipeline.h
new file mode 100644
index 0000000..b327edd
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-pipeline.h
@@ -0,0 +1,129 @@
+/*
+ * Samsung EXYNOS5 FIMC-IS (Imaging Subsystem) driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *  Arun Kumar K <arun.kk@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_IS_PIPELINE_H_
+#define FIMC_IS_PIPELINE_H_
+
+#include "fimc-is-core.h"
+#include "fimc-is-sensor.h"
+#include "fimc-is-isp.h"
+#include "fimc-is-scaler.h"
+
+#define FIMC_IS_A5_MEM_SIZE		0x00a00000
+#define FIMC_IS_A5_SEN_SIZE		0x00100000
+#define FIMC_IS_REGION_SIZE		0x5000
+#define FIMC_IS_SETFILE_SIZE		0xc0d8
+#define FIMC_IS_TDNR_MEM_SIZE		(1920 * 1080 * 4)
+#define FIMC_IS_DEBUG_REGION_ADDR	0x00840000
+#define FIMC_IS_SHARED_REGION_ADDR	0x008c0000
+#define FIMC_IS_A5_TIMEOUT		1000
+
+#define FIMC_IS_SCP_REGION_INDEX	400
+#define FIMC_IS_SCC_REGION_INDEX	447
+
+#define MAX_ODC_INTERNAL_BUF_WIDTH	2560  /* 4808 in HW */
+#define MAX_ODC_INTERNAL_BUF_HEIGHT	1920  /* 3356 in HW */
+#define SIZE_ODC_INTERNAL_BUF \
+	(MAX_ODC_INTERNAL_BUF_WIDTH * MAX_ODC_INTERNAL_BUF_HEIGHT * 3)
+
+#define MAX_DIS_INTERNAL_BUF_WIDTH	2400
+#define MAX_DIS_INTERNAL_BUF_HEIGHT	1360
+#define SIZE_DIS_INTERNAL_BUF \
+	(MAX_DIS_INTERNAL_BUF_WIDTH * MAX_DIS_INTERNAL_BUF_HEIGHT * 2)
+
+#define MAX_3DNR_INTERNAL_BUF_WIDTH	1920
+#define MAX_3DNR_INTERNAL_BUF_HEIGHT	1088
+#define SIZE_DNR_INTERNAL_BUF \
+	(MAX_3DNR_INTERNAL_BUF_WIDTH * MAX_3DNR_INTERNAL_BUF_HEIGHT * 2)
+
+#define NUM_ODC_INTERNAL_BUF		2
+#define NUM_DIS_INTERNAL_BUF		5
+#define NUM_DNR_INTERNAL_BUF		2
+
+#define FIMC_IS_FW_BASE_MASK		((1 << 26) - 1)
+
+#define FIMC_IS_NUM_COMPS		8
+
+#define FIMC_IS_MAGIC_NUMBER		0x23456789
+
+enum pipeline_state {
+	PIPELINE_INIT,
+	PIPELINE_OPEN,
+	PIPELINE_START,
+	PIPELINE_RUN,
+};
+
+enum is_components {
+	IS_ISP,
+	IS_DRC,
+	IS_SCC,
+	IS_ODC,
+	IS_DIS,
+	IS_TDNR,
+	IS_SCP,
+	IS_FD
+};
+
+enum component_state {
+	COMP_ENABLE,
+	COMP_START,
+	COMP_RUN
+};
+
+struct fimc_is_pipeline {
+	unsigned long		state;
+	unsigned long		comp_state[FIMC_IS_NUM_COMPS];
+	bool			force_down;
+	unsigned int		instance;
+	/* Locks the isp / scaler buffers */
+	spinlock_t		slock_buf;
+	unsigned long		slock_flags;
+	wait_queue_head_t	wait_q;
+	/* For locking pipeline ops */
+	struct mutex		pipe_lock;
+	/* For locking scaler ops in pipeline */
+	struct mutex		pipe_scl_lock;
+
+	struct fimc_is_meminfo	*minfo;
+	struct is_region	*is_region;
+	struct device		*dev;
+
+	struct fimc_is		*is;
+	struct fimc_is_sensor	*sensor;
+	struct fimc_is_isp	isp;
+	struct fimc_is_scaler	scaler[FIMC_IS_NUM_SCALERS];
+
+	unsigned int		fcount;
+	unsigned int		isp_width;
+	unsigned int		isp_height;
+};
+
+void fimc_is_pipeline_buf_lock(struct fimc_is_pipeline *pipeline);
+void fimc_is_pipeline_buf_unlock(struct fimc_is_pipeline *pipeline);
+int fimc_is_pipeline_setparams(struct fimc_is_pipeline *pipeline);
+int fimc_is_pipeline_scaler_start(struct fimc_is_pipeline *pipeline,
+		enum fimc_is_scaler_id scaler_id,
+		unsigned int num_bufs,
+		unsigned int num_planes);
+int fimc_is_pipeline_scaler_stop(struct fimc_is_pipeline *pipeline,
+		enum fimc_is_scaler_id scaler_id);
+void fimc_is_pipeline_config_shot(struct fimc_is_pipeline *pipeline);
+int fimc_is_pipeline_shot_safe(struct fimc_is_pipeline *pipeline);
+int fimc_is_pipeline_shot(struct fimc_is_pipeline *pipeline);
+int fimc_is_pipeline_start(struct fimc_is_pipeline *pipeline, int streamon);
+int fimc_is_pipeline_stop(struct fimc_is_pipeline *pipeline, int streamoff);
+int fimc_is_pipeline_init(struct fimc_is_pipeline *pipeline,
+			unsigned int instance, void *is_ctx);
+int fimc_is_pipeline_destroy(struct fimc_is_pipeline *pipeline);
+int fimc_is_pipeline_open(struct fimc_is_pipeline *pipeline,
+			struct fimc_is_sensor *sensor);
+int fimc_is_pipeline_close(struct fimc_is_pipeline *pipeline);
+
+#endif
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 09/12] [media] exynos5-fimc-is: Add the hardware interface module
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
                   ` (7 preceding siblings ...)
  2013-11-05 12:13 ` [PATCH v12 08/12] [media] exynos5-fimc-is: Add the hardware pipeline control Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 10/12] [media] exynos5-is: Add Kconfig and Makefile Arun Kumar K
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

The hardware interface module finally sends the commands to the
FIMC-IS firmware and runs the interrupt handler for getting the
responses.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Kilyeon Im <kilyeon.im@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 .../media/platform/exynos5-is/fimc-is-interface.c  |  810 ++++++++++++++++++++
 .../media/platform/exynos5-is/fimc-is-interface.h  |  124 +++
 2 files changed, 934 insertions(+)
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-interface.c
 create mode 100644 drivers/media/platform/exynos5-is/fimc-is-interface.h

diff --git a/drivers/media/platform/exynos5-is/fimc-is-interface.c b/drivers/media/platform/exynos5-is/fimc-is-interface.c
new file mode 100644
index 0000000..c5da6ff
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-interface.c
@@ -0,0 +1,810 @@
+/*
+ * Samsung EXYNOS5 FIMC-IS (Imaging Subsystem) driver
+*
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Kil-yeon Lim <kilyeon.im@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/debugfs.h>
+#include <linux/seq_file.h>
+#include "fimc-is.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+
+#define init_request_barrier(itf) mutex_init(&itf->request_barrier)
+#define enter_request_barrier(itf) mutex_lock(&itf->request_barrier)
+#define exit_request_barrier(itf) mutex_unlock(&itf->request_barrier)
+
+static inline void itf_get_cmd(struct fimc_is_interface *itf,
+	struct fimc_is_msg *msg, unsigned int index)
+{
+	struct is_common_reg __iomem *com_regs = itf->com_regs;
+
+	memset(msg, 0, sizeof(*msg));
+
+	switch (index) {
+	case INTR_GENERAL:
+		msg->command = com_regs->ihcmd;
+		msg->instance = com_regs->ihc_sensorid;
+		memcpy(msg->param, com_regs->ihc_param,
+				4 * sizeof(msg->param[0]));
+		break;
+	case INTR_SCC_FDONE:
+		msg->command = IHC_FRAME_DONE;
+		msg->instance = com_regs->scc_sensor_id;
+		memcpy(msg->param, com_regs->scc_param,
+				3 * sizeof(msg->param[0]));
+		break;
+	case INTR_SCP_FDONE:
+		msg->command = IHC_FRAME_DONE;
+		msg->instance = com_regs->scp_sensor_id;
+		memcpy(msg->param, com_regs->scp_param,
+				3 * sizeof(msg->param[0]));
+		break;
+	case INTR_META_DONE:
+		msg->command = IHC_FRAME_DONE;
+		msg->instance = com_regs->meta_sensor_id;
+		msg->param[0] = com_regs->meta_param1;
+		break;
+	case INTR_SHOT_DONE:
+		msg->command = IHC_FRAME_DONE;
+		msg->instance = com_regs->shot_sensor_id;
+		memcpy(msg->param, com_regs->shot_param,
+				2 * sizeof(msg->param[0]));
+		break;
+	default:
+		dev_err(itf->dev, "%s Unknown command\n", __func__);
+		break;
+	}
+}
+
+static inline unsigned int itf_get_intr(struct fimc_is_interface *itf)
+{
+	unsigned int status;
+	struct is_common_reg __iomem *com_regs = itf->com_regs;
+
+	status = readl(itf->regs + INTMSR1) | com_regs->ihcmd_iflag |
+		com_regs->scc_iflag |
+		com_regs->scp_iflag |
+		com_regs->meta_iflag |
+		com_regs->shot_iflag;
+
+	return status;
+}
+
+static void itf_set_state(struct fimc_is_interface *itf,
+		unsigned long state)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&itf->slock_state, flags);
+	__set_bit(state, &itf->state);
+	spin_unlock_irqrestore(&itf->slock_state, flags);
+}
+
+static void itf_clr_state(struct fimc_is_interface *itf,
+		unsigned long state)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&itf->slock_state, flags);
+	__clear_bit(state, &itf->state);
+	spin_unlock_irqrestore(&itf->slock_state, flags);
+}
+
+static int itf_get_state(struct fimc_is_interface *itf,
+		unsigned long state)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&itf->slock_state, flags);
+	ret = test_bit(state, &itf->state);
+	spin_unlock_irqrestore(&itf->slock_state, flags);
+	return ret;
+}
+
+static void itf_init_wakeup(struct fimc_is_interface *itf)
+{
+	itf_set_state(itf, IS_IF_STATE_INIT);
+	wake_up(&itf->irq_queue);
+}
+
+void itf_busy_wakeup(struct fimc_is_interface *itf)
+{
+	itf_clr_state(itf, IS_IF_STATE_BUSY);
+	wake_up(&itf->irq_queue);
+}
+
+static int itf_wait_hw_ready(struct fimc_is_interface *itf)
+{
+	int t;
+	for (t = TRY_RECV_AWARE_COUNT; t >= 0; t--) {
+		unsigned int cfg = readl(itf->regs + INTMSR0);
+		if (INTMSR0_GET_INTMSD(0, cfg) == 0)
+			return 0;
+	}
+	dev_err(itf->dev, "INTMSR0's 0 bit is not cleared.\n");
+	return -EINVAL;
+}
+
+static int itf_wait_idlestate(struct fimc_is_interface *itf)
+{
+	int ret;
+
+	ret = wait_event_timeout(itf->irq_queue,
+			!itf_get_state(itf, IS_IF_STATE_BUSY),
+			FIMC_IS_COMMAND_TIMEOUT);
+	if (!ret) {
+		dev_err(itf->dev, "%s Timeout\n", __func__);
+		return -ETIME;
+	}
+	return 0;
+}
+
+int fimc_is_itf_wait_init_state(struct fimc_is_interface *itf)
+{
+	int ret;
+
+	ret = wait_event_timeout(itf->irq_queue,
+		itf_get_state(itf, IS_IF_STATE_INIT),
+		FIMC_IS_STARTUP_TIMEOUT);
+
+	if (!ret) {
+		dev_err(itf->dev, "%s Timeout\n", __func__);
+		return -ETIME;
+	}
+	return 0;
+}
+
+/* Send Host to IS command interrupt */
+static void itf_hic_interrupt(struct fimc_is_interface *itf)
+{
+	writel(INTGR0_INTGD(0), itf->regs + INTGR0);
+}
+
+static int itf_send_sensor_number(struct fimc_is_interface *itf)
+{
+	struct fimc_is_msg msg = {
+		.command = ISR_DONE,
+		.param = { IHC_GET_SENSOR_NUMBER, 1 },
+	};
+	unsigned long flags;
+
+	spin_lock_irqsave(&itf->slock, flags);
+	itf->com_regs->hicmd = msg.command;
+	itf->com_regs->hic_sensorid = msg.instance;
+	memcpy(itf->com_regs->hic_param, msg.param,
+		4 * sizeof(itf->com_regs->hic_param[0]));
+	itf_hic_interrupt(itf);
+	spin_unlock_irqrestore(&itf->slock, flags);
+
+	return 0;
+}
+
+static int fimc_is_itf_set_cmd(struct fimc_is_interface *itf,
+	struct fimc_is_msg *msg)
+{
+	int ret = 0;
+	bool block_io = true;
+	unsigned long flags;
+
+	enter_request_barrier(itf);
+
+	switch (msg->command) {
+	case HIC_STREAM_ON:
+		if (itf->streaming == IS_IF_STREAMING_ON)
+			goto exit;
+		break;
+	case HIC_STREAM_OFF:
+		if (itf->streaming == IS_IF_STREAMING_OFF)
+			goto exit;
+		break;
+	case HIC_PROCESS_START:
+		if (itf->processing == IS_IF_PROCESSING_ON)
+			goto exit;
+		break;
+	case HIC_PROCESS_STOP:
+		if (itf->processing == IS_IF_PROCESSING_OFF)
+			goto exit;
+		break;
+	case HIC_POWER_DOWN:
+		if (itf->pdown_ready == IS_IF_POWER_DOWN_READY)
+			goto exit;
+		break;
+	case HIC_SHOT:
+	case ISR_DONE:
+		block_io = false;
+		break;
+	}
+
+	ret = itf_wait_hw_ready(itf);
+	if (ret) {
+		dev_err(itf->dev, "%s: itf_wait_hw_ready() failed", __func__);
+		ret = -EBUSY;
+		goto exit;
+	}
+
+	spin_lock_irqsave(&itf->slock, flags);
+	itf_set_state(itf, IS_IF_STATE_BUSY);
+	itf->com_regs->hicmd = msg->command;
+	itf->com_regs->hic_sensorid = msg->instance;
+	memcpy(itf->com_regs->hic_param, msg->param,
+			4 * sizeof(itf->com_regs->hic_param[0]));
+	itf_hic_interrupt(itf);
+	spin_unlock_irqrestore(&itf->slock, flags);
+
+	if (!block_io)
+		goto exit;
+
+	ret = itf_wait_idlestate(itf);
+	if (ret) {
+		dev_err(itf->dev, "%d command is timeout\n", msg->command);
+		itf_clr_state(itf, IS_IF_STATE_BUSY);
+		ret = -ETIME;
+		goto exit;
+	}
+
+	if (itf->reply.command == ISR_DONE) {
+		switch (msg->command) {
+		case HIC_STREAM_ON:
+			itf->streaming = IS_IF_STREAMING_ON;
+			break;
+		case HIC_STREAM_OFF:
+			itf->streaming = IS_IF_STREAMING_OFF;
+			break;
+		case HIC_PROCESS_START:
+			itf->processing = IS_IF_PROCESSING_ON;
+			break;
+		case HIC_PROCESS_STOP:
+			itf->processing = IS_IF_PROCESSING_OFF;
+			break;
+		case HIC_POWER_DOWN:
+			itf->pdown_ready = IS_IF_POWER_DOWN_READY;
+			break;
+		case HIC_OPEN_SENSOR:
+			if (itf->reply.param[0] == HIC_POWER_DOWN) {
+				dev_err(itf->dev, "firmware power down");
+				itf->pdown_ready = IS_IF_POWER_DOWN_READY;
+				ret = -ECANCELED;
+				goto exit;
+			} else
+				itf->pdown_ready = IS_IF_POWER_DOWN_NREADY;
+			break;
+		default:
+			break;
+		}
+	} else {
+		dev_err(itf->dev, "ISR_NDONE occured");
+		ret = -EINVAL;
+	}
+exit:
+	exit_request_barrier(itf);
+
+	if (ret)
+		dev_err(itf->dev, "Error returned from FW. See debugfs for error log\n");
+
+	return ret;
+}
+
+static int fimc_is_itf_set_cmd_shot(struct fimc_is_interface *itf,
+		struct fimc_is_msg *msg)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&itf->slock, flags);
+	itf->com_regs->hicmd = msg->command;
+	itf->com_regs->hic_sensorid = msg->instance;
+	memcpy(itf->com_regs->hic_param, msg->param,
+			4 * sizeof(itf->com_regs->hic_param[0]));
+	itf->com_regs->fcount = msg->param[2];
+	itf_hic_interrupt(itf);
+	spin_unlock_irqrestore(&itf->slock, flags);
+
+	return 0;
+}
+
+static void itf_handle_general(struct fimc_is_interface *itf,
+		struct fimc_is_msg *msg)
+{
+	bool is_blocking = true;
+
+	switch (msg->command) {
+
+	case IHC_GET_SENSOR_NUMBER:
+		pr_debug("IS version : %d.%d\n",
+			ISDRV_VERSION, msg->param[0]);
+		/* Respond with sensor number */
+		itf_send_sensor_number(itf);
+		itf_init_wakeup(itf);
+		break;
+	case ISR_DONE:
+		switch (msg->param[0]) {
+		case HIC_OPEN_SENSOR:
+			pr_debug("open done\n");
+			break;
+		case HIC_GET_SET_FILE_ADDR:
+			pr_debug("saddr(%p) done\n",
+				(void *)msg->param[1]);
+			break;
+		case HIC_LOAD_SET_FILE:
+			pr_debug("setfile done\n");
+			break;
+		case HIC_SET_A5_MEM_ACCESS:
+			pr_debug("cfgmem done\n");
+			break;
+		case HIC_PROCESS_START:
+			pr_debug("process_on done\n");
+			break;
+		case HIC_PROCESS_STOP:
+			pr_debug("process_off done\n");
+			break;
+		case HIC_STREAM_ON:
+			pr_debug("stream_on done\n");
+			break;
+		case HIC_STREAM_OFF:
+			pr_debug("stream_off done\n");
+			break;
+		case HIC_SET_PARAMETER:
+			pr_debug("s_param done\n");
+			break;
+		case HIC_GET_STATIC_METADATA:
+			pr_debug("g_capability done\n");
+			break;
+		case HIC_PREVIEW_STILL:
+			pr_debug("a_param(%dx%d) done\n",
+					msg->param[1], msg->param[2]);
+			break;
+		case HIC_POWER_DOWN:
+			pr_debug("powerdown done\n");
+			break;
+		/* Non-blocking command */
+		case HIC_SHOT:
+			is_blocking = false;
+			dev_err(itf->dev, "shot done is not acceptable\n");
+			break;
+		case HIC_SET_CAM_CONTROL:
+			is_blocking = false;
+			dev_err(itf->dev, "camctrl is not acceptable\n");
+			break;
+		default:
+			is_blocking = false;
+			dev_err(itf->dev, "unknown done is invokded\n");
+			break;
+		}
+		break;
+	case ISR_NDONE:
+		switch (msg->param[0]) {
+		case HIC_SHOT:
+			is_blocking = false;
+			dev_err(itf->dev, "shot NOT done is not acceptable\n");
+			break;
+		case HIC_SET_CAM_CONTROL:
+			is_blocking = false;
+			pr_debug("camctrl NOT done\n");
+			break;
+		case HIC_SET_PARAMETER:
+			dev_err(itf->dev, "s_param NOT done\n");
+			dev_err(itf->dev, "param2 : 0x%08X\n", msg->param[1]);
+			dev_err(itf->dev, "param3 : 0x%08X\n", msg->param[2]);
+			dev_err(itf->dev, "param4 : 0x%08X\n", msg->param[3]);
+			break;
+		default:
+			dev_err(itf->dev, "command(%d) not done",
+					msg->param[0]);
+			break;
+		}
+		break;
+	case IHC_SET_FACE_MARK:
+		is_blocking = false;
+		dev_err(itf->dev, "FACE_MARK(%d,%d,%d) is not acceptable\n",
+			msg->param[0], msg->param[1], msg->param[2]);
+		break;
+	case IHC_AA_DONE:
+		is_blocking = false;
+		dev_err(itf->dev, "AA_DONE(%d,%d,%d) is not acceptable\n",
+			msg->param[0], msg->param[1], msg->param[2]);
+		break;
+	case IHC_FLASH_READY:
+		is_blocking = false;
+		dev_err(itf->dev, "IHC_FLASH_READY is not acceptable");
+		break;
+	case IHC_NOT_READY:
+		is_blocking = false;
+		dev_err(itf->dev, "IHC_NOT_READY is occured, need reset");
+		break;
+	default:
+		is_blocking = false;
+		dev_err(itf->dev, "%s: unknown (#%08X) command\n",
+				__func__, msg->command);
+		break;
+	}
+
+	if (is_blocking) {
+		memcpy(&itf->reply, msg, sizeof(struct fimc_is_msg));
+		itf_busy_wakeup(itf);
+	}
+}
+
+static void itf_handle_scaler_done(struct fimc_is_interface *itf,
+		struct fimc_is_msg *msg)
+{
+	struct fimc_is *is = fimc_interface_to_is(itf);
+	struct fimc_is_pipeline *pipeline = &is->pipeline[msg->instance];
+	struct fimc_is_buf *buf;
+	struct fimc_is_scaler *scl;
+	const struct fimc_is_fmt *fmt;
+	struct timeval *tv;
+	struct timespec ts;
+	unsigned int wh, i;
+	unsigned int fcount = msg->param[0];
+	unsigned long *comp_state;
+
+	if (msg->param[3] == SCALER_SCC) {
+		scl = &pipeline->scaler[SCALER_SCC];
+		comp_state = &pipeline->comp_state[IS_SCC];
+	} else {
+		scl = &pipeline->scaler[SCALER_SCP];
+		comp_state = &pipeline->comp_state[IS_SCP];
+	}
+
+	fmt = scl->fmt;
+
+	fimc_is_pipeline_buf_lock(pipeline);
+	if (!list_empty(&scl->run_queue)) {
+
+		wh = scl->width * scl->height;
+		buf = fimc_is_scaler_run_queue_get(scl);
+		for (i = 0; i < fmt->num_planes; i++)
+			vb2_set_plane_payload(&buf->vb, i,
+					(wh * fmt->depth[i]) / 8);
+
+		/* Set timestamp */
+		ktime_get_ts(&ts);
+		tv = &buf->vb.v4l2_buf.timestamp;
+		tv->tv_sec = ts.tv_sec;
+		tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+		buf->vb.v4l2_buf.sequence = fcount;
+
+		pr_debug("SCP buffer done %d/%d\n",
+				msg->param[0], msg->param[2]);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+	}
+	fimc_is_pipeline_buf_unlock(pipeline);
+	clear_bit(COMP_RUN, comp_state);
+	wake_up(&scl->event_q);
+}
+
+static void itf_handle_shot_done(struct fimc_is_interface *itf,
+		struct fimc_is_msg *msg)
+{
+	struct fimc_is *is = fimc_interface_to_is(itf);
+	struct fimc_is_pipeline *pipeline = &is->pipeline[msg->instance];
+	unsigned int status = msg->param[1];
+	struct fimc_is_buf *bayer_buf;
+	int ret;
+
+	if (status != ISR_DONE)
+		dev_err(itf->dev, "Shot done is invalid(0x%08X)\n", status);
+
+	/* DQ the bayer input buffer */
+	fimc_is_pipeline_buf_lock(pipeline);
+	bayer_buf = fimc_is_isp_run_queue_get(&pipeline->isp);
+	if (bayer_buf) {
+		vb2_buffer_done(&bayer_buf->vb, VB2_BUF_STATE_DONE);
+		pr_debug("Bayer buffer done.\n");
+	}
+	fimc_is_pipeline_buf_unlock(pipeline);
+
+	/* Clear state & call shot again */
+	clear_bit(PIPELINE_RUN, &pipeline->state);
+
+	ret = fimc_is_pipeline_shot(pipeline);
+	if (ret)
+		dev_err(itf->dev, "Shot failed\n");
+}
+
+/* Main FIMC-IS interrupt handler */
+static irqreturn_t itf_irq_handler(int irq, void *data)
+{
+	struct fimc_is_interface *itf = data;
+	struct fimc_is_msg msg;
+	unsigned int status, intr;
+	struct is_common_reg __iomem *com_regs;
+
+	com_regs = itf->com_regs;
+	status = itf_get_intr(itf);
+
+	for (intr = INTR_GENERAL; intr < INTR_MAX_MAP; intr++) {
+
+		if (status & BIT(intr)) {
+			itf_get_cmd(itf, &msg, intr);
+
+			switch (intr) {
+			case INTR_GENERAL:
+				itf_handle_general(itf, &msg);
+				com_regs->ihcmd_iflag = 0;
+				break;
+			case INTR_SHOT_DONE:
+				itf_handle_shot_done(itf, &msg);
+				com_regs->shot_iflag = 0;
+				break;
+			case INTR_SCC_FDONE:
+				msg.param[3] = SCALER_SCC;
+				itf_handle_scaler_done(itf, &msg);
+				com_regs->scc_iflag = 0;
+				break;
+			case INTR_SCP_FDONE:
+				msg.param[3] = SCALER_SCP;
+				itf_handle_scaler_done(itf, &msg);
+				com_regs->scp_iflag = 0;
+				break;
+			case INTR_META_DONE:
+				com_regs->meta_iflag = 0;
+				break;
+			}
+			status &= ~BIT(intr);
+			writel(BIT(intr), itf->regs + INTCR1);
+		}
+	}
+
+	if (status != 0)
+		dev_err(itf->dev, "status is NOT all clear(0x%08X)", status);
+
+	return IRQ_HANDLED;
+}
+
+int fimc_is_itf_open_sensor(struct fimc_is_interface *itf,
+		unsigned int instance,
+		unsigned int sensor_id,
+		unsigned int i2c_channel,
+		unsigned int sensor_ext)
+{
+	struct fimc_is_msg msg = {
+		.command = HIC_OPEN_SENSOR,
+		.instance = instance,
+		.param = { sensor_id, i2c_channel, sensor_ext },
+	};
+
+	return fimc_is_itf_set_cmd(itf, &msg);
+}
+
+int fimc_is_itf_get_setfile_addr(struct fimc_is_interface *itf,
+		unsigned int instance, unsigned int *setfile_addr)
+{
+	int ret;
+	struct fimc_is_msg msg = {
+		.command = HIC_GET_SET_FILE_ADDR,
+		.instance = instance,
+	};
+
+	ret = fimc_is_itf_set_cmd(itf, &msg);
+	*setfile_addr = itf->reply.param[1];
+
+	return ret;
+}
+
+int fimc_is_itf_load_setfile(struct fimc_is_interface *itf,
+		unsigned int instance)
+{
+	struct fimc_is_msg msg = {
+		.command = HIC_LOAD_SET_FILE,
+		.instance = instance,
+	};
+
+	return fimc_is_itf_set_cmd(itf, &msg);
+}
+
+int fimc_is_itf_stream_on(struct fimc_is_interface *itf,
+		unsigned int instance)
+{
+	struct fimc_is_msg msg = {
+		.command = HIC_STREAM_ON,
+		.instance = instance,
+	};
+
+	return fimc_is_itf_set_cmd(itf, &msg);
+}
+
+int fimc_is_itf_stream_off(struct fimc_is_interface *itf,
+		unsigned int instance)
+{
+	struct fimc_is_msg msg = {
+		.command = HIC_STREAM_OFF,
+		.instance = instance,
+	};
+
+	return fimc_is_itf_set_cmd(itf, &msg);
+}
+
+int fimc_is_itf_process_on(struct fimc_is_interface *itf,
+		unsigned int instance)
+{
+	struct fimc_is_msg msg = {
+		.command = HIC_PROCESS_START,
+		.instance = instance,
+	};
+
+	return fimc_is_itf_set_cmd(itf, &msg);
+}
+
+int fimc_is_itf_process_off(struct fimc_is_interface *itf,
+		unsigned int instance)
+{
+	struct fimc_is_msg msg = {
+		.command = HIC_PROCESS_STOP,
+		.instance = instance,
+	};
+
+	return fimc_is_itf_set_cmd(itf, &msg);
+}
+
+int fimc_is_itf_set_param(struct fimc_is_interface *itf,
+		unsigned int instance,
+		unsigned int lindex,
+		unsigned int hindex)
+{
+	struct fimc_is_msg msg = {
+		.command = HIC_SET_PARAMETER,
+		.instance = instance,
+		.param = { ISS_PREVIEW_STILL, 0, lindex, hindex },
+	};
+
+	return fimc_is_itf_set_cmd(itf, &msg);
+}
+
+int fimc_is_itf_preview_still(struct fimc_is_interface *itf,
+		unsigned int instance)
+{
+	struct fimc_is_msg msg = {
+		.command = HIC_PREVIEW_STILL,
+		.instance = instance,
+	};
+
+	return fimc_is_itf_set_cmd(itf, &msg);
+}
+
+int fimc_is_itf_get_capability(struct fimc_is_interface *itf,
+	unsigned int instance, unsigned int address)
+{
+	struct fimc_is_msg msg = {
+		.command = HIC_GET_STATIC_METADATA,
+		.instance = instance,
+		.param[0] = address,
+	};
+
+	return fimc_is_itf_set_cmd(itf, &msg);
+}
+
+int fimc_is_itf_cfg_mem(struct fimc_is_interface *itf,
+		unsigned int instance, unsigned int address,
+		unsigned int size)
+{
+	struct fimc_is_msg msg = {
+		.command = HIC_SET_A5_MEM_ACCESS,
+		.instance = instance,
+		.param = { address, size },
+	};
+
+	return fimc_is_itf_set_cmd(itf, &msg);
+}
+
+int fimc_is_itf_shot_nblk(struct fimc_is_interface *itf,
+		unsigned int instance, unsigned int bayer,
+		unsigned int shot, unsigned int fcount, unsigned int rcount)
+{
+	struct fimc_is_msg msg = {
+		.command = HIC_SHOT,
+		.instance = instance,
+		.param = { bayer, shot, fcount, rcount },
+	};
+
+	return fimc_is_itf_set_cmd_shot(itf, &msg);
+}
+
+int fimc_is_itf_power_down(struct fimc_is_interface *itf,
+		unsigned int instance)
+{
+	int ret;
+	struct fimc_is_msg msg = {
+		.command = HIC_POWER_DOWN,
+		.instance = instance,
+	};
+
+	ret = fimc_is_itf_set_cmd(itf, &msg);
+	itf_clr_state(itf, IS_IF_STATE_INIT);
+
+	return ret;
+}
+
+/* Debugfs for showing FW debug messages */
+static int fimc_is_log_show(struct seq_file *s, void *data)
+{
+	struct fimc_is_interface *itf = s->private;
+	struct fimc_is *is = fimc_interface_to_is(itf);
+
+	const u8 *buf = (u8 *) (is->minfo.fw.vaddr + DEBUG_OFFSET);
+
+	if (is->minfo.fw.vaddr == 0) {
+		dev_err(itf->dev, "Firmware memory is not initialized\n");
+		return -EIO;
+	}
+
+	seq_printf(s, "%s\n", buf);
+	return 0;
+}
+
+static int fimc_is_debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, fimc_is_log_show, inode->i_private);
+}
+
+static const struct file_operations fimc_is_debugfs_fops = {
+	.open		= fimc_is_debugfs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void fimc_is_debugfs_remove(struct fimc_is_interface *itf)
+{
+	debugfs_remove(itf->debugfs_entry);
+	itf->debugfs_entry = NULL;
+}
+
+static int fimc_is_debugfs_create(struct fimc_is_interface *itf)
+{
+	struct dentry *dentry;
+
+	itf->debugfs_entry = debugfs_create_dir("fimc_is", NULL);
+
+	dentry = debugfs_create_file("fw_log", S_IRUGO, itf->debugfs_entry,
+					itf, &fimc_is_debugfs_fops);
+	if (!dentry)
+		fimc_is_debugfs_remove(itf);
+
+	return itf->debugfs_entry == NULL ? -EIO : 0;
+}
+
+int fimc_is_interface_init(struct fimc_is_interface *itf,
+		void __iomem *regs, int irq)
+{
+	struct fimc_is *is = fimc_interface_to_is(itf);
+	struct device *dev = &is->pdev->dev;
+	int ret;
+
+	if (!regs || !irq) {
+		dev_err(itf->dev, "Invalid args\n");
+		return -EINVAL;
+	}
+
+	itf->regs = regs;
+	itf->com_regs = (struct is_common_reg *)(regs + ISSR(0));
+	itf->dev = &is->pdev->dev;
+
+	init_waitqueue_head(&itf->irq_queue);
+	spin_lock_init(&itf->slock_state);
+	spin_lock_init(&itf->slock);
+
+	/* Register interrupt handler */
+	ret = devm_request_irq(dev, irq, itf_irq_handler,
+			       0, dev_name(dev), itf);
+	if (ret) {
+		dev_err(dev, "Failed to install irq (%d)\n", ret);
+		return ret;
+	}
+
+	/* Initialize context vars */
+	itf->streaming = IS_IF_STREAMING_INIT;
+	itf->processing = IS_IF_PROCESSING_INIT;
+	itf->pdown_ready = IS_IF_POWER_DOWN_READY;
+	itf->debug_cnt = 0;
+	init_request_barrier(itf);
+
+	/* Debugfs for FW debug log */
+	fimc_is_debugfs_create(itf);
+
+	return 0;
+}
diff --git a/drivers/media/platform/exynos5-is/fimc-is-interface.h b/drivers/media/platform/exynos5-is/fimc-is-interface.h
new file mode 100644
index 0000000..44b641b
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-interface.h
@@ -0,0 +1,124 @@
+/*
+ * Samsung EXYNOS5 FIMC-IS (Imaging Subsystem) driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *  Arun Kumar K <arun.kk@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_IS_INTERFACE_H_
+#define FIMC_IS_INTERFACE_H_
+
+#include "fimc-is-core.h"
+
+#define TRY_RECV_AWARE_COUNT    100
+
+#define ISDRV_VERSION		111
+
+enum interrupt_map {
+	INTR_GENERAL            = 0,
+	INTR_ISP_FDONE          = 1,
+	INTR_SCC_FDONE          = 2,
+	INTR_DNR_FDONE          = 3,
+	INTR_SCP_FDONE          = 4,
+	INTR_ISP_YUV_DONE	= 5,
+	INTR_META_DONE          = 6,
+	INTR_SHOT_DONE          = 7,
+	INTR_MAX_MAP
+};
+
+enum fimc_is_interface_state {
+	IS_IF_STATE_INIT,
+	IS_IF_STATE_OPEN,
+	IS_IF_STATE_START,
+	IS_IF_STATE_BUSY
+};
+
+enum streaming_state {
+	IS_IF_STREAMING_INIT,
+	IS_IF_STREAMING_OFF,
+	IS_IF_STREAMING_ON
+};
+
+enum processing_state {
+	IS_IF_PROCESSING_INIT,
+	IS_IF_PROCESSING_OFF,
+	IS_IF_PROCESSING_ON
+};
+
+enum pdown_ready_state {
+	IS_IF_POWER_DOWN_READY,
+	IS_IF_POWER_DOWN_NREADY
+};
+
+struct fimc_is_msg {
+	u32 id;
+	u32 command;
+	u32 instance;
+	u32 param[4];
+};
+
+struct fimc_is_interface {
+	unsigned long			state;
+
+	void __iomem			*regs;
+	struct is_common_reg __iomem    *com_regs;
+	/* Lock for writing into MCUCTL registers */
+	spinlock_t			slock;
+	/* Lock for context state variable */
+	spinlock_t			slock_state;
+	wait_queue_head_t		irq_queue;
+	struct device			*dev;
+	/* Held while sending commands to FW */
+	struct mutex			request_barrier;
+
+	enum streaming_state		streaming;
+	enum processing_state		processing;
+	enum pdown_ready_state		pdown_ready;
+
+	struct fimc_is_msg		reply;
+
+	int				debug_cnt;
+	struct dentry                   *debugfs_entry;
+
+};
+
+int fimc_is_interface_init(struct fimc_is_interface *itf,
+		void __iomem *regs, int irq);
+int fimc_is_itf_wait_init_state(struct fimc_is_interface *itf);
+int fimc_is_itf_open_sensor(struct fimc_is_interface *itf,
+		unsigned int instance,
+		unsigned int sensor_id,
+		unsigned int i2c_channel,
+		unsigned int sensor_ext);
+int fimc_is_itf_get_setfile_addr(struct fimc_is_interface *this,
+		unsigned int instance, unsigned int *setfile_addr);
+int fimc_is_itf_load_setfile(struct fimc_is_interface *itf,
+		unsigned int instance);
+int fimc_is_itf_stream_on(struct fimc_is_interface *itf,
+		unsigned int instance);
+int fimc_is_itf_stream_off(struct fimc_is_interface *itf,
+		unsigned int instance);
+int fimc_is_itf_process_on(struct fimc_is_interface *itf,
+		unsigned int instance);
+int fimc_is_itf_process_off(struct fimc_is_interface *itf,
+		unsigned int instance);
+int fimc_is_itf_set_param(struct fimc_is_interface *this,
+		unsigned int instance,
+		unsigned int lindex,
+		unsigned int hindex);
+int fimc_is_itf_preview_still(struct fimc_is_interface *itf,
+		unsigned int instance);
+int fimc_is_itf_get_capability(struct fimc_is_interface *itf,
+	unsigned int instance, unsigned int address);
+int fimc_is_itf_cfg_mem(struct fimc_is_interface *itf,
+		unsigned int instance, unsigned int address,
+		unsigned int size);
+int fimc_is_itf_shot_nblk(struct fimc_is_interface *itf,
+		unsigned int instance, unsigned int bayer,
+		unsigned int shot, unsigned int fcount, unsigned int rcount);
+int fimc_is_itf_power_down(struct fimc_is_interface *itf,
+		unsigned int instance);
+#endif
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 10/12] [media] exynos5-is: Add Kconfig and Makefile
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
                   ` (8 preceding siblings ...)
  2013-11-05 12:13 ` [PATCH v12 09/12] [media] exynos5-fimc-is: Add the hardware interface module Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 11/12] V4L: Add DT binding doc for s5k4e5 image sensor Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 12/12] V4L: Add s5k4e5 sensor driver Arun Kumar K
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

Adds Kconfig and Makefile for exynos5-is driver files.

Signed-off-by: Shaik Ameer Basha <shaik.ameer@samsung.com>
Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/media/platform/Kconfig                   |    1 +
 drivers/media/platform/Makefile                  |    1 +
 drivers/media/platform/exynos5-is/Kconfig        |   20 ++++++++++++++++++++
 drivers/media/platform/exynos5-is/Makefile       |    7 +++++++
 drivers/media/platform/exynos5-is/fimc-is-core.c |    1 +
 5 files changed, 30 insertions(+)
 create mode 100644 drivers/media/platform/exynos5-is/Kconfig
 create mode 100644 drivers/media/platform/exynos5-is/Makefile

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 08de865..4b0475e 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -123,6 +123,7 @@ config VIDEO_S3C_CAMIF
 
 source "drivers/media/platform/soc_camera/Kconfig"
 source "drivers/media/platform/exynos4-is/Kconfig"
+source "drivers/media/platform/exynos5-is/Kconfig"
 source "drivers/media/platform/s5p-tv/Kconfig"
 
 endif # V4L_PLATFORM_DRIVERS
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index eee28dd..40bf09f 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV)	+= s5p-tv/
 
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D)	+= s5p-g2d/
 obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC)	+= exynos-gsc/
+obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS5_CAMERA) += exynos5-is/
 
 obj-$(CONFIG_BLACKFIN)                  += blackfin/
 
diff --git a/drivers/media/platform/exynos5-is/Kconfig b/drivers/media/platform/exynos5-is/Kconfig
new file mode 100644
index 0000000..b67d11a
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/Kconfig
@@ -0,0 +1,20 @@
+config VIDEO_SAMSUNG_EXYNOS5_CAMERA
+	bool "Samsung Exynos5 SoC Camera Media Device driver"
+	depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && PM_RUNTIME
+	depends on VIDEO_SAMSUNG_EXYNOS4_IS
+	help
+	  This is a V4L2 media device driver for Exynos5 SoC series
+	  camera subsystem.
+
+if VIDEO_SAMSUNG_EXYNOS5_CAMERA
+
+config VIDEO_SAMSUNG_EXYNOS5_FIMC_IS
+	tristate "Samsung Exynos5 SoC FIMC-IS driver"
+	depends on I2C && OF
+	depends on VIDEO_EXYNOS4_FIMC_IS
+	select VIDEOBUF2_DMA_CONTIG
+	help
+	  This is a V4L2 driver for Samsung Exynos5 SoC series Imaging
+	  Subsystem known as FIMC-IS.
+
+endif #VIDEO_SAMSUNG_EXYNOS5_MDEV
diff --git a/drivers/media/platform/exynos5-is/Makefile b/drivers/media/platform/exynos5-is/Makefile
new file mode 100644
index 0000000..6cdb037
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/Makefile
@@ -0,0 +1,7 @@
+ccflags-y += -Idrivers/media/platform/exynos4-is
+exynos5-fimc-is-objs := fimc-is-core.o fimc-is-isp.o fimc-is-scaler.o
+exynos5-fimc-is-objs += fimc-is-pipeline.o fimc-is-interface.o fimc-is-sensor.o
+exynos-mdevice-objs := exynos5-mdev.o
+
+obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS5_FIMC_IS) += exynos5-fimc-is.o
+obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS5_CAMERA) += exynos-mdevice.o
diff --git a/drivers/media/platform/exynos5-is/fimc-is-core.c b/drivers/media/platform/exynos5-is/fimc-is-core.c
index 136e3c1..0b391f2 100644
--- a/drivers/media/platform/exynos5-is/fimc-is-core.c
+++ b/drivers/media/platform/exynos5-is/fimc-is-core.c
@@ -12,6 +12,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/of_platform.h>
 #include <linux/videodev2.h>
 
 #include <media/v4l2-device.h>
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 11/12] V4L: Add DT binding doc for s5k4e5 image sensor
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
                   ` (9 preceding siblings ...)
  2013-11-05 12:13 ` [PATCH v12 10/12] [media] exynos5-is: Add Kconfig and Makefile Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  2013-11-05 12:13 ` [PATCH v12 12/12] V4L: Add s5k4e5 sensor driver Arun Kumar K
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

S5K4E5 is a Samsung raw image sensor controlled via I2C.
This patch adds the DT binding documentation for the same.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
---
 .../devicetree/bindings/media/samsung-s5k4e5.txt   |   45 ++++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/samsung-s5k4e5.txt

diff --git a/Documentation/devicetree/bindings/media/samsung-s5k4e5.txt b/Documentation/devicetree/bindings/media/samsung-s5k4e5.txt
new file mode 100644
index 0000000..fc37792
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/samsung-s5k4e5.txt
@@ -0,0 +1,45 @@
+* Samsung S5K4E5 Raw Image Sensor
+
+S5K4E5 is a raw image sensor with maximum resolution of 2560x1920
+pixels. Data transfer is carried out via MIPI CSI-2 port and controls
+via I2C bus.
+
+Required Properties:
+- compatible	: should contain "samsung,s5k4e5"
+- reg		: I2C device address
+- reset-gpios	: specifier of a GPIO connected to the RESET pin
+- clocks	: should refer to the clock named in clock-names, from
+		  the common clock bindings
+- clock-names	: should contain "extclk" entry
+- svdda-supply	: core voltage supply
+- svddio-supply	: I/O voltage supply
+
+Optional Properties:
+- clock-frequency : the frequency at which the "extclk" clock should be
+		    configured to operate, in Hz; if this property is not
+		    specified default 24 MHz value will be used
+
+The device node should be added to respective control bus controller
+(e.g. I2C0) nodes and linked to the csis port node, using the common
+video interfaces bindings, defined in video-interfaces.txt.
+
+Example:
+
+	i2c-isp@13130000 {
+		s5k4e5@20 {
+			compatible = "samsung,s5k4e5";
+			reg = <0x20>;
+			reset-gpios = <&gpx1 2 1>;
+			clock-frequency = <24000000>;
+			clocks = <&clock 129>;
+			clock-names = "extclk"
+			svdda-supply = <...>;
+			svddio-supply = <...>;
+			port {
+				is_s5k4e5_ep: endpoint {
+					data-lanes = <1 2 3 4>;
+					remote-endpoint = <&csis0_ep>;
+				};
+			};
+		};
+	};
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 12/12] V4L: Add s5k4e5 sensor driver
  2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
                   ` (10 preceding siblings ...)
  2013-11-05 12:13 ` [PATCH v12 11/12] V4L: Add DT binding doc for s5k4e5 image sensor Arun Kumar K
@ 2013-11-05 12:13 ` Arun Kumar K
  11 siblings, 0 replies; 13+ messages in thread
From: Arun Kumar K @ 2013-11-05 12:13 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc, devicetree
  Cc: s.nawrocki, shaik.ameer, kilyeon.im, arunkk.samsung

This patch adds subdev driver for Samsung S5K4E5 raw image sensor.
Like s5k6a3, it is also another fimc-is firmware controlled
sensor. This minimal sensor driver doesn't do any I2C communications
as its done by ISP firmware. It can be updated if needed to a
regular sensor driver by adding the I2C communication.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/media/i2c/Kconfig  |    8 ++
 drivers/media/i2c/Makefile |    1 +
 drivers/media/i2c/s5k4e5.c |  344 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 353 insertions(+)
 create mode 100644 drivers/media/i2c/s5k4e5.c

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index f7e9147..271028b 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -572,6 +572,14 @@ config VIDEO_S5K6A3
 	  This is a V4L2 sensor-level driver for Samsung S5K6A3 raw
 	  camera sensor.
 
+config VIDEO_S5K4E5
+	tristate "Samsung S5K4E5 sensor support"
+	depends on MEDIA_CAMERA_SUPPORT
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF
+	---help---
+	  This is a V4L2 sensor-level driver for Samsung S5K4E5 raw
+	  camera sensor.
+
 config VIDEO_S5K4ECGX
         tristate "Samsung S5K4ECGX sensor support"
         depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index cf3cf03..0aeed8e 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_VIDEO_SR030PC30)	+= sr030pc30.o
 obj-$(CONFIG_VIDEO_NOON010PC30)	+= noon010pc30.o
 obj-$(CONFIG_VIDEO_S5K6AA)	+= s5k6aa.o
 obj-$(CONFIG_VIDEO_S5K6A3)	+= s5k6a3.o
+obj-$(CONFIG_VIDEO_S5K4E5)	+= s5k4e5.o
 obj-$(CONFIG_VIDEO_S5K4ECGX)	+= s5k4ecgx.o
 obj-$(CONFIG_VIDEO_S5C73M3)	+= s5c73m3/
 obj-$(CONFIG_VIDEO_ADP1653)	+= adp1653.o
diff --git a/drivers/media/i2c/s5k4e5.c b/drivers/media/i2c/s5k4e5.c
new file mode 100644
index 0000000..5d4007e
--- /dev/null
+++ b/drivers/media/i2c/s5k4e5.c
@@ -0,0 +1,344 @@
+/*
+ * Samsung S5K4E5 image sensor driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Arun Kumar K <arun.kk@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/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-subdev.h>
+
+#define S5K4E5_SENSOR_MAX_WIDTH		2576
+#define S5K4E5_SENSOR_MAX_HEIGHT	1930
+
+#define S5K4E5_SENSOR_MIN_WIDTH		(32 + 16)
+#define S5K4E5_SENSOR_MIN_HEIGHT	(32 + 10)
+
+#define S5K4E5_DEF_WIDTH		1296
+#define S5K4E5_DEF_HEIGHT		732
+
+#define S5K4E5_DRV_NAME			"S5K4E5"
+#define S5K4E5_CLK_NAME			"extclk"
+
+#define S5K4E5_NUM_SUPPLIES		2
+
+#define S5K4E5_DEF_CLK_FREQ		24000000
+
+/**
+ * struct s5k4e5 - s5k4e5 sensor data structure
+ * @dev: pointer to this I2C client device structure
+ * @subdev: the image sensor's v4l2 subdev
+ * @pad: subdev media source pad
+ * @supplies: image sensor's voltage regulator supplies
+ * @gpio_reset: GPIO connected to the sensor's reset pin
+ * @lock: mutex protecting the structure's members below
+ * @format: media bus format at the sensor's source pad
+ */
+struct s5k4e5 {
+	struct device *dev;
+	struct v4l2_subdev subdev;
+	struct media_pad pad;
+	struct regulator_bulk_data supplies[S5K4E5_NUM_SUPPLIES];
+	int gpio_reset;
+	struct mutex lock;
+	struct v4l2_mbus_framefmt format;
+	struct clk *clock;
+	u32 clock_frequency;
+};
+
+static const char * const s5k4e5_supply_names[] = {
+	"svdda",
+	"svddio"
+};
+
+static inline struct s5k4e5 *sd_to_s5k4e5(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct s5k4e5, subdev);
+}
+
+static const struct v4l2_mbus_framefmt s5k4e5_formats[] = {
+	{
+		.code = V4L2_MBUS_FMT_SGRBG10_1X10,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.field = V4L2_FIELD_NONE,
+	}
+};
+
+static const struct v4l2_mbus_framefmt *find_sensor_format(
+	struct v4l2_mbus_framefmt *mf)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(s5k4e5_formats); i++)
+		if (mf->code == s5k4e5_formats[i].code)
+			return &s5k4e5_formats[i];
+
+	return &s5k4e5_formats[0];
+}
+
+static int s5k4e5_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index >= ARRAY_SIZE(s5k4e5_formats))
+		return -EINVAL;
+
+	code->code = s5k4e5_formats[code->index].code;
+	return 0;
+}
+
+static void s5k4e5_try_format(struct v4l2_mbus_framefmt *mf)
+{
+	const struct v4l2_mbus_framefmt *fmt;
+
+	fmt = find_sensor_format(mf);
+	mf->code = fmt->code;
+	v4l_bound_align_image(&mf->width,
+			S5K4E5_SENSOR_MIN_WIDTH, S5K4E5_SENSOR_MAX_WIDTH, 0,
+			&mf->height,
+			S5K4E5_SENSOR_MIN_HEIGHT, S5K4E5_SENSOR_MAX_HEIGHT, 0,
+			0);
+}
+
+static struct v4l2_mbus_framefmt *__s5k4e5_get_format(
+		struct s5k4e5 *sensor, struct v4l2_subdev_fh *fh,
+		u32 pad, enum v4l2_subdev_format_whence which)
+{
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
+		return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL;
+
+	return &sensor->format;
+}
+
+static int s5k4e5_set_fmt(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_format *fmt)
+{
+	struct s5k4e5 *sensor = sd_to_s5k4e5(sd);
+	struct v4l2_mbus_framefmt *mf;
+
+	s5k4e5_try_format(&fmt->format);
+
+	mf = __s5k4e5_get_format(sensor, fh, fmt->pad, fmt->which);
+	if (mf) {
+		mutex_lock(&sensor->lock);
+		if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+			*mf = fmt->format;
+		mutex_unlock(&sensor->lock);
+	}
+	return 0;
+}
+
+static int s5k4e5_get_fmt(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_format *fmt)
+{
+	struct s5k4e5 *sensor = sd_to_s5k4e5(sd);
+	struct v4l2_mbus_framefmt *mf;
+
+	mf = __s5k4e5_get_format(sensor, fh, fmt->pad, fmt->which);
+
+	mutex_lock(&sensor->lock);
+	fmt->format = *mf;
+	mutex_unlock(&sensor->lock);
+	return 0;
+}
+
+static struct v4l2_subdev_pad_ops s5k4e5_pad_ops = {
+	.enum_mbus_code	= s5k4e5_enum_mbus_code,
+	.get_fmt	= s5k4e5_get_fmt,
+	.set_fmt	= s5k4e5_set_fmt,
+};
+
+static int s5k4e5_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+
+	*format		= s5k4e5_formats[0];
+	format->width	= S5K4E5_DEF_WIDTH;
+	format->height	= S5K4E5_DEF_HEIGHT;
+
+	return 0;
+}
+
+static const struct v4l2_subdev_internal_ops s5k4e5_sd_internal_ops = {
+	.open = s5k4e5_open,
+};
+
+static int s5k4e5_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct s5k4e5 *sensor = sd_to_s5k4e5(sd);
+	int gpio = sensor->gpio_reset;
+	int ret = 0;
+
+	if (on) {
+		ret = clk_set_rate(sensor->clock, sensor->clock_frequency);
+		if (ret < 0)
+			return ret;
+
+		ret = pm_runtime_get(sensor->dev);
+		if (ret < 0)
+			return ret;
+
+		ret = regulator_bulk_enable(S5K4E5_NUM_SUPPLIES,
+					    sensor->supplies);
+		if (ret < 0)
+			goto rpm_put;
+
+		ret = clk_prepare_enable(sensor->clock);
+		if (ret < 0)
+			goto reg_dis;
+
+		if (gpio_is_valid(gpio)) {
+			gpio_set_value(gpio, 1);
+			usleep_range(600, 800);
+			gpio_set_value(gpio, 0);
+			usleep_range(10000, 11000);
+			gpio_set_value(gpio, 1);
+		}
+
+		/* Delay needed for the sensor initialization */
+		msleep(20);
+	} else {
+		if (gpio_is_valid(gpio))
+			gpio_set_value(gpio, 0);
+
+		clk_disable_unprepare(sensor->clock);
+reg_dis:
+		regulator_bulk_disable(S5K4E5_NUM_SUPPLIES,
+						sensor->supplies);
+rpm_put:
+		pm_runtime_put(sensor->dev);
+	}
+	return ret;
+}
+
+static struct v4l2_subdev_core_ops s5k4e5_core_ops = {
+	.s_power = s5k4e5_s_power,
+};
+
+static struct v4l2_subdev_ops s5k4e5_subdev_ops = {
+	.core = &s5k4e5_core_ops,
+	.pad = &s5k4e5_pad_ops,
+};
+
+static int s5k4e5_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct s5k4e5 *sensor;
+	struct v4l2_subdev *sd;
+	int gpio, i, ret;
+
+	sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
+	if (!sensor)
+		return -ENOMEM;
+
+	mutex_init(&sensor->lock);
+	sensor->gpio_reset = -EINVAL;
+	sensor->clock = ERR_PTR(-EINVAL);
+	sensor->dev = dev;
+
+	gpio = of_get_named_gpio_flags(dev->of_node, "reset-gpios", 0, NULL);
+	if (gpio_is_valid(gpio)) {
+		ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW,
+							S5K4E5_DRV_NAME);
+		if (ret < 0)
+			return ret;
+	}
+	sensor->gpio_reset = gpio;
+
+	if (of_property_read_u32(dev->of_node, "clock-frequency",
+				 &sensor->clock_frequency)) {
+		/* Fallback to default value */
+		sensor->clock_frequency = S5K4E5_DEF_CLK_FREQ;
+	}
+
+	for (i = 0; i < S5K4E5_NUM_SUPPLIES; i++)
+		sensor->supplies[i].supply = s5k4e5_supply_names[i];
+
+	ret = devm_regulator_bulk_get(&client->dev, S5K4E5_NUM_SUPPLIES,
+				      sensor->supplies);
+	if (ret < 0)
+		return ret;
+
+	/* Defer probing if the clock is not available yet */
+	sensor->clock = clk_get(dev, S5K4E5_CLK_NAME);
+	if (IS_ERR(sensor->clock))
+		return -EPROBE_DEFER;
+
+	sd = &sensor->subdev;
+	v4l2_i2c_subdev_init(sd, client, &s5k4e5_subdev_ops);
+	sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	sensor->format.code = s5k4e5_formats[0].code;
+	sensor->format.width = S5K4E5_DEF_WIDTH;
+	sensor->format.height = S5K4E5_DEF_HEIGHT;
+
+	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&sd->entity, 1, &sensor->pad, 0);
+	if (ret < 0)
+		return ret;
+
+	pm_runtime_no_callbacks(dev);
+	pm_runtime_enable(dev);
+
+	ret = v4l2_async_register_subdev(sd);
+
+	return ret;
+}
+
+static int s5k4e5_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_async_unregister_subdev(sd);
+	media_entity_cleanup(&sd->entity);
+	return 0;
+}
+
+static const struct i2c_device_id s5k4e5_ids[] = {
+	{ }
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id s5k4e5_of_match[] = {
+	{ .compatible = "samsung,s5k4e5" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s5k4e5_of_match);
+#endif
+
+static struct i2c_driver s5k4e5_driver = {
+	.driver = {
+		.of_match_table	= of_match_ptr(s5k4e5_of_match),
+		.name		= S5K4E5_DRV_NAME,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= s5k4e5_probe,
+	.remove		= s5k4e5_remove,
+	.id_table	= s5k4e5_ids,
+};
+
+module_i2c_driver(s5k4e5_driver);
+
+MODULE_DESCRIPTION("S5K4E5 image sensor subdev driver");
+MODULE_AUTHOR("Arun Kumar K <arun.kk@samsung.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2013-11-05 12:14 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-11-05 12:13 [PATCH v12 00/12] Exynos5 IS driver Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 01/12] [media] exynos5-fimc-is: Add Exynos5 FIMC-IS device tree bindings documentation Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 02/12] [media] exynos5-fimc-is: Add driver core files Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 03/12] [media] exynos5-fimc-is: Add common driver header files Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 04/12] [media] exynos5-fimc-is: Add register definition and context header Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 05/12] [media] exynos5-fimc-is: Add isp subdev Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 06/12] [media] exynos5-fimc-is: Add scaler subdev Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 07/12] [media] exynos5-fimc-is: Add sensor interface Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 08/12] [media] exynos5-fimc-is: Add the hardware pipeline control Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 09/12] [media] exynos5-fimc-is: Add the hardware interface module Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 10/12] [media] exynos5-is: Add Kconfig and Makefile Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 11/12] V4L: Add DT binding doc for s5k4e5 image sensor Arun Kumar K
2013-11-05 12:13 ` [PATCH v12 12/12] V4L: Add s5k4e5 sensor driver Arun Kumar K

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).