aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Paul <seanpaul@chromium.org>2014-01-30 16:19:27 -0500
committerInki Dae <daeinki@gmail.com>2014-03-23 11:36:36 -0400
commitaf65c804877078a58cb02cc0f2ce4198401402fc (patch)
tree1894a3b77ee5098bafe60f69694ca5d122a1be36
parenta43b933bcbbd6c7e2660b672a311345cea9524c1 (diff)
drm/exynos: Consolidate suspend/resume in drm_drv
This patch removes all of the suspend/resume logic from the individual drivers and consolidates it in drm_drv. This consolidation reduces the number of functions which enable/disable the hardware to just one -- the dpms callback. This ensures that we always power up/down in a consistent manner. Signed-off-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c97
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c86
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c119
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c88
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c68
5 files changed, 170 insertions, 288 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 8619a537e6ff..8789d64109ca 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -11,6 +11,7 @@
11 * option) any later version. 11 * option) any later version.
12 */ 12 */
13 13
14#include <linux/pm_runtime.h>
14#include <drm/drmP.h> 15#include <drm/drmP.h>
15#include <drm/drm_crtc_helper.h> 16#include <drm/drm_crtc_helper.h>
16 17
@@ -53,6 +54,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
53 return -ENOMEM; 54 return -ENOMEM;
54 55
55 INIT_LIST_HEAD(&private->pageflip_event_list); 56 INIT_LIST_HEAD(&private->pageflip_event_list);
57 dev_set_drvdata(dev->dev, dev);
56 dev->dev_private = (void *)private; 58 dev->dev_private = (void *)private;
57 59
58 /* 60 /*
@@ -163,6 +165,41 @@ static const struct file_operations exynos_drm_gem_fops = {
163 .mmap = exynos_drm_gem_mmap_buffer, 165 .mmap = exynos_drm_gem_mmap_buffer,
164}; 166};
165 167
168static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state)
169{
170 struct drm_connector *connector;
171
172 drm_modeset_lock_all(dev);
173 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
174 int old_dpms = connector->dpms;
175
176 if (connector->funcs->dpms)
177 connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
178
179 /* Set the old mode back to the connector for resume */
180 connector->dpms = old_dpms;
181 }
182 drm_modeset_unlock_all(dev);
183
184 return 0;
185}
186
187static int exynos_drm_resume(struct drm_device *dev)
188{
189 struct drm_connector *connector;
190
191 drm_modeset_lock_all(dev);
192 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
193 if (connector->funcs->dpms)
194 connector->funcs->dpms(connector, connector->dpms);
195 }
196
197 drm_helper_resume_force_mode(dev);
198 drm_modeset_unlock_all(dev);
199
200 return 0;
201}
202
166static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) 203static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
167{ 204{
168 struct drm_exynos_file_private *file_priv; 205 struct drm_exynos_file_private *file_priv;
@@ -300,6 +337,8 @@ static struct drm_driver exynos_drm_driver = {
300 DRIVER_GEM | DRIVER_PRIME, 337 DRIVER_GEM | DRIVER_PRIME,
301 .load = exynos_drm_load, 338 .load = exynos_drm_load,
302 .unload = exynos_drm_unload, 339 .unload = exynos_drm_unload,
340 .suspend = exynos_drm_suspend,
341 .resume = exynos_drm_resume,
303 .open = exynos_drm_open, 342 .open = exynos_drm_open,
304 .preclose = exynos_drm_preclose, 343 .preclose = exynos_drm_preclose,
305 .lastclose = exynos_drm_lastclose, 344 .lastclose = exynos_drm_lastclose,
@@ -334,6 +373,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
334 if (ret) 373 if (ret)
335 return ret; 374 return ret;
336 375
376 pm_runtime_enable(&pdev->dev);
377 pm_runtime_get_sync(&pdev->dev);
378
337 return drm_platform_init(&exynos_drm_driver, pdev); 379 return drm_platform_init(&exynos_drm_driver, pdev);
338} 380}
339 381
@@ -344,12 +386,67 @@ static int exynos_drm_platform_remove(struct platform_device *pdev)
344 return 0; 386 return 0;
345} 387}
346 388
389#ifdef CONFIG_PM_SLEEP
390static int exynos_drm_sys_suspend(struct device *dev)
391{
392 struct drm_device *drm_dev = dev_get_drvdata(dev);
393 pm_message_t message;
394
395 if (pm_runtime_suspended(dev))
396 return 0;
397
398 message.event = PM_EVENT_SUSPEND;
399 return exynos_drm_suspend(drm_dev, message);
400}
401
402static int exynos_drm_sys_resume(struct device *dev)
403{
404 struct drm_device *drm_dev = dev_get_drvdata(dev);
405
406 if (pm_runtime_suspended(dev))
407 return 0;
408
409 return exynos_drm_resume(drm_dev);
410}
411#endif
412
413#ifdef CONFIG_PM_RUNTIME
414static int exynos_drm_runtime_suspend(struct device *dev)
415{
416 struct drm_device *drm_dev = dev_get_drvdata(dev);
417 pm_message_t message;
418
419 if (pm_runtime_suspended(dev))
420 return 0;
421
422 message.event = PM_EVENT_SUSPEND;
423 return exynos_drm_suspend(drm_dev, message);
424}
425
426static int exynos_drm_runtime_resume(struct device *dev)
427{
428 struct drm_device *drm_dev = dev_get_drvdata(dev);
429
430 if (!pm_runtime_suspended(dev))
431 return 0;
432
433 return exynos_drm_resume(drm_dev);
434}
435#endif
436
437static const struct dev_pm_ops exynos_drm_pm_ops = {
438 SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume)
439 SET_RUNTIME_PM_OPS(exynos_drm_runtime_suspend,
440 exynos_drm_runtime_resume, NULL)
441};
442
347static struct platform_driver exynos_drm_platform_driver = { 443static struct platform_driver exynos_drm_platform_driver = {
348 .probe = exynos_drm_platform_probe, 444 .probe = exynos_drm_platform_probe,
349 .remove = exynos_drm_platform_remove, 445 .remove = exynos_drm_platform_remove,
350 .driver = { 446 .driver = {
351 .owner = THIS_MODULE, 447 .owner = THIS_MODULE,
352 .name = "exynos-drm", 448 .name = "exynos-drm",
449 .pm = &exynos_drm_pm_ops,
353 }, 450 },
354}; 451};
355 452
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 1efdcac4510d..f78fbf4682b4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -732,6 +732,8 @@ static int fimd_poweron(struct exynos_drm_manager *mgr)
732 732
733 ctx->suspended = false; 733 ctx->suspended = false;
734 734
735 pm_runtime_get_sync(ctx->dev);
736
735 ret = clk_prepare_enable(ctx->bus_clk); 737 ret = clk_prepare_enable(ctx->bus_clk);
736 if (ret < 0) { 738 if (ret < 0) {
737 DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret); 739 DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
@@ -785,32 +787,24 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr)
785 clk_disable_unprepare(ctx->lcd_clk); 787 clk_disable_unprepare(ctx->lcd_clk);
786 clk_disable_unprepare(ctx->bus_clk); 788 clk_disable_unprepare(ctx->bus_clk);
787 789
790 pm_runtime_put_sync(ctx->dev);
791
788 ctx->suspended = true; 792 ctx->suspended = true;
789 return 0; 793 return 0;
790} 794}
791 795
792static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) 796static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
793{ 797{
794 struct fimd_context *ctx = mgr->ctx; 798 DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
795
796 DRM_DEBUG_KMS("%d\n", mode);
797 799
798 switch (mode) { 800 switch (mode) {
799 case DRM_MODE_DPMS_ON: 801 case DRM_MODE_DPMS_ON:
800 /* 802 fimd_poweron(mgr);
801 * enable fimd hardware only if suspended status.
802 *
803 * P.S. fimd_dpms function would be called at booting time so
804 * clk_enable could be called double time.
805 */
806 if (ctx->suspended)
807 pm_runtime_get_sync(ctx->dev);
808 break; 803 break;
809 case DRM_MODE_DPMS_STANDBY: 804 case DRM_MODE_DPMS_STANDBY:
810 case DRM_MODE_DPMS_SUSPEND: 805 case DRM_MODE_DPMS_SUSPEND:
811 case DRM_MODE_DPMS_OFF: 806 case DRM_MODE_DPMS_OFF:
812 if (!ctx->suspended) 807 fimd_poweroff(mgr);
813 pm_runtime_put_sync(ctx->dev);
814 break; 808 break;
815 default: 809 default:
816 DRM_DEBUG_KMS("unspecified mode %d\n", mode); 810 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
@@ -929,7 +923,6 @@ static int fimd_probe(struct platform_device *pdev)
929 exynos_drm_manager_register(&fimd_manager); 923 exynos_drm_manager_register(&fimd_manager);
930 924
931 pm_runtime_enable(dev); 925 pm_runtime_enable(dev);
932 pm_runtime_get_sync(dev);
933 926
934 for (win = 0; win < WINDOWS_NR; win++) 927 for (win = 0; win < WINDOWS_NR; win++)
935 fimd_clear_win(ctx, win); 928 fimd_clear_win(ctx, win);
@@ -939,84 +932,23 @@ static int fimd_probe(struct platform_device *pdev)
939 932
940static int fimd_remove(struct platform_device *pdev) 933static int fimd_remove(struct platform_device *pdev)
941{ 934{
942 struct device *dev = &pdev->dev;
943 struct exynos_drm_manager *mgr = platform_get_drvdata(pdev); 935 struct exynos_drm_manager *mgr = platform_get_drvdata(pdev);
944 struct fimd_context *ctx = mgr->ctx;
945 936
946 exynos_drm_manager_unregister(&fimd_manager); 937 exynos_drm_manager_unregister(&fimd_manager);
947 938
948 if (ctx->suspended) 939 fimd_dpms(mgr, DRM_MODE_DPMS_OFF);
949 goto out;
950
951 pm_runtime_set_suspended(dev);
952 pm_runtime_put_sync(dev);
953 940
954out: 941 pm_runtime_disable(&pdev->dev);
955 pm_runtime_disable(dev);
956
957 return 0;
958}
959
960#ifdef CONFIG_PM_SLEEP
961static int fimd_suspend(struct device *dev)
962{
963 struct exynos_drm_manager *mgr = get_fimd_manager(dev);
964
965 /*
966 * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
967 * called here, an error would be returned by that interface
968 * because the usage_count of pm runtime is more than 1.
969 */
970 if (!pm_runtime_suspended(dev))
971 return fimd_poweroff(mgr);
972 942
973 return 0; 943 return 0;
974} 944}
975 945
976static int fimd_resume(struct device *dev)
977{
978 struct exynos_drm_manager *mgr = get_fimd_manager(dev);
979
980 /*
981 * if entered to sleep when lcd panel was on, the usage_count
982 * of pm runtime would still be 1 so in this case, fimd driver
983 * should be on directly not drawing on pm runtime interface.
984 */
985 if (pm_runtime_suspended(dev))
986 return 0;
987
988 return fimd_poweron(mgr);
989}
990#endif
991
992#ifdef CONFIG_PM_RUNTIME
993static int fimd_runtime_suspend(struct device *dev)
994{
995 struct exynos_drm_manager *mgr = get_fimd_manager(dev);
996
997 return fimd_poweroff(mgr);
998}
999
1000static int fimd_runtime_resume(struct device *dev)
1001{
1002 struct exynos_drm_manager *mgr = get_fimd_manager(dev);
1003
1004 return fimd_poweron(mgr);
1005}
1006#endif
1007
1008static const struct dev_pm_ops fimd_pm_ops = {
1009 SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
1010 SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
1011};
1012
1013struct platform_driver fimd_driver = { 946struct platform_driver fimd_driver = {
1014 .probe = fimd_probe, 947 .probe = fimd_probe,
1015 .remove = fimd_remove, 948 .remove = fimd_remove,
1016 .driver = { 949 .driver = {
1017 .name = "exynos4-fb", 950 .name = "exynos4-fb",
1018 .owner = THIS_MODULE, 951 .owner = THIS_MODULE,
1019 .pm = &fimd_pm_ops,
1020 .of_match_table = fimd_driver_dt_match, 952 .of_match_table = fimd_driver_dt_match,
1021 }, 953 },
1022}; 954};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index f6f4438a40d9..5d0b5cdeaacf 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -140,31 +140,6 @@ static struct exynos_drm_display vidi_display = {
140 .ops = &vidi_display_ops, 140 .ops = &vidi_display_ops,
141}; 141};
142 142
143static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
144{
145 struct vidi_context *ctx = mgr->ctx;
146
147 DRM_DEBUG_KMS("%d\n", mode);
148
149 mutex_lock(&ctx->lock);
150
151 switch (mode) {
152 case DRM_MODE_DPMS_ON:
153 /* TODO. */
154 break;
155 case DRM_MODE_DPMS_STANDBY:
156 case DRM_MODE_DPMS_SUSPEND:
157 case DRM_MODE_DPMS_OFF:
158 /* TODO. */
159 break;
160 default:
161 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
162 break;
163 }
164
165 mutex_unlock(&ctx->lock);
166}
167
168static void vidi_apply(struct exynos_drm_manager *mgr) 143static void vidi_apply(struct exynos_drm_manager *mgr)
169{ 144{
170 struct vidi_context *ctx = mgr->ctx; 145 struct vidi_context *ctx = mgr->ctx;
@@ -319,6 +294,55 @@ static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
319 /* TODO. */ 294 /* TODO. */
320} 295}
321 296
297static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
298{
299 struct vidi_context *ctx = mgr->ctx;
300
301 DRM_DEBUG_KMS("%s\n", __FILE__);
302
303 if (enable != false && enable != true)
304 return -EINVAL;
305
306 if (enable) {
307 ctx->suspended = false;
308
309 /* if vblank was enabled status, enable it again. */
310 if (test_and_clear_bit(0, &ctx->irq_flags))
311 vidi_enable_vblank(mgr);
312
313 vidi_apply(mgr);
314 } else {
315 ctx->suspended = true;
316 }
317
318 return 0;
319}
320
321static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
322{
323 struct vidi_context *ctx = mgr->ctx;
324
325 DRM_DEBUG_KMS("%d\n", mode);
326
327 mutex_lock(&ctx->lock);
328
329 switch (mode) {
330 case DRM_MODE_DPMS_ON:
331 vidi_power_on(mgr, true);
332 break;
333 case DRM_MODE_DPMS_STANDBY:
334 case DRM_MODE_DPMS_SUSPEND:
335 case DRM_MODE_DPMS_OFF:
336 vidi_power_on(mgr, false);
337 break;
338 default:
339 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
340 break;
341 }
342
343 mutex_unlock(&ctx->lock);
344}
345
322static int vidi_mgr_initialize(struct exynos_drm_manager *mgr, 346static int vidi_mgr_initialize(struct exynos_drm_manager *mgr,
323 struct drm_device *drm_dev, int pipe) 347 struct drm_device *drm_dev, int pipe)
324{ 348{
@@ -390,30 +414,6 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
390 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); 414 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
391} 415}
392 416
393static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
394{
395 struct vidi_context *ctx = mgr->ctx;
396
397 DRM_DEBUG_KMS("%s\n", __FILE__);
398
399 if (enable != false && enable != true)
400 return -EINVAL;
401
402 if (enable) {
403 ctx->suspended = false;
404
405 /* if vblank was enabled status, enable it again. */
406 if (test_and_clear_bit(0, &ctx->irq_flags))
407 vidi_enable_vblank(mgr);
408
409 vidi_apply(mgr);
410 } else {
411 ctx->suspended = true;
412 }
413
414 return 0;
415}
416
417static int vidi_show_connection(struct device *dev, 417static int vidi_show_connection(struct device *dev,
418 struct device_attribute *attr, char *buf) 418 struct device_attribute *attr, char *buf)
419{ 419{
@@ -578,32 +578,11 @@ static int vidi_remove(struct platform_device *pdev)
578 return 0; 578 return 0;
579} 579}
580 580
581#ifdef CONFIG_PM_SLEEP
582static int vidi_suspend(struct device *dev)
583{
584 struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
585
586 return vidi_power_on(mgr, false);
587}
588
589static int vidi_resume(struct device *dev)
590{
591 struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
592
593 return vidi_power_on(mgr, true);
594}
595#endif
596
597static const struct dev_pm_ops vidi_pm_ops = {
598 SET_SYSTEM_SLEEP_PM_OPS(vidi_suspend, vidi_resume)
599};
600
601struct platform_driver vidi_driver = { 581struct platform_driver vidi_driver = {
602 .probe = vidi_probe, 582 .probe = vidi_probe,
603 .remove = vidi_remove, 583 .remove = vidi_remove,
604 .driver = { 584 .driver = {
605 .name = "exynos-drm-vidi", 585 .name = "exynos-drm-vidi",
606 .owner = THIS_MODULE, 586 .owner = THIS_MODULE,
607 .pm = &vidi_pm_ops,
608 }, 587 },
609}; 588};
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index b31a51da50f6..1a06a54a901f 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1789,6 +1789,8 @@ static void hdmi_poweron(struct exynos_drm_display *display)
1789 1789
1790 mutex_unlock(&hdata->hdmi_mutex); 1790 mutex_unlock(&hdata->hdmi_mutex);
1791 1791
1792 pm_runtime_get_sync(hdata->dev);
1793
1792 if (regulator_bulk_enable(res->regul_count, res->regul_bulk)) 1794 if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
1793 DRM_DEBUG_KMS("failed to enable regulator bulk\n"); 1795 DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1794 1796
@@ -1822,8 +1824,9 @@ static void hdmi_poweroff(struct exynos_drm_display *display)
1822 clk_disable_unprepare(res->hdmiphy); 1824 clk_disable_unprepare(res->hdmiphy);
1823 regulator_bulk_disable(res->regul_count, res->regul_bulk); 1825 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1824 1826
1825 mutex_lock(&hdata->hdmi_mutex); 1827 pm_runtime_put_sync(hdata->dev);
1826 1828
1829 mutex_lock(&hdata->hdmi_mutex);
1827 hdata->powered = false; 1830 hdata->powered = false;
1828 1831
1829out: 1832out:
@@ -1832,20 +1835,16 @@ out:
1832 1835
1833static void hdmi_dpms(struct exynos_drm_display *display, int mode) 1836static void hdmi_dpms(struct exynos_drm_display *display, int mode)
1834{ 1837{
1835 struct hdmi_context *hdata = display->ctx;
1836
1837 DRM_DEBUG_KMS("mode %d\n", mode); 1838 DRM_DEBUG_KMS("mode %d\n", mode);
1838 1839
1839 switch (mode) { 1840 switch (mode) {
1840 case DRM_MODE_DPMS_ON: 1841 case DRM_MODE_DPMS_ON:
1841 if (pm_runtime_suspended(hdata->dev)) 1842 hdmi_poweron(display);
1842 pm_runtime_get_sync(hdata->dev);
1843 break; 1843 break;
1844 case DRM_MODE_DPMS_STANDBY: 1844 case DRM_MODE_DPMS_STANDBY:
1845 case DRM_MODE_DPMS_SUSPEND: 1845 case DRM_MODE_DPMS_SUSPEND:
1846 case DRM_MODE_DPMS_OFF: 1846 case DRM_MODE_DPMS_OFF:
1847 if (!pm_runtime_suspended(hdata->dev)) 1847 hdmi_poweroff(display);
1848 pm_runtime_put_sync(hdata->dev);
1849 break; 1848 break;
1850 default: 1849 default:
1851 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); 1850 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
@@ -2085,11 +2084,11 @@ static int hdmi_probe(struct platform_device *pdev)
2085 goto err_hdmiphy; 2084 goto err_hdmiphy;
2086 } 2085 }
2087 2086
2087 pm_runtime_enable(dev);
2088
2088 hdmi_display.ctx = hdata; 2089 hdmi_display.ctx = hdata;
2089 exynos_drm_display_register(&hdmi_display); 2090 exynos_drm_display_register(&hdmi_display);
2090 2091
2091 pm_runtime_enable(dev);
2092
2093 return 0; 2092 return 0;
2094 2093
2095err_hdmiphy: 2094err_hdmiphy:
@@ -2105,88 +2104,19 @@ static int hdmi_remove(struct platform_device *pdev)
2105 struct exynos_drm_display *display = get_hdmi_display(dev); 2104 struct exynos_drm_display *display = get_hdmi_display(dev);
2106 struct hdmi_context *hdata = display->ctx; 2105 struct hdmi_context *hdata = display->ctx;
2107 2106
2108 pm_runtime_disable(dev);
2109
2110 put_device(&hdata->hdmiphy_port->dev); 2107 put_device(&hdata->hdmiphy_port->dev);
2111 put_device(&hdata->ddc_port->dev); 2108 put_device(&hdata->ddc_port->dev);
2109 pm_runtime_disable(&pdev->dev);
2112 2110
2113 return 0; 2111 return 0;
2114} 2112}
2115 2113
2116#ifdef CONFIG_PM_SLEEP
2117static int hdmi_suspend(struct device *dev)
2118{
2119 struct exynos_drm_display *display = get_hdmi_display(dev);
2120 struct hdmi_context *hdata = display->ctx;
2121
2122 disable_irq(hdata->irq);
2123
2124 hdata->hpd = false;
2125 if (hdata->drm_dev)
2126 drm_helper_hpd_irq_event(hdata->drm_dev);
2127
2128 if (pm_runtime_suspended(dev)) {
2129 DRM_DEBUG_KMS("Already suspended\n");
2130 return 0;
2131 }
2132
2133 hdmi_poweroff(display);
2134
2135 return 0;
2136}
2137
2138static int hdmi_resume(struct device *dev)
2139{
2140 struct exynos_drm_display *display = get_hdmi_display(dev);
2141 struct hdmi_context *hdata = display->ctx;
2142
2143 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2144
2145 enable_irq(hdata->irq);
2146
2147 if (!pm_runtime_suspended(dev)) {
2148 DRM_DEBUG_KMS("Already resumed\n");
2149 return 0;
2150 }
2151
2152 hdmi_poweron(display);
2153
2154 return 0;
2155}
2156#endif
2157
2158#ifdef CONFIG_PM_RUNTIME
2159static int hdmi_runtime_suspend(struct device *dev)
2160{
2161 struct exynos_drm_display *display = get_hdmi_display(dev);
2162
2163 hdmi_poweroff(display);
2164
2165 return 0;
2166}
2167
2168static int hdmi_runtime_resume(struct device *dev)
2169{
2170 struct exynos_drm_display *display = get_hdmi_display(dev);
2171
2172 hdmi_poweron(display);
2173
2174 return 0;
2175}
2176#endif
2177
2178static const struct dev_pm_ops hdmi_pm_ops = {
2179 SET_SYSTEM_SLEEP_PM_OPS(hdmi_suspend, hdmi_resume)
2180 SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
2181};
2182
2183struct platform_driver hdmi_driver = { 2114struct platform_driver hdmi_driver = {
2184 .probe = hdmi_probe, 2115 .probe = hdmi_probe,
2185 .remove = hdmi_remove, 2116 .remove = hdmi_remove,
2186 .driver = { 2117 .driver = {
2187 .name = "exynos-hdmi", 2118 .name = "exynos-hdmi",
2188 .owner = THIS_MODULE, 2119 .owner = THIS_MODULE,
2189 .pm = &hdmi_pm_ops,
2190 .of_match_table = hdmi_match_types, 2120 .of_match_table = hdmi_match_types,
2191 }, 2121 },
2192}; 2122};
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index d5228577cabb..ce288818d2c0 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -1061,6 +1061,8 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
1061 ctx->powered = true; 1061 ctx->powered = true;
1062 mutex_unlock(&ctx->mixer_mutex); 1062 mutex_unlock(&ctx->mixer_mutex);
1063 1063
1064 pm_runtime_get_sync(ctx->dev);
1065
1064 clk_prepare_enable(res->mixer); 1066 clk_prepare_enable(res->mixer);
1065 if (ctx->vp_enabled) { 1067 if (ctx->vp_enabled) {
1066 clk_prepare_enable(res->vp); 1068 clk_prepare_enable(res->vp);
@@ -1093,6 +1095,8 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
1093 clk_disable_unprepare(res->sclk_mixer); 1095 clk_disable_unprepare(res->sclk_mixer);
1094 } 1096 }
1095 1097
1098 pm_runtime_put_sync(ctx->dev);
1099
1096 mutex_lock(&ctx->mixer_mutex); 1100 mutex_lock(&ctx->mixer_mutex);
1097 ctx->powered = false; 1101 ctx->powered = false;
1098 1102
@@ -1102,18 +1106,14 @@ out:
1102 1106
1103static void mixer_dpms(struct exynos_drm_manager *mgr, int mode) 1107static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
1104{ 1108{
1105 struct mixer_context *mixer_ctx = mgr->ctx;
1106
1107 switch (mode) { 1109 switch (mode) {
1108 case DRM_MODE_DPMS_ON: 1110 case DRM_MODE_DPMS_ON:
1109 if (pm_runtime_suspended(mixer_ctx->dev)) 1111 mixer_poweron(mgr);
1110 pm_runtime_get_sync(mixer_ctx->dev);
1111 break; 1112 break;
1112 case DRM_MODE_DPMS_STANDBY: 1113 case DRM_MODE_DPMS_STANDBY:
1113 case DRM_MODE_DPMS_SUSPEND: 1114 case DRM_MODE_DPMS_SUSPEND:
1114 case DRM_MODE_DPMS_OFF: 1115 case DRM_MODE_DPMS_OFF:
1115 if (!pm_runtime_suspended(mixer_ctx->dev)) 1116 mixer_poweroff(mgr);
1116 pm_runtime_put_sync(mixer_ctx->dev);
1117 break; 1117 break;
1118 default: 1118 default:
1119 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); 1119 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
@@ -1250,66 +1250,10 @@ static int mixer_remove(struct platform_device *pdev)
1250 return 0; 1250 return 0;
1251} 1251}
1252 1252
1253#ifdef CONFIG_PM_SLEEP
1254static int mixer_suspend(struct device *dev)
1255{
1256 struct exynos_drm_manager *mgr = get_mixer_manager(dev);
1257
1258 if (pm_runtime_suspended(dev)) {
1259 DRM_DEBUG_KMS("Already suspended\n");
1260 return 0;
1261 }
1262
1263 mixer_poweroff(mgr);
1264
1265 return 0;
1266}
1267
1268static int mixer_resume(struct device *dev)
1269{
1270 struct exynos_drm_manager *mgr = get_mixer_manager(dev);
1271
1272 if (!pm_runtime_suspended(dev)) {
1273 DRM_DEBUG_KMS("Already resumed\n");
1274 return 0;
1275 }
1276
1277 mixer_poweron(mgr);
1278
1279 return 0;
1280}
1281#endif
1282
1283#ifdef CONFIG_PM_RUNTIME
1284static int mixer_runtime_suspend(struct device *dev)
1285{
1286 struct exynos_drm_manager *mgr = get_mixer_manager(dev);
1287
1288 mixer_poweroff(mgr);
1289
1290 return 0;
1291}
1292
1293static int mixer_runtime_resume(struct device *dev)
1294{
1295 struct exynos_drm_manager *mgr = get_mixer_manager(dev);
1296
1297 mixer_poweron(mgr);
1298
1299 return 0;
1300}
1301#endif
1302
1303static const struct dev_pm_ops mixer_pm_ops = {
1304 SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend, mixer_resume)
1305 SET_RUNTIME_PM_OPS(mixer_runtime_suspend, mixer_runtime_resume, NULL)
1306};
1307
1308struct platform_driver mixer_driver = { 1253struct platform_driver mixer_driver = {
1309 .driver = { 1254 .driver = {
1310 .name = "exynos-mixer", 1255 .name = "exynos-mixer",
1311 .owner = THIS_MODULE, 1256 .owner = THIS_MODULE,
1312 .pm = &mixer_pm_ops,
1313 .of_match_table = mixer_match_types, 1257 .of_match_table = mixer_match_types,
1314 }, 1258 },
1315 .probe = mixer_probe, 1259 .probe = mixer_probe,