[PATCH] video: mmp: add device tree support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



add device tree support for mmp fb/controller
the description at Documentation/devicetree/bindings/fb/mmp-disp.txt

Signed-off-by: Zhou Zhu <zzhu3@xxxxxxxxxxx>
---
 Documentation/devicetree/bindings/fb/mmp-disp.txt |   71 ++++++++++++
 drivers/video/mmp/fb/mmpfb.c                      |   71 ++++++++----
 drivers/video/mmp/hw/mmp_ctrl.c                   |  120 ++++++++++++++++-----
 3 files changed, 217 insertions(+), 45 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/fb/mmp-disp.txt

diff --git a/Documentation/devicetree/bindings/fb/mmp-disp.txt b/Documentation/devicetree/bindings/fb/mmp-disp.txt
new file mode 100644
index 0000000..3cf2903
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/mmp-disp.txt
@@ -0,0 +1,71 @@
+* Marvell MMP Display (MMP_DISP)
+
+To config mmp display, 3 parts are required to be set in dts:
+1. mmp fb
+Required properties:
+- compatible: Should be "marvell,mmp-fb".
+- marvell,fb-name: Should be the name of this fb.
+- marvell,path-name: Should be the name of path this fb connecting to.
+- marvell,overlay-id: Should be the id of overlay this fb is on.
+- marvell,dmafetch-id: Should be the dma fetch id this fb using.
+- marvell,default-pixfmt: Should be the default pixel format when this fb is
+turned on.
+
+2. mmp controller
+Required properties:
+- compatible: Should be "marvell,mmp-disp".
+- reg: Should be address and length of the register set for this controller.
+- interrupts: Should be interrupt of this controller.
+- marvell,disp-name: Should be name of this controller
+- marvell,path-num: Should be path number exists in this controller.
+- marvell,clk-name: Should be name of clock this controller using.
+
+Required sub-node:
+- path:
+Required properties in this sub-node:
+-- marvell,path-name: Should be name of this path, fb/panel uses this name to
+connect to this path.
+-- marvell,overlay_num: Should be number of overlay this path has.
+-- marvell,output-type: Should be output-type settings
+-- marvell,path-config: Should be path-config settings
+-- marvell,link-config: Should be link-config settings
+-- marvell,rbswap: Should be rbswap settings
+
+3. panel
+Required properties:
+- marvell,path-name: Should be path name that this panel connected to.
+- other properties each panel has.
+
+Examples:
+
+fb: fb {
+	compatible = "marvell,mmp-fb";
+	marvell,fb-name = "mmp_fb";
+	marvell,path-name = "mmp_pnpath";
+	marvell,overlay-id = <0>;
+	marvell,dmafetch-id = <1>;
+	marvell,default-pixfmt = <0x108>;
+};
+
+disp: disp@d420b000 {
+	compatible = "marvell,mmp-disp";
+	reg = <0xd420b000 0x1fc>;
+	interrupts = <0 41 0x4>;
+	marvell,disp-name = "mmp_disp";
+	marvell,path-num = <1>;
+	marvell,clk-name = "LCDCIHCLK";
+	path1 {
+		marvell,path-name = "mmp_pnpath";
+		marvell,overlay-num = <2>;
+		marvell,output-type = <0>;
+		marvell,path-config = <0x20000000>;
+		marvell,link-config = <0x60000001>;
+		marvell,rbswap = <0>;
+	};
+};
+
+panel: <panel-name> {
+	...
+	marvell,path-name = "mmp_pnpath";
+	...
+};
diff --git a/drivers/video/mmp/fb/mmpfb.c b/drivers/video/mmp/fb/mmpfb.c
index 7ab31eb..e84a411 100644
--- a/drivers/video/mmp/fb/mmpfb.c
+++ b/drivers/video/mmp/fb/mmpfb.c
@@ -22,6 +22,8 @@
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include "mmpfb.h"
 
 static int var_to_pixfmt(struct fb_var_screeninfo *var)
