devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] drm/exynos: Add device tree support for IPP driver
@ 2013-04-17  9:53 Sylwester Nawrocki
  2013-04-17  9:53 ` [PATCH v2 1/3] drm/exynos: Remove redundant devm_kfree() Sylwester Nawrocki
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Sylwester Nawrocki @ 2013-04-17  9:53 UTC (permalink / raw)
  To: inki.dae
  Cc: kyungmin.park, linux-samsung-soc, dri-devel, devicetree-discuss,
	Sylwester Nawrocki

Hi Inki,

This small patch series adds device tree support for the DRM FIMC driver.
The binding documentation can be found in -next at Documentation/devicetree/
bindings/media/samsung-fimc.txt.
It will make the driver dependent on OF. This patch series is needed in
3.10 to ensure simultaneous operation of the DRM FIMC and the camera ISP
on Exynos4x12.

Changes since v1:
 - removed devm_kfree() that got erroneously re-added in patch 2/3 during
   rebase.

Thanks,
Sylwester

Sylwester Nawrocki (3):
  drm/exynos: Remove redundant devm_kfree()
  drm/exynos: Rework fimc clocks handling
  drm/exynos: Add device tree support for fimc ipp driver

 drivers/gpu/drm/exynos/Kconfig           |    2 +-
 drivers/gpu/drm/exynos/exynos_drm_fimc.c |  264 ++++++++++++++++--------------
 drivers/gpu/drm/exynos/regs-fimc.h       |    7 +-
 3 files changed, 147 insertions(+), 126 deletions(-)

--
1.7.9.5

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

* [PATCH v2 1/3] drm/exynos: Remove redundant devm_kfree()
  2013-04-17  9:53 [PATCH v2 0/3] drm/exynos: Add device tree support for IPP driver Sylwester Nawrocki
@ 2013-04-17  9:53 ` Sylwester Nawrocki
  2013-04-17  9:53 ` [PATCH v2 2/3] drm/exynos: Rework fimc clocks handling Sylwester Nawrocki
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Sylwester Nawrocki @ 2013-04-17  9:53 UTC (permalink / raw)
  To: inki.dae
  Cc: kyungmin.park, linux-samsung-soc, dri-devel, devicetree-discuss,
	Sylwester Nawrocki

There is no need for explicit calls of devm_kfree(), as
the allocated memory will be freed during driver's detach.
Remove the redundant devm_kfree() calls from probe() and
remove() callbacks.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_fimc.c |    2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 411f69b7..d812c57 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -1843,7 +1843,6 @@ static int fimc_probe(struct platform_device *pdev)
 	return 0;
 
 err_ippdrv_register:
-	devm_kfree(dev, ippdrv->prop_list);
 	pm_runtime_disable(dev);
 err_get_irq:
 	free_irq(ctx->irq, ctx);
@@ -1857,7 +1856,6 @@ static int fimc_remove(struct platform_device *pdev)
 	struct fimc_context *ctx = get_fimc_context(dev);
 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
 
-	devm_kfree(dev, ippdrv->prop_list);
 	exynos_drm_ippdrv_unregister(ippdrv);
 	mutex_destroy(&ctx->lock);
 
-- 
1.7.9.5

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

* [PATCH v2 2/3] drm/exynos: Rework fimc clocks handling
  2013-04-17  9:53 [PATCH v2 0/3] drm/exynos: Add device tree support for IPP driver Sylwester Nawrocki
  2013-04-17  9:53 ` [PATCH v2 1/3] drm/exynos: Remove redundant devm_kfree() Sylwester Nawrocki
@ 2013-04-17  9:53 ` Sylwester Nawrocki
  2013-04-19 11:26   ` Eunchul Kim
  2013-04-17  9:53 ` [PATCH v2 3/3] drm/exynos: Add device tree support for fimc ipp driver Sylwester Nawrocki
       [not found] ` <1366192384-18829-1-git-send-email-s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
  3 siblings, 1 reply; 8+ messages in thread
From: Sylwester Nawrocki @ 2013-04-17  9:53 UTC (permalink / raw)
  To: inki.dae
  Cc: kyungmin.park, linux-samsung-soc, dri-devel, devicetree-discuss,
	Sylwester Nawrocki

The clocks handling is refactored and a "mux" clock handling is
added to account for changes in the clocks driver. After switching
to the common clock framework the sclk_fimc clock is now split
into two clocks: a gate and a mux clock. In order to retain the
exisiting functionality two additional consumer clocks are passed
to the driver from device tree: "mux" and "parent". Then the driver
sets "parent" clock as a parent clock of the "mux" clock. These two
additional clocks are optional, and should go away when there is a
standard way of setting up parent clocks on DT platforms.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_fimc.c |  167 +++++++++++++++++-------------
 1 file changed, 97 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index d812c57..bc8411a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -76,6 +76,27 @@ enum fimc_wb {
 	FIMC_WB_B,
 };
 
+enum {
+	FIMC_CLK_LCLK,
+	FIMC_CLK_GATE,
+	FIMC_CLK_WB_A,
+	FIMC_CLK_WB_B,
+	FIMC_CLK_MUX,
+	FIMC_CLK_PARENT,
+	FIMC_CLKS_MAX
+};
+
+static const char * fimc_clock_names[] = {
+	[FIMC_CLK_LCLK]   = "sclk_fimc",
+	[FIMC_CLK_GATE]   = "fimc",
+	[FIMC_CLK_WB_A]   = "pxl_async0",
+	[FIMC_CLK_WB_B]   = "pxl_async1",
+	[FIMC_CLK_MUX]    = "mux",
+	[FIMC_CLK_PARENT] = "parent",
+};
+
+#define FIMC_DEFAULT_LCLK_FREQUENCY 133000000UL
+
 /*
  * A structure of scaler.
  *
@@ -132,15 +153,12 @@ struct fimc_driverdata {
  *
  * @ippdrv: prepare initialization using ippdrv.
  * @regs_res: register resources.
+ * @dev: pointer to the fimc device structure.
  * @regs: memory mapped io registers.
  * @lock: locking of operations.
- * @sclk_fimc_clk: fimc source clock.
- * @fimc_clk: fimc clock.
- * @wb_clk: writeback a clock.
- * @wb_b_clk: writeback b clock.
+ * @clocks: fimc clocks.
+ * @clk_frequency: LCLK clock frequency.
  * @sc: scaler infomations.
- * @odr: ordering of YUV.
- * @ver: fimc version.
  * @pol: porarity of writeback.
  * @id: fimc id.
  * @irq: irq number.
@@ -148,13 +166,12 @@ struct fimc_driverdata {
  */
 struct fimc_context {
 	struct exynos_drm_ippdrv	ippdrv;
+	struct device	*dev;
 	struct resource	*regs_res;
 	void __iomem	*regs;
 	struct mutex	lock;
-	struct clk	*sclk_fimc_clk;
-	struct clk	*fimc_clk;
-	struct clk	*wb_clk;
-	struct clk	*wb_b_clk;
+	struct clk	*clocks[FIMC_CLKS_MAX];
+	u32		clk_frequency;
 	struct fimc_scaler	sc;
 	struct fimc_driverdata	*ddata;
 	struct exynos_drm_ipp_pol	pol;
@@ -1301,14 +1318,12 @@ static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
 	DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
 
 	if (enable) {
-		clk_enable(ctx->sclk_fimc_clk);
-		clk_enable(ctx->fimc_clk);
-		clk_enable(ctx->wb_clk);
+		clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
+		clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]);
 		ctx->suspended = false;
 	} else {
-		clk_disable(ctx->sclk_fimc_clk);
-		clk_disable(ctx->fimc_clk);
-		clk_disable(ctx->wb_clk);
+		clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
+		clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]);
 		ctx->suspended = true;
 	}
 
