aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAjay Kumar <ajaykumar.rs@samsung.com>2012-10-12 16:48:00 -0400
committerJingoo Han <jg1.han@samsung.com>2012-11-28 20:33:26 -0500
commitc4e235c2addfaef034e428dda309136ec809a96c (patch)
tree5eba5e1ca3a2daecb964fc91d9edeb5b4fdc5e89
parentf4a75d2eb7b1e2206094b901be09adb31ba63681 (diff)
video: exynos_dp: Add device tree support to DP driver
This patch enables device tree based discovery support for DP driver. The driver is modified to handle platform data in both the cases: with DT and non-DT. Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com> Signed-off-by: Jingoo Han <jg1.han@samsung.com>
-rw-r--r--drivers/video/exynos/exynos_dp_core.c216
-rw-r--r--drivers/video/exynos/exynos_dp_core.h2
2 files changed, 198 insertions, 20 deletions
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index d55470e75412..9a9ecc16269a 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -18,6 +18,7 @@
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/of.h>
21 22
22#include <video/exynos_dp.h> 23#include <video/exynos_dp.h>
23 24
@@ -856,6 +857,145 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
856 return IRQ_HANDLED; 857 return IRQ_HANDLED;
857} 858}
858 859
860#ifdef CONFIG_OF
861static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
862{
863 struct device_node *dp_node = dev->of_node;
864 struct exynos_dp_platdata *pd;
865 struct video_info *dp_video_config;
866
867 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
868 if (!pd) {
869 dev_err(dev, "memory allocation for pdata failed\n");
870 return ERR_PTR(-ENOMEM);
871 }
872 dp_video_config = devm_kzalloc(dev,
873 sizeof(*dp_video_config), GFP_KERNEL);
874
875 if (!dp_video_config) {
876 dev_err(dev, "memory allocation for video config failed\n");
877 return ERR_PTR(-ENOMEM);
878 }
879 pd->video_info = dp_video_config;
880
881 dp_video_config->h_sync_polarity =
882 of_property_read_bool(dp_node, "hsync-active-high");
883
884 dp_video_config->v_sync_polarity =
885 of_property_read_bool(dp_node, "vsync-active-high");
886
887 dp_video_config->interlaced =
888 of_property_read_bool(dp_node, "interlaced");
889
890 if (of_property_read_u32(dp_node, "samsung,color-space",
891 &dp_video_config->color_space)) {
892 dev_err(dev, "failed to get color-space\n");
893 return ERR_PTR(-EINVAL);
894 }
895
896 if (of_property_read_u32(dp_node, "samsung,dynamic-range",
897 &dp_video_config->dynamic_range)) {
898 dev_err(dev, "failed to get dynamic-range\n");
899 return ERR_PTR(-EINVAL);
900 }
901
902 if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
903 &dp_video_config->ycbcr_coeff)) {
904 dev_err(dev, "failed to get ycbcr-coeff\n");
905 return ERR_PTR(-EINVAL);
906 }
907
908 if (of_property_read_u32(dp_node, "samsung,color-depth",
909 &dp_video_config->color_depth)) {
910 dev_err(dev, "failed to get color-depth\n");
911 return ERR_PTR(-EINVAL);
912 }
913
914 if (of_property_read_u32(dp_node, "samsung,link-rate",
915 &dp_video_config->link_rate)) {
916 dev_err(dev, "failed to get link-rate\n");
917 return ERR_PTR(-EINVAL);
918 }
919
920 if (of_property_read_u32(dp_node, "samsung,lane-count",
921 &dp_video_config->lane_count)) {
922 dev_err(dev, "failed to get lane-count\n");
923 return ERR_PTR(-EINVAL);
924 }
925
926 return pd;
927}
928
929static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
930{
931 struct device_node *dp_phy_node;
932 u32 phy_base;
933
934 dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy");
935 if (!dp_phy_node) {
936 dev_err(dp->dev, "could not find dptx-phy node\n");
937 return -ENODEV;
938 }
939
940 if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
941 dev_err(dp->dev, "faild to get reg for dptx-phy\n");
942 return -EINVAL;
943 }
944
945 if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
946 &dp->enable_mask)) {
947 dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n");
948 return -EINVAL;
949 }
950
951 dp->phy_addr = ioremap(phy_base, SZ_4);
952 if (!dp->phy_addr) {
953 dev_err(dp->dev, "failed to ioremap dp-phy\n");
954 return -ENOMEM;
955 }
956
957 return 0;
958}
959
960static void exynos_dp_phy_init(struct exynos_dp_device *dp)
961{
962 u32 reg;
963
964 reg = __raw_readl(dp->phy_addr);
965 reg |= dp->enable_mask;
966 __raw_writel(reg, dp->phy_addr);
967}
968
969static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
970{
971 u32 reg;
972
973 reg = __raw_readl(dp->phy_addr);
974 reg &= ~(dp->enable_mask);
975 __raw_writel(reg, dp->phy_addr);
976}
977#else
978static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
979{
980 return NULL;
981}
982
983static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
984{
985 return -EINVAL;
986}
987
988static void exynos_dp_phy_init(struct exynos_dp_device *dp)
989{
990 return;
991}
992
993static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
994{
995 return;
996}
997#endif /* CONFIG_OF */
998
859static int __devinit exynos_dp_probe(struct platform_device *pdev) 999static int __devinit exynos_dp_probe(struct platform_device *pdev)
860{ 1000{
861 struct resource *res; 1001 struct resource *res;
@@ -864,12 +1004,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
864 1004
865 int ret = 0; 1005 int ret = 0;
866 1006
867 pdata = pdev->dev.platform_data;
868 if (!pdata) {
869 dev_err(&pdev->dev, "no platform data\n");
870 return -EINVAL;
871 }
872
873 dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), 1007 dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
874 GFP_KERNEL); 1008 GFP_KERNEL);
875 if (!dp) { 1009 if (!dp) {
@@ -879,6 +1013,22 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
879 1013
880 dp->dev = &pdev->dev; 1014 dp->dev = &pdev->dev;
881 1015
1016 if (pdev->dev.of_node) {
1017 pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
1018 if (IS_ERR(pdata))
1019 return PTR_ERR(pdata);
1020
1021 ret = exynos_dp_dt_parse_phydata(dp);
1022 if (ret)
1023 return ret;
1024 } else {
1025 pdata = pdev->dev.platform_data;
1026 if (!pdata) {
1027 dev_err(&pdev->dev, "no platform data\n");
1028 return -EINVAL;
1029 }
1030 }
1031
882 dp->clock = devm_clk_get(&pdev->dev, "dp"); 1032 dp->clock = devm_clk_get(&pdev->dev, "dp");
883 if (IS_ERR(dp->clock)) { 1033 if (IS_ERR(dp->clock)) {
884 dev_err(&pdev->dev, "failed to get clock\n"); 1034 dev_err(&pdev->dev, "failed to get clock\n");
@@ -909,8 +1059,14 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
909 } 1059 }
910 1060
911 dp->video_info = pdata->video_info; 1061 dp->video_info = pdata->video_info;
912 if (pdata->phy_init) 1062
913 pdata->phy_init(); 1063 if (pdev->dev.of_node) {
1064 if (dp->phy_addr)
1065 exynos_dp_phy_init(dp);
1066 } else {
1067 if (pdata->phy_init)
1068 pdata->phy_init();
1069 }
914 1070
915 exynos_dp_init_dp(dp); 1071 exynos_dp_init_dp(dp);
916 1072
@@ -953,8 +1109,13 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
953 struct exynos_dp_platdata *pdata = pdev->dev.platform_data; 1109 struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
954 struct exynos_dp_device *dp = platform_get_drvdata(pdev); 1110 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
955 1111
956 if (pdata && pdata->phy_exit) 1112 if (pdev->dev.of_node) {
957 pdata->phy_exit(); 1113 if (dp->phy_addr)
1114 exynos_dp_phy_exit(dp);
1115 } else {
1116 if (pdata->phy_exit)
1117 pdata->phy_exit();
1118 }
958 1119
959 clk_disable_unprepare(dp->clock); 1120 clk_disable_unprepare(dp->clock);
960 1121
@@ -964,12 +1125,16 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
964#ifdef CONFIG_PM_SLEEP 1125#ifdef CONFIG_PM_SLEEP
965static int exynos_dp_suspend(struct device *dev) 1126static int exynos_dp_suspend(struct device *dev)
966{ 1127{
967 struct platform_device *pdev = to_platform_device(dev); 1128 struct exynos_dp_platdata *pdata = dev->platform_data;
968 struct exynos_dp_platdata *pdata = pdev->dev.platform_data; 1129 struct exynos_dp_device *dp = dev_get_drvdata(dev);
969 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
970 1130
971 if (pdata && pdata->phy_exit) 1131 if (dev->of_node) {
972 pdata->phy_exit(); 1132 if (dp->phy_addr)
1133 exynos_dp_phy_exit(dp);
1134 } else {
1135 if (pdata->phy_exit)
1136 pdata->phy_exit();
1137 }
973 1138
974 clk_disable_unprepare(dp->clock); 1139 clk_disable_unprepare(dp->clock);
975 1140
@@ -978,12 +1143,16 @@ static int exynos_dp_suspend(struct device *dev)
978 1143
979static int exynos_dp_resume(struct device *dev) 1144static int exynos_dp_resume(struct device *dev)
980{ 1145{
981 struct platform_device *pdev = to_platform_device(dev); 1146 struct exynos_dp_platdata *pdata = dev->platform_data;
982 struct exynos_dp_platdata *pdata = pdev->dev.platform_data; 1147 struct exynos_dp_device *dp = dev_get_drvdata(dev);
983 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
984 1148
985 if (pdata && pdata->phy_init) 1149 if (dev->of_node) {
986 pdata->phy_init(); 1150 if (dp->phy_addr)
1151 exynos_dp_phy_init(dp);
1152 } else {
1153 if (pdata->phy_init)
1154 pdata->phy_init();
1155 }
987 1156
988 clk_prepare_enable(dp->clock); 1157 clk_prepare_enable(dp->clock);
989 1158
@@ -1013,6 +1182,12 @@ static const struct dev_pm_ops exynos_dp_pm_ops = {
1013 SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume) 1182 SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
1014}; 1183};
1015 1184
1185static const struct of_device_id exynos_dp_match[] = {
1186 { .compatible = "samsung,exynos5-dp" },
1187 {},
1188};
1189MODULE_DEVICE_TABLE(of, exynos_dp_match);
1190
1016static struct platform_driver exynos_dp_driver = { 1191static struct platform_driver exynos_dp_driver = {
1017 .probe = exynos_dp_probe, 1192 .probe = exynos_dp_probe,
1018 .remove = __devexit_p(exynos_dp_remove), 1193 .remove = __devexit_p(exynos_dp_remove),
@@ -1020,6 +1195,7 @@ static struct platform_driver exynos_dp_driver = {
1020 .name = "exynos-dp", 1195 .name = "exynos-dp",
1021 .owner = THIS_MODULE, 1196 .owner = THIS_MODULE,
1022 .pm = &exynos_dp_pm_ops, 1197 .pm = &exynos_dp_pm_ops,
1198 .of_match_table = of_match_ptr(exynos_dp_match),
1023 }, 1199 },
1024}; 1200};
1025 1201
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
index 57b8a6531c0e..6dbeeb2c7bcb 100644
--- a/drivers/video/exynos/exynos_dp_core.h
+++ b/drivers/video/exynos/exynos_dp_core.h
@@ -29,6 +29,8 @@ struct exynos_dp_device {
29 struct clk *clock; 29 struct clk *clock;
30 unsigned int irq; 30 unsigned int irq;
31 void __iomem *reg_base; 31 void __iomem *reg_base;
32 void __iomem *phy_addr;
33 unsigned int enable_mask;
32 34
33 struct video_info *video_info; 35 struct video_info *video_info;
34 struct link_train link_train; 36 struct link_train link_train;