aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAjay Kumar <ajaykumar.rs@samsung.com>2014-07-31 13:42:14 -0400
committerThierry Reding <treding@nvidia.com>2014-08-06 10:44:16 -0400
commit5f1dcd8b7ec8189c2b147cdaa1589d5644c3cef3 (patch)
tree515c9198065ff932810886ecfeb532801bbce5be
parent4deabfa00049465cc1e4ed6fe0b5082bcff98d57 (diff)
drm/exynos: dp: Modify driver to support drm_panel
Add drm_panel controls to support powerup/down of the eDP panel, if one is present at the sink side. Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com> Acked-by: Inki Dae <inki.dae@samsung.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--drivers/gpu/drm/exynos/Kconfig1
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_core.c88
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_core.h3
3 files changed, 71 insertions, 21 deletions
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 178d2a9672a8..fd1c070f0297 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -52,6 +52,7 @@ config DRM_EXYNOS_DP
52 bool "EXYNOS DRM DP driver support" 52 bool "EXYNOS DRM DP driver support"
53 depends on DRM_EXYNOS_FIMD && ARCH_EXYNOS && (DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS) 53 depends on DRM_EXYNOS_FIMD && ARCH_EXYNOS && (DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS)
54 default DRM_EXYNOS 54 default DRM_EXYNOS
55 select DRM_PANEL
55 help 56 help
56 This enables support for DP device. 57 This enables support for DP device.
57 58
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index c33a9d0a87c1..0d3f88bfeca5 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -16,7 +16,6 @@
16#include <linux/clk.h> 16#include <linux/clk.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/delay.h>
20#include <linux/of.h> 19#include <linux/of.h>
21#include <linux/of_gpio.h> 20#include <linux/of_gpio.h>
22#include <linux/gpio.h> 21#include <linux/gpio.h>
@@ -28,6 +27,7 @@
28#include <drm/drmP.h> 27#include <drm/drmP.h>
29#include <drm/drm_crtc.h> 28#include <drm/drm_crtc.h>
30#include <drm/drm_crtc_helper.h> 29#include <drm/drm_crtc_helper.h>
30#include <drm/drm_panel.h>
31#include <drm/bridge/ptn3460.h> 31#include <drm/bridge/ptn3460.h>
32 32
33#include "exynos_drm_drv.h" 33#include "exynos_drm_drv.h"
@@ -41,7 +41,7 @@ struct bridge_init {
41 struct device_node *node; 41 struct device_node *node;
42}; 42};
43 43
44static int exynos_dp_init_dp(struct exynos_dp_device *dp) 44static void exynos_dp_init_dp(struct exynos_dp_device *dp)
45{ 45{
46 exynos_dp_reset(dp); 46 exynos_dp_reset(dp);
47 47
@@ -58,8 +58,6 @@ static int exynos_dp_init_dp(struct exynos_dp_device *dp)
58 58
59 exynos_dp_init_hpd(dp); 59 exynos_dp_init_hpd(dp);
60 exynos_dp_init_aux(dp); 60 exynos_dp_init_aux(dp);
61
62 return 0;
63} 61}
64 62
65static int exynos_dp_detect_hpd(struct exynos_dp_device *dp) 63static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
@@ -887,6 +885,12 @@ static void exynos_dp_commit(struct exynos_drm_display *display)
887 struct exynos_dp_device *dp = display->ctx; 885 struct exynos_dp_device *dp = display->ctx;
888 int ret; 886 int ret;
889 887
888 /* Keep the panel disabled while we configure video */
889 if (dp->panel) {
890 if (drm_panel_disable(dp->panel))
891 DRM_ERROR("failed to disable the panel\n");
892 }
893
890 ret = exynos_dp_detect_hpd(dp); 894 ret = exynos_dp_detect_hpd(dp);
891 if (ret) { 895 if (ret) {
892 /* Cable has been disconnected, we're done */ 896 /* Cable has been disconnected, we're done */
@@ -917,6 +921,12 @@ static void exynos_dp_commit(struct exynos_drm_display *display)
917 ret = exynos_dp_config_video(dp); 921 ret = exynos_dp_config_video(dp);
918 if (ret) 922 if (ret)
919 dev_err(dp->dev, "unable to config video\n"); 923 dev_err(dp->dev, "unable to config video\n");
924
925 /* Safe to enable the panel now */
926 if (dp->panel) {
927 if (drm_panel_enable(dp->panel))
928 DRM_ERROR("failed to enable the panel\n");
929 }
920} 930}
921 931
922static enum drm_connector_status exynos_dp_detect( 932static enum drm_connector_status exynos_dp_detect(
@@ -941,15 +951,18 @@ static int exynos_dp_get_modes(struct drm_connector *connector)
941 struct exynos_dp_device *dp = ctx_from_connector(connector); 951 struct exynos_dp_device *dp = ctx_from_connector(connector);
942 struct drm_display_mode *mode; 952 struct drm_display_mode *mode;
943 953
954 if (dp->panel)
955 return drm_panel_get_modes(dp->panel);
956
944 mode = drm_mode_create(connector->dev); 957 mode = drm_mode_create(connector->dev);
945 if (!mode) { 958 if (!mode) {
946 DRM_ERROR("failed to create a new display mode.\n"); 959 DRM_ERROR("failed to create a new display mode.\n");
947 return 0; 960 return 0;
948 } 961 }
949 962
950 drm_display_mode_from_videomode(&dp->panel.vm, mode); 963 drm_display_mode_from_videomode(&dp->priv.vm, mode);
951 mode->width_mm = dp->panel.width_mm; 964 mode->width_mm = dp->priv.width_mm;
952 mode->height_mm = dp->panel.height_mm; 965 mode->height_mm = dp->priv.height_mm;
953 connector->display_info.width_mm = mode->width_mm; 966 connector->display_info.width_mm = mode->width_mm;
954 connector->display_info.height_mm = mode->height_mm; 967 connector->display_info.height_mm = mode->height_mm;
955 968
@@ -1029,7 +1042,10 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display,
1029 drm_sysfs_connector_add(connector); 1042 drm_sysfs_connector_add(connector);
1030 drm_mode_connector_attach_encoder(connector, encoder); 1043 drm_mode_connector_attach_encoder(connector, encoder);
1031 1044
1032 return 0; 1045 if (dp->panel)
1046 ret = drm_panel_attach(dp->panel, &dp->connector);
1047
1048 return ret;
1033} 1049}
1034 1050
1035static void exynos_dp_phy_init(struct exynos_dp_device *dp) 1051static void exynos_dp_phy_init(struct exynos_dp_device *dp)
@@ -1065,6 +1081,13 @@ static void exynos_dp_poweron(struct exynos_drm_display *display)
1065 if (dp->dpms_mode == DRM_MODE_DPMS_ON) 1081 if (dp->dpms_mode == DRM_MODE_DPMS_ON)
1066 return; 1082 return;
1067 1083
1084 if (dp->panel) {
1085 if (drm_panel_prepare(dp->panel)) {
1086 DRM_ERROR("failed to setup the panel\n");
1087 return;
1088 }
1089 }
1090
1068 clk_prepare_enable(dp->clock); 1091 clk_prepare_enable(dp->clock);
1069 exynos_dp_phy_init(dp); 1092 exynos_dp_phy_init(dp);
1070 exynos_dp_init_dp(dp); 1093 exynos_dp_init_dp(dp);
@@ -1079,10 +1102,22 @@ static void exynos_dp_poweroff(struct exynos_drm_display *display)
1079 if (dp->dpms_mode != DRM_MODE_DPMS_ON) 1102 if (dp->dpms_mode != DRM_MODE_DPMS_ON)
1080 return; 1103 return;
1081 1104
1105 if (dp->panel) {
1106 if (drm_panel_disable(dp->panel)) {
1107 DRM_ERROR("failed to disable the panel\n");
1108 return;
1109 }
1110 }
1111
1082 disable_irq(dp->irq); 1112 disable_irq(dp->irq);
1083 flush_work(&dp->hotplug_work); 1113 flush_work(&dp->hotplug_work);
1084 exynos_dp_phy_exit(dp); 1114 exynos_dp_phy_exit(dp);
1085 clk_disable_unprepare(dp->clock); 1115 clk_disable_unprepare(dp->clock);
1116
1117 if (dp->panel) {
1118 if (drm_panel_unprepare(dp->panel))
1119 DRM_ERROR("failed to turnoff the panel\n");
1120 }
1086} 1121}
1087 1122
1088static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) 1123static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
@@ -1215,7 +1250,7 @@ static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
1215{ 1250{
1216 int ret; 1251 int ret;
1217 1252
1218 ret = of_get_videomode(dp->dev->of_node, &dp->panel.vm, 1253 ret = of_get_videomode(dp->dev->of_node, &dp->priv.vm,
1219 OF_USE_NATIVE_MODE); 1254 OF_USE_NATIVE_MODE);
1220 if (ret) { 1255 if (ret) {
1221 DRM_ERROR("failed: of_get_videomode() : %d\n", ret); 1256 DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
@@ -1229,16 +1264,10 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
1229 struct platform_device *pdev = to_platform_device(dev); 1264 struct platform_device *pdev = to_platform_device(dev);
1230 struct drm_device *drm_dev = data; 1265 struct drm_device *drm_dev = data;
1231 struct resource *res; 1266 struct resource *res;
1232 struct exynos_dp_device *dp; 1267 struct exynos_dp_device *dp = exynos_dp_display.ctx;
1233 unsigned int irq_flags; 1268 unsigned int irq_flags;
1234
1235 int ret = 0; 1269 int ret = 0;
1236 1270
1237 dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
1238 GFP_KERNEL);
1239 if (!dp)
1240 return -ENOMEM;
1241
1242 dp->dev = &pdev->dev; 1271 dp->dev = &pdev->dev;
1243 dp->dpms_mode = DRM_MODE_DPMS_OFF; 1272 dp->dpms_mode = DRM_MODE_DPMS_OFF;
1244 1273
@@ -1250,9 +1279,11 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
1250 if (ret) 1279 if (ret)
1251 return ret; 1280 return ret;
1252 1281
1253 ret = exynos_dp_dt_parse_panel(dp); 1282 if (!dp->panel) {
1254 if (ret) 1283 ret = exynos_dp_dt_parse_panel(dp);
1255 return ret; 1284 if (ret)
1285 return ret;
1286 }
1256 1287
1257 dp->clock = devm_clk_get(&pdev->dev, "dp"); 1288 dp->clock = devm_clk_get(&pdev->dev, "dp");
1258 if (IS_ERR(dp->clock)) { 1289 if (IS_ERR(dp->clock)) {
@@ -1312,7 +1343,6 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
1312 disable_irq(dp->irq); 1343 disable_irq(dp->irq);
1313 1344
1314 dp->drm_dev = drm_dev; 1345 dp->drm_dev = drm_dev;
1315 exynos_dp_display.ctx = dp;
1316 1346
1317 platform_set_drvdata(pdev, &exynos_dp_display); 1347 platform_set_drvdata(pdev, &exynos_dp_display);
1318 1348
@@ -1339,6 +1369,9 @@ static const struct component_ops exynos_dp_ops = {
1339 1369
1340static int exynos_dp_probe(struct platform_device *pdev) 1370static int exynos_dp_probe(struct platform_device *pdev)
1341{ 1371{
1372 struct device *dev = &pdev->dev;
1373 struct device_node *panel_node;
1374 struct exynos_dp_device *dp;
1342 int ret; 1375 int ret;
1343 1376
1344 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR, 1377 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
@@ -1346,6 +1379,21 @@ static int exynos_dp_probe(struct platform_device *pdev)
1346 if (ret) 1379 if (ret)
1347 return ret; 1380 return ret;
1348 1381
1382 dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
1383 GFP_KERNEL);
1384 if (!dp)
1385 return -ENOMEM;
1386
1387 panel_node = of_parse_phandle(dev->of_node, "panel", 0);
1388 if (panel_node) {
1389 dp->panel = of_drm_find_panel(panel_node);
1390 of_node_put(panel_node);
1391 if (!dp->panel)
1392 return -EPROBE_DEFER;
1393 }
1394
1395 exynos_dp_display.ctx = dp;
1396
1349 ret = component_add(&pdev->dev, &exynos_dp_ops); 1397 ret = component_add(&pdev->dev, &exynos_dp_ops);
1350 if (ret) 1398 if (ret)
1351 exynos_drm_component_del(&pdev->dev, 1399 exynos_drm_component_del(&pdev->dev,
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
index 02cc4f9ab903..a1aee6931bd7 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.h
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
@@ -149,6 +149,7 @@ struct exynos_dp_device {
149 struct drm_device *drm_dev; 149 struct drm_device *drm_dev;
150 struct drm_connector connector; 150 struct drm_connector connector;
151 struct drm_encoder *encoder; 151 struct drm_encoder *encoder;
152 struct drm_panel *panel;
152 struct clk *clock; 153 struct clk *clock;
153 unsigned int irq; 154 unsigned int irq;
154 void __iomem *reg_base; 155 void __iomem *reg_base;
@@ -162,7 +163,7 @@ struct exynos_dp_device {
162 int dpms_mode; 163 int dpms_mode;
163 int hpd_gpio; 164 int hpd_gpio;
164 165
165 struct exynos_drm_panel_info panel; 166 struct exynos_drm_panel_info priv;
166}; 167};
167 168
168/* exynos_dp_reg.c */ 169/* exynos_dp_reg.c */