@@ -1713,11 +1728,66 @@ static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
 	fimc_write(cfg, EXYNOS_CIGCTRL);
 }
 
+static void fimc_put_clocks(struct fimc_context *ctx)
+{
+	int i;
+
+	for (i = 0; i < FIMC_CLKS_MAX; i++) {
+		if (IS_ERR(ctx->clocks[i]))
+			continue;
+		clk_put(ctx->clocks[i]);
+		ctx->clocks[i] = ERR_PTR(-EINVAL);
+	}
+}
+
+static int fimc_setup_clocks(struct fimc_context *ctx)
+{
+	struct device *dev;
+	int ret, i;
+
+	for (i = 0; i < FIMC_CLKS_MAX; i++)
+		ctx->clocks[i] = ERR_PTR(-EINVAL);
+
+	for (i = 0; i < FIMC_CLKS_MAX; i++) {
+		if (i == FIMC_CLK_WB_A || i == FIMC_CLK_WB_B)
+			dev = ctx->dev->parent;
+		else
+			dev = ctx->dev;
+
+		ctx->clocks[i] = clk_get(dev, fimc_clock_names[i]);
+		if (IS_ERR(ctx->clocks[i])) {
+			if (i >= FIMC_CLK_MUX)
+				break;
+			ret = PTR_ERR(ctx->clocks[i]);
+			goto e_clk_free;
+		}
+	}
+
+	if (!IS_ERR(ctx->clocks[FIMC_CLK_PARENT])) {
+		ret = clk_set_parent(ctx->clocks[FIMC_CLK_MUX],
+				     ctx->clocks[FIMC_CLK_PARENT]);
+		if (ret < 0) {
+			dev_err(ctx->dev, "failed to set parent: %d\n", ret);
+			return ret;
+		}
+	}
+
+	ret = clk_set_rate(ctx->clocks[FIMC_CLK_LCLK], ctx->clk_frequency);
+	if (ret < 0)
+		return ret;
+
+	return clk_prepare_enable(ctx->clocks[FIMC_CLK_LCLK]);
+
+e_clk_free:
+	dev_err(ctx->dev, "failed to get clock: %s\n", fimc_clock_names[i]);
+	fimc_put_clocks(ctx);
+	return ret;
+}
+
 static int fimc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct fimc_context *ctx;
-	struct clk	*parent_clk;
 	struct resource *res;
 	struct exynos_drm_ippdrv *ippdrv;
 	struct exynos_drm_fimc_pdata *pdata;
@@ -1734,55 +1804,6 @@ static int fimc_probe(struct platform_device *pdev)
 	if (!ctx)
 		return -ENOMEM;
 
-	ddata = (struct fimc_driverdata *)
-		platform_get_device_id(pdev)->driver_data;
-
-	/* clock control */
-	ctx->sclk_fimc_clk = devm_clk_get(dev, "sclk_fimc");
-	if (IS_ERR(ctx->sclk_fimc_clk)) {
-		dev_err(dev, "failed to get src fimc clock.\n");
-		return PTR_ERR(ctx->sclk_fimc_clk);
-	}
-	clk_enable(ctx->sclk_fimc_clk);
-
-	ctx->fimc_clk = devm_clk_get(dev, "fimc");
-	if (IS_ERR(ctx->fimc_clk)) {
-		dev_err(dev, "failed to get fimc clock.\n");
-		clk_disable(ctx->sclk_fimc_clk);
-		return PTR_ERR(ctx->fimc_clk);
-	}
-
-	ctx->wb_clk = devm_clk_get(dev, "pxl_async0");
-	if (IS_ERR(ctx->wb_clk)) {
-		dev_err(dev, "failed to get writeback a clock.\n");
-		clk_disable(ctx->sclk_fimc_clk);
-		return PTR_ERR(ctx->wb_clk);
-	}
-
-	ctx->wb_b_clk = devm_clk_get(dev, "pxl_async1");
-	if (IS_ERR(ctx->wb_b_clk)) {
-		dev_err(dev, "failed to get writeback b clock.\n");
-		clk_disable(ctx->sclk_fimc_clk);
-		return PTR_ERR(ctx->wb_b_clk);
-	}
-
-	parent_clk = devm_clk_get(dev, ddata->parent_clk);
-
-	if (IS_ERR(parent_clk)) {
-		dev_err(dev, "failed to get parent clock.\n");
-		clk_disable(ctx->sclk_fimc_clk);
-		return PTR_ERR(parent_clk);
-	}
-
-	if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) {
-		dev_err(dev, "failed to set parent.\n");
-		clk_disable(ctx->sclk_fimc_clk);
-		return -EINVAL;
-	}
-
-	devm_clk_put(dev, parent_clk);
-	clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate);
-
 	/* resource memory */
 	ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	ctx->regs = devm_ioremap_resource(dev, ctx->regs_res);
@@ -1804,6 +1825,9 @@ static int fimc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	ret = fimc_setup_clocks(ctx);
+	if (ret < 0)
+		goto err_free_irq;
 	/* context initailization */
 	ctx->id = pdev->id;
 	ctx->pol = pdata->pol;
@@ -1820,7 +1844,7 @@ static int fimc_probe(struct platform_device *pdev)
 	ret = fimc_init_prop_list(ippdrv);
 	if (ret < 0) {
 		dev_err(dev, "failed to init property list.\n");
-		goto err_get_irq;
+		goto err_put_clk;
 	}
 
 	DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
@@ -1835,16 +1859,18 @@ static int fimc_probe(struct platform_device *pdev)
 	ret = exynos_drm_ippdrv_register(ippdrv);
 	if (ret < 0) {
 		dev_err(dev, "failed to register drm fimc device.\n");
-		goto err_ippdrv_register;
+		goto err_pm_dis;
 	}
 
 	dev_info(&pdev->dev, "drm fimc registered successfully.\n");
 
 	return 0;
 
-err_ippdrv_register:
+err_pm_dis:
 	pm_runtime_disable(dev);
-err_get_irq:
+err_put_clk:
+	fimc_put_clocks(ctx);
+err_free_irq:
 	free_irq(ctx->irq, ctx);
 
 	return ret;
