drm: exynos: hdmi: add support for exynos5 hdmi
authorRahul Sharma <rahul.sharma@samsung.com>
Thu, 4 Oct 2012 15:18:55 +0000 (20:48 +0530)
committerInki Dae <inki.dae@samsung.com>
Fri, 5 Oct 2012 10:15:14 +0000 (19:15 +0900)
This patch adds support for exynos5 hdmi with device tree enabled.

Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
drivers/gpu/drm/exynos/exynos_hdmi.c

index 89e798b..5caf49f 100644 (file)
@@ -32,6 +32,9 @@
 #include <linux/pm_runtime.h>
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
+#include <linux/io.h>
+#include <linux/of_gpio.h>
+#include <plat/gpio-cfg.h>
 
 #include <drm/exynos_drm.h>
 
@@ -2250,6 +2253,41 @@ void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
                hdmi_hdmiphy = hdmiphy;
 }
 
+#ifdef CONFIG_OF
+static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
+                                       (struct device *dev)
+{
+       struct device_node *np = dev->of_node;
+       struct s5p_hdmi_platform_data *pd;
+       enum of_gpio_flags flags;
+       u32 value;
+
+       pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+       if (!pd) {
+               DRM_ERROR("memory allocation for pdata failed\n");
+               goto err_data;
+       }
+
+       if (!of_find_property(np, "hpd-gpio", &value)) {
+               DRM_ERROR("no hpd gpio property found\n");
+               goto err_data;
+       }
+
+       pd->hpd_gpio = of_get_named_gpio_flags(np, "hpd-gpio", 0, &flags);
+
+       return pd;
+
+err_data:
+       return NULL;
+}
+#else
+static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
+                                       (struct device *dev)
+{
+       return NULL;
+}
+#endif
+
 static struct platform_device_id hdmi_driver_types[] = {
        {
                .name           = "s5pv210-hdmi",
@@ -2259,7 +2297,19 @@ static struct platform_device_id hdmi_driver_types[] = {
                .driver_data    = HDMI_TYPE13,
        }, {
                .name           = "exynos4-hdmi14",
-               .driver_data    = HDMI_TYPE14,
+               .driver_data    = HDMI_TYPE14,
+       }, {
+               .name           = "exynos5-hdmi",
+               .driver_data    = HDMI_TYPE14,
+       }, {
+               /* end node */
+       }
+};
+
+static struct of_device_id hdmi_match_types[] = {
+       {
+               .compatible = "samsung,exynos5-hdmi",
+               .data   = (void *)HDMI_TYPE14,
        }, {
                /* end node */
        }
@@ -2276,7 +2326,16 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
 
        DRM_DEBUG_KMS("[%d]\n", __LINE__);
 
-       pdata = pdev->dev.platform_data;
+       if (pdev->dev.of_node) {
+               pdata = drm_hdmi_dt_parse_pdata(dev);
+               if (IS_ERR(pdata)) {
+                       DRM_ERROR("failed to parse dt\n");
+                       return PTR_ERR(pdata);
+               }
+       } else {
+               pdata = pdev->dev.platform_data;
+       }
+
        if (!pdata) {
                DRM_ERROR("no platform data specified\n");
                return -EINVAL;
@@ -2303,18 +2362,33 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, drm_hdmi_ctx);
 
-       hdata->type = (enum hdmi_type)platform_get_device_id
+       if (dev->of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(of_match_ptr(hdmi_match_types),
+                                       pdev->dev.of_node);
+               hdata->type = (enum hdmi_type)match->data;
+       } else {
+               hdata->type = (enum hdmi_type)platform_get_device_id
                                        (pdev)->driver_data;
+       }
+
        hdata->hpd_gpio = pdata->hpd_gpio;
        hdata->dev = dev;
 
        ret = hdmi_resources_init(hdata);
+
        if (ret) {
                ret = -EINVAL;
+               DRM_ERROR("hdmi_resources_init failed\n");
                goto err_data;
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               DRM_ERROR("failed to find registers\n");
+               ret = -ENOENT;
+               goto err_resource;
+       }
 
        hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
        if (!hdata->regs) {
@@ -2462,8 +2536,9 @@ struct platform_driver hdmi_driver = {
        .remove         = __devexit_p(hdmi_remove),
        .id_table = hdmi_driver_types,
        .driver         = {
-               .name   = "exynos4-hdmi",
+               .name   = "exynos-hdmi",
                .owner  = THIS_MODULE,
                .pm     = &hdmi_pm_ops,
+               .of_match_table = hdmi_match_types,
        },
 };