@@ -551,56 +553,86 @@ static void fb_info_clear(struct fb_info *info)
 	fb_dealloc_cmap(&info->cmap);
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id mmp_fb_dt_match[] = {
+	{ .compatible = "marvell,mmp-fb" },
+	{},
+};
+#endif
+
 static int mmpfb_probe(struct platform_device *pdev)
 {
+#ifdef CONFIG_OF
+	struct device_node *np;
+#else
 	struct mmp_buffer_driver_mach_info *mi;
+#endif
 	struct fb_info *info = 0;
 	struct mmpfb_info *fbi = 0;
-	int ret, modes_num;
-
-	mi = pdev->dev.platform_data;
-	if (mi == NULL) {
-		dev_err(&pdev->dev, "no platform data defined\n");
-		return -EINVAL;
-	}
+	int ret = -EINVAL, modes_num;
+	int overlay_id, dmafetch_id;
+	const char *path_name;
 
 	/* initialize fb */
 	info = framebuffer_alloc(sizeof(struct mmpfb_info), &pdev->dev);
 	if (info == NULL)
 		return -ENOMEM;
 	fbi = info->par;
-	if (!fbi) {
-		ret = -EINVAL;
+	if (!fbi)
+		goto failed;
+
+#ifdef CONFIG_OF
+	np = pdev->dev.of_node;
+
+	if (!np || of_property_read_string(np,
+				"marvell,fb-name", &fbi->name) ||
+			of_property_read_string(np,
+				"marvell,path-name", &path_name) ||
+			of_property_read_u32(np,
+				"marvell,overlay-id", &overlay_id) ||
+			of_property_read_u32(np,
+				"marvell,dmafetch-id", &dmafetch_id) ||
+			of_property_read_u32(np,
+				"marvell,default-pixfmt", &fbi->pix_fmt)) {
+		dev_err(&pdev->dev, "unable to get fb setting from dt\n");
 		goto failed;
 	}
+#else
+	mi = pdev->dev.platform_data;
+	if (mi == NULL) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		goto failed;
+	}
+	fbi->name = mi->name;
+	path_name = mi->path_name;
+	overlay_id = mi->overlay_id;
+	dmafetch_id = mi->dmafetch_id;
+	fbi->pix_fmt = mi->default_pixfmt;
+#endif
 
 	/* init fb */
 	fbi->fb_info = info;
 	platform_set_drvdata(pdev, fbi);
 	fbi->dev = &pdev->dev;
-	fbi->name = mi->name;
-	fbi->pix_fmt = mi->default_pixfmt;
 	pixfmt_to_var(&info->var, fbi->pix_fmt);
 	mutex_init(&fbi->access_ok);
 
 	/* get display path by name */
-	fbi->path = mmp_get_path(mi->path_name);
+	fbi->path = mmp_get_path(path_name);
 	if (!fbi->path) {
-		dev_err(&pdev->dev, "can't get the path %s\n", mi->path_name);
-		ret = -EINVAL;
+		dev_err(&pdev->dev, "can't get the path %s\n", path_name);
 		goto failed_destroy_mutex;
 	}
 
 	dev_info(fbi->dev, "path %s get\n", fbi->path->name);
 
 	/* get overlay */
-	fbi->overlay = mmp_path_get_overlay(fbi->path, mi->overlay_id);
-	if (!fbi->overlay) {
-		ret = -EINVAL;
+	fbi->overlay = mmp_path_get_overlay(fbi->path, overlay_id);
+	if (!fbi->overlay)
 		goto failed_destroy_mutex;
-	}
+
 	/* set fetch used */
-	mmp_overlay_set_fetch(fbi->overlay, mi->dmafetch_id);
+	mmp_overlay_set_fetch(fbi->overlay, dmafetch_id);
 
 	modes_num = modes_setup(fbi);
 	if (modes_num < 0) {
@@ -679,6 +711,7 @@ static struct platform_driver mmpfb_driver = {
 	.driver		= {
 		.name	= "mmp-fb",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(mmp_fb_dt_match),
 	},
 	.probe		= mmpfb_probe,
 };
diff --git a/drivers/video/mmp/hw/mmp_ctrl.c b/drivers/video/mmp/hw/mmp_ctrl.c
index 8621a9f..19d68bc 100644
--- a/drivers/video/mmp/hw/mmp_ctrl.c
+++ b/drivers/video/mmp/hw/mmp_ctrl.c
@@ -37,6 +37,8 @@
 #include <linux/uaccess.h>
 #include <linux/kthread.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include "mmp_ctrl.h"
 
@@ -396,26 +398,57 @@ static void path_set_default(struct mmp_path *path)
 	writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id));
 }
 