@@ -1859,6 +1885,7 @@ static int fimc_remove(struct platform_device *pdev)
 	exynos_drm_ippdrv_unregister(ippdrv);
 	mutex_destroy(&ctx->lock);
 
+	fimc_put_clocks(ctx);
 	pm_runtime_set_suspended(dev);
 	pm_runtime_disable(dev);
 
-- 
1.7.9.5

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

* [PATCH v2 3/3] drm/exynos: Add device tree support for fimc ipp driver
  2013-04-17  9:53 [PATCH v2 0/3] drm/exynos: Add device tree support for IPP driver Sylwester Nawrocki
  2013-04-17  9:53 ` [PATCH v2 1/3] drm/exynos: Remove redundant devm_kfree() Sylwester Nawrocki
  2013-04-17  9:53 ` [PATCH v2 2/3] drm/exynos: Rework fimc clocks handling Sylwester Nawrocki
@ 2013-04-17  9:53 ` Sylwester Nawrocki
       [not found] ` <1366192384-18829-1-git-send-email-s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
  3 siblings, 0 replies; 8+ messages in thread
From: Sylwester Nawrocki @ 2013-04-17  9:53 UTC (permalink / raw)
  To: inki.dae
  Cc: kyungmin.park, linux-samsung-soc, dri-devel, devicetree-discuss,
	Sylwester Nawrocki

This patch adds OF initialization support for the FIMC driver.
The binding documentation can be found at Documentation/devicetree/
bindings/media/samsung-fimc.txt.

The syscon regmap interface is used to serialize access to the
shared CAMBLK registers from within the V4L2 FIMC-IS and the DRM
FIMC drivers. The DRM driver uses this interface for setting up
the FIFO data link between FIMD and FIMC IP blocks, while the V4L2
one for setting up a data link between the camera ISP and FIMC for
camera capture. The CAMBLK registers are not accessed any more
through a statically mapped IO. Synchronized access to these
registers is required for simultaneous operation of the camera
ISP and the DRM IPP on Exynos4x12.

Exynos4 is going to be a dt-only platform since 3.10, thus the
driver data and driver_ids static data structures are removed.

Camera input signal polarities are not currently parsed from the
device tree.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/gpu/drm/exynos/Kconfig           |    2 +-
 drivers/gpu/drm/exynos/exynos_drm_fimc.c |  101 +++++++++++++++---------------
 drivers/gpu/drm/exynos/regs-fimc.h       |    7 +--
 3 files changed, 53 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 406f32a..5c4be2a 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -56,7 +56,7 @@ config DRM_EXYNOS_IPP
 
 config DRM_EXYNOS_FIMC
 	bool "Exynos DRM FIMC"
-	depends on DRM_EXYNOS_IPP
+	depends on DRM_EXYNOS_IPP && MFD_SYSCON && OF
 	help
 	  Choose this option if you want to use Exynos FIMC for DRM.
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index bc8411a..2e182ba 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -12,11 +12,12 @@
  *
  */
 #include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
-#include <plat/map-base.h>
 
 #include <drm/drmP.h>
 #include <drm/exynos_drm.h>
@@ -140,15 +141,6 @@ struct fimc_capability {
 };
 
 /*
- * A structure of fimc driver data.
- *
- * @parent_clk: name of parent clock.
- */
-struct fimc_driverdata {
-	char	*parent_clk;
-};
-
-/*
  * A structure of fimc context.
  *
  * @ippdrv: prepare initialization using ippdrv.
@@ -158,6 +150,7 @@ struct fimc_driverdata {
  * @lock: locking of operations.
  * @clocks: fimc clocks.
  * @clk_frequency: LCLK clock frequency.
+ * @sysreg: handle to SYSREG block regmap.
  * @sc: scaler infomations.
  * @pol: porarity of writeback.
  * @id: fimc id.
@@ -172,8 +165,8 @@ struct fimc_context {
 	struct mutex	lock;
 	struct clk	*clocks[FIMC_CLKS_MAX];
 	u32		clk_frequency;
+	struct regmap	*sysreg;
 	struct fimc_scaler	sc;
-	struct fimc_driverdata	*ddata;
 	struct exynos_drm_ipp_pol	pol;
 	int	id;
 	int	irq;
@@ -217,17 +210,13 @@ static void fimc_sw_reset(struct fimc_context *ctx)
 	fimc_write(0x0, EXYNOS_CIFCNTSEQ);
 }
 
-static void fimc_set_camblk_fimd0_wb(struct fimc_context *ctx)
+static int fimc_set_camblk_fimd0_wb(struct fimc_context *ctx)
 {
-	u32 camblk_cfg;
-
 	DRM_DEBUG_KMS("%s\n", __func__);
 
-	camblk_cfg = readl(SYSREG_CAMERA_BLK);
-	camblk_cfg &= ~(SYSREG_FIMD0WB_DEST_MASK);
-	camblk_cfg |= ctx->id << (SYSREG_FIMD0WB_DEST_SHIFT);
-
-	writel(camblk_cfg, SYSREG_CAMERA_BLK);
+	return regmap_update_bits(ctx->sysreg, SYSREG_CAMERA_BLK,
+				  SYSREG_FIMD0WB_DEST_MASK,
+				  ctx->id << SYSREG_FIMD0WB_DEST_SHIFT);
 }
 
 static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb)
@@ -1628,7 +1617,9 @@ static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
 		fimc_handle_lastend(ctx, true);
 
 		/* setup FIMD */
-		fimc_set_camblk_fimd0_wb(ctx);
+		ret = fimc_set_camblk_fimd0_wb(ctx);
+		if (ret < 0)
+			return ret;
 
 		set_wb.enable = 1;
 		set_wb.refresh = property->refresh_rate;
@@ -1784,26 +1775,50 @@ e_clk_free:
 	return ret;
 }
 
+static int fimc_parse_dt(struct fimc_context *ctx)
+{
+	struct device_node *node = ctx->dev->of_node;
+
+	if (!of_property_read_bool(node, "samsung,lcd-wb"))
+		return -ENODEV;
+
+	if (of_property_read_u32(node, "clock-frequency",
+					&ctx->clk_frequency))
+		ctx->clk_frequency = FIMC_DEFAULT_LCLK_FREQUENCY;
+
+	ctx->id = of_alias_get_id(node, "fimc");
+	if (ctx->id < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
 static int fimc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct fimc_context *ctx;
 	struct resource *res;
 	struct exynos_drm_ippdrv *ippdrv;
-	struct exynos_drm_fimc_pdata *pdata;
-	struct fimc_driverdata *ddata;
 	int ret;
 
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(dev, "no platform data specified.\n");
-		return -EINVAL;
-	}
+	if (!dev->of_node)
+		return -ENODEV;
 
 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
 		return -ENOMEM;
 
+	ctx->dev = dev;
+
+	ret = fimc_parse_dt(ctx);
+	if (ret < 0)
+		return ret;
+
+	ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
+						"samsung,sysreg");
+	if (IS_ERR(ctx->sysreg))
+		return PTR_ERR(ctx->sysreg);
+
 	/* resource memory */
 	ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	ctx->regs = devm_ioremap_resource(dev, ctx->regs_res);
