Blob Blame Raw
From 0725e95ea56698774e893edb7e7276b1d6890954 Mon Sep 17 00:00:00 2001
From: Bernhard Rosenkraenzer <br@blankpage.ch>
Date: Wed, 10 Mar 2010 12:36:43 +0100
Subject: USB: qcserial: add new device ids

From: Bernhard Rosenkraenzer <br@blankpage.ch>

commit 0725e95ea56698774e893edb7e7276b1d6890954 upstream.

This patch adds various USB device IDs for Gobi 2000 devices, as found in the
drivers available at https://www.codeaurora.org/wiki/GOBI_Releases

Signed-off-by: Bernhard Rosenkraenzer <bero@arklinux.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/usb/serial/qcserial.c |   29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -47,6 +47,35 @@ static struct usb_device_id id_table[] =
 	{USB_DEVICE(0x05c6, 0x9221)},	/* Generic Gobi QDL device */
 	{USB_DEVICE(0x05c6, 0x9231)},	/* Generic Gobi QDL device */
 	{USB_DEVICE(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */
+	{USB_DEVICE(0x413c, 0x8185)},	/* Dell Gobi 2000 QDL device (N0218, VU936) */
+	{USB_DEVICE(0x413c, 0x8186)},	/* Dell Gobi 2000 Modem device (N0218, VU936) */
+	{USB_DEVICE(0x05c6, 0x9224)},	/* Sony Gobi 2000 QDL device (N0279, VU730) */
+	{USB_DEVICE(0x05c6, 0x9225)},	/* Sony Gobi 2000 Modem device (N0279, VU730) */
+	{USB_DEVICE(0x05c6, 0x9244)},	/* Samsung Gobi 2000 QDL device (VL176) */
+	{USB_DEVICE(0x05c6, 0x9245)},	/* Samsung Gobi 2000 Modem device (VL176) */
+	{USB_DEVICE(0x03f0, 0x241d)},	/* HP Gobi 2000 QDL device (VP412) */
+	{USB_DEVICE(0x03f0, 0x251d)},	/* HP Gobi 2000 Modem device (VP412) */
+	{USB_DEVICE(0x05c6, 0x9214)},	/* Acer Gobi 2000 QDL device (VP413) */
+	{USB_DEVICE(0x05c6, 0x9215)},	/* Acer Gobi 2000 Modem device (VP413) */
+	{USB_DEVICE(0x05c6, 0x9264)},	/* Asus Gobi 2000 QDL device (VR305) */
+	{USB_DEVICE(0x05c6, 0x9265)},	/* Asus Gobi 2000 Modem device (VR305) */
+	{USB_DEVICE(0x05c6, 0x9234)},	/* Top Global Gobi 2000 QDL device (VR306) */
+	{USB_DEVICE(0x05c6, 0x9235)},	/* Top Global Gobi 2000 Modem device (VR306) */
+	{USB_DEVICE(0x05c6, 0x9274)},	/* iRex Technologies Gobi 2000 QDL device (VR307) */
+	{USB_DEVICE(0x05c6, 0x9275)},	/* iRex Technologies Gobi 2000 Modem device (VR307) */
+	{USB_DEVICE(0x1199, 0x9000)},	/* Sierra Wireless Gobi 2000 QDL device (VT773) */
+	{USB_DEVICE(0x1199, 0x9001)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9002)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9003)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9004)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9005)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9006)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9007)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9008)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9009)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x900a)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x16d8, 0x8001)},	/* CMDTech Gobi 2000 QDL device (VU922) */
+	{USB_DEVICE(0x16d8, 0x8002)},	/* CMDTech Gobi 2000 Modem device (VU922) */
 	{ }				/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
From 9cf00977da092096c7a983276dad8b3002d23a99 Mon Sep 17 00:00:00 2001
From: Adam Jackson <ajax@redhat.com>
Date: Thu, 3 Dec 2009 17:44:36 -0500
Subject: drm/edid: Unify detailed block parsing between base and extension blocks

From: Adam Jackson <ajax@redhat.com>

commit 9cf00977da092096c7a983276dad8b3002d23a99 upstream.

Also fix an embarassing bug in standard timing subblock parsing that
would result in an infinite loop.

Signed-off-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Cc: maximilian attems <max@stro.at>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/drm_edid.c |  163 ++++++++++++++++-----------------------------
 1 file changed, 61 insertions(+), 102 deletions(-)

--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -834,8 +834,57 @@ static int add_standard_modes(struct drm
 	return modes;
 }
 
+static int add_detailed_modes(struct drm_connector *connector,
+			      struct detailed_timing *timing,
+			      struct edid *edid, u32 quirks, int preferred)
+{
+	int i, modes = 0;
+	struct detailed_non_pixel *data = &timing->data.other_data;
+	int timing_level = standard_timing_level(edid);
+	struct drm_display_mode *newmode;
+	struct drm_device *dev = connector->dev;
+
+	if (timing->pixel_clock) {
+		newmode = drm_mode_detailed(dev, edid, timing, quirks);
+		if (!newmode)
+			return 0;
+
+		if (preferred)
+			newmode->type |= DRM_MODE_TYPE_PREFERRED;
+
+		drm_mode_probed_add(connector, newmode);
+		return 1;
+	}
+
+	/* other timing types */
+	switch (data->type) {
+	case EDID_DETAIL_MONITOR_RANGE:
+		/* Get monitor range data */
+		break;
+	case EDID_DETAIL_STD_MODES:
+		/* Six modes per detailed section */
+		for (i = 0; i < 6; i++) {
+			struct std_timing *std;
+			struct drm_display_mode *newmode;
+
+			std = &data->data.timings[i];
+			newmode = drm_mode_std(dev, std, edid->revision,
+					       timing_level);
+			if (newmode) {
+				drm_mode_probed_add(connector, newmode);
+				modes++;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+
+	return modes;
+}
+
 /**
- * add_detailed_modes - get detailed mode info from EDID data
+ * add_detailed_info - get detailed mode info from EDID data
  * @connector: attached connector
  * @edid: EDID block to scan
  * @quirks: quirks to apply
@@ -846,67 +895,24 @@ static int add_standard_modes(struct drm
 static int add_detailed_info(struct drm_connector *connector,
 			     struct edid *edid, u32 quirks)
 {
-	struct drm_device *dev = connector->dev;
-	int i, j, modes = 0;
-	int timing_level;
-
-	timing_level = standard_timing_level(edid);
+	int i, modes = 0;
 
 	for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
 		struct detailed_timing *timing = &edid->detailed_timings[i];
-		struct detailed_non_pixel *data = &timing->data.other_data;
-		struct drm_display_mode *newmode;
+		int preferred = (i == 0) && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);
 
-		/* X server check is version 1.1 or higher */
-		if (edid->version == 1 && edid->revision >= 1 &&
-		    !timing->pixel_clock) {
-			/* Other timing or info */
-			switch (data->type) {
-			case EDID_DETAIL_MONITOR_SERIAL:
-				break;
-			case EDID_DETAIL_MONITOR_STRING:
-				break;
-			case EDID_DETAIL_MONITOR_RANGE:
-				/* Get monitor range data */
-				break;
-			case EDID_DETAIL_MONITOR_NAME:
-				break;
-			case EDID_DETAIL_MONITOR_CPDATA:
-				break;
-			case EDID_DETAIL_STD_MODES:
-				for (j = 0; j < 6; i++) {
-					struct std_timing *std;
-					struct drm_display_mode *newmode;
-
-					std = &data->data.timings[j];
-					newmode = drm_mode_std(dev, std,
-							       edid->revision,
-							       timing_level);
-					if (newmode) {
-						drm_mode_probed_add(connector, newmode);
-						modes++;
-					}
-				}
-				break;
-			default:
-				break;
-			}
-		} else {
-			newmode = drm_mode_detailed(dev, edid, timing, quirks);
-			if (!newmode)
-				continue;
-
-			/* First detailed mode is preferred */
-			if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING))
-				newmode->type |= DRM_MODE_TYPE_PREFERRED;
-			drm_mode_probed_add(connector, newmode);
+		/* In 1.0, only timings are allowed */
+		if (!timing->pixel_clock && edid->version == 1 &&
+			edid->revision == 0)
+			continue;
 
-			modes++;
-		}
+		modes += add_detailed_modes(connector, timing, edid, quirks,
+					    preferred);
 	}
 
 	return modes;
 }
