From b67fa40a11b840208f00ef30ca4cdcb9c2e73b67 Mon Sep 17 00:00:00 2001
From: Alex Deucher <alexdeucher@gmail.com>
Date: Thu, 18 Mar 2010 15:32:27 -0400
Subject: [PATCH] drm/radeon/kms/pm: add voltage drop support for r1xx-r4xx

Voltage drop is controlled by a gpio pulled high or low.

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

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 9a7d16b..0ef5b2f 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -66,6 +66,49 @@ MODULE_FIRMWARE(FIRMWARE_R520);
  * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
  */
 
+void r100_set_voltage(struct radeon_device *rdev)
+{
+	int requested_index = rdev->pm.requested_power_state_index;
+	struct radeon_voltage *voltage;
+	u32 tmp;
+
+	/* first power state is lowest.  if there is no voltage drop,
+	 * no need to mess with it
+	 */
+	if (!rdev->pm.power_state[0].voltage_drop_active)
+		return;
+
+	if (rdev->pm.power_state[requested_index].voltage_drop_active) {
+		/* enable voltage drop */
+		voltage =
+			&rdev->pm.power_state[requested_index].clock_info[0].voltage;
+		if (voltage->gpio.valid) {
+			tmp = RREG32(voltage->gpio.reg);
+			if (voltage->active_high)
+				tmp |= voltage->gpio.mask;
+			else
+				tmp &= ~(voltage->gpio.mask);
+			WREG32(voltage->gpio.reg, tmp);
+			if (voltage->delay)
+				udelay(voltage->delay);
+		}
+	} else {
+		/* disable voltage drop */
+		voltage =
+			&rdev->pm.power_state[0].clock_info[0].voltage;
+		if (voltage->gpio.valid) {
+			tmp = RREG32(voltage->gpio.reg);
+			if (voltage->active_high)
+				tmp &= ~(voltage->gpio.mask);
+			else
+				tmp |= voltage->gpio.mask;
+			WREG32(voltage->gpio.reg, tmp);
+			if (voltage->delay)
+				udelay(voltage->delay);
+		}
+	}
+}
+
 void r100_get_power_state(struct radeon_device *rdev,
 			  enum radeon_pm_action action)
 {
@@ -183,7 +226,9 @@ void r100_set_power_state(struct radeon_device *rdev)
 		/* TODO */
 
 		/* set voltage */
-		/* TODO */
+		if (rdev->family <= CHIP_RS480)
+			r100_set_voltage(rdev);
+		/* TODO: r5xx+ */
 
 		/* set engine clock */
 		/* reclocking the engine appears to be ok as long as the engine is idle
-- 
1.5.6.3