-static int path_init(struct mmphw_path_plat *path_plat,
-		struct mmp_mach_path_config *config)
+static int path_init(struct mmphw_path_plat *path_plat, void *arg)
 {
 	struct mmphw_ctrl *ctrl = path_plat->ctrl;
 	struct mmp_path_info *path_info;
 	struct mmp_path *path = NULL;
-
-	dev_info(ctrl->dev, "%s: %s\n", __func__, config->name);
+#ifdef CONFIG_OF
+	struct device_node *path_np = arg;
+#else
+	struct mmp_mach_path_config *config = arg;
+#endif
 
 	/* init driver data */
 	path_info = kzalloc(sizeof(struct mmp_path_info), GFP_KERNEL);
 	if (!path_info) {
-		dev_err(ctrl->dev, "%s: unable to alloc path_info for %s\n",
-				__func__, config->name);
-		return 0;
+		dev_err(ctrl->dev, "%s: unable to alloc path_info\n",
+				__func__);
+		return -ENOMEM;
+	}
+
+#ifdef CONFIG_OF
+	if (!path_np || of_property_read_string(path_np, "marvell,path-name",
+				&path_info->name) ||
+			of_property_read_u32(path_np, "marvell,overlay-num",
+				&path_info->output_type) ||
+			of_property_read_u32(path_np, "marvell,output-type",
+				&path_info->overlay_num)) {
+		dev_err(ctrl->dev, "%s: unable to get path setting from dt\n",
+			__func__);
+		kfree(path_info);
+		return -EINVAL;
 	}
+	/* allow these settings not set */
+	of_property_read_u32(path_np, "marvell,path-config",
+		&path_plat->path_config);
+	of_property_read_u32(path_np, "marvell,link-config",
+		&path_plat->link_config);
+	of_property_read_u32(path_np, "marvell,rbswap",
+		&path_plat->dsi_rbswap);
+#else
 	path_info->name = config->name;
+	path_info->overlay_num = config->overlay_num;
+	path_info->output_type = config->output_type;
+	path_plat->path_config = config->path_config;
+	path_plat->link_config = config->link_config;
+	path_plat->dsi_rbswap = config->dsi_rbswap;
+#endif
+
+	dev_info(ctrl->dev, "%s: %s\n", __func__, path_info->name);
+
 	path_info->id = path_plat->id;
 	path_info->dev = ctrl->dev;
-	path_info->overlay_num = config->overlay_num;
 	path_info->overlay_ops = &mmphw_overlay_ops;
 	path_info->set_mode = path_set_mode;
 	path_info->plat_data = path_plat;
@@ -424,16 +457,13 @@ static int path_init(struct mmphw_path_plat *path_plat,
 	path = mmp_register_path(path_info);
 	if (!path) {
 		kfree(path_info);
-		return 0;
+		return -EINVAL;
 	}
 	path_plat->path = path;
-	path_plat->path_config = config->path_config;
-	path_plat->link_config = config->link_config;
-	path_plat->dsi_rbswap = config->dsi_rbswap;
 	path_set_default(path);
 
 	kfree(path_info);
-	return 1;
+	return 0;
 }
 
 static void path_deinit(struct mmphw_path_plat *path_plat)
@@ -445,13 +475,25 @@ static void path_deinit(struct mmphw_path_plat *path_plat)
 		mmp_unregister_path(path_plat->path);
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id mmp_disp_dt_match[] = {
+	{ .compatible = "marvell,mmp-disp" },
+	{},
+};
+#endif
+
 static int mmphw_probe(struct platform_device *pdev)
 {
-	struct mmp_mach_plat_info *mi;
 	struct resource *res;
-	int ret, i, size, irq;
+	int ret, i, size, irq, path_num;
+	const char *clk_name, *disp_name;
 	struct mmphw_path_plat *path_plat;
 	struct mmphw_ctrl *ctrl = NULL;
+#ifdef CONFIG_OF
+	struct device_node *np, *path_np = NULL;
+#else
+	struct mmp_mach_plat_info *mi;
+#endif
 
 	/* get resources from platform data */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -468,6 +510,22 @@ static int mmphw_probe(struct platform_device *pdev)
 		goto failed;
 	}
 
+#ifdef CONFIG_OF
+	np = pdev->dev.of_node;
+
+	if (!np || of_property_read_u32(np,
+				"marvell,path-num", &path_num) ||
+			of_property_read_string(np,
+				"marvell,disp-name", &disp_name) ||
+			of_property_read_string(np,
+				"marvell,clk-name", &clk_name) ||
+			of_get_child_count(np) != ctrl->path_num) {
+		dev_err(&pdev->dev, "%s: failed to get settings from dt\n",
+			__func__);
+		ret = -EINVAL;
+		goto failed;
+	}
+#else
 	/* get configs from platform data */
 	mi = pdev->dev.platform_data;
 	if (mi == NULL || !mi->path_num || !mi->paths) {
@@ -476,17 +534,21 @@ static int mmphw_probe(struct platform_device *pdev)
 		goto failed;
 	}
 
-	/* allocate */
+	disp_name = mi->name;
+	path_num = mi->path_num;
+	clk_name = mi->clk_name;
+#endif
+
+	/* allocate ctrl */
 	size = sizeof(struct mmphw_ctrl) + sizeof(struct mmphw_path_plat) *
-	       mi->path_num;
+	       path_num;
 	ctrl = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	if (!ctrl) {
 		ret = -ENOMEM;
 		goto failed;
 	}
-
-	ctrl->name = mi->name;
-	ctrl->path_num = mi->path_num;
+	ctrl->path_num = path_num;
+	ctrl->name = disp_name;
 	ctrl->dev = &pdev->dev;
 	ctrl->irq = irq;
 	platform_set_drvdata(pdev, ctrl);
@@ -521,9 +583,9 @@ static int mmphw_probe(struct platform_device *pdev)
 	}
 
 	/* get clock */