+
 /**
  * add_detailed_mode_eedid - get detailed mode info from addtional timing
  * 			EDID block
@@ -920,12 +926,9 @@ static int add_detailed_info(struct drm_
 static int add_detailed_info_eedid(struct drm_connector *connector,
 			     struct edid *edid, u32 quirks)
 {
-	struct drm_device *dev = connector->dev;
-	int i, j, modes = 0;
+	int i, modes = 0;
 	char *edid_ext = NULL;
 	struct detailed_timing *timing;
-	struct detailed_non_pixel *data;
-	struct drm_display_mode *newmode;
 	int edid_ext_num;
 	int start_offset, end_offset;
 	int timing_level;
@@ -976,51 +979,7 @@ static int add_detailed_info_eedid(struc
 	for (i = start_offset; i < end_offset;
 			i += sizeof(struct detailed_timing)) {
 		timing = (struct detailed_timing *)(edid_ext + i);
-		data = &timing->data.other_data;
-		/* Detailed mode timing */
-		if (timing->pixel_clock) {
-			newmode = drm_mode_detailed(dev, edid, timing, quirks);
-			if (!newmode)
-				continue;
-
-			drm_mode_probed_add(connector, newmode);
-
-			modes++;
-			continue;
-		}
-
-		/* Other timing or info */
-		switch (data->type) {
-		case EDID_DETAIL_MONITOR_SERIAL:
-			break;
-		case EDID_DETAIL_MONITOR_STRING:
-			break;
-		case EDID_DETAIL_MONITOR_RANGE:
-			/* Get monitor range data */
-			break;
-		case EDID_DETAIL_MONITOR_NAME:
-			break;
-		case EDID_DETAIL_MONITOR_CPDATA:
-			break;
-		case EDID_DETAIL_STD_MODES:
-			/* Five modes per detailed section */
-			for (j = 0; j < 5; i++) {
-				struct std_timing *std;
-				struct drm_display_mode *newmode;
-
-				std = &data->data.timings[j];
-				newmode = drm_mode_std(dev, std,
-						       edid->revision,
-						       timing_level);
-				if (newmode) {
-					drm_mode_probed_add(connector, newmode);
-					modes++;
-				}
-			}
-			break;
-		default:
-			break;
-		}
+		modes += add_detailed_modes(connector, timing, edid, quirks, 0);
 	}
 
 	return modes;
From 29874f44fbcbc24b231b42c9956f8f9de9407231 Mon Sep 17 00:00:00 2001
From: Shaohua Li <shaohua.li@intel.com>
Date: Wed, 18 Nov 2009 15:15:02 +0800
Subject: drm/i915: fix gpio register detection logic for BIOS without VBT

From: Shaohua Li <shaohua.li@intel.com>

commit 29874f44fbcbc24b231b42c9956f8f9de9407231 upstream.

if no VBT is present, crt_ddc_bus will be left at 0, and cause us
to use that for the GPIO register offset. That's never a valid register
offset, so let the "undefined" value be 0 instead of -1.

Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
[anholt: clarified the commit message a bit]
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/i915_drv.h   |    2 +-
 drivers/gpu/drm/i915/intel_bios.c |    4 ----
 drivers/gpu/drm/i915/intel_crt.c  |    2 +-
 3 files changed, 2 insertions(+), 6 deletions(-)

