diff options
| -rw-r--r-- | drivers/gpu/drm/exynos/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_dp_core.c | 88 | ||||
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_dp_core.h | 3 |
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 | ||
| 44 | static int exynos_dp_init_dp(struct exynos_dp_device *dp) | 44 | static 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 | ||
| 65 | static int exynos_dp_detect_hpd(struct exynos_dp_device *dp) | 63 | static 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 | ||
| 922 | static enum drm_connector_status exynos_dp_detect( | 932 | static 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 | ||
| 1035 | static void exynos_dp_phy_init(struct exynos_dp_device *dp) | 1051 | static 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 | ||
| 1088 | static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) | 1123 | static 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 | ||
| 1340 | static int exynos_dp_probe(struct platform_device *pdev) | 1370 | static 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 */ |
