OMAPDSS: Add DT support to DSS
authorTomi Valkeinen <tomi.valkeinen@ti.com>
Mon, 16 Dec 2013 13:13:24 +0000 (15:13 +0200)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Wed, 19 Mar 2014 09:03:07 +0000 (11:03 +0200)
Add DT support for DSS. Contrary to the non-DT version, the DSS in DT
mode contains DPI and SDI outputs, which better reflects the hardware.
The non-DT code will be removed after all boards have been converted to
DT, so there's no need to change the non-DT code to act the same way.

The code for DPI and SDI needs to be refined later to make it possible
to add multiple DPI ports. For now, handling just a single DPI port is
enough for all the boards.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Reviewed-by: Archit Taneja <archit@ti.com>
drivers/video/omap2/dss/dpi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/dss.h
drivers/video/omap2/dss/sdi.c

index 23ef21ffc2c4998eee877e956f95c4b6d3166082..f02520ff6e32c6821d0f31d4c565727ff1bc9110 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/string.h>
+#include <linux/of.h>
 
 #include <video/omapdss.h>
 
@@ -49,6 +50,8 @@ static struct {
        int data_lines;
 
        struct omap_dss_device output;
+
+       bool port_initialized;
 } dpi;
 
 static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
@@ -726,3 +729,47 @@ void __exit dpi_uninit_platform_driver(void)
 {
        platform_driver_unregister(&omap_dpi_driver);
 }
+
+int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
+{
+       struct device_node *ep;
+       u32 datalines;
+       int r;
+
+       ep = omapdss_of_get_next_endpoint(port, NULL);
+       if (!ep)
+               return 0;
+
+       r = of_property_read_u32(ep, "data-lines", &datalines);
+       if (r) {
+               DSSERR("failed to parse datalines\n");
+               goto err_datalines;
+       }
+
+       dpi.data_lines = datalines;
+
+       of_node_put(ep);
+
+       dpi.pdev = pdev;
+
+       mutex_init(&dpi.lock);
+
+       dpi_init_output(pdev);
+
+       dpi.port_initialized = true;
+
+       return 0;
+
+err_datalines:
+       of_node_put(ep);
+
+       return r;
+}
+
+void __exit dpi_uninit_port(void)
+{
+       if (!dpi.port_initialized)
+               return;
+
+       dpi_uninit_output(dpi.pdev);
+}
index 9a145da35ad3a20402dd10fb6202e27f61e44cac..1b1c02dfdcf9b0c73b409df708bd0a4a10150a2d 100644 (file)
@@ -23,6 +23,7 @@
 #define DSS_SUBSYS_NAME "DSS"
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/io.h>
 #include <linux/export.h>
 #include <linux/err.h>
@@ -33,6 +34,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/gfp.h>
 #include <linux/sizes.h>
+#include <linux/of.h>
 
 #include <video/omapdss.h>
 
@@ -788,6 +790,56 @@ static int __init dss_init_features(struct platform_device *pdev)
        return 0;
 }
 
