Re: [PATCH v8 02/12] [media] exynos5-fimc-is: Add driver core files

2013-09-16 Thread Sylwester Nawrocki

On 09/12/2013 02:07 PM, Arun Kumar K wrote:


+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 (!pdev-dev.of_node)


nit: Could be simplified to:

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  0) {
+   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);
+
+   ret = pm_runtime_get_sync(dev);
+   if (ret  0)
+   goto err_pm;


Is activating the device at this point really needed ? Perhaps you
could drop the pm_runtime_get/put calls ?


+   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;
+
+   pm_runtime_put(dev);
+
+   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_pm:
+   pm_runtime_put(dev);
+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]);


Shouldn't you disable the first enabled clock when this call fails ?


+   return ret;
+}

[...]

+static void *fimc_is_get_drvdata(struct platform_device *pdev)
+{
+   struct fimc_is_drvdata *driver_data = NULL;
+
+   if (pdev-dev.of_node) {


pdev-dev.of_node is being tested against NULL before call to this
function, you could make this code slightly simpler with that assumption.


+   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;
+}


--
Thanks,
Sylwester
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v8 02/12] [media] exynos5-fimc-is: Add driver core files

2013-09-12 Thread Arun Kumar K
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...@samsung.com
Signed-off-by: Kilyeon Im kilyeon...@samsung.com
Reviewed-by: Sylwester Nawrocki s.nawro...@samsung.com
---
 drivers/media/platform/exynos5-is/fimc-is-core.c |  413 ++
 drivers/media/platform/exynos5-is/fimc-is-core.h |  132 +++
 2 files changed, 545 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 000..6910581
--- /dev/null
+++ b/drivers/media/platform/exynos5-is/fimc-is-core.c
@@ -0,0 +1,413 @@
+/*
+ * Samsung EXYNOS5 FIMC-IS (Imaging Subsystem) driver
+*
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Arun Kumar K arun...@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/bug.h
+#include linux/ctype.h
+#include linux/device.h
+#include linux/debugfs.h
+#include linux/delay.h
+#include linux/errno.h
+#include linux/err.h
+#include linux/firmware.h
+#include linux/fs.h
+#include linux/gpio.h
+#include linux/interrupt.h
+#include linux/kernel.h
+#include linux/list.h
+#include linux/module.h
+#include linux/of.h
+#include linux/of_gpio.h
+#include linux/of_address.h
+#include linux/of_platform.h
+#include linux/of_irq.h
+#include linux/pinctrl/consumer.h
+#include linux/platform_device.h
+#include linux/pm_runtime.h
+#include linux/slab.h
+#include linux/types.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 * 100)
+#define CLK_MCU_ISP_DIV1_FREQ  (100 * 100)
+#define CLK_ISP_DIV0_FREQ  (134 * 100)
+#define CLK_ISP_DIV1_FREQ  (68 * 100)
+#define CLK_ISP_DIVMPWM_FREQ   (34 * 100)
+
+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);
+   pr_err(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;
+   ret = clk_set_rate(is-clock[IS_CLK_ISP_DIVMPWM],
+   CLK_ISP_DIVMPWM_FREQ);
+   return ret;
+}
+
+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,
+