--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -258,7 +258,7 @@ typedef struct drm_i915_private {
 
 	struct notifier_block lid_notifier;
 
-	int crt_ddc_bus; /* -1 = unknown, else GPIO to use for CRT DDC */
+	int crt_ddc_bus; /* 0 = unknown, else GPIO to use for CRT DDC */
 	struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
 	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
 	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -241,10 +241,6 @@ parse_general_definitions(struct drm_i91
 		GPIOF,
 	};
 
-	/* Set sensible defaults in case we can't find the general block
-	   or it is the wrong chipset */
-	dev_priv->crt_ddc_bus = -1;
-
 	general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
 	if (general) {
 		u16 block_size = get_blocksize(general);
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -557,7 +557,7 @@ void intel_crt_init(struct drm_device *d
 	else {
 		i2c_reg = GPIOA;
 		/* Use VBT information for CRT DDC if available */
-		if (dev_priv->crt_ddc_bus != -1)
+		if (dev_priv->crt_ddc_bus != 0)
 			i2c_reg = dev_priv->crt_ddc_bus;
 	}
 	intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
From 290e55056ec3d25c72088628245d8cae037b30db Mon Sep 17 00:00:00 2001
From: Maarten Maathuis <madman2003@gmail.com>
Date: Sat, 20 Feb 2010 03:22:21 +0100
Subject: drm/ttm: handle OOM in ttm_tt_swapout

From: Maarten Maathuis <madman2003@gmail.com>

commit 290e55056ec3d25c72088628245d8cae037b30db upstream.

- Without this change I get a general protection fault.
- Also use PTR_ERR where applicable.

Signed-off-by: Maarten Maathuis <madman2003@gmail.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
Acked-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/ttm/ttm_tt.c |   18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -466,7 +466,7 @@ static int ttm_tt_swapin(struct ttm_tt *
 	void *from_virtual;
 	void *to_virtual;
 	int i;
-	int ret;
+	int ret = -ENOMEM;
 
 	if (ttm->page_flags & TTM_PAGE_FLAG_USER) {
 		ret = ttm_tt_set_user(ttm, ttm->tsk, ttm->start,
@@ -485,8 +485,10 @@ static int ttm_tt_swapin(struct ttm_tt *
 
 	for (i = 0; i < ttm->num_pages; ++i) {
 		from_page = read_mapping_page(swap_space, i, NULL);
-		if (IS_ERR(from_page))
+		if (IS_ERR(from_page)) {
+			ret = PTR_ERR(from_page);
 			goto out_err;
+		}
 		to_page = __ttm_tt_get_page(ttm, i);
 		if (unlikely(to_page == NULL))
 			goto out_err;
@@ -509,7 +511,7 @@ static int ttm_tt_swapin(struct ttm_tt *
 	return 0;
 out_err:
 	ttm_tt_free_alloced_pages(ttm);
-	return -ENOMEM;
+	return ret;
 }
 
 int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistant_swap_storage)
@@ -521,6 +523,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, s
 	void *from_virtual;
 	void *to_virtual;
 	int i;
+	int ret = -ENOMEM;
 
 	BUG_ON(ttm->state != tt_unbound && ttm->state != tt_unpopulated);
 	BUG_ON(ttm->caching_state != tt_cached);
@@ -543,7 +546,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, s
 						0);
 		if (unlikely(IS_ERR(swap_storage))) {
 			printk(KERN_ERR "Failed allocating swap storage.\n");
-			return -ENOMEM;
+			return PTR_ERR(swap_storage);
 		}
 	} else
 		swap_storage = persistant_swap_storage;
@@ -555,9 +558,10 @@ int ttm_tt_swapout(struct ttm_tt *ttm, s
 		if (unlikely(from_page == NULL))
 			continue;
 		to_page = read_mapping_page(swap_space, i, NULL);
-		if (unlikely(to_page == NULL))
+		if (unlikely(IS_ERR(to_page))) {
+			ret = PTR_ERR(to_page);
 			goto out_err;
-
+		}
 		preempt_disable();
 		from_virtual = kmap_atomic(from_page, KM_USER0);
 		to_virtual = kmap_atomic(to_page, KM_USER1);
@@ -581,5 +585,5 @@ out_err:
 	if (!persistant_swap_storage)
 		fput(swap_storage);
 
-	return -ENOMEM;
+	return ret;
 }
From 70136081fc67ea77d849f86fa323e5773c8e40ea Mon Sep 17 00:00:00 2001
From: Theodore Kilgore <kilgota@auburn.edu>
Date: Fri, 25 Dec 2009 05:15:10 -0300
Subject: V4L/DVB (13991): gspca_mr973010a: Fix cif type 1 cameras not streaming on UHCI controllers

From: Theodore Kilgore <kilgota@auburn.edu>

commit 70136081fc67ea77d849f86fa323e5773c8e40ea upstream.

If you read the mail to Oliver Neukum on the linux-usb list, then you know
that I found a cure for the mysterious problem that the MR97310a CIF "type
1" cameras have been freezing up and refusing to stream if hooked up to a
machine with a UHCI controller.

Namely, the cure is that if the camera is an mr97310a CIF type 1 camera, you
have to send it 0xa0, 0x00. Somehow, this is a timing reset command, or
such. It un-blocks whatever was previously stopping the CIF type 1 cameras
from working on the UHCI-based machines.

Signed-off-by: Theodore Kilgore <kilgota@auburn.edu>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/media/video/gspca/mr97310a.c |    6 ++++++
 1 file changed, 6 insertions(+)

--- a/drivers/media/video/gspca/mr97310a.c
+++ b/drivers/media/video/gspca/mr97310a.c
@@ -530,6 +530,12 @@ static int start_cif_cam(struct gspca_de
 			{0x13, 0x00, {0x01}, 1},
 			{0, 0, {0}, 0}
 		};
+		/* Without this command the cam won't work with USB-UHCI */
+		gspca_dev->usb_buf[0] = 0x0a;
+		gspca_dev->usb_buf[1] = 0x00;
+		err_code = mr_write(gspca_dev, 2);
+		if (err_code < 0)
+			return err_code;
 		err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
 					 ARRAY_SIZE(cif_sensor1_init_data));
 	}
From 8fcc501831aa5b37a4a5a8cd9dc965be3cacc599 Mon Sep 17 00:00:00 2001
From: Zhenyu Wang <zhenyuw@linux.intel.com>
Date: Mon, 28 Dec 2009 13:15:20 +0800
Subject: drm/i915: disable TV hotplug status check

From: Zhenyu Wang <zhenyuw@linux.intel.com>

commit 8fcc501831aa5b37a4a5a8cd9dc965be3cacc599 upstream.

As we removed TV hotplug, don't check its status ever.

Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/intel_tv.c |    2 --
 1 file changed, 2 deletions(-)

--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1801,8 +1801,6 @@ intel_tv_init(struct drm_device *dev)
 	drm_connector_attach_property(connector,
 				   dev->mode_config.tv_bottom_margin_property,
 				   tv_priv->margin[TV_MARGIN_BOTTOM]);
-
-	dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS;
 out:
 	drm_sysfs_connector_add(connector);
 }
From 43bcd61fae05fc6062b4f117c5adb1a72c9f8c57 Mon Sep 17 00:00:00 2001
From: Daniel Vetter <daniel.vetter@ffwll.ch>
Date: Tue, 3 Nov 2009 09:03:34 +0000
Subject: drm/i915: fix get_core_clock_speed for G33 class desktop chips

From: Daniel Vetter <daniel.vetter@ffwll.ch>

commit 43bcd61fae05fc6062b4f117c5adb1a72c9f8c57 upstream.

Somehow the case for G33 got dropped while porting from ums code.
This made a 400MHz chip into a 133MHz one which resulted in the
unnecessary enabling of double wide pipe mode which in turn
screwed up the overlay code.

Nothing else (than the overlay code) seems to be affected.

This fixes fdo.org bug #24835

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/intel_display.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4322,7 +4322,7 @@ static void intel_init_display(struct dr
 	}
 
 	/* Returns the core display clock speed */
-	if (IS_I945G(dev))
+	if (IS_I945G(dev) || (IS_G33(dev) && ! IS_IGDGM(dev)))
 		dev_priv->display.get_display_clock_speed =
 			i945_get_display_clock_speed;
 	else if (IS_I915G(dev))
From ceb0297d3da7ecf44bccec2c4520c8710612c238 Mon Sep 17 00:00:00 2001
From: Jerome Glisse <jglisse@redhat.com>
Date: Sun, 14 Feb 2010 19:33:18 +0000
Subject: drm/radeon: r6xx/r7xx possible security issue, system ram access

From: Jerome Glisse <jglisse@redhat.com>

commit c8c15ff1e90bfc4a2db1ba77a01b3b2783e723fc upstream

This patch workaround a possible security issue which can allow
user to abuse drm on r6xx/r7xx hw to access any system ram memory.
This patch doesn't break userspace, it detect "valid" old use of
CB_COLOR[0-7]_FRAG & CB_COLOR[0-7]_TILE registers and overwritte
the address these registers are pointing to with the one of the
last color buffer. This workaround will work for old mesa &
xf86-video-ati and any old user which did use similar register
programming pattern as those (we expect that there is no others
user of those ioctl except possibly a malicious one). This patch
add a warning if it detects such usage, warning encourage people
to update their mesa & xf86-video-ati. New userspace will submit
proper relocation.

Fix for xf86-video-ati / mesa (this kernel patch is enough to
prevent abuse, fix for userspace are to set proper cs stream and
avoid kernel warning) :
http://cgit.freedesktop.org/xorg/driver/xf86-video-ati/commit/?id=95d63e408cc88b6934bec84a0b1ef94dfe8bee7b
http://cgit.freedesktop.org/mesa/mesa/commit/?id=46dc6fd3ed5ef96cda53641a97bc68c3bc104a9f

Abusing this register to perform system ram memory is not easy,
here is outline on how it could be achieve. First attacker must
have access to the drm device and be able to submit command stream
throught cs ioctl. Then attacker must build a proper command stream
for r6xx/r7xx hw which will abuse the FRAG or TILE buffer to
overwrite the GPU GART which is in VRAM. To achieve so attacker
as to setup CB_COLOR[0-7]_FRAG or CB_COLOR[0-7]_TILE to point
to the GPU GART, then it has to find a way to write predictable
value into those buffer (with little cleverness i believe this
can be done but this is an hard task). Once attacker have such
program it can overwritte GPU GART to program GPU gart to point
anywhere in system memory. It then can reusse same method as he
used to reprogram GART to overwritte the system ram through the
GART mapping. In the process the attacker has to be carefull to
not overwritte any sensitive area of the GART table, like ring
or IB gart entry as it will more then likely lead to GPU lockup.
Bottom line is that i think it's very hard to use this flaw
to get system ram access but in theory one can achieve so.

Side note: I am not aware of anyone ever using the GPU as an
attack vector, nevertheless we take great care in the opensource
driver to try to detect and forbid malicious use of GPU. I don't
think the closed source driver are as cautious as we are.

[bwh: Adjusted context for 2.6.32]
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@linux.ie>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/radeon/r600_cs.c   |   83 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/r600d.h     |   26 +++++++++++
 drivers/gpu/drm/radeon/radeon.h    |    1 
 drivers/gpu/drm/radeon/radeon_cs.c |    1 
 4 files changed, 111 insertions(+)

--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -36,6 +36,10 @@ static int r600_cs_packet_next_reloc_nom
 typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
 static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
 
+struct r600_cs_track {
+	u32	cb_color0_base_last;
+};
+
 /**
  * r600_cs_packet_parse() - parse cp packet and point ib index to next packet
  * @parser:	parser structure holding parsing context.
@@ -177,6 +181,28 @@ static int r600_cs_packet_next_reloc_nom
 }
 
 /**
+ * r600_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
+ * @parser:		parser structure holding parsing context.
+ *
+ * Check next packet is relocation packet3, do bo validation and compute
+ * GPU offset using the provided start.
+ **/
+static inline int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+{
+	struct radeon_cs_packet p3reloc;
+	int r;
+
+	r = r600_cs_packet_parse(p, &p3reloc, p->idx);
+	if (r) {
+		return 0;
+	}
+	if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+		return 0;
+	}
+	return 1;
+}
+
+/**
  * r600_cs_packet_next_vline() - parse userspace VLINE packet
  * @parser:		parser structure holding parsing context.
  *
@@ -337,6 +363,7 @@ static int r600_packet3_check(struct rad
 				struct radeon_cs_packet *pkt)
 {
 	struct radeon_cs_reloc *reloc;
+	struct r600_cs_track *track;
 	volatile u32 *ib;
 	unsigned idx;
 	unsigned i;
@@ -344,6 +371,7 @@ static int r600_packet3_check(struct rad
 	int r;
 	u32 idx_value;
 
+	track = (struct r600_cs_track *)p->track;
 	ib = p->ib->ptr;
 	idx = pkt->idx + 1;
 	idx_value = radeon_get_ib_value(p, idx);
@@ -503,9 +531,60 @@ static int r600_packet3_check(struct rad
 		for (i = 0; i < pkt->count; i++) {
 			reg = start_reg + (4 * i);
 			switch (reg) {
+			/* This register were added late, there is userspace
+			 * which does provide relocation for those but set
+			 * 0 offset. In order to avoid breaking old userspace
+			 * we detect this and set address to point to last
+			 * CB_COLOR0_BASE, note that if userspace doesn't set
+			 * CB_COLOR0_BASE before this register we will report
+			 * error. Old userspace always set CB_COLOR0_BASE
+			 * before any of this.
+			 */
+			case R_0280E0_CB_COLOR0_FRAG:
+			case R_0280E4_CB_COLOR1_FRAG:
+			case R_0280E8_CB_COLOR2_FRAG:
+			case R_0280EC_CB_COLOR3_FRAG:
+			case R_0280F0_CB_COLOR4_FRAG:
+			case R_0280F4_CB_COLOR5_FRAG:
+			case R_0280F8_CB_COLOR6_FRAG:
+			case R_0280FC_CB_COLOR7_FRAG:
+			case R_0280C0_CB_COLOR0_TILE:
+			case R_0280C4_CB_COLOR1_TILE:
+			case R_0280C8_CB_COLOR2_TILE:
+			case R_0280CC_CB_COLOR3_TILE:
+			case R_0280D0_CB_COLOR4_TILE:
+			case R_0280D4_CB_COLOR5_TILE:
+			case R_0280D8_CB_COLOR6_TILE:
+			case R_0280DC_CB_COLOR7_TILE:
+				if (!r600_cs_packet_next_is_pkt3_nop(p)) {
+					if (!track->cb_color0_base_last) {
+						dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
+						return -EINVAL;
+					}
+					ib[idx+1+i] = track->cb_color0_base_last;
+					printk_once(KERN_WARNING "You have old & broken userspace "
+						"please consider updating mesa & xf86-video-ati\n");
+				} else {
+					r = r600_cs_packet_next_reloc(p, &reloc);
+					if (r) {
+						dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+						return -EINVAL;
+					}
+					ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+				}
+				break;
 			case DB_DEPTH_BASE:
 			case DB_HTILE_DATA_BASE:
 			case CB_COLOR0_BASE:
+				r = r600_cs_packet_next_reloc(p, &reloc);
+				if (r) {
+					DRM_ERROR("bad SET_CONTEXT_REG "
+							"0x%04X\n", reg);
+					return -EINVAL;
+				}
+				ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+				track->cb_color0_base_last = ib[idx+1+i];
+				break;
 			case CB_COLOR1_BASE:
 			case CB_COLOR2_BASE:
 			case CB_COLOR3_BASE:
@@ -678,8 +757,11 @@ static int r600_packet3_check(struct rad
 int r600_cs_parse(struct radeon_cs_parser *p)
 {
 	struct radeon_cs_packet pkt;
+	struct r600_cs_track *track;
 	int r;
 
+	track = kzalloc(sizeof(*track), GFP_KERNEL);
+	p->track = track;
 	do {
 		r = r600_cs_packet_parse(p, &pkt, p->idx);
 		if (r) {
@@ -757,6 +839,7 @@ int r600_cs_legacy(struct drm_device *de
 	/* initialize parser */
 	memset(&parser, 0, sizeof(struct radeon_cs_parser));
 	parser.filp = filp;
+	parser.dev = &dev->pdev->dev;
 	parser.rdev = NULL;
 	parser.family = family;
 	parser.ib = &fake_ib;
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -674,4 +674,30 @@
 #define		S_000E60_SOFT_RESET_TSC(x)		(((x) & 1) << 16)
 #define		S_000E60_SOFT_RESET_VMC(x)		(((x) & 1) << 17)
 
+#define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL		0x5480
+
+#define R_0280E0_CB_COLOR0_FRAG                      0x0280E0
+#define   S_0280E0_BASE_256B(x)                        (((x) & 0xFFFFFFFF) << 0)
+#define   G_0280E0_BASE_256B(x)                        (((x) >> 0) & 0xFFFFFFFF)
+#define   C_0280E0_BASE_256B                           0x00000000
+#define R_0280E4_CB_COLOR1_FRAG                      0x0280E4
+#define R_0280E8_CB_COLOR2_FRAG                      0x0280E8
+#define R_0280EC_CB_COLOR3_FRAG                      0x0280EC
+#define R_0280F0_CB_COLOR4_FRAG                      0x0280F0
+#define R_0280F4_CB_COLOR5_FRAG                      0x0280F4
+#define R_0280F8_CB_COLOR6_FRAG                      0x0280F8
+#define R_0280FC_CB_COLOR7_FRAG                      0x0280FC
+#define R_0280C0_CB_COLOR0_TILE                      0x0280C0
+#define   S_0280C0_BASE_256B(x)                        (((x) & 0xFFFFFFFF) << 0)
+#define   G_0280C0_BASE_256B(x)                        (((x) >> 0) & 0xFFFFFFFF)
+#define   C_0280C0_BASE_256B                           0x00000000
+#define R_0280C4_CB_COLOR1_TILE                      0x0280C4
+#define R_0280C8_CB_COLOR2_TILE                      0x0280C8
+#define R_0280CC_CB_COLOR3_TILE                      0x0280CC
+#define R_0280D0_CB_COLOR4_TILE                      0x0280D0
+#define R_0280D4_CB_COLOR5_TILE                      0x0280D4
+#define R_0280D8_CB_COLOR6_TILE                      0x0280D8
+#define R_0280DC_CB_COLOR7_TILE                      0x0280DC
+
+
 #endif
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -448,6 +448,7 @@ struct radeon_cs_chunk {
 };
 
 struct radeon_cs_parser {
+	struct device		*dev;
 	struct radeon_device	*rdev;
 	struct drm_file		*filp;
 	/* chunks */
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -230,6 +230,7 @@ int radeon_cs_ioctl(struct drm_device *d
 	memset(&parser, 0, sizeof(struct radeon_cs_parser));
 	parser.filp = filp;
 	parser.rdev = rdev;
+	parser.dev = rdev->dev;
 	r = radeon_cs_parser_init(&parser, data);
 	if (r) {
 		DRM_ERROR("Failed to initialize parser !\n");
From e3dae5087754984ed7e6daf4fbb742ff026aadd5 Mon Sep 17 00:00:00 2001
From: Jerome Glisse <jglisse@redhat.com>
Date: Sun, 14 Feb 2010 19:31:58 +0000
Subject: drm/radeon/kms: r600/r700 don't test ib if ib initialization fails

From: Jerome Glisse <jglisse@redhat.com>

commit db96380ea26fcc31ab37189aedeabd12894b1431 upstream

If ib initialization failed don't try to test ib as it will result
in an oops (accessing NULL ib buffer ptr).

[bwh: Adjusted context for 2.6.32]
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@linux.ie>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/radeon/r600.c  |   13 +++++++------
 drivers/gpu/drm/radeon/rv770.c |   13 +++++++------
 2 files changed, 14 insertions(+), 12 deletions(-)

--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1686,13 +1686,14 @@ int r600_init(struct radeon_device *rdev
 	if (rdev->accel_working) {
 		r = radeon_ib_pool_init(rdev);
 		if (r) {
-			DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
-			rdev->accel_working = false;
-		}
-		r = r600_ib_test(rdev);
-		if (r) {
-			DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+			dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
 			rdev->accel_working = false;
+		} else {
+			r = r600_ib_test(rdev);
+			if (r) {
+				dev_err(rdev->dev, "IB test failed (%d).\n", r);
+				rdev->accel_working = false;
+			}
 		}
 	}
 	return 0;
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -1034,13 +1034,14 @@ int rv770_init(struct radeon_device *rde
 	if (rdev->accel_working) {
 		r = radeon_ib_pool_init(rdev);
 		if (r) {
-			DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
-			rdev->accel_working = false;
-		}
-		r = r600_ib_test(rdev);
-		if (r) {
-			DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+			dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
 			rdev->accel_working = false;
+		} else {
+			r = r600_ib_test(rdev);
+			if (r) {
+				dev_err(rdev->dev, "IB test failed (%d).\n", r);
+				rdev->accel_working = false;
+			}
 		}
 	}
 	return 0;
From 7e71c9e2e7704ebf044d4a964e02fbd2098a173f Mon Sep 17 00:00:00 2001
From: Jerome Glisse <jglisse@redhat.com>
Date: Sun, 17 Jan 2010 21:21:41 +0100
Subject: drm/radeon/kms: Forbid creation of framebuffer with no valid GEM object

From: Jerome Glisse <jglisse@redhat.com>

commit 7e71c9e2e7704ebf044d4a964e02fbd2098a173f upstream.

This will avoid oops if at later point the fb is use. Trying to create
a framebuffer with no valid GEM object is bogus and should be forbidden
as this patch does.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@linux.ie>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/radeon/radeon_display.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -599,7 +599,11 @@ radeon_user_framebuffer_create(struct dr
 	struct drm_gem_object *obj;
 
 	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
-
+	if (obj ==  NULL) {
+		dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, "
+			"can't create framebuffer\n", mode_cmd->handle);
+		return NULL;
+	}
 	return radeon_framebuffer_create(dev, mode_cmd, obj);
 }
 
From 1379d2fef0ec07c7027a5e89036025ce761470c8 Mon Sep 17 00:00:00 2001
From: Zhang Rui <rui.zhang@intel.com>
Date: Tue, 16 Feb 2010 04:16:55 -0500
Subject: ACPI, i915: blacklist Clevo M5x0N bad_lid state

From: Zhang Rui <rui.zhang@intel.com>

commit 1379d2fef0ec07c7027a5e89036025ce761470c8 upstream.

Wrong Lid state reported.
Need to blacklist this machine for LVDS detection.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/intel_lvds.c |    7 +++++++
 1 file changed, 7 insertions(+)

--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -629,6 +629,13 @@ static const struct dmi_system_id bad_li
 			DMI_MATCH(DMI_PRODUCT_NAME, "PC-81005"),
 		},
 	},
+	{
+		.ident = "Clevo M5x0N",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
+			DMI_MATCH(DMI_BOARD_NAME, "M5x0N"),
+		},
+	},
 	{ }
 };
 
From 01d4503968f471f876fb44335800d2cf8dc5a2ce Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@redhat.com>
Date: Sun, 31 Jan 2010 07:07:14 +1000
Subject: drm/radeon/kms: use udelay for short delays

From: Dave Airlie <airlied@redhat.com>

commit 01d4503968f471f876fb44335800d2cf8dc5a2ce upstream.

For usec delays use udelay instead of scheduling, this should
allow reclocking to happen faster. This also was the cause
of reported 33s delays at bootup on certain systems.

fixes: freedesktop.org bug 25506

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/radeon/atom.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/gpu/drm/radeon/atom.c
+++ b/drivers/gpu/drm/radeon/atom.c
@@ -607,7 +607,7 @@ static void atom_op_delay(atom_exec_cont
 	uint8_t count = U8((*ptr)++);
 	SDEBUG("   count: %d\n", count);
 	if (arg == ATOM_UNIT_MICROSEC)
-		schedule_timeout_uninterruptible(usecs_to_jiffies(count));
+		udelay(count);
 	else
 		schedule_timeout_uninterruptible(msecs_to_jiffies(count));
 }
From b9241ea31fae4887104e5d1b3b18f4009c25a0c4 Mon Sep 17 00:00:00 2001
From: Zhenyu Wang <zhenyuw@linux.intel.com>
Date: Wed, 25 Nov 2009 13:09:39 +0800
Subject: drm/i915: Don't wait interruptible for possible plane buffer flush

From: Zhenyu Wang <zhenyuw@linux.intel.com>

commit b9241ea31fae4887104e5d1b3b18f4009c25a0c4 upstream.

When we setup buffer for display plane, we'll check any pending
required GPU flush and possible make interruptible wait for flush
complete. But that wait would be most possibly to fail in case of
signals received for X process, which will then fail modeset process
and put display engine in unconsistent state. The result could be
blank screen or CPU hang, and DDX driver would always turn on outputs
DPMS after whatever modeset fails or not.

So this one creates new helper for setup display plane buffer, and
when needing flush using uninterruptible wait for that.

This one should fix bug like https://bugs.freedesktop.org/show_bug.cgi?id=24009.
Also fixing mode switch stress test on Ironlake.

Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/i915_drv.h      |    1 
 drivers/gpu/drm/i915/i915_gem.c      |   51 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c |    2 -
 3 files changed, 53 insertions(+), 1 deletion(-)

--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -829,6 +829,7 @@ int i915_lp_ring_sync(struct drm_device
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
 				      int write);
+int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj);
 int i915_gem_attach_phys_object(struct drm_device *dev,
 				struct drm_gem_object *obj, int id);
 void i915_gem_detach_phys_object(struct drm_device *dev,
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2825,6 +2825,57 @@ i915_gem_object_set_to_gtt_domain(struct
 	return 0;
 }
 
+/*
+ * Prepare buffer for display plane. Use uninterruptible for possible flush
+ * wait, as in modesetting process we're not supposed to be interrupted.
+ */
+int
+i915_gem_object_set_to_display_plane(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	uint32_t old_write_domain, old_read_domains;
+	int ret;
+
+	/* Not valid to be called on unbound objects. */
+	if (obj_priv->gtt_space == NULL)
+		return -EINVAL;
+
+	i915_gem_object_flush_gpu_write_domain(obj);
+
+	/* Wait on any GPU rendering and flushing to occur. */
+	if (obj_priv->active) {
+#if WATCH_BUF
+		DRM_INFO("%s: object %p wait for seqno %08x\n",
+			  __func__, obj, obj_priv->last_rendering_seqno);
+#endif
+		ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0);
+		if (ret != 0)
+			return ret;
+	}
+
+	old_write_domain = obj->write_domain;
+	old_read_domains = obj->read_domains;
+
+	obj->read_domains &= I915_GEM_DOMAIN_GTT;
+
+	i915_gem_object_flush_cpu_write_domain(obj);
+
+	/* It should now be out of any other write domains, and we can update
+	 * the domain values for our changes.
+	 */
+	BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
+	obj->read_domains |= I915_GEM_DOMAIN_GTT;
+	obj->write_domain = I915_GEM_DOMAIN_GTT;
+	obj_priv->dirty = 1;
+
+	trace_i915_gem_object_change_domain(obj,
+					    old_read_domains,
+					    old_write_domain);
+
+	return 0;
+}
+
 /**
  * Moves a single object to the CPU read, and possibly write domain.
  *
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1253,7 +1253,7 @@ intel_pipe_set_base(struct drm_crtc *crt
 		return ret;
 	}
 
-	ret = i915_gem_object_set_to_gtt_domain(obj, 1);
+	ret = i915_gem_object_set_to_display_plane(obj);
 	if (ret != 0) {
 		i915_gem_object_unpin(obj);
 		mutex_unlock(&dev->struct_mutex);
From 48764bf43f746113fc77877d7e80f2df23ca4cbb Mon Sep 17 00:00:00 2001
From: Daniel Vetter <daniel.vetter@ffwll.ch>
Date: Tue, 15 Sep 2009 22:57:32 +0200
Subject: drm/i915: add i915_lp_ring_sync helper

From: Daniel Vetter <daniel.vetter@ffwll.ch>

commit 48764bf43f746113fc77877d7e80f2df23ca4cbb upstream.

This just waits until the hw passed the current ring position with
cmd execution. This slightly changes the existing i915_wait_request
function to make uninterruptible waiting possible - no point in
returning to userspace while mucking around with the overlay, that
piece of hw is just too fragile.

Also replace a magic 0 with the symbolic constant (and kill the then
superflous comment) while I was looking at the code.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/i915_drv.h |    1 
 drivers/gpu/drm/i915/i915_gem.c |   49 +++++++++++++++++++++++++++++++---------
 include/drm/drm_os_linux.h      |    2 -
 3 files changed, 41 insertions(+), 11 deletions(-)

--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -825,6 +825,7 @@ void i915_gem_cleanup_ringbuffer(struct
 int i915_gem_do_init(struct drm_device *dev, unsigned long start,
 		     unsigned long end);
 int i915_gem_idle(struct drm_device *dev);
+int i915_lp_ring_sync(struct drm_device *dev);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
 				      int write);
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1809,12 +1809,8 @@ i915_gem_retire_work_handler(struct work
 	mutex_unlock(&dev->struct_mutex);
 }
 
-/**
- * Waits for a sequence number to be signaled, and cleans up the
- * request and object lists appropriately for that event.
- */
 static int
-i915_wait_request(struct drm_device *dev, uint32_t seqno)
+i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 ier;
@@ -1841,10 +1837,15 @@ i915_wait_request(struct drm_device *dev
 
 		dev_priv->mm.waiting_gem_seqno = seqno;
 		i915_user_irq_get(dev);
-		ret = wait_event_interruptible(dev_priv->irq_queue,
-					       i915_seqno_passed(i915_get_gem_seqno(dev),
-								 seqno) ||
-					       atomic_read(&dev_priv->mm.wedged));
+		if (interruptible)
+			ret = wait_event_interruptible(dev_priv->irq_queue,
+				i915_seqno_passed(i915_get_gem_seqno(dev), seqno) ||
+				atomic_read(&dev_priv->mm.wedged));
+		else
+			wait_event(dev_priv->irq_queue,
+				i915_seqno_passed(i915_get_gem_seqno(dev), seqno) ||
+				atomic_read(&dev_priv->mm.wedged));
+
 		i915_user_irq_put(dev);
 		dev_priv->mm.waiting_gem_seqno = 0;
 
@@ -1868,6 +1869,34 @@ i915_wait_request(struct drm_device *dev
 	return ret;
 }
 
+/**
+ * Waits for a sequence number to be signaled, and cleans up the
+ * request and object lists appropriately for that event.
+ */
+static int
+i915_wait_request(struct drm_device *dev, uint32_t seqno)
+{
+	return i915_do_wait_request(dev, seqno, 1);
+}
+
+/**
+ * Waits for the ring to finish up to the latest request. Usefull for waiting
+ * for flip events, e.g for the overlay support. */
+int i915_lp_ring_sync(struct drm_device *dev)
+{
+	uint32_t seqno;
+	int ret;
+
+	seqno = i915_add_request(dev, NULL, 0);
+
+	if (seqno == 0)
+		return -ENOMEM;
+
+	ret = i915_do_wait_request(dev, seqno, 0);
+	BUG_ON(ret == -ERESTARTSYS);
+	return ret;
+}
+
 static void
 i915_gem_flush(struct drm_device *dev,
 	       uint32_t invalidate_domains,
@@ -1936,7 +1965,7 @@ i915_gem_flush(struct drm_device *dev,
 #endif
 		BEGIN_LP_RING(2);
 		OUT_RING(cmd);
-		OUT_RING(0); /* noop */
+		OUT_RING(MI_NOOP);
 		ADVANCE_LP_RING();
 	}
 }
--- a/include/drm/drm_os_linux.h
+++ b/include/drm/drm_os_linux.h
@@ -123,5 +123,5 @@ do {								\
 	remove_wait_queue(&(queue), &entry);			\
 } while (0)
 
-#define DRM_WAKEUP( queue ) wake_up_interruptible( queue )
+#define DRM_WAKEUP( queue ) wake_up( queue )
 #define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
From 823f68fd646da6a39a9c0d3eb4c60d69dab5aa13 Mon Sep 17 00:00:00 2001
From: Zhenyu Wang <zhenyuw@linux.intel.com>
Date: Mon, 28 Dec 2009 13:23:36 +0800
Subject: drm/i915: remove full registers dump debug

From: Zhenyu Wang <zhenyuw@linux.intel.com>

commit 823f68fd646da6a39a9c0d3eb4c60d69dab5aa13 upstream.

This one reverts 9e3a6d155ed0a7636b926a798dd7221ea107b274.
As reported by http://bugzilla.kernel.org/show_bug.cgi?id=14485,
this dump will cause hang problem on some machine. If something
really needs this kind of full registers dump, that could be done
within intel-gpu-tools.

Cc: Ben Gamari <bgamari.foss@gmail.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>


---
 drivers/gpu/drm/i915/i915_debugfs.c |   30 ------------------------------
 1 file changed, 30 deletions(-)

--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -384,37 +384,7 @@ out:
 	return 0;
 }
 
-static int i915_registers_info(struct seq_file *m, void *data) {
-	struct drm_info_node *node = (struct drm_info_node *) m->private;
-	struct drm_device *dev = node->minor->dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t reg;
-
-#define DUMP_RANGE(start, end) \
-	for (reg=start; reg < end; reg += 4) \
-	seq_printf(m, "%08x\t%08x\n", reg, I915_READ(reg));
-
-	DUMP_RANGE(0x00000, 0x00fff);   /* VGA registers */
-	DUMP_RANGE(0x02000, 0x02fff);   /* instruction, memory, interrupt control registers */
-	DUMP_RANGE(0x03000, 0x031ff);   /* FENCE and PPGTT control registers */
-	DUMP_RANGE(0x03200, 0x03fff);   /* frame buffer compression registers */
-	DUMP_RANGE(0x05000, 0x05fff);   /* I/O control registers */
-	DUMP_RANGE(0x06000, 0x06fff);   /* clock control registers */
-	DUMP_RANGE(0x07000, 0x07fff);   /* 3D internal debug registers */
-	DUMP_RANGE(0x07400, 0x088ff);   /* GPE debug registers */
-	DUMP_RANGE(0x0a000, 0x0afff);   /* display palette registers */
-	DUMP_RANGE(0x10000, 0x13fff);   /* MMIO MCHBAR */
-	DUMP_RANGE(0x30000, 0x3ffff);   /* overlay registers */
-	DUMP_RANGE(0x60000, 0x6ffff);   /* display engine pipeline registers */
-	DUMP_RANGE(0x70000, 0x72fff);   /* display and cursor registers */
-	DUMP_RANGE(0x73000, 0x73fff);   /* performance counters */
-
-	return 0;
-}
-
-
 static struct drm_info_list i915_debugfs_list[] = {
-	{"i915_regs", i915_registers_info, 0},
 	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
 	{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
 	{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
From 99fcb766a3a50466fe31d743260a3400c1aee855 Mon Sep 17 00:00:00 2001
From: Daniel Vetter <daniel.vetter@ffwll.ch>
Date: Sun, 7 Feb 2010 16:20:18 +0100
Subject: drm/i915: Update write_domains on active list after flush.

From: Daniel Vetter <daniel.vetter@ffwll.ch>

commit 99fcb766a3a50466fe31d743260a3400c1aee855 upstream.

Before changing the status of a buffer with a pending write we will await
upon a new flush for that buffer. So we can take advantage of any flushes
posted whilst the buffer is active and pending processing by the GPU, by
clearing its write_domain and updating its last_rendering_seqno -- thus
saving a potential flush in deep queues and improves flushing behaviour
upon eviction for both GTT space and fences.

In order to reduce the time spent searching the active list for matching
write_domains, we move those to a separate list whose elements are
the buffers belong to the active/flushing list with pending writes.

Orignal patch by Chris Wilson <chris@chris-wilson.co.uk>, forward-ported
by me.

In addition to better performance, this also fixes a real bug. Before
this changes, i915_gem_evict_everything didn't work as advertised. When
the gpu was actually busy and processing request, the flush and subsequent
wait would not move active and dirty buffers to the inactive list, but
just to the flushing list. Which triggered the BUG_ON at the end of this
function. With the more tight dirty buffer tracking, all currently busy and
dirty buffers get moved to the inactive list by one i915_gem_flush operation.

I've left the BUG_ON I've used to prove this in there.

References:
  Bug 25911 - 2.10.0 causes kernel oops and system hangs
  http://bugs.freedesktop.org/show_bug.cgi?id=25911

  Bug 26101 - [i915] xf86-video-intel 2.10.0 (and git) triggers kernel oops
              within seconds after login
  http://bugs.freedesktop.org/show_bug.cgi?id=26101

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Tested-by: Adam Lantos <hege@playma.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/i915_drv.h |   11 +++++++++++
 drivers/gpu/drm/i915/i915_gem.c |   23 +++++++++++++++++++----
 2 files changed, 30 insertions(+), 4 deletions(-)

--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -467,6 +467,15 @@ typedef struct drm_i915_private {
 		struct list_head flushing_list;
 
 		/**
+		 * List of objects currently pending a GPU write flush.
+		 *
+		 * All elements on this list will belong to either the
+		 * active_list or flushing_list, last_rendering_seqno can
+		 * be used to differentiate between the two elements.
+		 */
+		struct list_head gpu_write_list;
+
+		/**
 		 * LRU list of objects which are not in the ringbuffer and
 		 * are ready to unbind, but are still in the GTT.
 		 *
@@ -558,6 +567,8 @@ struct drm_i915_gem_object {
 
 	/** This object's place on the active/flushing/inactive lists */
 	struct list_head list;
+	/** This object's place on GPU write list */
+	struct list_head gpu_write_list;
 
 	/** This object's place on the fenced object LRU */
 	struct list_head fence_list;
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1552,6 +1552,8 @@ i915_gem_object_move_to_inactive(struct
 	else
 		list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
 
+	BUG_ON(!list_empty(&obj_priv->gpu_write_list));
+
 	obj_priv->last_rendering_seqno = 0;
 	if (obj_priv->active) {
 		obj_priv->active = 0;
@@ -1622,7 +1624,8 @@ i915_add_request(struct drm_device *dev,
 		struct drm_i915_gem_object *obj_priv, *next;
 
 		list_for_each_entry_safe(obj_priv, next,
-					 &dev_priv->mm.flushing_list, list) {
+					 &dev_priv->mm.gpu_write_list,
+					 gpu_write_list) {
 			struct drm_gem_object *obj = obj_priv->obj;
 
 			if ((obj->write_domain & flush_domains) ==
@@ -1630,6 +1633,7 @@ i915_add_request(struct drm_device *dev,
 				uint32_t old_write_domain = obj->write_domain;
 
 				obj->write_domain = 0;
+				list_del_init(&obj_priv->gpu_write_list);
 				i915_gem_object_move_to_active(obj, seqno);
 
 				trace_i915_gem_object_change_domain(obj,
@@ -2073,8 +2077,8 @@ static int
 i915_gem_evict_everything(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t seqno;
 	int ret;
+	uint32_t seqno;
 	bool lists_empty;
 
 	spin_lock(&dev_priv->mm.active_list_lock);
@@ -2096,6 +2100,8 @@ i915_gem_evict_everything(struct drm_dev
 	if (ret)
 		return ret;
 
+	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+
 	ret = i915_gem_evict_from_inactive_list(dev);
 	if (ret)
 		return ret;
@@ -2690,7 +2696,7 @@ i915_gem_object_flush_gpu_write_domain(s
 	old_write_domain = obj->write_domain;
 	i915_gem_flush(dev, 0, obj->write_domain);
 	seqno = i915_add_request(dev, NULL, obj->write_domain);
-	obj->write_domain = 0;
+	BUG_ON(obj->write_domain);
 	i915_gem_object_move_to_active(obj, seqno);
 
 	trace_i915_gem_object_change_domain(obj,
@@ -3710,16 +3716,23 @@ i915_gem_execbuffer(struct drm_device *d
 		i915_gem_flush(dev,
 			       dev->invalidate_domains,
 			       dev->flush_domains);
-		if (dev->flush_domains)
+		if (dev->flush_domains & I915_GEM_GPU_DOMAINS)
 			(void)i915_add_request(dev, file_priv,
 					       dev->flush_domains);
 	}
 
 	for (i = 0; i < args->buffer_count; i++) {
 		struct drm_gem_object *obj = object_list[i];
+		struct drm_i915_gem_object *obj_priv = obj->driver_private;
 		uint32_t old_write_domain = obj->write_domain;
 
 		obj->write_domain = obj->pending_write_domain;
+		if (obj->write_domain)
+			list_move_tail(&obj_priv->gpu_write_list,
+				       &dev_priv->mm.gpu_write_list);
+		else
+			list_del_init(&obj_priv->gpu_write_list);
+
 		trace_i915_gem_object_change_domain(obj,
 						    obj->read_domains,
 						    old_write_domain);
@@ -4112,6 +4125,7 @@ int i915_gem_init_object(struct drm_gem_
 	obj_priv->obj = obj;
 	obj_priv->fence_reg = I915_FENCE_REG_NONE;
 	INIT_LIST_HEAD(&obj_priv->list);
+	INIT_LIST_HEAD(&obj_priv->gpu_write_list);
 	INIT_LIST_HEAD(&obj_priv->fence_list);
 	obj_priv->madv = I915_MADV_WILLNEED;
 
@@ -4563,6 +4577,7 @@ i915_gem_load(struct drm_device *dev)
 	spin_lock_init(&dev_priv->mm.active_list_lock);
 	INIT_LIST_HEAD(&dev_priv->mm.active_list);
 	INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
+	INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list);
 	INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
 	INIT_LIST_HEAD(&dev_priv->mm.request_list);
 	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
From fd2e8ea597222b8f38ae8948776a61ea7958232e Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris@chris-wilson.co.uk>
Date: Tue, 9 Feb 2010 14:14:36 +0000
Subject: drm/i915: Increase fb alignment to 64k

From: Chris Wilson <chris@chris-wilson.co.uk>

commit fd2e8ea597222b8f38ae8948776a61ea7958232e upstream.

An untiled framebuffer must be aligned to 64k. This is normally handled
by intel_pin_and_fence_fb_obj(), but the intelfb_create() likes to be
different and do the pinning itself. However, it aligns the buffer
object incorrectly for pre-i965 chipsets causing a PGTBL_ERR when it is
installed onto the output.

Fixes:
  KMS error message while initializing modesetting -
  render error detected: EIR: 0x10 [i915]
  http://bugs.freedesktop.org/show_bug.cgi?id=22936

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/intel_fb.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -148,7 +148,7 @@ static int intelfb_create(struct drm_dev
 
 	mutex_lock(&dev->struct_mutex);
 
-	ret = i915_gem_object_pin(fbo, PAGE_SIZE);
+	ret = i915_gem_object_pin(fbo, 64*1024);
 	if (ret) {
 		DRM_ERROR("failed to pin fb: %d\n", ret);
 		goto out_unref;
From ee25df2bc379728c45d81e04cf87984db1425edf Mon Sep 17 00:00:00 2001
From: Jesse Barnes <jbarnes@virtuousgeek.org>
Date: Sat, 6 Feb 2010 10:41:53 -0800
Subject: drm/i915: handle FBC and self-refresh better

From: Jesse Barnes <jbarnes@virtuousgeek.org>

commit ee25df2bc379728c45d81e04cf87984db1425edf upstream.

On 945, we need to avoid entering self-refresh if the compressor is
busy, or we may cause display FIFO underruns leading to ugly flicker.

Fixes fdo bug #24314, kernel bug #15043.

Tested-by: Alexander Lam <lambchop468@gmail.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Tested-by: Julien Cristau <jcristau@debian.org> (fd.o #25371)
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/i915_reg.h      |    1 +
 drivers/gpu/drm/i915/intel_display.c |    2 ++
 2 files changed, 3 insertions(+)

--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -329,6 +329,7 @@
 #define   FBC_CTL_PERIODIC	(1<<30)
 #define   FBC_CTL_INTERVAL_SHIFT (16)
 #define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
+#define   FBC_C3_IDLE		(1<<13)
 #define   FBC_CTL_STRIDE_SHIFT	(5)
 #define   FBC_CTL_FENCENO	(1<<0)
 #define FBC_COMMAND		0x0320c
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -988,6 +988,8 @@ static void i8xx_enable_fbc(struct drm_c
 
 	/* enable it... */
 	fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC;
+	if (IS_I945GM(dev))
+		fbc_ctl |= FBC_C3_IDLE; /* 945 needs special SR handling */
 	fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
 	fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
 	if (obj_priv->tiling_mode != I915_TILING_NONE)
From a3cb5195f6db58dbebd8a31b877ddce082c9b63d Mon Sep 17 00:00:00 2001
From: Zhao Yakui <yakui.zhao@intel.com>
Date: Fri, 11 Dec 2009 09:26:10 +0800
Subject: drm/i915: Add MALATA PC-81005 to ACPI LID quirk list

From: Zhao Yakui <yakui.zhao@intel.com>

commit a3cb5195f6db58dbebd8a31b877ddce082c9b63d upstream.

The MALATA PC-81005 laptop always reports that the LID status is closed and we
can't use it reliabily for LVDS detection. So add this box into the quirk list.

https://bugs.freedesktop.org/show_bug.cgi?id=25523

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Review-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Tested-by: Hector <hector1987@gmail.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/intel_lvds.c |    7 +++++++
 1 file changed, 7 insertions(+)

--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -622,6 +622,13 @@ static const struct dmi_system_id bad_li
 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire one"),
 		},
 	},
+	{
+		.ident = "PC-81005",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MALATA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PC-81005"),
+		},
+	},
 	{ }
 };
 
From f034b12dbb5749b11e9390e15e93ffa87ece8038 Mon Sep 17 00:00:00 2001
From: Zhao Yakui <yakui.zhao@intel.com>
Date: Thu, 21 Jan 2010 15:20:18 +0800
Subject: drm/i915: Fix the incorrect DMI string for Samsung SX20S laptop

From: Zhao Yakui <yakui.zhao@intel.com>

commit f034b12dbb5749b11e9390e15e93ffa87ece8038 upstream.

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Reported-by: Philipp Kohlbecher <xt28@gmx.de>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/intel_lvds.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -611,7 +611,7 @@ static const struct dmi_system_id bad_li
 	{
 		.ident = "Samsung SX20S",
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Phoenix Technologies LTD"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"),
 			DMI_MATCH(DMI_BOARD_NAME, "SX20S"),
 		},
 	},
From 40f33a92100f4d9b6e85ad642100cfe42d7ff57d Mon Sep 17 00:00:00 2001
From: Zhao Yakui <yakui.zhao@intel.com>
Date: Wed, 6 Jan 2010 13:30:36 +0800
Subject: drm/i915: Add HP nx9020/SamsungSX20S to ACPI LID quirk list

From: Zhao Yakui <yakui.zhao@intel.com>

commit 40f33a92100f4d9b6e85ad642100cfe42d7ff57d upstream.

The HP comaq nx9020/Samsung SX20S laptop always report that the LID status is
closed and we can't use it reliabily for LVDS detection. So add the two boxes
into the quirk list.

http://bugzilla.kernel.org/show_bug.cgi?id=14957
http://bugzilla.kernel.org/show_bug.cgi?id=14554

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/intel_lvds.c |   14 ++++++++++++++
 1 file changed, 14 insertions(+)

--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -602,6 +602,20 @@ static void intel_lvds_mode_set(struct d
 /* Some lid devices report incorrect lid status, assume they're connected */
 static const struct dmi_system_id bad_lid_status[] = {
 	{
+		.ident = "Compaq nx9020",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_BOARD_NAME, "3084"),
+		},
+	},
+	{
+		.ident = "Samsung SX20S",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Phoenix Technologies LTD"),
+			DMI_MATCH(DMI_BOARD_NAME, "SX20S"),
+		},
+	},
+	{
 		.ident = "Aspire One",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
From f0217c42c9ab3d772e543f635ce628b9478f70b6 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Tue, 1 Dec 2009 11:56:30 -0800
Subject: drm/i915: Fix DDC on some systems by clearing BIOS GMBUS setup.

From: Eric Anholt <eric@anholt.net>

commit f0217c42c9ab3d772e543f635ce628b9478f70b6 upstream.

This is a sync of a fix I made in the old UMS code.  If the BIOS uses
the GMBUS and doesn't clear that setup, then our bit-banging I2C can
fail, leading to monitors not being detected.

Signed-off-by: Eric Anholt <eric@anholt.net>
Cc: maximilian attems <max@stro.at>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/i915_reg.h     |   14 ++++++++++++++
 drivers/gpu/drm/i915/i915_suspend.c |    5 ++++-
 drivers/gpu/drm/i915/intel_drv.h    |    2 ++
 drivers/gpu/drm/i915/intel_i2c.c    |   19 +++++++++++++++++++
 4 files changed, 39 insertions(+), 1 deletion(-)

--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -405,6 +405,13 @@
 # define GPIO_DATA_VAL_IN		(1 << 12)
 # define GPIO_DATA_PULLUP_DISABLE	(1 << 13)
 
+#define GMBUS0			0x5100
+#define GMBUS1			0x5104
+#define GMBUS2			0x5108
+#define GMBUS3			0x510c
+#define GMBUS4			0x5110
+#define GMBUS5			0x5120
+
 /*
  * Clock control & power management
  */
@@ -2153,6 +2160,13 @@
 #define PCH_GPIOE               0xc5020
 #define PCH_GPIOF               0xc5024
 
+#define PCH_GMBUS0		0xc5100
+#define PCH_GMBUS1		0xc5104
+#define PCH_GMBUS2		0xc5108
+#define PCH_GMBUS3		0xc510c
+#define PCH_GMBUS4		0xc5110
+#define PCH_GMBUS5		0xc5120
+
 #define PCH_DPLL_A              0xc6014
 #define PCH_DPLL_B              0xc6018
 
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -27,7 +27,7 @@
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
-#include "i915_drv.h"
+#include "intel_drv.h"
 
 static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
 {
@@ -846,6 +846,9 @@ int i915_restore_state(struct drm_device
 	for (i = 0; i < 3; i++)
 		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
 
+	/* I2C state */
+	intel_i2c_reset_gmbus(dev);
+
 	return 0;
 }
 
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -134,6 +134,8 @@ void intel_i2c_destroy(struct i2c_adapte
 int intel_ddc_get_modes(struct intel_output *intel_output);
 extern bool intel_ddc_probe(struct intel_output *intel_output);
 void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
+void intel_i2c_reset_gmbus(struct drm_device *dev);
+
 extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
 extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -118,6 +118,23 @@ static void set_data(void *data, int sta
 	udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
 }
 
+/* Clears the GMBUS setup.  Our driver doesn't make use of the GMBUS I2C
+ * engine, but if the BIOS leaves it enabled, then that can break our use
+ * of the bit-banging I2C interfaces.  This is notably the case with the
+ * Mac Mini in EFI mode.
+ */
+void
+intel_i2c_reset_gmbus(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (IS_IGDNG(dev)) {
+		I915_WRITE(PCH_GMBUS0, 0);
+	} else {
+		I915_WRITE(GMBUS0, 0);
+	}
+}
+
 /**
  * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
  * @dev: DRM device
@@ -168,6 +185,8 @@ struct i2c_adapter *intel_i2c_create(str
 	if(i2c_bit_add_bus(&chan->adapter))
 		goto out_free;
 
+	intel_i2c_reset_gmbus(dev);
+
 	/* JJJ:  raise SCL and SDA? */
 	intel_i2c_quirk_set(dev, true);
 	set_data(chan, 1);
From 33c5fd121eabbccc9103daf6cda36941eb3c349f Mon Sep 17 00:00:00 2001
From: David John <davidjon@xenontk.org>
Date: Wed, 27 Jan 2010 15:19:08 +0530
Subject: drm/i915: Disable SR when more than one pipe is enabled

From: David John <davidjon@xenontk.org>

commit 33c5fd121eabbccc9103daf6cda36941eb3c349f upstream.

Self Refresh should be disabled on dual plane configs.  Otherwise, as
the SR watermark is not calculated for such configs, switching to non
VGA mode causes FIFO underrun and display flicker.

This fixes Korg Bug #14897.

Signed-off-by: David John <davidjon@xenontk.org>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/intel_display.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)

--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2538,6 +2538,10 @@ static void g4x_update_wm(struct drm_dev
 		sr_entries = roundup(sr_entries / cacheline_size, 1);
 		DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
 		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+	} else {
+		/* Turn off self refresh if both pipes are enabled */
+		I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
+					& ~FW_BLC_SELF_EN);
 	}
 
 	DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n",
@@ -2581,6 +2585,10 @@ static void i965_update_wm(struct drm_de
 			srwm = 1;
 		srwm &= 0x3f;
 		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+	} else {
+		/* Turn off self refresh if both pipes are enabled */
+		I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
+					& ~FW_BLC_SELF_EN);
 	}
 
 	DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
@@ -2649,6 +2657,10 @@ static void i9xx_update_wm(struct drm_de
 		if (srwm < 0)
 			srwm = 1;
 		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f));
+	} else {
+		/* Turn off self refresh if both pipes are enabled */
+		I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
+					& ~FW_BLC_SELF_EN);
 	}
 
 	DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
From 1dc7546d1a73664e5d117715b214bea9cae5951c Mon Sep 17 00:00:00 2001
From: Jesse Barnes <jbarnes@jbarnes-x200.(none)>
Date: Mon, 19 Oct 2009 10:08:17 +0900
Subject: drm/i915: enable self-refresh on 965

From: Jesse Barnes <jbarnes@jbarnes-x200.(none)>

commit 1dc7546d1a73664e5d117715b214bea9cae5951c upstream.

Need to calculate the SR watermark and enable it.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/intel_display.c |   32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)

--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2556,15 +2556,39 @@ static void g4x_update_wm(struct drm_dev
 		   (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
 }
 
-static void i965_update_wm(struct drm_device *dev, int unused, int unused2,
-			   int unused3, int unused4)
+static void i965_update_wm(struct drm_device *dev, int planea_clock,
+			   int planeb_clock, int sr_hdisplay, int pixel_size)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long line_time_us;
+	int sr_clock, sr_entries, srwm = 1;
 
-	DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n");
+	/* Calc sr entries for one plane configs */
+	if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
+		/* self-refresh has much higher latency */
+		const static int sr_latency_ns = 12000;
+
+		sr_clock = planea_clock ? planea_clock : planeb_clock;
+		line_time_us = ((sr_hdisplay * 1000) / sr_clock);
+
+		/* Use ns/us then divide to preserve precision */
+		sr_entries = (((sr_latency_ns / line_time_us) + 1) *
+			      pixel_size * sr_hdisplay) / 1000;
+		sr_entries = roundup(sr_entries / I915_FIFO_LINE_SIZE, 1);
+		DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
+		srwm = I945_FIFO_SIZE - sr_entries;
+		if (srwm < 0)
+			srwm = 1;
+		srwm &= 0x3f;
+		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+	}
+
+	DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
+		      srwm);
 
 	/* 965 has limitations... */
-	I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0));
+	I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) | (8 << 16) | (8 << 8) |
+		   (8 << 0));
 	I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
 }
 
From eceb784cec4dc0fcc2993d9ee4a7c0d111ada80a Mon Sep 17 00:00:00 2001
From: Zhenyu Wang <zhenyuw@linux.intel.com>
Date: Mon, 25 Jan 2010 10:35:16 +0800
Subject: drm/i915: disable hotplug detect before Ironlake CRT detect

From: Zhenyu Wang <zhenyuw@linux.intel.com>

commit eceb784cec4dc0fcc2993d9ee4a7c0d111ada80a upstream.

This tries to fix CRT detect loop hang seen on some Ironlake form
factor, to clear up hotplug detect state before taking CRT detect
to make sure next hotplug detect cycle is consistent.

Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/gpu/drm/i915/intel_crt.c |    3 +++
 1 file changed, 3 insertions(+)

--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -185,6 +185,9 @@ static bool intel_igdng_crt_detect_hotpl
 	adpa = I915_READ(PCH_ADPA);
 
 	adpa &= ~ADPA_CRT_HOTPLUG_MASK;
+	/* disable HPD first */
+	I915_WRITE(PCH_ADPA, adpa);
+	(void)I915_READ(PCH_ADPA);
 
 	adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 |
 			ADPA_CRT_HOTPLUG_WARMUP_10MS |