+static int dss_init_ports(struct platform_device *pdev)
+{
+       struct device_node *parent = pdev->dev.of_node;
+       struct device_node *port;
+       int r;
+
+       if (parent == NULL)
+               return 0;
+
+       port = omapdss_of_get_next_port(parent, NULL);
+       if (!port) {
+#ifdef CONFIG_OMAP2_DSS_DPI
+               dpi_init_port(pdev, parent);
+#endif
+               return 0;
+       }
+
+       do {
+               u32 reg;
+
+               r = of_property_read_u32(port, "reg", &reg);
+               if (r)
+                       reg = 0;
+
+#ifdef CONFIG_OMAP2_DSS_DPI
+               if (reg == 0)
+                       dpi_init_port(pdev, port);
+#endif
+
+#ifdef CONFIG_OMAP2_DSS_SDI
+               if (reg == 1)
+                       sdi_init_port(pdev, port);
+#endif
+
+       } while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
+
+       return 0;
+}
+
+static void dss_uninit_ports(void)
+{
+#ifdef CONFIG_OMAP2_DSS_DPI
+       dpi_uninit_port();
+#endif
+
+#ifdef CONFIG_OMAP2_DSS_SDI
+       sdi_uninit_port();
+#endif
+}
+
 /* DSS HW IP initialisation */
 static int __init omap_dsshw_probe(struct platform_device *pdev)
 {
@@ -846,6 +898,8 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
        dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
        dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
 
+       dss_init_ports(pdev);
+
        rev = dss_read_reg(DSS_REVISION);
        printk(KERN_INFO "OMAP DSS rev %d.%d\n",
                        FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
@@ -865,6 +919,8 @@ err_setup_clocks:
 
 static int __exit omap_dsshw_remove(struct platform_device *pdev)
 {
+       dss_uninit_ports();
+
        pm_runtime_disable(&pdev->dev);
 
        dss_put_clocks();
@@ -902,12 +958,22 @@ static const struct dev_pm_ops dss_pm_ops = {
        .runtime_resume = dss_runtime_resume,
 };
 
+static const struct of_device_id dss_of_match[] = {
+       { .compatible = "ti,omap2-dss", },
+       { .compatible = "ti,omap3-dss", },
+       { .compatible = "ti,omap4-dss", },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, dss_of_match);
+
 static struct platform_driver omap_dsshw_driver = {
        .remove         = __exit_p(omap_dsshw_remove),
        .driver         = {
                .name   = "omapdss_dss",
                .owner  = THIS_MODULE,
                .pm     = &dss_pm_ops,
+               .of_match_table = dss_of_match,
        },
 };
 
index 057f24c8a3325b1ebc0e8b97f1f9dcca32c900a6..8ece4f531006038b2b85a1d15a8e15f501ea89a7 100644 (file)
@@ -252,6 +252,9 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min,
 int sdi_init_platform_driver(void) __init;
 void sdi_uninit_platform_driver(void) __exit;
 
+int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init;
+void sdi_uninit_port(void) __exit;
+
 /* DSI */
 
 typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
@@ -363,6 +366,9 @@ static inline bool dsi_pll_calc(struct platform_device *dsidev,
 int dpi_init_platform_driver(void) __init;
 void dpi_uninit_platform_driver(void) __exit;
 
+int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init;
+void dpi_uninit_port(void) __exit;
+
 /* DISPC */
 int dispc_init_platform_driver(void) __init;
 void dispc_uninit_platform_driver(void) __exit;
index ba806c9e7f5486ffa40c1e6ba6e38e4dcc993ed7..d16277ca22a831102aea790bcb8edccae470eff3 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/string.h>
+#include <linux/of.h>
 
 #include <video/omapdss.h>
 #include "dss.h"
@@ -41,6 +42,8 @@ static struct {
        int datapairs;
 
        struct omap_dss_device output;
+
+       bool port_initialized;
 } sdi;
 
 struct sdi_clk_calc_ctx {
@@ -387,3 +390,45 @@ void __exit sdi_uninit_platform_driver(void)
 {
        platform_driver_unregister(&omap_sdi_driver);
 }
+
+int __init sdi_init_port(struct platform_device *pdev, struct device_node *port)
+{
+       struct device_node *ep;
+       u32 datapairs;
+       int r;
+
+       ep = omapdss_of_get_next_endpoint(port, NULL);
+       if (!ep)
+               return 0;
+
+       r = of_property_read_u32(ep, "datapairs", &datapairs);
+       if (r) {
+               DSSERR("failed to parse datapairs\n");
+               goto err_datapairs;
+       }
+
+       sdi.datapairs = datapairs;
+
+       of_node_put(ep);
+
+       sdi.pdev = pdev;
+
+       sdi_init_output(pdev);
+
+       sdi.port_initialized = true;
+
+       return 0;
+
+err_datapairs:
+       of_node_put(ep);
+
+       return r;
+}
+
+void __exit sdi_uninit_port(void)
+{
+       if (!sdi.port_initialized)
+               return;
+
+       sdi_uninit_output(sdi.pdev);
+}