drm/exynos: fixed pm feature for fimd module.

this patch separates fimd specific power on/off function from pm function
and the pm interfaces will call that function for power on or off.
and also removes unnecessary codes of resume function.

Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index ca83139..b6a737d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -158,7 +158,8 @@
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
-		pm_runtime_put_sync(subdrv_dev);
+		if (!ctx->suspended)
+			pm_runtime_put_sync(subdrv_dev);
 		break;
 	default:
 		DRM_DEBUG_KMS("unspecified mode %d\n", mode);
@@ -734,6 +735,46 @@
 	writel(val, ctx->regs + SHADOWCON);
 }
 
+static int fimd_power_on(struct fimd_context *ctx, bool enable)
+{
+	struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
+	struct device *dev = subdrv->manager.dev;
+
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	if (enable != false && enable != true)
+		return -EINVAL;
+
+	if (enable) {
+		int ret;
+
+		ret = clk_enable(ctx->bus_clk);
+		if (ret < 0)
+			return ret;
+
+		ret = clk_enable(ctx->lcd_clk);
+		if  (ret < 0) {
+			clk_disable(ctx->bus_clk);
+			return ret;
+		}
+
+		ctx->suspended = false;
+
+		/* if vblank was enabled status, enable it again. */
+		if (test_and_clear_bit(0, &ctx->irq_flags))
+			fimd_enable_vblank(dev);
+
+		fimd_apply(dev);
+	} else {
+		clk_disable(ctx->lcd_clk);
+		clk_disable(ctx->bus_clk);
+
+		ctx->suspended = true;
+	}
+
+	return 0;
+}
+
 static int __devinit fimd_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -911,39 +952,30 @@
 #ifdef CONFIG_PM_SLEEP
 static int fimd_suspend(struct device *dev)
 {
-	int ret;
+	struct fimd_context *ctx = get_fimd_context(dev);
 
 	if (pm_runtime_suspended(dev))
 		return 0;
 
-	ret = pm_runtime_suspend(dev);
-	if (ret < 0)
-		return ret;
-
-	return 0;
+	/*
+	 * 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.
+	 */
+	return fimd_power_on(ctx, false);
 }
 
 static int fimd_resume(struct device *dev)
 {
-	int ret;
+	struct fimd_context *ctx = get_fimd_context(dev);
 
-	ret = pm_runtime_resume(dev);
-	if (ret < 0) {
-		DRM_ERROR("failed to resume runtime pm.\n");
-		return ret;
-	}
-
-	pm_runtime_disable(dev);
-
-	ret = pm_runtime_set_active(dev);
-	if (ret < 0) {
-		DRM_ERROR("failed to active runtime pm.\n");
-		pm_runtime_enable(dev);
-		pm_runtime_suspend(dev);
-		return ret;
-	}
-
-	pm_runtime_enable(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 fimd_power_on(ctx, true);
 
 	return 0;
 }
@@ -956,39 +988,16 @@
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
-	clk_disable(ctx->lcd_clk);
-	clk_disable(ctx->bus_clk);
-
-	ctx->suspended = true;
-	return 0;
+	return fimd_power_on(ctx, false);
 }
 
 static int fimd_runtime_resume(struct device *dev)
 {
 	struct fimd_context *ctx = get_fimd_context(dev);
-	int ret;
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
-	ret = clk_enable(ctx->bus_clk);
-	if (ret < 0)
-		return ret;
-
-	ret = clk_enable(ctx->lcd_clk);
-	if  (ret < 0) {
-		clk_disable(ctx->bus_clk);
-		return ret;
-	}
-
-	ctx->suspended = false;
-
-	/* if vblank was enabled status, enable it again. */
-	if (test_and_clear_bit(0, &ctx->irq_flags))
-		fimd_enable_vblank(dev);
-
-	fimd_apply(dev);
-
-	return 0;
+	return fimd_power_on(ctx, true);
 }
 #endif