diff options
author | Sean Paul <seanpaul@chromium.org> | 2014-01-30 16:19:25 -0500 |
---|---|---|
committer | Inki Dae <daeinki@gmail.com> | 2014-03-23 11:36:35 -0400 |
commit | 12f5ad6c89b1716f010d5de3042560b2887ca1bc (patch) | |
tree | 4a6acdb18561c431baee019a391eba8cba574f26 /drivers/gpu/drm/exynos | |
parent | 1417f109a82f8a57b46e6789ccf66241bfddf411 (diff) |
drm/exynos: Implement dpms display callback in DP
This patch implements the dpms display callback for the DP driver.
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_dp_core.c | 142 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_dp_core.h | 1 |
2 files changed, 81 insertions, 62 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 5c261616c06f..05ce947e3347 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c | |||
@@ -915,10 +915,78 @@ static int exynos_dp_check_mode(struct exynos_drm_display *display, | |||
915 | return 0; | 915 | return 0; |
916 | } | 916 | } |
917 | 917 | ||
918 | static void exynos_dp_phy_init(struct exynos_dp_device *dp) | ||
919 | { | ||
920 | if (dp->phy) { | ||
921 | phy_power_on(dp->phy); | ||
922 | } else if (dp->phy_addr) { | ||
923 | u32 reg; | ||
924 | |||
925 | reg = __raw_readl(dp->phy_addr); | ||
926 | reg |= dp->enable_mask; | ||
927 | __raw_writel(reg, dp->phy_addr); | ||
928 | } | ||
929 | } | ||
930 | |||
931 | static void exynos_dp_phy_exit(struct exynos_dp_device *dp) | ||
932 | { | ||
933 | if (dp->phy) { | ||
934 | phy_power_off(dp->phy); | ||
935 | } else if (dp->phy_addr) { | ||
936 | u32 reg; | ||
937 | |||
938 | reg = __raw_readl(dp->phy_addr); | ||
939 | reg &= ~(dp->enable_mask); | ||
940 | __raw_writel(reg, dp->phy_addr); | ||
941 | } | ||
942 | } | ||
943 | |||
944 | static void exynos_dp_poweron(struct exynos_dp_device *dp) | ||
945 | { | ||
946 | if (dp->dpms_mode == DRM_MODE_DPMS_ON) | ||
947 | return; | ||
948 | |||
949 | clk_prepare_enable(dp->clock); | ||
950 | exynos_dp_phy_init(dp); | ||
951 | exynos_dp_init_dp(dp); | ||
952 | enable_irq(dp->irq); | ||
953 | } | ||
954 | |||
955 | static void exynos_dp_poweroff(struct exynos_dp_device *dp) | ||
956 | { | ||
957 | if (dp->dpms_mode != DRM_MODE_DPMS_ON) | ||
958 | return; | ||
959 | |||
960 | disable_irq(dp->irq); | ||
961 | flush_work(&dp->hotplug_work); | ||
962 | exynos_dp_phy_exit(dp); | ||
963 | clk_disable_unprepare(dp->clock); | ||
964 | } | ||
965 | |||
966 | static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) | ||
967 | { | ||
968 | struct exynos_dp_device *dp = display->ctx; | ||
969 | |||
970 | switch (mode) { | ||
971 | case DRM_MODE_DPMS_ON: | ||
972 | exynos_dp_poweron(dp); | ||
973 | break; | ||
974 | case DRM_MODE_DPMS_STANDBY: | ||
975 | case DRM_MODE_DPMS_SUSPEND: | ||
976 | case DRM_MODE_DPMS_OFF: | ||
977 | exynos_dp_poweroff(dp); | ||
978 | break; | ||
979 | default: | ||
980 | break; | ||
981 | }; | ||
982 | dp->dpms_mode = mode; | ||
983 | } | ||
984 | |||
918 | static struct exynos_drm_display_ops exynos_dp_display_ops = { | 985 | static struct exynos_drm_display_ops exynos_dp_display_ops = { |
919 | .is_connected = exynos_dp_display_is_connected, | 986 | .is_connected = exynos_dp_display_is_connected, |
920 | .get_panel = exynos_dp_get_panel, | 987 | .get_panel = exynos_dp_get_panel, |
921 | .check_mode = exynos_dp_check_mode, | 988 | .check_mode = exynos_dp_check_mode, |
989 | .dpms = exynos_dp_dpms, | ||
922 | }; | 990 | }; |
923 | 991 | ||
924 | static struct exynos_drm_display exynos_dp_display = { | 992 | static struct exynos_drm_display exynos_dp_display = { |
@@ -1040,54 +1108,6 @@ static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) | |||
1040 | return 0; | 1108 | return 0; |
1041 | } | 1109 | } |
1042 | 1110 | ||
1043 | static void exynos_dp_phy_init(struct exynos_dp_device *dp) | ||
1044 | { | ||
1045 | if (dp->phy) { | ||
1046 | phy_power_on(dp->phy); | ||
1047 | } else if (dp->phy_addr) { | ||
1048 | u32 reg; | ||
1049 | |||
1050 | reg = __raw_readl(dp->phy_addr); | ||
1051 | reg |= dp->enable_mask; | ||
1052 | __raw_writel(reg, dp->phy_addr); | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | static void exynos_dp_phy_exit(struct exynos_dp_device *dp) | ||
1057 | { | ||
1058 | if (dp->phy) { | ||
1059 | phy_power_off(dp->phy); | ||
1060 | } else if (dp->phy_addr) { | ||
1061 | u32 reg; | ||
1062 | |||
1063 | reg = __raw_readl(dp->phy_addr); | ||
1064 | reg &= ~(dp->enable_mask); | ||
1065 | __raw_writel(reg, dp->phy_addr); | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1069 | void exynos_dp_poweron(struct exynos_dp_device *dp) | ||
1070 | { | ||
1071 | exynos_dp_phy_init(dp); | ||
1072 | |||
1073 | clk_prepare_enable(dp->clock); | ||
1074 | |||
1075 | exynos_dp_init_dp(dp); | ||
1076 | |||
1077 | enable_irq(dp->irq); | ||
1078 | } | ||
1079 | |||
1080 | void exynos_dp_poweroff(struct exynos_dp_device *dp) | ||
1081 | { | ||
1082 | disable_irq(dp->irq); | ||
1083 | |||
1084 | flush_work(&dp->hotplug_work); | ||
1085 | |||
1086 | exynos_dp_phy_exit(dp); | ||
1087 | |||
1088 | clk_disable_unprepare(dp->clock); | ||
1089 | } | ||
1090 | |||
1091 | static int exynos_dp_probe(struct platform_device *pdev) | 1111 | static int exynos_dp_probe(struct platform_device *pdev) |
1092 | { | 1112 | { |
1093 | struct resource *res; | 1113 | struct resource *res; |
@@ -1103,6 +1123,7 @@ static int exynos_dp_probe(struct platform_device *pdev) | |||
1103 | } | 1123 | } |
1104 | 1124 | ||
1105 | dp->dev = &pdev->dev; | 1125 | dp->dev = &pdev->dev; |
1126 | dp->dpms_mode = DRM_MODE_DPMS_OFF; | ||
1106 | 1127 | ||
1107 | dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev); | 1128 | dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev); |
1108 | if (IS_ERR(dp->video_info)) | 1129 | if (IS_ERR(dp->video_info)) |
@@ -1148,10 +1169,11 @@ static int exynos_dp_probe(struct platform_device *pdev) | |||
1148 | dev_err(&pdev->dev, "failed to request irq\n"); | 1169 | dev_err(&pdev->dev, "failed to request irq\n"); |
1149 | return ret; | 1170 | return ret; |
1150 | } | 1171 | } |
1151 | 1172 | disable_irq(dp->irq); | |
1152 | platform_set_drvdata(pdev, dp); | ||
1153 | 1173 | ||
1154 | exynos_dp_display.ctx = dp; | 1174 | exynos_dp_display.ctx = dp; |
1175 | |||
1176 | platform_set_drvdata(pdev, &exynos_dp_display); | ||
1155 | exynos_drm_display_register(&exynos_dp_display); | 1177 | exynos_drm_display_register(&exynos_dp_display); |
1156 | 1178 | ||
1157 | return 0; | 1179 | return 0; |
@@ -1159,34 +1181,30 @@ static int exynos_dp_probe(struct platform_device *pdev) | |||
1159 | 1181 | ||
1160 | static int exynos_dp_remove(struct platform_device *pdev) | 1182 | static int exynos_dp_remove(struct platform_device *pdev) |
1161 | { | 1183 | { |
1162 | struct exynos_dp_device *dp = platform_get_drvdata(pdev); | 1184 | struct exynos_drm_display *display = platform_get_drvdata(pdev); |
1163 | 1185 | ||
1186 | exynos_dp_dpms(display, DRM_MODE_DPMS_OFF); | ||
1164 | exynos_drm_display_unregister(&exynos_dp_display); | 1187 | exynos_drm_display_unregister(&exynos_dp_display); |
1165 | 1188 | ||
1166 | flush_work(&dp->hotplug_work); | ||
1167 | |||
1168 | exynos_dp_phy_exit(dp); | ||
1169 | |||
1170 | clk_disable_unprepare(dp->clock); | ||
1171 | |||
1172 | |||
1173 | return 0; | 1189 | return 0; |
1174 | } | 1190 | } |
1175 | 1191 | ||
1176 | #ifdef CONFIG_PM_SLEEP | 1192 | #ifdef CONFIG_PM_SLEEP |
1177 | static int exynos_dp_suspend(struct device *dev) | 1193 | static int exynos_dp_suspend(struct device *dev) |
1178 | { | 1194 | { |
1179 | struct exynos_dp_device *dp = dev_get_drvdata(dev); | 1195 | struct platform_device *pdev = to_platform_device(dev); |
1196 | struct exynos_drm_display *display = platform_get_drvdata(pdev); | ||
1180 | 1197 | ||
1181 | exynos_dp_poweroff(dp); | 1198 | exynos_dp_dpms(display, DRM_MODE_DPMS_OFF); |
1182 | return 0; | 1199 | return 0; |
1183 | } | 1200 | } |
1184 | 1201 | ||
1185 | static int exynos_dp_resume(struct device *dev) | 1202 | static int exynos_dp_resume(struct device *dev) |
1186 | { | 1203 | { |
1187 | struct exynos_dp_device *dp = dev_get_drvdata(dev); | 1204 | struct platform_device *pdev = to_platform_device(dev); |
1205 | struct exynos_drm_display *display = platform_get_drvdata(pdev); | ||
1188 | 1206 | ||
1189 | exynos_dp_poweron(dp); | 1207 | exynos_dp_dpms(display, DRM_MODE_DPMS_ON); |
1190 | return 0; | 1208 | return 0; |
1191 | } | 1209 | } |
1192 | #endif | 1210 | #endif |
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h index 4f1414162bbe..ccaeadc8ee16 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.h +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h | |||
@@ -154,6 +154,7 @@ struct exynos_dp_device { | |||
154 | struct link_train link_train; | 154 | struct link_train link_train; |
155 | struct work_struct hotplug_work; | 155 | struct work_struct hotplug_work; |
156 | struct phy *phy; | 156 | struct phy *phy; |
157 | int dpms_mode; | ||
157 | 158 | ||
158 | struct exynos_drm_panel_info panel; | 159 | struct exynos_drm_panel_info panel; |
159 | }; | 160 | }; |