Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (21 commits)
  drm/radeon: load the right microcode on rs780
  drm: remove unused "can_grow" parameter from drm_crtc_helper_initial_config
  drm: fix EDID backward compat check
  drm: sync the mode validation for INTERLACE/DBLSCAN
  drm: fix typo in edid vendor parsing.
  DRM: drm_crtc_helper.h doesn't actually need i2c.h
  drm: fix missing inline function on 32-bit powerpc.
  drm: Use pgprot_writecombine in GEM GTT mapping to get the right bits for !PAT.
  drm/i915: Add a spinlock to protect the active_list
  drm/i915: Fix SDVO TV support
  drm/i915: Fix SDVO CREATE_PREFERRED_INPUT_TIMING command
  drm/i915: Fix error in SDVO DTD and modeline convert
  drm/i915: Fix SDVO command debug function
  drm/i915: fix TV mode setting in property change
  drm/i915: only set TV mode when any property changed
  drm/i915: clean up udelay usage
  drm/i915: add VGA hotplug support for 945+
  drm/i915: correctly set IGD device's gtt size for KMS.
  drm/i915: avoid hanging on to a stale pointer to raw_edid.
  drm/i915: check for -EINVAL from vm_insert_pfn
  ...
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 1c3a8c5..a04639d 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -42,6 +42,26 @@
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 };
 
+static void drm_mode_validate_flag(struct drm_connector *connector,
+				   int flags)
+{
+	struct drm_display_mode *mode, *t;
+
+	if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE))
+		return;
+
+	list_for_each_entry_safe(mode, t, &connector->modes, head) {
+		if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
+				!(flags & DRM_MODE_FLAG_INTERLACE))
+			mode->status = MODE_NO_INTERLACE;
+		if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
+				!(flags & DRM_MODE_FLAG_DBLSCAN))
+			mode->status = MODE_NO_DBLESCAN;
+	}
+
+	return;
+}
+
 /**
  * drm_helper_probe_connector_modes - get complete set of display modes
  * @dev: DRM device
@@ -72,6 +92,7 @@
 	struct drm_connector_helper_funcs *connector_funcs =
 		connector->helper_private;
 	int count = 0;
+	int mode_flags = 0;
 
 	DRM_DEBUG("%s\n", drm_get_connector_name(connector));
 	/* set all modes to the unverified state */
@@ -96,6 +117,13 @@
 	if (maxX && maxY)
 		drm_mode_validate_size(dev, &connector->modes, maxX,
 				       maxY, 0);
+
+	if (connector->interlace_allowed)
+		mode_flags |= DRM_MODE_FLAG_INTERLACE;
+	if (connector->doublescan_allowed)
+		mode_flags |= DRM_MODE_FLAG_DBLSCAN;
+	drm_mode_validate_flag(connector, mode_flags);
+
 	list_for_each_entry_safe(mode, t, &connector->modes, head) {
 		if (mode->status == MODE_OK)
 			mode->status = connector_funcs->mode_valid(connector,
@@ -885,7 +913,6 @@
 /**
  * drm_initial_config - setup a sane initial connector configuration
  * @dev: DRM device
- * @can_grow: this configuration is growable
  *
  * LOCKING:
  * Called at init time, must take mode config lock.
@@ -897,7 +924,7 @@
  * RETURNS:
  * Zero if everything went ok, nonzero otherwise.
  */
-bool drm_helper_initial_config(struct drm_device *dev, bool can_grow)
+bool drm_helper_initial_config(struct drm_device *dev)
 {
 	struct drm_connector *connector;
 	int count = 0;
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index c674000..ca9c616 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -125,10 +125,8 @@
 		DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
 		goto bad;
 	}
-	if (edid->revision > 3) {
-		DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision);
-		goto bad;
-	}
+	if (edid->revision > 4)
+		DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n");
 
 	for (i = 0; i < EDID_LENGTH; i++)
 		csum += raw_edid[i];
@@ -162,7 +160,7 @@
 	edid_vendor[0] = ((edid->mfg_id[0] & 0x7c) >> 2) + '@';
 	edid_vendor[1] = (((edid->mfg_id[0] & 0x3) << 3) |
 			  ((edid->mfg_id[1] & 0xe0) >> 5)) + '@';
-	edid_vendor[2] = (edid->mfg_id[2] & 0x1f) + '@';
+	edid_vendor[2] = (edid->mfg_id[1] & 0x1f) + '@';
 
 	return !strncmp(edid_vendor, vendor, 3);
 }
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index c1173d8..4984aa8 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -505,7 +505,6 @@
 	struct drm_local_map *map = NULL;
 	struct drm_gem_object *obj;
 	struct drm_hash_item *hash;
-	unsigned long prot;
 	int ret = 0;
 
 	mutex_lock(&dev->struct_mutex);
@@ -538,11 +537,7 @@
 	vma->vm_ops = obj->dev->driver->gem_vm_ops;
 	vma->vm_private_data = map->handle;
 	/* FIXME: use pgprot_writecombine when available */