-	ctrl->clk = devm_clk_get(ctrl->dev, mi->clk_name);
+	ctrl->clk = devm_clk_get(ctrl->dev, clk_name);
 	if (IS_ERR(ctrl->clk)) {
-		dev_err(ctrl->dev, "unable to get clk %s\n", mi->clk_name);
+		dev_err(ctrl->dev, "unable to get clk %s\n", clk_name);
 		ret = -ENOENT;
 		goto failed;
 	}
@@ -539,11 +601,16 @@ static int mmphw_probe(struct platform_device *pdev)
 		path_plat->id = i;
 		path_plat->ctrl = ctrl;
 
-		/* path init */
-		if (!path_init(path_plat, &mi->paths[i])) {
-			ret = -EINVAL;
+		/* path init from mach info or dt */
+#ifdef CONFIG_OF
+		path_np = of_get_next_child(np, path_np);
+		ret = path_init(path_plat, path_np);
+#else
+		ret = path_init(path_plat, &mi->paths[i]);
+#endif
+
+		if (ret)
 			goto failed_path_init;
-		}
 	}
 
 #ifdef CONFIG_MMP_DISP_SPI
@@ -573,6 +640,7 @@ static struct platform_driver mmphw_driver = {
 	.driver		= {
 		.name	= "mmp-disp",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(mmp_disp_dt_match),
 	},
 	.probe		= mmphw_probe,
 };
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Tourism]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux