Skip to content

Commit af65c80

Browse files
atseanpauldaeinki
authored andcommitted
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 <[email protected]> Signed-off-by: Inki Dae <[email protected]>
1 parent a43b933 commit af65c80

File tree

5 files changed

+170
-288
lines changed

5 files changed

+170
-288
lines changed

drivers/gpu/drm/exynos/exynos_drm_drv.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* option) any later version.
1212
*/
1313

14+
#include <linux/pm_runtime.h>
1415
#include <drm/drmP.h>
1516
#include <drm/drm_crtc_helper.h>
1617

@@ -53,6 +54,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
5354
return -ENOMEM;
5455

5556
INIT_LIST_HEAD(&private->pageflip_event_list);
57+
dev_set_drvdata(dev->dev, dev);
5658
dev->dev_private = (void *)private;
5759

5860
/*
@@ -163,6 +165,41 @@ static const struct file_operations exynos_drm_gem_fops = {
163165
.mmap = exynos_drm_gem_mmap_buffer,
164166
};
165167

168+
static 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+
187+
static 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+
166203
static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
167204
{
168205
struct drm_exynos_file_private *file_priv;
@@ -300,6 +337,8 @@ static struct drm_driver exynos_drm_driver = {
300337
DRIVER_GEM | DRIVER_PRIME,
301338
.load = exynos_drm_load,
302339
.unload = exynos_drm_unload,
340+
.suspend = exynos_drm_suspend,
341+
.resume = exynos_drm_resume,
303342
.open = exynos_drm_open,
304343
.preclose = exynos_drm_preclose,
305344
.lastclose = exynos_drm_lastclose,
@@ -334,6 +373,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
334373
if (ret)
335374
return ret;
336375

376+
pm_runtime_enable(&pdev->dev);
377+
pm_runtime_get_sync(&pdev->dev);
378+
337379
return drm_platform_init(&exynos_drm_driver, pdev);
338380
}
339381

@@ -344,12 +386,67 @@ static int exynos_drm_platform_remove(struct platform_device *pdev)
344386
return 0;
345387
}
346388

389+
#ifdef CONFIG_PM_SLEEP
390+
static 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+
402+
static 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
414+
static 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+
426+
static 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+
437+
static 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+
347443
static struct platform_driver exynos_drm_platform_driver = {
348444
.probe = exynos_drm_platform_probe,
349445
.remove = exynos_drm_platform_remove,
350446
.driver = {
351447
.owner = THIS_MODULE,
352448
.name = "exynos-drm",
449+
.pm = &exynos_drm_pm_ops,
353450
},
354451
};
355452

drivers/gpu/drm/exynos/exynos_drm_fimd.c

Lines changed: 9 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,8 @@ static int fimd_poweron(struct exynos_drm_manager *mgr)
732732

733733
ctx->suspended = false;
734734

735+
pm_runtime_get_sync(ctx->dev);
736+
735737
ret = clk_prepare_enable(ctx->bus_clk);
736738
if (ret < 0) {
737739
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)
785787
clk_disable_unprepare(ctx->lcd_clk);
786788
clk_disable_unprepare(ctx->bus_clk);
787789

790+
pm_runtime_put_sync(ctx->dev);
791+
788792
ctx->suspended = true;
789793
return 0;
790794
}
791795

792796
static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
793797
{
794-
struct fimd_context *ctx = mgr->ctx;
795-
796-
DRM_DEBUG_KMS("%d\n", mode);
798+
DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
797799

798800
switch (mode) {
799801
case DRM_MODE_DPMS_ON:
800-
/*
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);
802+
fimd_poweron(mgr);
808803
break;
809804
case DRM_MODE_DPMS_STANDBY:
810805
case DRM_MODE_DPMS_SUSPEND:
811806
case DRM_MODE_DPMS_OFF:
812-
if (!ctx->suspended)
813-
pm_runtime_put_sync(ctx->dev);
807+
fimd_poweroff(mgr);
814808
break;
815809
default:
816810
DRM_DEBUG_KMS("unspecified mode %d\n", mode);
@@ -929,7 +923,6 @@ static int fimd_probe(struct platform_device *pdev)
929923
exynos_drm_manager_register(&fimd_manager);
930924

931925
pm_runtime_enable(dev);
932-
pm_runtime_get_sync(dev);
933926

934927
for (win = 0; win < WINDOWS_NR; win++)
935928
fimd_clear_win(ctx, win);
@@ -939,84 +932,23 @@ static int fimd_probe(struct platform_device *pdev)
939932

940933
static int fimd_remove(struct platform_device *pdev)
941934
{
942-
struct device *dev = &pdev->dev;
943935
struct exynos_drm_manager *mgr = platform_get_drvdata(pdev);
944-
struct fimd_context *ctx = mgr->ctx;
945936

946937
exynos_drm_manager_unregister(&fimd_manager);
947938

948-
if (ctx->suspended)
949-
goto out;
950-
951-
pm_runtime_set_suspended(dev);
952-
pm_runtime_put_sync(dev);
939+
fimd_dpms(mgr, DRM_MODE_DPMS_OFF);
953940

954-
out:
955-
pm_runtime_disable(dev);
956-
957-
return 0;
958-
}
959-
960-
#ifdef CONFIG_PM_SLEEP
961-
static 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);
941+
pm_runtime_disable(&pdev->dev);
972942

973943
return 0;
974944
}
975945

976-
static 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
993-
static 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-
1000-
static 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-
1008-
static 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-
1013946
struct platform_driver fimd_driver = {
1014947
.probe = fimd_probe,
1015948
.remove = fimd_remove,
1016949
.driver = {
1017950
.name = "exynos4-fb",
1018951
.owner = THIS_MODULE,
1019-
.pm = &fimd_pm_ops,
1020952
.of_match_table = fimd_driver_dt_match,
1021953
},
1022954
};

0 commit comments

Comments
 (0)