-	prot = pgprot_val(vma->vm_page_prot);
-#ifdef CONFIG_X86
-	prot |= _PAGE_CACHE_WC;
-#endif
-	vma->vm_page_prot = __pgprot(prot);
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 
 	/* Take a ref for this mapping of the object, so that the fault
 	 * handler can dereference the mmap offset's pointer to the object.
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 5de573a..bc0c6849 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -451,6 +451,7 @@
 
 	kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, envp);
 }
+EXPORT_SYMBOL(drm_sysfs_hotplug_event);
 
 /**
  * drm_sysfs_device_add - adds a class device to sysfs for a character driver
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 85549f6..c23b3a9 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -922,7 +922,7 @@
 	 * Some of the preallocated space is taken by the GTT
 	 * and popup.  GTT is 1K per MB of aperture size, and popup is 4K.
 	 */
-	if (IS_G4X(dev))
+	if (IS_G4X(dev) || IS_IGD(dev))
 		overhead = 4096;
 	else
 		overhead = (*aperture_size / 1024) + 4096;
@@ -1030,13 +1030,6 @@
 	if (ret)
 		goto destroy_ringbuffer;
 
-	/* FIXME: re-add hotplug support */
-#if 0
-	ret = drm_hotplug_init(dev);
-	if (ret)
-		goto destroy_ringbuffer;
-#endif
-
 	/* Always safe in the mode setting case. */
 	/* FIXME: do pre/post-mode set stuff in core KMS code */
 	dev->vblank_disable_allowed = 1;
@@ -1049,7 +1042,7 @@
 
 	intel_modeset_init(dev);
 
-	drm_helper_initial_config(dev, false);
+	drm_helper_initial_config(dev);
 
 	return 0;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c1685d0..317b122 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -159,6 +159,9 @@
 	u32 irq_mask_reg;
 	u32 pipestat[2];
 
+	u32 hotplug_supported_mask;
+	struct work_struct hotplug_work;
+
 	int tex_lru_log_granularity;
 	int allow_batchbuffer;
 	struct mem_block *agp_heap;
@@ -297,6 +300,7 @@
 		 *
 		 * A reference is held on the buffer while on this list.
 		 */
+		spinlock_t active_list_lock;
 		struct list_head active_list;
 
 		/**
@@ -810,6 +814,7 @@
 #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
 						      IS_I915GM(dev)))
 #define SUPPORTS_INTEGRATED_HDMI(dev)	(IS_G4X(dev))
+#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev))
 
 #define PRIMARY_RINGBUFFER_SIZE         (128*1024)
 
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index e0389ad..1449b45 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1072,6 +1072,7 @@
 	case -EAGAIN:
 		return VM_FAULT_OOM;
 	case -EFAULT:
+	case -EINVAL:
 		return VM_FAULT_SIGBUS;
 	default:
 		return VM_FAULT_NOPAGE;
@@ -1324,8 +1325,10 @@
 		obj_priv->active = 1;
 	}
 	/* Move from whatever list we were on to the tail of execution. */
+	spin_lock(&dev_priv->mm.active_list_lock);
 	list_move_tail(&obj_priv->list,
 		       &dev_priv->mm.active_list);
+	spin_unlock(&dev_priv->mm.active_list_lock);
 	obj_priv->last_rendering_seqno = seqno;
 }
 
@@ -1467,6 +1470,7 @@
 	/* Move any buffers on the active list that are no longer referenced
 	 * by the ringbuffer to the flushing/inactive lists as appropriate.
 	 */
+	spin_lock(&dev_priv->mm.active_list_lock);
 	while (!list_empty(&dev_priv->mm.active_list)) {
 		struct drm_gem_object *obj;
 		struct drm_i915_gem_object *obj_priv;
@@ -1481,7 +1485,7 @@
 		 * this seqno.
 		 */
 		if (obj_priv->last_rendering_seqno != request->seqno)
-			return;
+			goto out;
 
 #if WATCH_LRU
 		DRM_INFO("%s: retire %d moves to inactive list %p\n",
@@ -1493,6 +1497,8 @@
 		else
 			i915_gem_object_move_to_inactive(obj);
 	}
+out:
+	spin_unlock(&dev_priv->mm.active_list_lock);
 }
 
 /**
@@ -1990,20 +1996,23 @@
 	int regnum = obj_priv->fence_reg;
 	uint32_t val;
 	uint32_t pitch_val;
+	uint32_t fence_size_bits;
 
-	if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
+	if ((obj_priv->gtt_offset & ~I830_FENCE_START_MASK) ||
 	    (obj_priv->gtt_offset & (obj->size - 1))) {
-		WARN(1, "%s: object 0x%08x not 1M or size aligned\n",
+		WARN(1, "%s: object 0x%08x not 512K or size aligned\n",
 		     __func__, obj_priv->gtt_offset);
 		return;
 	}
 
 	pitch_val = (obj_priv->stride / 128) - 1;
-
+	WARN_ON(pitch_val & ~0x0000000f);
 	val = obj_priv->gtt_offset;
 	if (obj_priv->tiling_mode == I915_TILING_Y)
 		val |= 1 << I830_FENCE_TILING_Y_SHIFT;
-	val |= I830_FENCE_SIZE_BITS(obj->size);
+	fence_size_bits = I830_FENCE_SIZE_BITS(obj->size);
+	WARN_ON(fence_size_bits & ~0x00000f00);
+	val |= fence_size_bits;
 	val |= pitch_val << I830_FENCE_PITCH_SHIFT;
 	val |= I830_FENCE_REG_VALID;
 
@@ -2194,7 +2203,7 @@
 		return -EBUSY;
 	if (alignment == 0)
 		alignment = i915_gem_get_gtt_alignment(obj);
-	if (alignment & (PAGE_SIZE - 1)) {
+	if (alignment & (i915_gem_get_gtt_alignment(obj) - 1)) {
 		DRM_ERROR("Invalid object alignment requested %u\n", alignment);
 		return -EINVAL;
 	}
@@ -2211,15 +2220,20 @@
 		}
 	}
 	if (obj_priv->gtt_space == NULL) {
+		bool lists_empty;
+
 		/* If the gtt is empty and we're still having trouble
 		 * fitting our object in, we're out of memory.
 		 */
 #if WATCH_LRU
 		DRM_INFO("%s: GTT full, evicting something\n", __func__);
 #endif
