From 9d3e1e6cc94f0bd6739c00e29aef148c0b194192 Mon Sep 17 00:00:00 2001
From: Alex Deucher <alexdeucher@gmail.com>
Date: Mon, 4 Jan 2010 18:23:55 -0500
Subject: [PATCH] drm/radeon/kms: update LVDS power sequence

Based on r4xx atombios.  This might help LVDS resume
on some pre-atom laptops.

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
---
 drivers/gpu/drm/radeon/radeon_legacy_encoders.c |   57 ++++++++++++++---------
 1 files changed, 35 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index eb1af3a..cd4d16c 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -44,7 +44,7 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
+	u32 lvds_gen_cntl, pixclks_cntl;
 	int panel_pwr_delay = 2000;
 	DRM_DEBUG("\n");
 
@@ -60,20 +60,8 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-		disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN);
-		disp_pwr_man |= RADEON_AUTO_PWRUP_EN;
-		WREG32(RADEON_DISP_PWR_MAN, disp_pwr_man);
-		lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
-		lvds_pll_cntl |= RADEON_LVDS_PLL_EN;
-		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
-		udelay(1000);
-
-		lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
-		lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
-		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
-
 		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
-		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON);
+		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON);
 		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
 		udelay(panel_pwr_delay * 1000);
 		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
@@ -85,7 +73,7 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 		WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
 		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
 		lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
-		lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
+		lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON);
 		udelay(panel_pwr_delay * 1000);
 		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
 		WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
@@ -131,14 +119,29 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	uint32_t lvds_pll_cntl, lvds_gen_cntl, lvds_ss_gen_cntl;
+	u32 lvds_pll_cntl, lvds_gen_cntl, lvds_ss_gen_cntl, disp_pwr_man;
+	int panel_pwr_delay = 2000;
 
 	DRM_DEBUG("\n");
 
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			panel_pwr_delay = lvds->panel_pwr_delay;
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			panel_pwr_delay = lvds->panel_pwr_delay;
+		}
+	}
+
 	lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
-	lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
+	lvds_pll_cntl &= ~(RADEON_LVDS_PLL_EN | RADEON_LVDS_PLL_RESET);
 
 	lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
+
+	disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN);
+	disp_pwr_man |= RADEON_AUTO_PWRUP_EN;
+
 	if (rdev->is_atom_bios) {
 		/* LVDS_GEN_CNTL parameters are computed in LVDSEncoderControl
 		 * need to call that on resume to set up the reg properly.
@@ -158,10 +161,12 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
 		} else
 			lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
 	}
-	lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
+	lvds_gen_cntl |= (RADEON_LVDS_DISPLAY_DIS |
+			  /*RADEON_LVDS_DIGON | */
+			  RADEON_LVDS_EN);
+
 	lvds_gen_cntl &= ~(RADEON_LVDS_ON |
 			   RADEON_LVDS_BLON |
-			   RADEON_LVDS_EN |
 			   RADEON_LVDS_RST_FM);
 
 	if (ASIC_IS_R300(rdev))
@@ -180,9 +185,17 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
 			lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2;
 	}
 
-	WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
-	WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
-	WREG32(RADEON_LVDS_SS_GEN_CNTL, lvds_ss_gen_cntl);
+	if (rdev->is_atom_bios) {
+		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
+	} else {
+		WREG32(RADEON_LVDS_SS_GEN_CNTL, lvds_ss_gen_cntl);
+		WREG32(RADEON_DISP_PWR_MAN, disp_pwr_man);
+		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl | RADEON_LVDS_PLL_EN);
+		udelay(panel_pwr_delay * 1000);
+		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
+		udelay(panel_pwr_delay * 1000);
+		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
+	}
 
 	if (rdev->family == CHIP_RV410)
 		WREG32(RADEON_CLOCK_CNTL_INDEX, 0);
-- 
1.5.6.3

