mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-30 14:06:51 +07:00
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>
This commit is contained in:
parent
a43b933bcb
commit
af65c80487
@ -11,6 +11,7 @@
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
||||
@ -53,6 +54,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&private->pageflip_event_list);
|
||||
dev_set_drvdata(dev->dev, dev);
|
||||
dev->dev_private = (void *)private;
|
||||
|
||||
/*
|
||||
@ -163,6 +165,41 @@ static const struct file_operations exynos_drm_gem_fops = {
|
||||
.mmap = exynos_drm_gem_mmap_buffer,
|
||||
};
|
||||
|
||||
static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
int old_dpms = connector->dpms;
|
||||
|
||||
if (connector->funcs->dpms)
|
||||
connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
|
||||
|
||||
/* Set the old mode back to the connector for resume */
|
||||
connector->dpms = old_dpms;
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_drm_resume(struct drm_device *dev)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
if (connector->funcs->dpms)
|
||||
connector->funcs->dpms(connector, connector->dpms);
|
||||
}
|
||||
|
||||
drm_helper_resume_force_mode(dev);
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
|
||||
{
|
||||
struct drm_exynos_file_private *file_priv;
|
||||
@ -300,6 +337,8 @@ static struct drm_driver exynos_drm_driver = {
|
||||
DRIVER_GEM | DRIVER_PRIME,
|
||||
.load = exynos_drm_load,
|
||||
.unload = exynos_drm_unload,
|
||||
.suspend = exynos_drm_suspend,
|
||||
.resume = exynos_drm_resume,
|
||||
.open = exynos_drm_open,
|
||||
.preclose = exynos_drm_preclose,
|
||||
.lastclose = exynos_drm_lastclose,
|
||||
@ -334,6 +373,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
return drm_platform_init(&exynos_drm_driver, pdev);
|
||||
}
|
||||
|
||||
@ -344,12 +386,67 @@ static int exynos_drm_platform_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int exynos_drm_sys_suspend(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
pm_message_t message;
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
message.event = PM_EVENT_SUSPEND;
|
||||
return exynos_drm_suspend(drm_dev, message);
|
||||
}
|
||||
|
||||
static int exynos_drm_sys_resume(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
return exynos_drm_resume(drm_dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int exynos_drm_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
pm_message_t message;
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
message.event = PM_EVENT_SUSPEND;
|
||||
return exynos_drm_suspend(drm_dev, message);
|
||||
}
|
||||
|
||||
static int exynos_drm_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
|
||||
if (!pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
return exynos_drm_resume(drm_dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops exynos_drm_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume)
|
||||
SET_RUNTIME_PM_OPS(exynos_drm_runtime_suspend,
|
||||
exynos_drm_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver exynos_drm_platform_driver = {
|
||||
.probe = exynos_drm_platform_probe,
|
||||
.remove = exynos_drm_platform_remove,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "exynos-drm",
|
||||
.pm = &exynos_drm_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -732,6 +732,8 @@ static int fimd_poweron(struct exynos_drm_manager *mgr)
|
||||
|
||||
ctx->suspended = false;
|
||||
|
||||
pm_runtime_get_sync(ctx->dev);
|
||||
|
||||
ret = clk_prepare_enable(ctx->bus_clk);
|
||||
if (ret < 0) {
|
||||
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)
|
||||
clk_disable_unprepare(ctx->lcd_clk);
|
||||
clk_disable_unprepare(ctx->bus_clk);
|
||||
|
||||
pm_runtime_put_sync(ctx->dev);
|
||||
|
||||
ctx->suspended = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
|
||||
{
|
||||
struct fimd_context *ctx = mgr->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("%d\n", mode);
|
||||
DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
/*
|
||||
* enable fimd hardware only if suspended status.
|
||||
*
|
||||
* P.S. fimd_dpms function would be called at booting time so
|
||||
* clk_enable could be called double time.
|
||||
*/
|
||||
if (ctx->suspended)
|
||||
pm_runtime_get_sync(ctx->dev);
|
||||
fimd_poweron(mgr);
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
if (!ctx->suspended)
|
||||
pm_runtime_put_sync(ctx->dev);
|
||||
fimd_poweroff(mgr);
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("unspecified mode %d\n", mode);
|
||||
@ -929,7 +923,6 @@ static int fimd_probe(struct platform_device *pdev)
|
||||
exynos_drm_manager_register(&fimd_manager);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
for (win = 0; win < WINDOWS_NR; win++)
|
||||
fimd_clear_win(ctx, win);
|
||||
@ -939,84 +932,23 @@ static int fimd_probe(struct platform_device *pdev)
|
||||
|
||||
static int fimd_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct exynos_drm_manager *mgr = platform_get_drvdata(pdev);
|
||||
struct fimd_context *ctx = mgr->ctx;
|
||||
|
||||
exynos_drm_manager_unregister(&fimd_manager);
|
||||
|
||||
if (ctx->suspended)
|
||||
goto out;
|
||||
fimd_dpms(mgr, DRM_MODE_DPMS_OFF);
|
||||
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
out:
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int fimd_suspend(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_manager *mgr = get_fimd_manager(dev);
|
||||
|
||||
/*
|
||||
* do not use pm_runtime_suspend(). if pm_runtime_suspend() is
|
||||
* called here, an error would be returned by that interface
|
||||
* because the usage_count of pm runtime is more than 1.
|
||||
*/
|
||||
if (!pm_runtime_suspended(dev))
|
||||
return fimd_poweroff(mgr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fimd_resume(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_manager *mgr = get_fimd_manager(dev);
|
||||
|
||||
/*
|
||||
* if entered to sleep when lcd panel was on, the usage_count
|
||||
* of pm runtime would still be 1 so in this case, fimd driver
|
||||
* should be on directly not drawing on pm runtime interface.
|
||||
*/
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
return fimd_poweron(mgr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int fimd_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_manager *mgr = get_fimd_manager(dev);
|
||||
|
||||
return fimd_poweroff(mgr);
|
||||
}
|
||||
|
||||
static int fimd_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_manager *mgr = get_fimd_manager(dev);
|
||||
|
||||
return fimd_poweron(mgr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops fimd_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(fimd_suspend, fimd_resume)
|
||||
SET_RUNTIME_PM_OPS(fimd_runtime_suspend, fimd_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
struct platform_driver fimd_driver = {
|
||||
.probe = fimd_probe,
|
||||
.remove = fimd_remove,
|
||||
.driver = {
|
||||
.name = "exynos4-fb",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &fimd_pm_ops,
|
||||
.of_match_table = fimd_driver_dt_match,
|
||||
},
|
||||
};
|
||||
|
@ -140,31 +140,6 @@ static struct exynos_drm_display vidi_display = {
|
||||
.ops = &vidi_display_ops,
|
||||
};
|
||||
|
||||
static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
|
||||
{
|
||||
struct vidi_context *ctx = mgr->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("%d\n", mode);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
/* TODO. */
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
/* TODO. */
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("unspecified mode %d\n", mode);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&ctx->lock);
|
||||
}
|
||||
|
||||
static void vidi_apply(struct exynos_drm_manager *mgr)
|
||||
{
|
||||
struct vidi_context *ctx = mgr->ctx;
|
||||
@ -319,6 +294,55 @@ static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
|
||||
/* TODO. */
|
||||
}
|
||||
|
||||
static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
|
||||
{
|
||||
struct vidi_context *ctx = mgr->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (enable != false && enable != true)
|
||||
return -EINVAL;
|
||||
|
||||
if (enable) {
|
||||
ctx->suspended = false;
|
||||
|
||||
/* if vblank was enabled status, enable it again. */
|
||||
if (test_and_clear_bit(0, &ctx->irq_flags))
|
||||
vidi_enable_vblank(mgr);
|
||||
|
||||
vidi_apply(mgr);
|
||||
} else {
|
||||
ctx->suspended = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
|
||||
{
|
||||
struct vidi_context *ctx = mgr->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("%d\n", mode);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
vidi_power_on(mgr, true);
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
vidi_power_on(mgr, false);
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("unspecified mode %d\n", mode);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&ctx->lock);
|
||||
}
|
||||
|
||||
static int vidi_mgr_initialize(struct exynos_drm_manager *mgr,
|
||||
struct drm_device *drm_dev, int pipe)
|
||||
{
|
||||
@ -390,30 +414,6 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
|
||||
exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
|
||||
}
|
||||
|
||||
static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
|
||||
{
|
||||
struct vidi_context *ctx = mgr->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (enable != false && enable != true)
|
||||
return -EINVAL;
|
||||
|
||||
if (enable) {
|
||||
ctx->suspended = false;
|
||||
|
||||
/* if vblank was enabled status, enable it again. */
|
||||
if (test_and_clear_bit(0, &ctx->irq_flags))
|
||||
vidi_enable_vblank(mgr);
|
||||
|
||||
vidi_apply(mgr);
|
||||
} else {
|
||||
ctx->suspended = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidi_show_connection(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@ -578,32 +578,11 @@ static int vidi_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int vidi_suspend(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
|
||||
|
||||
return vidi_power_on(mgr, false);
|
||||
}
|
||||
|
||||
static int vidi_resume(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
|
||||
|
||||
return vidi_power_on(mgr, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops vidi_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(vidi_suspend, vidi_resume)
|
||||
};
|
||||
|
||||
struct platform_driver vidi_driver = {
|
||||
.probe = vidi_probe,
|
||||
.remove = vidi_remove,
|
||||
.driver = {
|
||||
.name = "exynos-drm-vidi",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &vidi_pm_ops,
|
||||
},
|
||||
};
|
||||
|
@ -1789,6 +1789,8 @@ static void hdmi_poweron(struct exynos_drm_display *display)
|
||||
|
||||
mutex_unlock(&hdata->hdmi_mutex);
|
||||
|
||||
pm_runtime_get_sync(hdata->dev);
|
||||
|
||||
if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
|
||||
DRM_DEBUG_KMS("failed to enable regulator bulk\n");
|
||||
|
||||
@ -1822,8 +1824,9 @@ static void hdmi_poweroff(struct exynos_drm_display *display)
|
||||
clk_disable_unprepare(res->hdmiphy);
|
||||
regulator_bulk_disable(res->regul_count, res->regul_bulk);
|
||||
|
||||
mutex_lock(&hdata->hdmi_mutex);
|
||||
pm_runtime_put_sync(hdata->dev);
|
||||
|
||||
mutex_lock(&hdata->hdmi_mutex);
|
||||
hdata->powered = false;
|
||||
|
||||
out:
|
||||
@ -1832,20 +1835,16 @@ static void hdmi_poweroff(struct exynos_drm_display *display)
|
||||
|
||||
static void hdmi_dpms(struct exynos_drm_display *display, int mode)
|
||||
{
|
||||
struct hdmi_context *hdata = display->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("mode %d\n", mode);
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
if (pm_runtime_suspended(hdata->dev))
|
||||
pm_runtime_get_sync(hdata->dev);
|
||||
hdmi_poweron(display);
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
if (!pm_runtime_suspended(hdata->dev))
|
||||
pm_runtime_put_sync(hdata->dev);
|
||||
hdmi_poweroff(display);
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
|
||||
@ -2085,11 +2084,11 @@ static int hdmi_probe(struct platform_device *pdev)
|
||||
goto err_hdmiphy;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
hdmi_display.ctx = hdata;
|
||||
exynos_drm_display_register(&hdmi_display);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_hdmiphy:
|
||||
@ -2105,88 +2104,19 @@ static int hdmi_remove(struct platform_device *pdev)
|
||||
struct exynos_drm_display *display = get_hdmi_display(dev);
|
||||
struct hdmi_context *hdata = display->ctx;
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
put_device(&hdata->hdmiphy_port->dev);
|
||||
put_device(&hdata->ddc_port->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int hdmi_suspend(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_display *display = get_hdmi_display(dev);
|
||||
struct hdmi_context *hdata = display->ctx;
|
||||
|
||||
disable_irq(hdata->irq);
|
||||
|
||||
hdata->hpd = false;
|
||||
if (hdata->drm_dev)
|
||||
drm_helper_hpd_irq_event(hdata->drm_dev);
|
||||
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
DRM_DEBUG_KMS("Already suspended\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdmi_poweroff(display);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hdmi_resume(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_display *display = get_hdmi_display(dev);
|
||||
struct hdmi_context *hdata = display->ctx;
|
||||
|
||||
hdata->hpd = gpio_get_value(hdata->hpd_gpio);
|
||||
|
||||
enable_irq(hdata->irq);
|
||||
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
DRM_DEBUG_KMS("Already resumed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdmi_poweron(display);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int hdmi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_display *display = get_hdmi_display(dev);
|
||||
|
||||
hdmi_poweroff(display);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hdmi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_display *display = get_hdmi_display(dev);
|
||||
|
||||
hdmi_poweron(display);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops hdmi_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(hdmi_suspend, hdmi_resume)
|
||||
SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
struct platform_driver hdmi_driver = {
|
||||
.probe = hdmi_probe,
|
||||
.remove = hdmi_remove,
|
||||
.driver = {
|
||||
.name = "exynos-hdmi",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &hdmi_pm_ops,
|
||||
.of_match_table = hdmi_match_types,
|
||||
},
|
||||
};
|
||||
|
@ -1061,6 +1061,8 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
|
||||
ctx->powered = true;
|
||||
mutex_unlock(&ctx->mixer_mutex);
|
||||
|
||||
pm_runtime_get_sync(ctx->dev);
|
||||
|
||||
clk_prepare_enable(res->mixer);
|
||||
if (ctx->vp_enabled) {
|
||||
clk_prepare_enable(res->vp);
|
||||
@ -1093,6 +1095,8 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
|
||||
clk_disable_unprepare(res->sclk_mixer);
|
||||
}
|
||||
|
||||
pm_runtime_put_sync(ctx->dev);
|
||||
|
||||
mutex_lock(&ctx->mixer_mutex);
|
||||
ctx->powered = false;
|
||||
|
||||
@ -1102,18 +1106,14 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
|
||||
|
||||
static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
|
||||
{
|
||||
struct mixer_context *mixer_ctx = mgr->ctx;
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
if (pm_runtime_suspended(mixer_ctx->dev))
|
||||
pm_runtime_get_sync(mixer_ctx->dev);
|
||||
mixer_poweron(mgr);
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
if (!pm_runtime_suspended(mixer_ctx->dev))
|
||||
pm_runtime_put_sync(mixer_ctx->dev);
|
||||
mixer_poweroff(mgr);
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
|
||||
@ -1250,66 +1250,10 @@ static int mixer_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int mixer_suspend(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_manager *mgr = get_mixer_manager(dev);
|
||||
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
DRM_DEBUG_KMS("Already suspended\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mixer_poweroff(mgr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_resume(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_manager *mgr = get_mixer_manager(dev);
|
||||
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
DRM_DEBUG_KMS("Already resumed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mixer_poweron(mgr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int mixer_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_manager *mgr = get_mixer_manager(dev);
|
||||
|
||||
mixer_poweroff(mgr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_manager *mgr = get_mixer_manager(dev);
|
||||
|
||||
mixer_poweron(mgr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops mixer_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend, mixer_resume)
|
||||
SET_RUNTIME_PM_OPS(mixer_runtime_suspend, mixer_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
struct platform_driver mixer_driver = {
|
||||
.driver = {
|
||||
.name = "exynos-mixer",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &mixer_pm_ops,
|
||||
.of_match_table = mixer_match_types,
|
||||
},
|
||||
.probe = mixer_probe,
|
||||
|
Loading…
Reference in New Issue
Block a user