-		if (list_empty(&dev_priv->mm.inactive_list) &&
-		    list_empty(&dev_priv->mm.flushing_list) &&
-		    list_empty(&dev_priv->mm.active_list)) {
+		spin_lock(&dev_priv->mm.active_list_lock);
+		lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
+			       list_empty(&dev_priv->mm.flushing_list) &&
+			       list_empty(&dev_priv->mm.active_list));
+		spin_unlock(&dev_priv->mm.active_list_lock);
+		if (lists_empty) {
 			DRM_ERROR("GTT full, but LRU list empty\n");
 			return -ENOMEM;
 		}
@@ -3675,6 +3689,7 @@
 
 	i915_gem_retire_requests(dev);
 
+	spin_lock(&dev_priv->mm.active_list_lock);
 	if (!dev_priv->mm.wedged) {
 		/* Active and flushing should now be empty as we've
 		 * waited for a sequence higher than any pending execbuffer
@@ -3701,6 +3716,7 @@
 		obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
 		i915_gem_object_move_to_inactive(obj_priv->obj);
 	}
+	spin_unlock(&dev_priv->mm.active_list_lock);
 
 	while (!list_empty(&dev_priv->mm.flushing_list)) {
 		struct drm_i915_gem_object *obj_priv;
@@ -3949,7 +3965,10 @@
 	if (ret != 0)
 		return ret;
 
+	spin_lock(&dev_priv->mm.active_list_lock);
 	BUG_ON(!list_empty(&dev_priv->mm.active_list));
+	spin_unlock(&dev_priv->mm.active_list_lock);
+
 	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
 	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
 	BUG_ON(!list_empty(&dev_priv->mm.request_list));
@@ -3993,6 +4012,7 @@
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
+	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.inactive_list);
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c
index 131c088..8d0b943 100644
--- a/drivers/gpu/drm/i915/i915_gem_debug.c
+++ b/drivers/gpu/drm/i915/i915_gem_debug.c
@@ -105,12 +105,14 @@
 	struct drm_i915_gem_object	*obj_priv;
 
 	DRM_INFO("active list %s {\n", where);
+	spin_lock(&dev_priv->mm.active_list_lock);
 	list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
 			    list)
 	{
 		DRM_INFO("    %p: %08x\n", obj_priv,
 			 obj_priv->last_rendering_seqno);
 	}
+	spin_unlock(&dev_priv->mm.active_list_lock);
 	DRM_INFO("}\n");
 	DRM_INFO("flushing list %s {\n", where);
 	list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c
index 455ec97..a1ac0c5 100644
--- a/drivers/gpu/drm/i915/i915_gem_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c
@@ -69,10 +69,13 @@
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj_priv;
+	spinlock_t *lock = NULL;
 
 	switch (list) {
 	case ACTIVE_LIST:
 		seq_printf(m, "Active:\n");
+		lock = &dev_priv->mm.active_list_lock;
+		spin_lock(lock);
 		head = &dev_priv->mm.active_list;
 		break;
 	case INACTIVE_LIST:
@@ -104,6 +107,9 @@
 			seq_printf(m, " (fence: %d\n", obj_priv->fence_reg);
 		seq_printf(m, "\n");
 	}
+
+	if (lock)
+	    spin_unlock(lock);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 4cce1ae..6be3f92 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -216,6 +216,22 @@
 	else
 		tile_width = 512;
 
+	/* check maximum stride & object size */
+	if (IS_I965G(dev)) {
+		/* i965 stores the end address of the gtt mapping in the fence
+		 * reg, so dont bother to check the size */
+		if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
+			return false;
+	} else if (IS_I9XX(dev)) {
+		if (stride / tile_width > I830_FENCE_MAX_PITCH_VAL ||
+		    size > (I830_FENCE_MAX_SIZE_VAL << 20))
+			return false;
+	} else {
+		if (stride / 128 > I830_FENCE_MAX_PITCH_VAL ||
+		    size > (I830_FENCE_MAX_SIZE_VAL << 19))
+			return false;
+	}
+
 	/* 965+ just needs multiples of tile width */
 	if (IS_I965G(dev)) {
 		if (stride & (tile_width - 1))
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 87b6b60..ee7ce7b 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -48,10 +48,6 @@
 /** Interrupts that we mask and unmask at runtime. */
 #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
 
-/** These are all of the interrupts used by the driver */
-#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \
-				    I915_INTERRUPT_ENABLE_VAR)
-
 #define I915_PIPE_VBLANK_STATUS	(PIPE_START_VBLANK_INTERRUPT_STATUS |\
 				 PIPE_VBLANK_INTERRUPT_STATUS)
 
@@ -187,6 +183,19 @@
 	return I915_READ(reg);
 }
 
+/*
+ * Handle hotplug events outside the interrupt handler proper.
+ */
+static void i915_hotplug_work_func(struct work_struct *work)
+{
+	drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
+						    hotplug_work);
+	struct drm_device *dev = dev_priv->dev;
+
+	/* Just fire off a uevent and let userspace tell us what to do */
+	drm_sysfs_hotplug_event(dev);
+}
+
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -244,6 +253,20 @@
 
 		ret = IRQ_HANDLED;
 
+		/* Consume port.  Then clear IIR or we'll miss events */
+		if ((I915_HAS_HOTPLUG(dev)) &&
+		    (iir & I915_DISPLAY_PORT_INTERRUPT)) {
+			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
+
+			DRM_DEBUG("hotplug event received, stat 0x%08x\n",
+				  hotplug_status);
+			if (hotplug_status & dev_priv->hotplug_supported_mask)
+				schedule_work(&dev_priv->hotplug_work);
+
+			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
+			I915_READ(PORT_HOTPLUG_STAT);
+		}
+
 		I915_WRITE(IIR, iir);
 		new_iir = I915_READ(IIR); /* Flush posted writes */
 
@@ -528,17 +551,24 @@
 
 	atomic_set(&dev_priv->irq_received, 0);
 
+	if (I915_HAS_HOTPLUG(dev)) {
+		I915_WRITE(PORT_HOTPLUG_EN, 0);
+		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+	}
+
 	I915_WRITE(HWSTAM, 0xeffe);
 	I915_WRITE(PIPEASTAT, 0);
 	I915_WRITE(PIPEBSTAT, 0);
 	I915_WRITE(IMR, 0xffffffff);
 	I915_WRITE(IER, 0x0);
 	(void) I915_READ(IER);
+	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
 }
 
 int i915_driver_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
 
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
@@ -550,13 +580,35 @@
 	dev_priv->pipestat[0] = 0;
 	dev_priv->pipestat[1] = 0;
 
+	if (I915_HAS_HOTPLUG(dev)) {
+		u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+
+		/* Leave other bits alone */
+		hotplug_en |= HOTPLUG_EN_MASK;
+		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+
+		dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS |
+			TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS |
+			SDVOB_HOTPLUG_INT_STATUS;
+		if (IS_G4X(dev)) {
+			dev_priv->hotplug_supported_mask |=
+				HDMIB_HOTPLUG_INT_STATUS |
+				HDMIC_HOTPLUG_INT_STATUS |
+				HDMID_HOTPLUG_INT_STATUS;
+		}
+		/* Enable in IER... */
+		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
+		/* and unmask in IMR */
+		i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT);
+	}
+
 	/* Disable pipe interrupt enables, clear pending pipe status */
 	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
 	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
 	/* Clear pending interrupt status */
 	I915_WRITE(IIR, I915_READ(IIR));
 
-	I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
+	I915_WRITE(IER, enable_mask);
 	I915_WRITE(IMR, dev_priv->irq_mask_reg);
 	(void) I915_READ(IER);
 
@@ -575,6 +627,11 @@
 
 	dev_priv->vblank_pipe = 0;
 
+	if (I915_HAS_HOTPLUG(dev)) {
+		I915_WRITE(PORT_HOTPLUG_EN, 0);
+		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+	}
+
 	I915_WRITE(HWSTAM, 0xffffffff);
 	I915_WRITE(PIPEASTAT, 0);
 	I915_WRITE(PIPEBSTAT, 0);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 377cc58..e805b59 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -190,6 +190,8 @@
 #define   I830_FENCE_SIZE_BITS(size)	((ffs((size) >> 19) - 1) << 8)
 #define   I830_FENCE_PITCH_SHIFT	4
 #define   I830_FENCE_REG_VALID		(1<<0)
+#define   I830_FENCE_MAX_PITCH_VAL	0x10
+#define   I830_FENCE_MAX_SIZE_VAL	(1<<8)
 
 #define   I915_FENCE_START_MASK		0x0ff00000
 #define   I915_FENCE_SIZE_BITS(size)	((ffs((size) >> 20) - 1) << 8)
@@ -198,6 +200,7 @@
 #define   I965_FENCE_PITCH_SHIFT	2
 #define   I965_FENCE_TILING_Y_SHIFT	1
 #define   I965_FENCE_REG_VALID		(1<<0)
+#define   I965_FENCE_MAX_PITCH_VAL	0x0400
 
 /*
  * Instruction and interrupt control regs
@@ -648,6 +651,14 @@
 #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV	(0 << 2)
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV	(1 << 2)
 #define CRT_HOTPLUG_MASK			(0x3fc) /* Bits 9-2 */
+#define CRT_FORCE_HOTPLUG_MASK			0xfffffe1f
+#define HOTPLUG_EN_MASK (HDMIB_HOTPLUG_INT_EN | \
+			 HDMIC_HOTPLUG_INT_EN |	  \
+			 HDMID_HOTPLUG_INT_EN |	  \
+			 SDVOB_HOTPLUG_INT_EN |	  \
+			 SDVOC_HOTPLUG_INT_EN |	  \
+			 TV_HOTPLUG_INT_EN |	  \
+			 CRT_HOTPLUG_INT_EN)
 
 
 #define PORT_HOTPLUG_STAT	0x61114
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 2b6d443..9bdd959 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -41,7 +41,7 @@
 
 	temp = I915_READ(ADPA);
 	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
