From 3494e3226155f773ce4522e8ad5b37bab22cb077 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
Date: Fri, 11 Sep 2009 20:22:02 +0200
Subject: [PATCH] drm/radeon/kms: correct min and max chip limits
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
 drivers/gpu/drm/radeon/Makefile        |    2 +-
 drivers/gpu/drm/radeon/radeon.h        |    2 +
 drivers/gpu/drm/radeon/radeon_device.c |    2 +
 drivers/gpu/drm/radeon/radeon_pm.c     |   80 ++++++++++++++++++++++++++++++++
 4 files changed, 85 insertions(+), 1 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/radeon_pm.c

diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 09a2892..b5713ee 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -49,7 +49,7 @@ radeon-y += radeon_device.o radeon_kms.o \
 	radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
 	rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
 	r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
-	r600_blit_kms.o
+	r600_blit_kms.o radeon_pm.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 40beff0..5cdf0a5 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -571,6 +571,8 @@ struct radeon_pm {
 	struct radeon_pm_state	chip_maximum;
 };
 
+void radeon_pm_init(struct radeon_device *rdev);
+
 
 /*
  * Benchmarking
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 72f6262..3792dad 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -595,6 +595,8 @@ int radeon_device_init(struct radeon_device *rdev,
 		if (r) {
 			return r;
 		}
+		/* Initialize power management */
+		radeon_pm_init(rdev);
 		/* Get vram informations */
 		radeon_vram_info(rdev);
 
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
new file mode 100644
index 0000000..9b79a0a
--- /dev/null
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -0,0 +1,80 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Original Authors:
+ *   Yang Zhao <yang@yangman.ca>
+ *   Matthias Hopf <mhopf@suse.de>
+ *
+ * Kernel port Authors:
+ *   Rafał Miłecki <zajec5@gmail.com>
+ */
+#include "drmP.h"
+#include "radeon.h"
+
+static void radeon_pm_print(char *name, struct radeon_pm_state *state)
+{
+	DRM_DEBUG("PM state %-8s: %8d0 KHz / %8d0 KHz / %6d mV\n",
+	    name, state->engine_clock, state->memory_clock,
+	    state->voltage);
+}
+
+/**
+ * radeon_pm_correct_min_max - corrects min and max chip limits
+ * @r_pm: radeon_pm
+ *
+ * Sometimes default configuration or manufacturer's provided configurations
+ * exceed limits read from AtomBIOS's firmware table. We can use that
+ * configurations as new limits. This is also useful when AtomBIOS's firmware
+ * doesn't have some limits.
+ **/
+static void radeon_pm_correct_min_max(struct radeon_pm *r_pm)
+{
+	/* Correct maximum limits using default state */
+	if (r_pm->chip_maximum.engine_clock < r_pm->chip_default.engine_clock)
+	    r_pm->chip_maximum.engine_clock = r_pm->chip_default.engine_clock;
+	if (r_pm->chip_maximum.memory_clock < r_pm->chip_default.memory_clock)
+	    r_pm->chip_maximum.memory_clock = r_pm->chip_default.memory_clock;
+	if (r_pm->chip_maximum.voltage < r_pm->chip_default.voltage)
+	    r_pm->chip_maximum.voltage = r_pm->chip_default.voltage;
+
+	/* Correct minimum limits using default state */
+	if (r_pm->chip_minimum.engine_clock > r_pm->chip_default.engine_clock)
+	    r_pm->chip_minimum.engine_clock = r_pm->chip_default.engine_clock;
+	if (r_pm->chip_minimum.memory_clock > r_pm->chip_default.memory_clock)
+	    r_pm->chip_minimum.memory_clock = r_pm->chip_default.memory_clock;
+	if (r_pm->chip_minimum.voltage > r_pm->chip_default.voltage)
+	    r_pm->chip_minimum.voltage = r_pm->chip_default.voltage;
+
+	/* TODO: Use configurations from AtomBIOS's PowerPlayInfo data table */
+}
+
+void radeon_pm_init(struct radeon_device *rdev)
+{
+	DRM_DEBUG("radeon: states from AtomBIOS's firmware:\n");
+	radeon_pm_print("Default", &rdev->pm.chip_default);
+	radeon_pm_print("Minimum", &rdev->pm.chip_minimum);
+	radeon_pm_print("Maximum", &rdev->pm.chip_maximum);
+
+	radeon_pm_correct_min_max(&rdev->pm);
+
+	DRM_DEBUG("radeon: states after correcting:\n");
+	radeon_pm_print("Default", &rdev->pm.chip_default);
+	radeon_pm_print("Minimum", &rdev->pm.chip_minimum);
+	radeon_pm_print("Maximum", &rdev->pm.chip_maximum);
+}
-- 
1.6.0.2