@@ -1828,10 +1843,6 @@ static int fimc_probe(struct platform_device *pdev)
 	ret = fimc_setup_clocks(ctx);
 	if (ret < 0)
 		goto err_free_irq;
-	/* context initailization */
-	ctx->id = pdev->id;
-	ctx->pol = pdata->pol;
-	ctx->ddata = ddata;
 
 	ippdrv = &ctx->ippdrv;
 	ippdrv->dev = dev;
@@ -1940,36 +1951,22 @@ static int fimc_runtime_resume(struct device *dev)
 }
 #endif
 
-static struct fimc_driverdata exynos4210_fimc_data = {
-	.parent_clk = "mout_mpll",
-};
-
-static struct fimc_driverdata exynos4410_fimc_data = {
-	.parent_clk = "mout_mpll_user",
-};
-
-static struct platform_device_id fimc_driver_ids[] = {
-	{
-		.name		= "exynos4210-fimc",
-		.driver_data	= (unsigned long)&exynos4210_fimc_data,
-	}, {
-		.name		= "exynos4412-fimc",
-		.driver_data	= (unsigned long)&exynos4410_fimc_data,
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
-
 static const struct dev_pm_ops fimc_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
 	SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
 };
 
+static const struct of_device_id fimc_of_match[] = {
+	{ .compatible = "samsung,exynos4210-fimc" },
+	{ .compatible = "samsung,exynos4212-fimc" },
+	{ },
+};
+
 struct platform_driver fimc_driver = {
 	.probe		= fimc_probe,
 	.remove		= fimc_remove,
-	.id_table	= fimc_driver_ids,
 	.driver		= {
+		.of_match_table = fimc_of_match,
 		.name	= "exynos-drm-fimc",
 		.owner	= THIS_MODULE,
 		.pm	= &fimc_pm_ops,
diff --git a/drivers/gpu/drm/exynos/regs-fimc.h b/drivers/gpu/drm/exynos/regs-fimc.h
index b4f9ca1..3049613 100644
--- a/drivers/gpu/drm/exynos/regs-fimc.h
+++ b/drivers/gpu/drm/exynos/regs-fimc.h
@@ -661,9 +661,8 @@
 #define EXYNOS_CLKSRC_SCLK				(1 << 1)
 
 /* SYSREG for FIMC writeback */
-#define SYSREG_CAMERA_BLK			(S3C_VA_SYS + 0x0218)
-#define SYSREG_ISP_BLK				(S3C_VA_SYS + 0x020c)
-#define SYSREG_FIMD0WB_DEST_MASK	(0x3 << 23)
-#define SYSREG_FIMD0WB_DEST_SHIFT	23
+#define SYSREG_CAMERA_BLK			(0x0218)
+#define SYSREG_FIMD0WB_DEST_MASK		(0x3 << 23)
+#define SYSREG_FIMD0WB_DEST_SHIFT		23
 
 #endif /* EXYNOS_REGS_FIMC_H */
-- 
1.7.9.5

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

* Re: [PATCH v2 2/3] drm/exynos: Rework fimc clocks handling
  2013-04-17  9:53 ` [PATCH v2 2/3] drm/exynos: Rework fimc clocks handling Sylwester Nawrocki
@ 2013-04-19 11:26   ` Eunchul Kim
  2013-04-22 15:07     ` Sylwester Nawrocki
  0 siblings, 1 reply; 8+ messages in thread
From: Eunchul Kim @ 2013-04-19 11:26 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: inki.dae, kyungmin.park, linux-samsung-soc, devicetree-discuss,
	dri-devel, chulspro.kim, jaejoon.seo, jmock.shin, jy0.jeon,
	th908.kim, lsmin.lee

Dear Sylwester Nawrocki

Thank you for your update. I have some question of your patch.
please give your information to me.

Thank's
BR
Eunchul Kim.

On 04/17/2013 06:53 PM, Sylwester Nawrocki wrote:
> The clocks handling is refactored and a "mux" clock handling is
> added to account for changes in the clocks driver. After switching
> to the common clock framework the sclk_fimc clock is now split
> into two clocks: a gate and a mux clock. In order to retain the
> exisiting functionality two additional consumer clocks are passed
> to the driver from device tree: "mux" and "parent". Then the driver
> sets "parent" clock as a parent clock of the "mux" clock. These two
> additional clocks are optional, and should go away when there is a
> standard way of setting up parent clocks on DT platforms.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>   drivers/gpu/drm/exynos/exynos_drm_fimc.c |  167 +++++++++++++++++-------------
>   1 file changed, 97 insertions(+), 70 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
> index d812c57..bc8411a 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
> @@ -76,6 +76,27 @@ enum fimc_wb {
>   	FIMC_WB_B,
>   };
>
> +enum {
> +	FIMC_CLK_LCLK,
> +	FIMC_CLK_GATE,
> +	FIMC_CLK_WB_A,
> +	FIMC_CLK_WB_B,
> +	FIMC_CLK_MUX,
> +	FIMC_CLK_PARENT,

- What is MUX, PARENT ?

> +	FIMC_CLKS_MAX
> +};
> +
> +static const char * fimc_clock_names[] = {
> +	[FIMC_CLK_LCLK]   = "sclk_fimc",
> +	[FIMC_CLK_GATE]   = "fimc",
> +	[FIMC_CLK_WB_A]   = "pxl_async0",
> +	[FIMC_CLK_WB_B]   = "pxl_async1",
> +	[FIMC_CLK_MUX]    = "mux",
> +	[FIMC_CLK_PARENT] = "parent",


- How can I get "mux", "parent" clock information ?
   Normally we are using "mout_mpll" in exynos4210, "mout_mpll_user" in 
  exynos 4412. I want to get this two kind of clock name information.


> +};
> +
> +#define FIMC_DEFAULT_LCLK_FREQUENCY 133000000UL


- When do I use this value in the patch ?
   If not use. please remove this macro. If you want to use this value.
   please use platform data instead of macro.


> +
>   /*
>    * A structure of scaler.
>    *
> @@ -132,15 +153,12 @@ struct fimc_driverdata {
>    *
>    * @ippdrv: prepare initialization using ippdrv.
>    * @regs_res: register resources.
> + * @dev: pointer to the fimc device structure.


- We already set the dev information in ippdrv structure.
   I think this value is duplicated value.


>    * @regs: memory mapped io registers.
>    * @lock: locking of operations.
> - * @sclk_fimc_clk: fimc source clock.
> - * @fimc_clk: fimc clock.
> - * @wb_clk: writeback a clock.
> - * @wb_b_clk: writeback b clock.
> + * @clocks: fimc clocks.
> + * @clk_frequency: LCLK clock frequency.
>    * @sc: scaler infomations.
> - * @odr: ordering of YUV.
> - * @ver: fimc version.
>    * @pol: porarity of writeback.
>    * @id: fimc id.
>    * @irq: irq number.
> @@ -148,13 +166,12 @@ struct fimc_driverdata {
>    */
>   struct fimc_context {
>   	struct exynos_drm_ippdrv	ippdrv;
> +	struct device	*dev;

- please check this value about really need ?

>   	struct resource	*regs_res;
>   	void __iomem	*regs;
>   	struct mutex	lock;
> -	struct clk	*sclk_fimc_clk;
> -	struct clk	*fimc_clk;
> -	struct clk	*wb_clk;
> -	struct clk	*wb_b_clk;
> +	struct clk	*clocks[FIMC_CLKS_MAX];
> +	u32		clk_frequency;
>   	struct fimc_scaler	sc;
>   	struct fimc_driverdata	*ddata;
>   	struct exynos_drm_ipp_pol	pol;
> @@ -1301,14 +1318,12 @@ static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
>   	DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
>
>   	if (enable) {
> -		clk_enable(ctx->sclk_fimc_clk);
> -		clk_enable(ctx->fimc_clk);
> -		clk_enable(ctx->wb_clk);
> +		clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
> +		clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]);
>   		ctx->suspended = false;
>   	} else {
> -		clk_disable(ctx->sclk_fimc_clk);
> -		clk_disable(ctx->fimc_clk);
> -		clk_disable(ctx->wb_clk);
> +		clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
> +		clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]);
>   		ctx->suspended = true;
>   	}
>
> @@ -1713,11 +1728,66 @@ static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
>   	fimc_write(cfg, EXYNOS_CIGCTRL);
>   }
>
> +static void fimc_put_clocks(struct fimc_context *ctx)
> +{
> +	int i;
> +
> +	for (i = 0; i < FIMC_CLKS_MAX; i++) {
> +		if (IS_ERR(ctx->clocks[i]))
> +			continue;
> +		clk_put(ctx->clocks[i]);
> +		ctx->clocks[i] = ERR_PTR(-EINVAL);
> +	}
> +}
> +
> +static int fimc_setup_clocks(struct fimc_context *ctx)
> +{
> +	struct device *dev;
> +	int ret, i;
> +
> +	for (i = 0; i < FIMC_CLKS_MAX; i++)
> +		ctx->clocks[i] = ERR_PTR(-EINVAL);
> +
> +	for (i = 0; i < FIMC_CLKS_MAX; i++) {
> +		if (i == FIMC_CLK_WB_A || i == FIMC_CLK_WB_B)
> +			dev = ctx->dev->parent;
> +		else
> +			dev = ctx->dev;
> +
> +		ctx->clocks[i] = clk_get(dev, fimc_clock_names[i]);
> +		if (IS_ERR(ctx->clocks[i])) {
> +			if (i >= FIMC_CLK_MUX)
> +				break;
> +			ret = PTR_ERR(ctx->clocks[i]);
> +			goto e_clk_free;
> +		}
> +	}
> +
> +	if (!IS_ERR(ctx->clocks[FIMC_CLK_PARENT])) {
> +		ret = clk_set_parent(ctx->clocks[FIMC_CLK_MUX],
> +				     ctx->clocks[FIMC_CLK_PARENT]);


- I can't review this code.


> +		if (ret < 0) {
> +			dev_err(ctx->dev, "failed to set parent: %d\n", ret);
> +			return ret;
> +		}
> +	}
> +
> +	ret = clk_set_rate(ctx->clocks[FIMC_CLK_LCLK], ctx->clk_frequency);


- When do I set clk_frequency value ? and why doesn't use pdata->clk_rate ?


> +	if (ret < 0)
> +		return ret;
> +
> +	return clk_prepare_enable(ctx->clocks[FIMC_CLK_LCLK]);
> +
> +e_clk_free:
> +	dev_err(ctx->dev, "failed to get clock: %s\n", fimc_clock_names[i]);
> +	fimc_put_clocks(ctx);
> +	return ret;
> +}
> +
>   static int fimc_probe(struct platform_device *pdev)
>   {
>   	struct device *dev = &pdev->dev;
>   	struct fimc_context *ctx;
> -	struct clk	*parent_clk;
>   	struct resource *res;
>   	struct exynos_drm_ippdrv *ippdrv;
>   	struct exynos_drm_fimc_pdata *pdata;
> @@ -1734,55 +1804,6 @@ static int fimc_probe(struct platform_device *pdev)
>   	if (!ctx)
>   		return -ENOMEM;
>
> -	ddata = (struct fimc_driverdata *)
> -		platform_get_device_id(pdev)->driver_data;
> -
> -	/* clock control */
> -	ctx->sclk_fimc_clk = devm_clk_get(dev, "sclk_fimc");
> -	if (IS_ERR(ctx->sclk_fimc_clk)) {
> -		dev_err(dev, "failed to get src fimc clock.\n");
> -		return PTR_ERR(ctx->sclk_fimc_clk);
> -	}
> -	clk_enable(ctx->sclk_fimc_clk);
> -
> -	ctx->fimc_clk = devm_clk_get(dev, "fimc");
> -	if (IS_ERR(ctx->fimc_clk)) {
> -		dev_err(dev, "failed to get fimc clock.\n");
> -		clk_disable(ctx->sclk_fimc_clk);
> -		return PTR_ERR(ctx->fimc_clk);
> -	}
> -
> -	ctx->wb_clk = devm_clk_get(dev, "pxl_async0");
> -	if (IS_ERR(ctx->wb_clk)) {
> -		dev_err(dev, "failed to get writeback a clock.\n");
> -		clk_disable(ctx->sclk_fimc_clk);
> -		return PTR_ERR(ctx->wb_clk);
> -	}
> -
> -	ctx->wb_b_clk = devm_clk_get(dev, "pxl_async1");
> -	if (IS_ERR(ctx->wb_b_clk)) {
> -		dev_err(dev, "failed to get writeback b clock.\n");
> -		clk_disable(ctx->sclk_fimc_clk);
> -		return PTR_ERR(ctx->wb_b_clk);
> -	}
> -
> -	parent_clk = devm_clk_get(dev, ddata->parent_clk);
> -
> -	if (IS_ERR(parent_clk)) {
> -		dev_err(dev, "failed to get parent clock.\n");
> -		clk_disable(ctx->sclk_fimc_clk);
> -		return PTR_ERR(parent_clk);
> -	}
> -
> -	if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) {
> -		dev_err(dev, "failed to set parent.\n");
> -		clk_disable(ctx->sclk_fimc_clk);
> -		return -EINVAL;
> -	}
> -
> -	devm_clk_put(dev, parent_clk);
> -	clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate);
> -
>   	/* resource memory */
>   	ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   	ctx->regs = devm_ioremap_resource(dev, ctx->regs_res);
> @@ -1804,6 +1825,9 @@ static int fimc_probe(struct platform_device *pdev)
>   		return ret;
>   	}
>
> +	ret = fimc_setup_clocks(ctx);
> +	if (ret < 0)
> +		goto err_free_irq;

- please blank line and error log.

>   	/* context initailization */
>   	ctx->id = pdev->id;
>   	ctx->pol = pdata->pol;
> @@ -1820,7 +1844,7 @@ static int fimc_probe(struct platform_device *pdev)
>   	ret = fimc_init_prop_list(ippdrv);
>   	if (ret < 0) {
>   		dev_err(dev, "failed to init property list.\n");
> -		goto err_get_irq;
> +		goto err_put_clk;
>   	}
>
>   	DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
> @@ -1835,16 +1859,18 @@ static int fimc_probe(struct platform_device *pdev)
>   	ret = exynos_drm_ippdrv_register(ippdrv);
>   	if (ret < 0) {
>   		dev_err(dev, "failed to register drm fimc device.\n");
> -		goto err_ippdrv_register;
> +		goto err_pm_dis;
>   	}
>
>   	dev_info(&pdev->dev, "drm fimc registered successfully.\n");
>
>   	return 0;
>
> -err_ippdrv_register:
> +err_pm_dis:
>   	pm_runtime_disable(dev);
> -err_get_irq:
> +err_put_clk:
> +	fimc_put_clocks(ctx);
> +err_free_irq:
>   	free_irq(ctx->irq, ctx);
>
>   	return ret;
> @@ -1859,6 +1885,7 @@ static int fimc_remove(struct platform_device *pdev)
>   	exynos_drm_ippdrv_unregister(ippdrv);
>   	mutex_destroy(&ctx->lock);
>
> +	fimc_put_clocks(ctx);
>   	pm_runtime_set_suspended(dev);
>   	pm_runtime_disable(dev);
>
>

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

* Re: [PATCH v2 0/3] drm/exynos: Add device tree support for IPP driver
       [not found] ` <1366192384-18829-1-git-send-email-s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
@ 2013-04-20 16:11   ` Inki Dae
  2013-04-22 15:23     ` Sylwester Nawrocki
  0 siblings, 1 reply; 8+ messages in thread
From: Inki Dae @ 2013-04-20 16:11 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: Kyungmin Park, linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
	DRI mailing list


[-- Attachment #1.1: Type: text/plain, Size: 1950 bytes --]

Hi Sylwester,

DRM FIMC driver could be more cleaned up with this patch series. And your
third patch
And just minor issue. The second patch has build warnings like below,

WARNING: static const char * array should probably be static const char *
const
#111: FILE: drivers/gpu/drm/exynos/exynos_drm_fimc.c:89:
+static const char * fimc_clock_names[] = {

ERROR: "foo * bar" should be "foo *bar"
#111: FILE: drivers/gpu/drm/exynos/exynos_drm_fimc.c:89:


This is a minor issue so I can fix them. And as you already know, now drm
fimc driver should be more cleaned up. Your patch set looks good to me but
I'd like to take more opinions from others.

And you can find my comments at the third patch.

Thanks,
Inki Dae



2013/4/17 Sylwester Nawrocki <s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>

> Hi Inki,
>
> This small patch series adds device tree support for the DRM FIMC driver.
> The binding documentation can be found in -next at
> Documentation/devicetree/
> bindings/media/samsung-fimc.txt.
> It will make the driver dependent on OF. This patch series is needed in
> 3.10 to ensure simultaneous operation of the DRM FIMC and the camera ISP
> on Exynos4x12.
>
> Changes since v1:
>  - removed devm_kfree() that got erroneously re-added in patch 2/3 during
>    rebase.
>
> Thanks,
> Sylwester
>
> Sylwester Nawrocki (3):
>   drm/exynos: Remove redundant devm_kfree()
>   drm/exynos: Rework fimc clocks handling
>   drm/exynos: Add device tree support for fimc ipp driver
>
>  drivers/gpu/drm/exynos/Kconfig           |    2 +-
>  drivers/gpu/drm/exynos/exynos_drm_fimc.c |  264
> ++++++++++++++++--------------
>  drivers/gpu/drm/exynos/regs-fimc.h       |    7 +-
>  3 files changed, 147 insertions(+), 126 deletions(-)
>
> --
> 1.7.9.5
>
> _______________________________________________
> dri-devel mailing list
> dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>

[-- Attachment #1.2: Type: text/html, Size: 2735 bytes --]

[-- Attachment #2: Type: text/plain, Size: 192 bytes --]

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

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

* Re: [PATCH v2 2/3] drm/exynos: Rework fimc clocks handling
  2013-04-19 11:26   ` Eunchul Kim
@ 2013-04-22 15:07     ` Sylwester Nawrocki
  0 siblings, 0 replies; 8+ messages in thread
From: Sylwester Nawrocki @ 2013-04-22 15:07 UTC (permalink / raw)
  To: Eunchul Kim
  Cc: inki.dae, kyungmin.park, linux-samsung-soc, devicetree-discuss,
	dri-devel, jaejoon.seo, jmock.shin, jy0.jeon, th908.kim,
	lsmin.lee

Hi,

On 04/19/2013 01:26 PM, Eunchul Kim wrote:
>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
>> b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
>> index d812c57..bc8411a 100644
>> --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
>> @@ -76,6 +76,27 @@ enum fimc_wb {
>>       FIMC_WB_B,
>>   };
>>
>> +enum {
>> +    FIMC_CLK_LCLK,
>> +    FIMC_CLK_GATE,
>> +    FIMC_CLK_WB_A,
>> +    FIMC_CLK_WB_B,
>> +    FIMC_CLK_MUX,
>> +    FIMC_CLK_PARENT,
> 
> - What is MUX, PARENT ?
> 
>> +    FIMC_CLKS_MAX
>> +};
>> +
>> +static const char * fimc_clock_names[] = {
>> +    [FIMC_CLK_LCLK]   = "sclk_fimc",
>> +    [FIMC_CLK_GATE]   = "fimc",
>> +    [FIMC_CLK_WB_A]   = "pxl_async0",
>> +    [FIMC_CLK_WB_B]   = "pxl_async1",
>> +    [FIMC_CLK_MUX]    = "mux",
>> +    [FIMC_CLK_PARENT] = "parent",
> 
> 
> - How can I get "mux", "parent" clock information ?
>   Normally we are using "mout_mpll" in exynos4210, "mout_mpll_user" in  exynos
> 4412. I want to get this two kind of clock name information.

The issue is that this driver is driver is setting parent clock, which
really belongs to other layers, like platform code or the clocks driver.

It I think it was a bad idea in the first place to code platform clock
names in this driver. The driver should use generic clock (consumer)
names for all platforms, and association with platform clocks is created
by platform code (CLKDEV_INIT()) or the device tree binding.
So for example in your dts file you might have:

fimc_2: fimc@11820000 {
	compatible = "samsung,exynos4212-fimc";

	clocks = <&clock 258>, <&clock 130>, <&clock 386>, <&clock 17>;
	clock-names = "fimc", "sclk_fimc", "mux", "parent";
};

And the clock indexes are described in Documentation/devicetree/bindings/
clock/exynos4-clock.txt. As a side note, the plain numbers should be soon
replaced with symbolic identifiers, once there is pre-processor support
in dtc.

The additional "mux" clocks comes from the fact that struct clk_clksrc
is now represented by 2 generic clocks: a gate and a mux clock.
Probably "sclk_mux" would be more clear.

>> +#define FIMC_DEFAULT_LCLK_FREQUENCY 133000000UL
> 
> 
> - When do I use this value in the patch ?
>   If not use. please remove this macro. If you want to use this value.
>   please use platform data instead of macro.

Sorry, no good news. Since Exynos platform becomes dt-only the platform_data
is no more supposed to be used. We parse clock frequency from the device tree,
and FIMC_DEFAULT_LCLK_FREQUENCY is just a fallback value, that the driver will
use if there is no "clock-frequency" specified in device tree.

>>   /*
>>    * A structure of scaler.
>>    *
>> @@ -132,15 +153,12 @@ struct fimc_driverdata {
>>    *
>>    * @ippdrv: prepare initialization using ippdrv.
>>    * @regs_res: register resources.
>> + * @dev: pointer to the fimc device structure.
> 
> 
> - We already set the dev information in ippdrv structure.
>   I think this value is duplicated value.

OK, I've overlooked it. Will remove that.

>>    * @regs: memory mapped io registers.
>>    * @lock: locking of operations.
>> - * @sclk_fimc_clk: fimc source clock.
>> - * @fimc_clk: fimc clock.
>> - * @wb_clk: writeback a clock.
>> - * @wb_b_clk: writeback b clock.
>> + * @clocks: fimc clocks.
>> + * @clk_frequency: LCLK clock frequency.
>>    * @sc: scaler infomations.
>> - * @odr: ordering of YUV.
>> - * @ver: fimc version.
>>    * @pol: porarity of writeback.
>>    * @id: fimc id.
>>    * @irq: irq number.
>> @@ -148,13 +166,12 @@ struct fimc_driverdata {
>>    */
>>   struct fimc_context {
>>       struct exynos_drm_ippdrv    ippdrv;
>> +    struct device    *dev;
> 
> - please check this value about really need ?

Ok, I'll remove it.

>>       struct resource    *regs_res;
>>       void __iomem    *regs;
>>       struct mutex    lock;
>> -    struct clk    *sclk_fimc_clk;
>> -    struct clk    *fimc_clk;
>> -    struct clk    *wb_clk;
>> -    struct clk    *wb_b_clk;
>> +    struct clk    *clocks[FIMC_CLKS_MAX];
>> +    u32        clk_frequency;
>>       struct fimc_scaler    sc;
>>       struct fimc_driverdata    *ddata;
>>       struct exynos_drm_ipp_pol    pol;
>> @@ -1301,14 +1318,12 @@ static int fimc_clk_ctrl(struct fimc_context *ctx,
>> bool enable)
>>       DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
>>
>>       if (enable) {
>> -        clk_enable(ctx->sclk_fimc_clk);
>> -        clk_enable(ctx->fimc_clk);
>> -        clk_enable(ctx->wb_clk);
>> +        clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
>> +        clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]);
>>           ctx->suspended = false;
>>       } else {
>> -        clk_disable(ctx->sclk_fimc_clk);
>> -        clk_disable(ctx->fimc_clk);
>> -        clk_disable(ctx->wb_clk);
>> +        clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
>> +        clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]);
>>           ctx->suspended = true;
>>       }
>>
>> @@ -1713,11 +1728,66 @@ static void fimc_ippdrv_stop(struct device *dev, enum
>> drm_exynos_ipp_cmd cmd)
>>       fimc_write(cfg, EXYNOS_CIGCTRL);
>>   }
>>
>> +static void fimc_put_clocks(struct fimc_context *ctx)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < FIMC_CLKS_MAX; i++) {
>> +        if (IS_ERR(ctx->clocks[i]))
>> +            continue;
>> +        clk_put(ctx->clocks[i]);
>> +        ctx->clocks[i] = ERR_PTR(-EINVAL);
>> +    }
>> +}
>> +
>> +static int fimc_setup_clocks(struct fimc_context *ctx)
>> +{
>> +    struct device *dev;
>> +    int ret, i;
>> +
>> +    for (i = 0; i < FIMC_CLKS_MAX; i++)
>> +        ctx->clocks[i] = ERR_PTR(-EINVAL);
>> +
>> +    for (i = 0; i < FIMC_CLKS_MAX; i++) {
>> +        if (i == FIMC_CLK_WB_A || i == FIMC_CLK_WB_B)
>> +            dev = ctx->dev->parent;
>> +        else
>> +            dev = ctx->dev;
>> +
>> +        ctx->clocks[i] = clk_get(dev, fimc_clock_names[i]);
>> +        if (IS_ERR(ctx->clocks[i])) {
>> +            if (i >= FIMC_CLK_MUX)
>> +                break;
>> +            ret = PTR_ERR(ctx->clocks[i]);
>> +            goto e_clk_free;
>> +        }
>> +    }
>> +
>> +    if (!IS_ERR(ctx->clocks[FIMC_CLK_PARENT])) {
>> +        ret = clk_set_parent(ctx->clocks[FIMC_CLK_MUX],
>> +                     ctx->clocks[FIMC_CLK_PARENT]);
> 
> 
> - I can't review this code.

Since parent clock setting is optional (it shouldn't really be done here
in the driver) the parent clock is set only if FIMC_CLK_PARENT is found,
e.g. it was specified in the device tree.

I'm going to add a short comment above explaining that.

>> +        if (ret < 0) {
>> +            dev_err(ctx->dev, "failed to set parent: %d\n", ret);
>> +            return ret;
>> +        }
>> +    }
>> +
>> +    ret = clk_set_rate(ctx->clocks[FIMC_CLK_LCLK], ctx->clk_frequency);
> 
> 
> - When do I set clk_frequency value ? and why doesn't use pdata->clk_rate ?

It's parsed from device tree. I removed pdata since Exynos becomes dt-only
and there is no board in mainline that uses struct exynos_drm_fimc_pdata.

>> +    if (ret < 0)
>> +        return ret;
>> +
>> +    return clk_prepare_enable(ctx->clocks[FIMC_CLK_LCLK]);
>> +
>> +e_clk_free:
>> +    dev_err(ctx->dev, "failed to get clock: %s\n", fimc_clock_names[i]);
>> +    fimc_put_clocks(ctx);
>> +    return ret;
>> +}
>> +
>>   static int fimc_probe(struct platform_device *pdev)
>>   {
>>       struct device *dev = &pdev->dev;
>>       struct fimc_context *ctx;
>> -    struct clk    *parent_clk;
>>       struct resource *res;
>>       struct exynos_drm_ippdrv *ippdrv;
>>       struct exynos_drm_fimc_pdata *pdata;
>> @@ -1734,55 +1804,6 @@ static int fimc_probe(struct platform_device *pdev)
>>       if (!ctx)
>>           return -ENOMEM;
>>
>> -    ddata = (struct fimc_driverdata *)
>> -        platform_get_device_id(pdev)->driver_data;
>> -
>> -    /* clock control */
>> -    ctx->sclk_fimc_clk = devm_clk_get(dev, "sclk_fimc");
>> -    if (IS_ERR(ctx->sclk_fimc_clk)) {
>> -        dev_err(dev, "failed to get src fimc clock.\n");
>> -        return PTR_ERR(ctx->sclk_fimc_clk);
>> -    }
>> -    clk_enable(ctx->sclk_fimc_clk);
>> -
>> -    ctx->fimc_clk = devm_clk_get(dev, "fimc");
>> -    if (IS_ERR(ctx->fimc_clk)) {
>> -        dev_err(dev, "failed to get fimc clock.\n");
>> -        clk_disable(ctx->sclk_fimc_clk);
>> -        return PTR_ERR(ctx->fimc_clk);
>> -    }
>> -
>> -    ctx->wb_clk = devm_clk_get(dev, "pxl_async0");
>> -    if (IS_ERR(ctx->wb_clk)) {
>> -        dev_err(dev, "failed to get writeback a clock.\n");
>> -        clk_disable(ctx->sclk_fimc_clk);
>> -        return PTR_ERR(ctx->wb_clk);
>> -    }
>> -
>> -    ctx->wb_b_clk = devm_clk_get(dev, "pxl_async1");
>> -    if (IS_ERR(ctx->wb_b_clk)) {
>> -        dev_err(dev, "failed to get writeback b clock.\n");
>> -        clk_disable(ctx->sclk_fimc_clk);
>> -        return PTR_ERR(ctx->wb_b_clk);
>> -    }
>> -
>> -    parent_clk = devm_clk_get(dev, ddata->parent_clk);
>> -
>> -    if (IS_ERR(parent_clk)) {
>> -        dev_err(dev, "failed to get parent clock.\n");
>> -        clk_disable(ctx->sclk_fimc_clk);
>> -        return PTR_ERR(parent_clk);
>> -    }
>> -
>> -    if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) {
>> -        dev_err(dev, "failed to set parent.\n");
>> -        clk_disable(ctx->sclk_fimc_clk);
>> -        return -EINVAL;
>> -    }
>> -
>> -    devm_clk_put(dev, parent_clk);
>> -    clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate);
>> -
>>       /* resource memory */
>>       ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>       ctx->regs = devm_ioremap_resource(dev, ctx->regs_res);
>> @@ -1804,6 +1825,9 @@ static int fimc_probe(struct platform_device *pdev)
>>           return ret;
>>       }
>>
>> +    ret = fimc_setup_clocks(ctx);
>> +    if (ret < 0)
>> +        goto err_free_irq;
> 
> - please blank line and error log.