-	temp &= ~ADPA_DAC_ENABLE;
+	temp |= ADPA_DAC_ENABLE;
 
 	switch(mode) {
 	case DRM_MODE_DPMS_ON:
@@ -158,7 +158,7 @@
 	else
 		tries = 1;
 	hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-	hotplug_en &= ~(CRT_HOTPLUG_MASK);
+	hotplug_en &= CRT_FORCE_HOTPLUG_MASK;
 	hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
 
 	if (IS_GM45(dev))
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d9c50ff..64773ce 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -636,7 +636,7 @@
 intel_wait_for_vblank(struct drm_device *dev)
 {
 	/* Wait for 20ms, i.e. one cycle at 50hz. */
-	udelay(20000);
+	mdelay(20);
 }
 
 static int
@@ -1106,6 +1106,26 @@
 		return -EINVAL;
 	}
 
+	/* SDVO TV has fixed PLL values depend on its clock range,
+	   this mirrors vbios setting. */
+	if (is_sdvo && is_tv) {
+		if (adjusted_mode->clock >= 100000
+				&& adjusted_mode->clock < 140500) {
+			clock.p1 = 2;
+			clock.p2 = 10;
+			clock.n = 3;
+			clock.m1 = 16;
+			clock.m2 = 8;
+		} else if (adjusted_mode->clock >= 140500
+				&& adjusted_mode->clock <= 200000) {
+			clock.p1 = 1;
+			clock.p2 = 10;
+			clock.n = 6;
+			clock.m1 = 12;
+			clock.m2 = 8;
+		}
+	}
+
 	if (IS_IGD(dev))
 		fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
 	else
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index e42019e..07d7ec9 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -76,6 +76,7 @@
 		drm_mode_connector_update_edid_property(&intel_output->base,
 							edid);
 		ret = drm_add_edid_modes(&intel_output->base, edid);
+		intel_output->base.display_info.raw_edid = NULL;
 		kfree(edid);
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index fbe6f39..7b31f55 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -273,20 +273,20 @@
 	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
 	int i;
 
-	DRM_DEBUG("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
+	printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
 	for (i = 0; i < args_len; i++)
-		printk("%02X ", ((u8 *)args)[i]);
+		printk(KERN_DEBUG "%02X ", ((u8 *)args)[i]);
 	for (; i < 8; i++)
-		printk("   ");
+		printk(KERN_DEBUG "   ");
 	for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) {
 		if (cmd == sdvo_cmd_names[i].cmd) {
-			printk("(%s)", sdvo_cmd_names[i].name);
+			printk(KERN_DEBUG "(%s)", sdvo_cmd_names[i].name);
 			break;
 		}
 	}
 	if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0]))
-		printk("(%02X)",cmd);
-	printk("\n");
+		printk(KERN_DEBUG "(%02X)", cmd);
+	printk(KERN_DEBUG "\n");
 }
 #else
 #define intel_sdvo_debug_write(o, c, a, l)
@@ -323,17 +323,18 @@
 				      u8 status)
 {
 	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+	int i;
 
-	DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv));
+	printk(KERN_DEBUG "%s: R: ", SDVO_NAME(sdvo_priv));
 	for (i = 0; i < response_len; i++)
-		printk("%02X ", ((u8 *)response)[i]);
+		printk(KERN_DEBUG "%02X ", ((u8 *)response)[i]);
 	for (; i < 8; i++)
-		printk("   ");
+		printk(KERN_DEBUG "   ");
 	if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
-		printk("(%s)", cmd_status_names[status]);
+		printk(KERN_DEBUG "(%s)", cmd_status_names[status]);
 	else
-		printk("(??? %d)", status);
-	printk("\n");
+		printk(KERN_DEBUG "(??? %d)", status);
+	printk(KERN_DEBUG "\n");
 }
 #else
 #define intel_sdvo_debug_response(o, r, l, s)
@@ -588,9 +589,12 @@
 	struct intel_sdvo_preferred_input_timing_args args;
 	uint8_t status;
 
+	memset(&args, 0, sizeof(args));
 	args.clock = clock;
 	args.width = width;
 	args.height = height;
+	args.interlace = 0;
+	args.scaled = 0;
 	intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
 			     &args, sizeof(args));
 	status = intel_sdvo_read_response(output, NULL, 0);
@@ -683,7 +687,7 @@
 	dtd->part1.v_high = (((height >> 8) & 0xf) << 4) |
 		((v_blank_len >> 8) & 0xf);
 
-	dtd->part2.h_sync_off = h_sync_offset;
+	dtd->part2.h_sync_off = h_sync_offset & 0xff;
 	dtd->part2.h_sync_width = h_sync_len & 0xff;
 	dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
 		(v_sync_len & 0xf);
