Re: [PATCH v8 02/12] [media] exynos5-fimc-is: Add driver core files
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
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, +