There is already error logging in the fimc_setup_clocks() function,
plus you get logs from the driver core. So I don't think there is
need for any more. In general I find this driver overly stuffed with
error logs. If you feel it is necessary to add more logs, please
write a patch for it.

>>       /* context initailization */
>>       ctx->id = pdev->id;
>>       ctx->pol = pdata->pol;
>> @@ -1820,7 +1844,7 @@ static int fimc_probe(struct platform_device *pdev)
>>       ret = fimc_init_prop_list(ippdrv);
>>       if (ret < 0) {
>>           dev_err(dev, "failed to init property list.\n");
>> -        goto err_get_irq;
>> +        goto err_put_clk;
>>       }
>>
>>       DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
>> @@ -1835,16 +1859,18 @@ static int fimc_probe(struct platform_device *pdev)
>>       ret = exynos_drm_ippdrv_register(ippdrv);
>>       if (ret < 0) {
>>           dev_err(dev, "failed to register drm fimc device.\n");
>> -        goto err_ippdrv_register;
>> +        goto err_pm_dis;
>>       }
>>
>>       dev_info(&pdev->dev, "drm fimc registered successfully.\n");
>>
>>       return 0;
>>
>> -err_ippdrv_register:
>> +err_pm_dis:
>>       pm_runtime_disable(dev);
>> -err_get_irq:
>> +err_put_clk:
>> +    fimc_put_clocks(ctx);
>> +err_free_irq:
>>       free_irq(ctx->irq, ctx);
>>
>>       return ret;
>> @@ -1859,6 +1885,7 @@ static int fimc_remove(struct platform_device *pdev)
>>       exynos_drm_ippdrv_unregister(ippdrv);
>>       mutex_destroy(&ctx->lock);
>>
>> +    fimc_put_clocks(ctx);
>>       pm_runtime_set_suspended(dev);
>>       pm_runtime_disable(dev);