@@ -705,27 +709,10 @@
 static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
 					 struct intel_sdvo_dtd *dtd)
 {
-	uint16_t width, height;
-	uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len;
-	uint16_t h_sync_offset, v_sync_offset;
-
-	width = mode->crtc_hdisplay;
-	height = mode->crtc_vdisplay;
-
-	/* do some mode translations */
-	h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start;
-	h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
-
-	v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start;
-	v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
-
-	h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start;
-	v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start;
-
 	mode->hdisplay = dtd->part1.h_active;
 	mode->hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8;
 	mode->hsync_start = mode->hdisplay + dtd->part2.h_sync_off;
-	mode->hsync_start += (dtd->part2.sync_off_width_high & 0xa0) << 2;
+	mode->hsync_start += (dtd->part2.sync_off_width_high & 0xc0) << 2;
 	mode->hsync_end = mode->hsync_start + dtd->part2.h_sync_width;
 	mode->hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4;
 	mode->htotal = mode->hdisplay + dtd->part1.h_blank;
@@ -735,7 +722,7 @@
 	mode->vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8;
 	mode->vsync_start = mode->vdisplay;
 	mode->vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf;
-	mode->vsync_start += (dtd->part2.sync_off_width_high & 0x0a) << 2;
+	mode->vsync_start += (dtd->part2.sync_off_width_high & 0x0c) << 2;
 	mode->vsync_start += dtd->part2.v_sync_off_high & 0xc0;
 	mode->vsync_end = mode->vsync_start +
 		(dtd->part2.v_sync_off_width & 0xf);
@@ -745,7 +732,7 @@
 
 	mode->clock = dtd->part1.clock * 10;
 
-	mode->flags &= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
+	mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
 	if (dtd->part2.dtd_flags & 0x2)
 		mode->flags |= DRM_MODE_FLAG_PHSYNC;
 	if (dtd->part2.dtd_flags & 0x4)
@@ -924,6 +911,27 @@
 				SDVO_HBUF_TX_VSYNC);
 }
 
+static void intel_sdvo_set_tv_format(struct intel_output *output)
+{
+	struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
+	struct intel_sdvo_tv_format *format, unset;
+	u8 status;
+
+	format = &sdvo_priv->tv_format;
+	memset(&unset, 0, sizeof(unset));
+	if (memcmp(format, &unset, sizeof(*format))) {
+		DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n",
+				SDVO_NAME(sdvo_priv));
+		format->ntsc_m = 1;
+		intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, format,
+				sizeof(*format));
+		status = intel_sdvo_read_response(output, NULL, 0);
+		if (status != SDVO_CMD_STATUS_SUCCESS)
+			DRM_DEBUG("%s: Failed to set TV format\n",
+					SDVO_NAME(sdvo_priv));
+	}
+}
+
 static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode)
@@ -968,6 +976,12 @@
 							     &input_dtd);
 			intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
 
+			drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+			mode->clock = adjusted_mode->clock;
+
+			adjusted_mode->clock *=
+				intel_sdvo_get_pixel_multiplier(mode);
 		} else {
 			return false;
 		}
@@ -1012,7 +1026,12 @@
 		sdvox |= SDVO_AUDIO_ENABLE;
 	}
 
-	intel_sdvo_get_dtd_from_mode(&input_dtd, mode);
+	/* We have tried to get input timing in mode_fixup, and filled into
+	   adjusted_mode */
+	if (sdvo_priv->is_tv)
+		intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
+	else
+		intel_sdvo_get_dtd_from_mode(&input_dtd, mode);
 
 	/* If it's a TV, we already set the output timing in mode_fixup.
 	 * Otherwise, the output timing is equal to the input timing.
@@ -1027,6 +1046,9 @@
 	/* Set the input timing to the screen. Assume always input 0. */
 	intel_sdvo_set_target_input(output, true, false);
 
