CHROMIUM: drm/i915: Limit the GPU clock to 650MHz on Ninja/Sumo

The ninja/sumo power rails don't seem too stable, so this change
limits the GPU clock to 650MHz on the GPU for this device.

This change was previously:
https://chromium-review.googlesource.com/314110
but was dropped during the kernel 4.4 transition.

BUG=chrome-os-partner:46218, chromium:696734
TEST=sumo kernel 4.4 builds

Change-Id: Ie6a8a3d0f5ebeb17c7d552983960d52eac003b3c
Reviewed-on: https://chromium-review.googlesource.com/481224
Commit-Ready: Stéphane Marchesin <marcheu@chromium.org>
Tested-by: Stéphane Marchesin <marcheu@chromium.org>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/481405
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 0ed2e6b8..c3ad10e 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -26,6 +26,7 @@
  */
 
 #include <linux/cpufreq.h>
+#include <linux/dmi.h>
 #include "i915_drv.h"
 #include "intel_drv.h"
 #include "../../../platform/x86/intel_ips.h"
@@ -5271,6 +5272,62 @@
 	return rp1;
 }
 
+static int intel_broken_gpupower_dmi_callback(const struct dmi_system_id *id)
+{
+	return 1;
+}
+
+static const struct dmi_system_id intel_broken_gpupower_dmi[] = {
+	{
+		.callback = intel_broken_gpupower_dmi_callback,
+		.ident = "AOPEN Ninja",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Ninja"),
+		},
+	},
+	{
+		.callback = intel_broken_gpupower_dmi_callback,
+		.ident = "AOPEN Sumo",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Sumo"),
+		},
+	},
+	{ }
+};
+
+static int valleyview_freq_opcode(int ddr_freq, int val)
+{
+	int mult, base;
+
+	switch (ddr_freq) {
+		case 800:
+			mult = 20;
+			base = 120;
+			break;
+		case 1066:
+			mult = 22;
+			base = 133;
+			break;
+		case 1333:
+			mult = 21;
+			base = 125;
+			break;
+		default:
+			return -1;
+	}
+
+	val /= mult;
+	val -= base / mult;
+	val += 0xbd;
+
+	if (val > 0xea)
+		val = 0xea;
+
+	return val;
+}
+
 static int valleyview_rps_max_freq(struct drm_i915_private *dev_priv)
 {
 	u32 val, rp0;
@@ -5281,6 +5338,12 @@
 	/* Clamp to max */
 	rp0 = min_t(u32, rp0, 0xea);
 
+	/* Clamp to 650 MHz on AOpen baytrail chromeboxes */
+	if (dmi_check_system(intel_broken_gpupower_dmi)) {
+               DRM_INFO("AOPEN chromebox: clamping GPU clock to 650 MHz\n");
+               rp0 = min_t(u32, rp0, valleyview_freq_opcode(dev_priv->mem_freq, 650));
+	}
+
 	return rp0;
 }