Thanks,
Sylwester

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

* Re: [PATCH v2 0/3] drm/exynos: Add device tree support for IPP driver
  2013-04-20 16:11   ` [PATCH v2 0/3] drm/exynos: Add device tree support for IPP driver Inki Dae
@ 2013-04-22 15:23     ` Sylwester Nawrocki
  0 siblings, 0 replies; 8+ messages in thread
From: Sylwester Nawrocki @ 2013-04-22 15:23 UTC (permalink / raw)
  To: Inki Dae
  Cc: Kyungmin Park, linux-samsung-soc,
	devicetree-discuss@lists.ozlabs.org, DRI mailing list

Hi Inki,

On 04/20/2013 06:11 PM, Inki Dae wrote:
> Hi Sylwester,
> 
> DRM FIMC driver could be more cleaned up with this patch series. And your third
> patch
> And just minor issue. The second patch has build warnings like below,
> 
> WARNING: static const char * array should probably be static const char * const
> #111: FILE: drivers/gpu/drm/exynos/exynos_drm_fimc.c:89:
> +static const char * fimc_clock_names[] = {
> 
> ERROR: "foo * bar" should be "foo *bar"
> #111: FILE: drivers/gpu/drm/exynos/exynos_drm_fimc.c:89:

Oops, sorry. I'll fix those for v3.

> This is a minor issue so I can fix them. And as you already know, now drm fimc
> driver should be more cleaned up. Your patch set looks good to me but I'd like
> to take more opinions from others.

Thanks,
Sylwester

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

end of thread, other threads:[~2013-04-22 15:23 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-17  9:53 [PATCH v2 0/3] drm/exynos: Add device tree support for IPP driver Sylwester Nawrocki
2013-04-17  9:53 ` [PATCH v2 1/3] drm/exynos: Remove redundant devm_kfree() Sylwester Nawrocki
2013-04-17  9:53 ` [PATCH v2 2/3] drm/exynos: Rework fimc clocks handling Sylwester Nawrocki
2013-04-19 11:26   ` Eunchul Kim
2013-04-22 15:07     ` Sylwester Nawrocki
2013-04-17  9:53 ` [PATCH v2 3/3] drm/exynos: Add device tree support for fimc ipp driver Sylwester Nawrocki
     [not found] ` <1366192384-18829-1-git-send-email-s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-04-20 16:11   ` [PATCH v2 0/3] drm/exynos: Add device tree support for IPP driver Inki Dae
2013-04-22 15:23     ` Sylwester Nawrocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).