+	if (sdvo_priv->is_tv)
+		intel_sdvo_set_tv_format(output);
+
 	/* We would like to use intel_sdvo_create_preferred_input_timing() to
 	 * provide the device with a timing it can support, if it supports that
 	 * feature.  However, presumably we would need to adjust the CRTC to
@@ -1395,7 +1417,7 @@
 intel_sdvo_check_tv_format(struct intel_output *output)
 {
 	struct intel_sdvo_priv *dev_priv = output->dev_priv;
-	struct intel_sdvo_tv_format format, unset;
+	struct intel_sdvo_tv_format format;
 	uint8_t status;
 
 	intel_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0);
@@ -1403,15 +1425,7 @@
 	if (status != SDVO_CMD_STATUS_SUCCESS)
 		return;
 
-	memset(&unset, 0, sizeof(unset));
-	if (memcmp(&format, &unset, sizeof(format))) {
-		DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n",
-			  SDVO_NAME(dev_priv));
-
-		format.ntsc_m = true;
-		intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, NULL, 0);
-		status = intel_sdvo_read_response(output, NULL, 0);
-	}
+	memcpy(&dev_priv->tv_format, &format, sizeof(format));
 }
 
 /*
@@ -1420,68 +1434,70 @@
  * XXX: all 60Hz refresh?
  */
 struct drm_display_mode sdvo_tv_modes[] = {
-	{ DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815680, 321, 384, 416,
-		   200, 0, 232, 201, 233, 4196112, 0,
+	{ DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815, 320, 321, 384,
+		   416, 0, 200, 201, 232, 233, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 6814080, 321, 384, 416,
-		   240, 0, 272, 241, 273, 4196112, 0,
+	{ DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 6814, 320, 321, 384,
+		   416, 0, 240, 241, 272, 273, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 9910080, 401, 464, 496,
-		   300, 0, 332, 301, 333, 4196112, 0,
+	{ DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 9910, 400, 401, 464,
+		   496, 0, 300, 301, 332, 333, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 16913280, 641, 704, 736,
-		   350, 0, 382, 351, 383, 4196112, 0,
+	{ DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 16913, 640, 641, 704,
+		   736, 0, 350, 351, 382, 383, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121280, 641, 704, 736,
-		   400, 0, 432, 401, 433, 4196112, 0,
+	{ DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121, 640, 641, 704,
+		   736, 0, 400, 401, 432, 433, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121280, 641, 704, 736,
-		   400, 0, 432, 401, 433, 4196112, 0,
+	{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 22654, 640, 641, 704,
+		   736, 0, 480, 481, 512, 513, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("704x480", DRM_MODE_TYPE_DRIVER, 24624000, 705, 768, 800,
-		   480, 0, 512, 481, 513, 4196112, 0,
+	{ DRM_MODE("704x480", DRM_MODE_TYPE_DRIVER, 24624, 704, 705, 768,
+		   800, 0, 480, 481, 512, 513, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("704x576", DRM_MODE_TYPE_DRIVER, 29232000, 705, 768, 800,
-		   576, 0, 608, 577, 609, 4196112, 0,
+	{ DRM_MODE("704x576", DRM_MODE_TYPE_DRIVER, 29232, 704, 705, 768,
+		   800, 0, 576, 577, 608, 609, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("720x350", DRM_MODE_TYPE_DRIVER, 18751680, 721, 784, 816,
-		   350, 0, 382, 351, 383, 4196112, 0,
+	{ DRM_MODE("720x350", DRM_MODE_TYPE_DRIVER, 18751, 720, 721, 784,
+		   816, 0, 350, 351, 382, 383, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 21199680, 721, 784, 816,
-		   400, 0, 432, 401, 433, 4196112, 0,
+	{ DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 21199, 720, 721, 784,
+		   816, 0, 400, 401, 432, 433, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 25116480, 721, 784, 816,
-		   480, 0, 512, 481, 513, 4196112, 0,
+	{ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 25116, 720, 721, 784,
+		   816, 0, 480, 481, 512, 513, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("720x540", DRM_MODE_TYPE_DRIVER, 28054080, 721, 784, 816,
-		   540, 0, 572, 541, 573, 4196112, 0,
+	{ DRM_MODE("720x540", DRM_MODE_TYPE_DRIVER, 28054, 720, 721, 784,
+		   816, 0, 540, 541, 572, 573, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 29816640, 721, 784, 816,
-		   576, 0, 608, 577, 609, 4196112, 0,
+	{ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 29816, 720, 721, 784,
+		   816, 0, 576, 577, 608, 609, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("768x576", DRM_MODE_TYPE_DRIVER, 31570560, 769, 832, 864,
-		   576, 0, 608, 577, 609, 4196112, 0,
+	{ DRM_MODE("768x576", DRM_MODE_TYPE_DRIVER, 31570, 768, 769, 832,
+		   864, 0, 576, 577, 608, 609, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 34030080, 801, 864, 896,
-		   600, 0, 632, 601, 633, 4196112, 0,
+	{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 34030, 800, 801, 864,
+		   896, 0, 600, 601, 632, 633, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 36581760, 833, 896, 928,
-		   624, 0, 656, 625, 657, 4196112, 0,
+	{ DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 36581, 832, 833, 896,
+		   928, 0, 624, 625, 656, 657, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("920x766", DRM_MODE_TYPE_DRIVER, 48707040, 921, 984, 1016,
-		   766, 0, 798, 767, 799, 4196112, 0,
+	{ DRM_MODE("920x766", DRM_MODE_TYPE_DRIVER, 48707, 920, 921, 984,
+		   1016, 0, 766, 767, 798, 799, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 53827200, 1025, 1088, 1120,
-		   768, 0, 800, 769, 801, 4196112, 0,
+	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 53827, 1024, 1025, 1088,
+		   1120, 0, 768, 769, 800, 801, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-	{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 87265920, 1281, 1344, 1376,
-		   1024, 0, 1056, 1025, 1057, 4196112, 0,
+	{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 87265, 1280, 1281, 1344,
+		   1376, 0, 1024, 1025, 1056, 1057, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 };
 
 static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
 {
 	struct intel_output *output = to_intel_output(connector);
+	struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
+	struct intel_sdvo_sdtv_resolution_request tv_res;
 	uint32_t reply = 0;
 	uint8_t status;
 	int i = 0;
@@ -1491,15 +1507,22 @@
 	/* Read the list of supported input resolutions for the selected TV
 	 * format.
 	 */
+	memset(&tv_res, 0, sizeof(tv_res));
+	memcpy(&tv_res, &sdvo_priv->tv_format, sizeof(tv_res));
 	intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
-			     NULL, 0);
+			     &tv_res, sizeof(tv_res));
 	status = intel_sdvo_read_response(output, &reply, 3);
 	if (status != SDVO_CMD_STATUS_SUCCESS)
 		return;
 
 	for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++)
-		if (reply & (1 << i))
-			drm_mode_probed_add(connector, &sdvo_tv_modes[i]);
+		if (reply & (1 << i)) {
+			struct drm_display_mode *nmode;
+			nmode = drm_mode_duplicate(connector->dev,
+					&sdvo_tv_modes[i]);
+			if (nmode)
+				drm_mode_probed_add(connector, nmode);
+		}
 }
 
 static int intel_sdvo_get_modes(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h
index 1117b9c..193938b 100644
--- a/drivers/gpu/drm/i915/intel_sdvo_regs.h
+++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h
@@ -100,6 +100,9 @@
     u16 clock;
     u16 width;
     u16 height;
+    u8	interlace:1;
+    u8	scaled:1;
+    u8	pad:6;
 } __attribute__((packed));
 
 /* I2C registers for SDVO */
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index ceca947..d2c3298 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1570,33 +1570,49 @@
 	struct drm_device *dev = connector->dev;
 	struct intel_output *intel_output = to_intel_output(connector);
 	struct intel_tv_priv *tv_priv = intel_output->dev_priv;
+	struct drm_encoder *encoder = &intel_output->enc;
+	struct drm_crtc *crtc = encoder->crtc;
 	int ret = 0;
+	bool changed = false;
 
 	ret = drm_connector_property_set_value(connector, property, val);
 	if (ret < 0)
 		goto out;
 
-	if (property == dev->mode_config.tv_left_margin_property)
+	if (property == dev->mode_config.tv_left_margin_property &&
+		tv_priv->margin[TV_MARGIN_LEFT] != val) {
 		tv_priv->margin[TV_MARGIN_LEFT] = val;
-	else if (property == dev->mode_config.tv_right_margin_property)
+		changed = true;
+	} else if (property == dev->mode_config.tv_right_margin_property &&
+		tv_priv->margin[TV_MARGIN_RIGHT] != val) {
 		tv_priv->margin[TV_MARGIN_RIGHT] = val;
-	else if (property == dev->mode_config.tv_top_margin_property)
+		changed = true;
+	} else if (property == dev->mode_config.tv_top_margin_property &&
+		tv_priv->margin[TV_MARGIN_TOP] != val) {
 		tv_priv->margin[TV_MARGIN_TOP] = val;
-	else if (property == dev->mode_config.tv_bottom_margin_property)
+		changed = true;
+	} else if (property == dev->mode_config.tv_bottom_margin_property &&
+		tv_priv->margin[TV_MARGIN_BOTTOM] != val) {
 		tv_priv->margin[TV_MARGIN_BOTTOM] = val;
-	else if (property == dev->mode_config.tv_mode_property) {
+		changed = true;
+	} else if (property == dev->mode_config.tv_mode_property) {
 		if (val >= NUM_TV_MODES) {
 			ret = -EINVAL;
 			goto out;
 		}
+		if (!strcmp(tv_priv->tv_format, tv_modes[val].name))
+			goto out;
+
 		tv_priv->tv_format = tv_modes[val].name;
-		intel_tv_mode_set(&intel_output->enc, NULL, NULL);
+		changed = true;
 	} else {
 		ret = -EINVAL;
 		goto out;
 	}
 
-	intel_tv_mode_set(&intel_output->enc, NULL, NULL);
+	if (changed && crtc)
+		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
+				crtc->y, crtc->fb);
 out:
 	return ret;
 }
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c
index 9d14eee..bc9d09d 100644
--- a/drivers/gpu/drm/radeon/r600_cp.c
+++ b/drivers/gpu/drm/radeon/r600_cp.c
@@ -388,17 +388,17 @@
 		DRM_INFO("Loading RS780 CP Microcode\n");
 		for (i = 0; i < PM4_UCODE_SIZE; i++) {
 			RADEON_WRITE(R600_CP_ME_RAM_DATA,
-				     RV670_cp_microcode[i][0]);
+				     RS780_cp_microcode[i][0]);
 			RADEON_WRITE(R600_CP_ME_RAM_DATA,
-				     RV670_cp_microcode[i][1]);
+				     RS780_cp_microcode[i][1]);
 			RADEON_WRITE(R600_CP_ME_RAM_DATA,
-				     RV670_cp_microcode[i][2]);
+				     RS780_cp_microcode[i][2]);
 		}
 
 		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
 		DRM_INFO("Loading RS780 PFP Microcode\n");
 		for (i = 0; i < PFP_UCODE_SIZE; i++)
-			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV670_pfp_microcode[i]);
+			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RS780_pfp_microcode[i]);
 	}
 	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
 	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index c7d4b2e..ec073d82 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -33,7 +33,6 @@
 #ifndef __DRM_CRTC_HELPER_H__
 #define __DRM_CRTC_HELPER_H__
 
-#include <linux/i2c.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/idr.h>
@@ -92,7 +91,7 @@
 extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY);
 extern void drm_helper_disable_unused_functions(struct drm_device *dev);
 extern int drm_helper_hotplug_stage_two(struct drm_device *dev);
-extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow);
+extern bool drm_helper_initial_config(struct drm_device *dev);
 extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
 extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 				     struct drm_display_mode *mode,
diff --git a/include/drm/drm_os_linux.h b/include/drm/drm_os_linux.h
index 013551d..26641e95 100644
--- a/include/drm/drm_os_linux.h
+++ b/include/drm/drm_os_linux.h
@@ -7,12 +7,12 @@
 #include <linux/delay.h>
 
 #ifndef readq
-static u64 readq(void __iomem *reg)
+static inline u64 readq(void __iomem *reg)
 {
 	return ((u64) readl(reg)) | (((u64) readl(reg + 4UL)) << 32);
 }
 
-static void writeq(u64 val, void __iomem *reg)
+static inline void writeq(u64 val, void __iomem *reg)
 {
 	writel(val & 0xffffffff, reg);
 	writel(val >> 32, reg + 0x4UL);