aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-04-02 20:27:21 -0400
committerDave Airlie <airlied@redhat.com>2009-04-02 20:27:21 -0400
commit5f3dbedf2770cf6aeb5547b3c56734dee4e5186b (patch)
treee4930f7f4fe27b06079d2df8072a2bdf6457c666
parent7a1fb5d06d3936c0982e2cf8b53b046244a9aad6 (diff)
parent1055f9ddad093f54dfd708a0f976582034d4ce1a (diff)
Merge branch 'drm-intel-next' of ../anholt-2.6 into drm-linus
-rw-r--r--drivers/gpu/drm/drm_gem.c7
-rw-r--r--drivers/gpu/drm/drm_sysfs.c1
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c9
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h5
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c38
-rw-r--r--drivers/gpu/drm/i915/i915_gem_debug.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_debugfs.c6
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c16
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c67
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h11
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c4
-rw-r--r--drivers/gpu/drm/i915/intel_display.c22
-rw-r--r--drivers/gpu/drm/i915/intel_modes.c1
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c193
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo_regs.h3
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c30
16 files changed, 292 insertions, 123 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index c1173d8c4588..4984aa89cf3d 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -505,7 +505,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
505 struct drm_local_map *map = NULL; 505 struct drm_local_map *map = NULL;
506 struct drm_gem_object *obj; 506 struct drm_gem_object *obj;
507 struct drm_hash_item *hash; 507 struct drm_hash_item *hash;
508 unsigned long prot;
509 int ret = 0; 508 int ret = 0;
510 509
511 mutex_lock(&dev->struct_mutex); 510 mutex_lock(&dev->struct_mutex);
@@ -538,11 +537,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
538 vma->vm_ops = obj->dev->driver->gem_vm_ops; 537 vma->vm_ops = obj->dev->driver->gem_vm_ops;
539 vma->vm_private_data = map->handle; 538 vma->vm_private_data = map->handle;
540 /* FIXME: use pgprot_writecombine when available */ 539 /* FIXME: use pgprot_writecombine when available */
541 prot = pgprot_val(vma->vm_page_prot); 540 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
542#ifdef CONFIG_X86
543 prot |= _PAGE_CACHE_WC;
544#endif
545 vma->vm_page_prot = __pgprot(prot);
546 541
547 /* Take a ref for this mapping of the object, so that the fault 542 /* Take a ref for this mapping of the object, so that the fault
548 * handler can dereference the mmap offset's pointer to the object. 543 * 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 5de573a981cb..bc0c6849360c 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -451,6 +451,7 @@ void drm_sysfs_hotplug_event(struct drm_device *dev)
451 451
452 kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, envp); 452 kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, envp);
453} 453}
454EXPORT_SYMBOL(drm_sysfs_hotplug_event);
454 455
455/** 456/**
456 * drm_sysfs_device_add - adds a class device to sysfs for a character driver 457 * 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 9648d79fe36d..c23b3a95b7ce 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -922,7 +922,7 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
922 * Some of the preallocated space is taken by the GTT 922 * Some of the preallocated space is taken by the GTT
923 * and popup. GTT is 1K per MB of aperture size, and popup is 4K. 923 * and popup. GTT is 1K per MB of aperture size, and popup is 4K.
924 */ 924 */
925 if (IS_G4X(dev)) 925 if (IS_G4X(dev) || IS_IGD(dev))
926 overhead = 4096; 926 overhead = 4096;
927 else 927 else
928 overhead = (*aperture_size / 1024) + 4096; 928 overhead = (*aperture_size / 1024) + 4096;
@@ -1030,13 +1030,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
1030 if (ret) 1030 if (ret)
1031 goto destroy_ringbuffer; 1031 goto destroy_ringbuffer;
1032 1032
1033 /* FIXME: re-add hotplug support */
1034#if 0
1035 ret = drm_hotplug_init(dev);
1036 if (ret)
1037 goto destroy_ringbuffer;
1038#endif
1039
1040 /* Always safe in the mode setting case. */ 1033 /* Always safe in the mode setting case. */
1041 /* FIXME: do pre/post-mode set stuff in core KMS code */ 1034 /* FIXME: do pre/post-mode set stuff in core KMS code */
1042 dev->vblank_disable_allowed = 1; 1035 dev->vblank_disable_allowed = 1;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c1685d0c704f..317b1223e091 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -159,6 +159,9 @@ typedef struct drm_i915_private {
159 u32 irq_mask_reg; 159 u32 irq_mask_reg;
160 u32 pipestat[2]; 160 u32 pipestat[2];
161 161
162 u32 hotplug_supported_mask;
163 struct work_struct hotplug_work;
164
162 int tex_lru_log_granularity; 165 int tex_lru_log_granularity;
163 int allow_batchbuffer; 166 int allow_batchbuffer;
164 struct mem_block *agp_heap; 167 struct mem_block *agp_heap;
@@ -297,6 +300,7 @@ typedef struct drm_i915_private {
297 * 300 *
298 * A reference is held on the buffer while on this list. 301 * A reference is held on the buffer while on this list.
299 */ 302 */
303 spinlock_t active_list_lock;
300 struct list_head active_list; 304 struct list_head active_list;
301 305
302 /** 306 /**
@@ -810,6 +814,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
810#define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ 814#define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
811 IS_I915GM(dev))) 815 IS_I915GM(dev)))
812#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev)) 816#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev))
817#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev))
813 818
814#define PRIMARY_RINGBUFFER_SIZE (128*1024) 819#define PRIMARY_RINGBUFFER_SIZE (128*1024)
815 820
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index e0389ad1477d..1449b452cc63 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1072,6 +1072,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1072 case -EAGAIN: 1072 case -EAGAIN:
1073 return VM_FAULT_OOM; 1073 return VM_FAULT_OOM;
1074 case -EFAULT: 1074 case -EFAULT:
1075 case -EINVAL:
1075 return VM_FAULT_SIGBUS; 1076 return VM_FAULT_SIGBUS;
1076 default: 1077 default:
1077 return VM_FAULT_NOPAGE; 1078 return VM_FAULT_NOPAGE;
@@ -1324,8 +1325,10 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno)
1324 obj_priv->active = 1; 1325 obj_priv->active = 1;
1325 } 1326 }
1326 /* Move from whatever list we were on to the tail of execution. */ 1327 /* Move from whatever list we were on to the tail of execution. */
1328 spin_lock(&dev_priv->mm.active_list_lock);
1327 list_move_tail(&obj_priv->list, 1329 list_move_tail(&obj_priv->list,
1328 &dev_priv->mm.active_list); 1330 &dev_priv->mm.active_list);
1331 spin_unlock(&dev_priv->mm.active_list_lock);
1329 obj_priv->last_rendering_seqno = seqno; 1332 obj_priv->last_rendering_seqno = seqno;
1330} 1333}
1331 1334
@@ -1467,6 +1470,7 @@ i915_gem_retire_request(struct drm_device *dev,
1467 /* Move any buffers on the active list that are no longer referenced 1470 /* Move any buffers on the active list that are no longer referenced
1468 * by the ringbuffer to the flushing/inactive lists as appropriate. 1471 * by the ringbuffer to the flushing/inactive lists as appropriate.
1469 */ 1472 */
1473 spin_lock(&dev_priv->mm.active_list_lock);
1470 while (!list_empty(&dev_priv->mm.active_list)) { 1474 while (!list_empty(&dev_priv->mm.active_list)) {
1471 struct drm_gem_object *obj; 1475 struct drm_gem_object *obj;
1472 struct drm_i915_gem_object *obj_priv; 1476 struct drm_i915_gem_object *obj_priv;
@@ -1481,7 +1485,7 @@ i915_gem_retire_request(struct drm_device *dev,
1481 * this seqno. 1485 * this seqno.
1482 */ 1486 */
1483 if (obj_priv->last_rendering_seqno != request->seqno) 1487 if (obj_priv->last_rendering_seqno != request->seqno)
1484 return; 1488 goto out;
1485 1489
1486#if WATCH_LRU 1490#if WATCH_LRU
1487 DRM_INFO("%s: retire %d moves to inactive list %p\n", 1491 DRM_INFO("%s: retire %d moves to inactive list %p\n",
@@ -1493,6 +1497,8 @@ i915_gem_retire_request(struct drm_device *dev,
1493 else 1497 else
1494 i915_gem_object_move_to_inactive(obj); 1498 i915_gem_object_move_to_inactive(obj);
1495 } 1499 }
1500out:
1501 spin_unlock(&dev_priv->mm.active_list_lock);
1496} 1502}
1497 1503
1498/** 1504/**
@@ -1990,20 +1996,23 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
1990 int regnum = obj_priv->fence_reg; 1996 int regnum = obj_priv->fence_reg;
1991 uint32_t val; 1997 uint32_t val;
1992 uint32_t pitch_val; 1998 uint32_t pitch_val;
1999 uint32_t fence_size_bits;
1993 2000
1994 if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || 2001 if ((obj_priv->gtt_offset & ~I830_FENCE_START_MASK) ||
1995 (obj_priv->gtt_offset & (obj->size - 1))) { 2002 (obj_priv->gtt_offset & (obj->size - 1))) {
1996 WARN(1, "%s: object 0x%08x not 1M or size aligned\n", 2003 WARN(1, "%s: object 0x%08x not 512K or size aligned\n",
1997 __func__, obj_priv->gtt_offset); 2004 __func__, obj_priv->gtt_offset);
1998 return; 2005 return;
1999 } 2006 }
2000 2007
2001 pitch_val = (obj_priv->stride / 128) - 1; 2008 pitch_val = (obj_priv->stride / 128) - 1;
2002 2009 WARN_ON(pitch_val & ~0x0000000f);
2003 val = obj_priv->gtt_offset; 2010 val = obj_priv->gtt_offset;
2004 if (obj_priv->tiling_mode == I915_TILING_Y) 2011 if (obj_priv->tiling_mode == I915_TILING_Y)
2005 val |= 1 << I830_FENCE_TILING_Y_SHIFT; 2012 val |= 1 << I830_FENCE_TILING_Y_SHIFT;
2006 val |= I830_FENCE_SIZE_BITS(obj->size); 2013 fence_size_bits = I830_FENCE_SIZE_BITS(obj->size);
2014 WARN_ON(fence_size_bits & ~0x00000f00);
2015 val |= fence_size_bits;
2007 val |= pitch_val << I830_FENCE_PITCH_SHIFT; 2016 val |= pitch_val << I830_FENCE_PITCH_SHIFT;
2008 val |= I830_FENCE_REG_VALID; 2017 val |= I830_FENCE_REG_VALID;
2009 2018
@@ -2194,7 +2203,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
2194 return -EBUSY; 2203 return -EBUSY;
2195 if (alignment == 0) 2204 if (alignment == 0)
2196 alignment = i915_gem_get_gtt_alignment(obj); 2205 alignment = i915_gem_get_gtt_alignment(obj);
2197 if (alignment & (PAGE_SIZE - 1)) { 2206 if (alignment & (i915_gem_get_gtt_alignment(obj) - 1)) {
2198 DRM_ERROR("Invalid object alignment requested %u\n", alignment); 2207 DRM_ERROR("Invalid object alignment requested %u\n", alignment);
2199 return -EINVAL; 2208 return -EINVAL;
2200 } 2209 }
@@ -2211,15 +2220,20 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
2211 } 2220 }
2212 } 2221 }
2213 if (obj_priv->gtt_space == NULL) { 2222 if (obj_priv->gtt_space == NULL) {
2223 bool lists_empty;
2224
2214 /* If the gtt is empty and we're still having trouble 2225 /* If the gtt is empty and we're still having trouble
2215 * fitting our object in, we're out of memory. 2226 * fitting our object in, we're out of memory.
2216 */ 2227 */
2217#if WATCH_LRU 2228#if WATCH_LRU
2218 DRM_INFO("%s: GTT full, evicting something\n", __func__); 2229 DRM_INFO("%s: GTT full, evicting something\n", __func__);
2219#endif 2230#endif
2220 if (list_empty(&dev_priv->mm.inactive_list) && 2231 spin_lock(&dev_priv->mm.active_list_lock);
2221 list_empty(&dev_priv->mm.flushing_list) && 2232 lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
2222 list_empty(&dev_priv->mm.active_list)) { 2233 list_empty(&dev_priv->mm.flushing_list) &&
2234 list_empty(&dev_priv->mm.active_list));
2235 spin_unlock(&dev_priv->mm.active_list_lock);
2236 if (lists_empty) {
2223 DRM_ERROR("GTT full, but LRU list empty\n"); 2237 DRM_ERROR("GTT full, but LRU list empty\n");
2224 return -ENOMEM; 2238 return -ENOMEM;
2225 } 2239 }
@@ -3675,6 +3689,7 @@ i915_gem_idle(struct drm_device *dev)
3675 3689
3676 i915_gem_retire_requests(dev); 3690 i915_gem_retire_requests(dev);
3677 3691
3692 spin_lock(&dev_priv->mm.active_list_lock);
3678 if (!dev_priv->mm.wedged) { 3693 if (!dev_priv->mm.wedged) {
3679 /* Active and flushing should now be empty as we've 3694 /* Active and flushing should now be empty as we've
3680 * waited for a sequence higher than any pending execbuffer 3695 * waited for a sequence higher than any pending execbuffer
@@ -3701,6 +3716,7 @@ i915_gem_idle(struct drm_device *dev)
3701 obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS; 3716 obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
3702 i915_gem_object_move_to_inactive(obj_priv->obj); 3717 i915_gem_object_move_to_inactive(obj_priv->obj);
3703 } 3718 }
3719 spin_unlock(&dev_priv->mm.active_list_lock);
3704 3720
3705 while (!list_empty(&dev_priv->mm.flushing_list)) { 3721 while (!list_empty(&dev_priv->mm.flushing_list)) {
3706 struct drm_i915_gem_object *obj_priv; 3722 struct drm_i915_gem_object *obj_priv;
@@ -3949,7 +3965,10 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
3949 if (ret != 0) 3965 if (ret != 0)
3950 return ret; 3966 return ret;
3951 3967
3968 spin_lock(&dev_priv->mm.active_list_lock);
3952 BUG_ON(!list_empty(&dev_priv->mm.active_list)); 3969 BUG_ON(!list_empty(&dev_priv->mm.active_list));
3970 spin_unlock(&dev_priv->mm.active_list_lock);
3971
3953 BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); 3972 BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
3954 BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); 3973 BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
3955 BUG_ON(!list_empty(&dev_priv->mm.request_list)); 3974 BUG_ON(!list_empty(&dev_priv->mm.request_list));
@@ -3993,6 +4012,7 @@ i915_gem_load(struct drm_device *dev)
3993{ 4012{
3994 drm_i915_private_t *dev_priv = dev->dev_private; 4013 drm_i915_private_t *dev_priv = dev->dev_private;
3995 4014
4015 spin_lock_init(&dev_priv->mm.active_list_lock);
3996 INIT_LIST_HEAD(&dev_priv->mm.active_list); 4016 INIT_LIST_HEAD(&dev_priv->mm.active_list);
3997 INIT_LIST_HEAD(&dev_priv->mm.flushing_list); 4017 INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
3998 INIT_LIST_HEAD(&dev_priv->mm.inactive_list); 4018 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 131c088f8c8a..8d0b943e2c5a 100644
--- a/drivers/gpu/drm/i915/i915_gem_debug.c
+++ b/drivers/gpu/drm/i915/i915_gem_debug.c
@@ -105,12 +105,14 @@ i915_dump_lru(struct drm_device *dev, const char *where)
105 struct drm_i915_gem_object *obj_priv; 105 struct drm_i915_gem_object *obj_priv;
106 106
107 DRM_INFO("active list %s {\n", where); 107 DRM_INFO("active list %s {\n", where);
108 spin_lock(&dev_priv->mm.active_list_lock);
108 list_for_each_entry(obj_priv, &dev_priv->mm.active_list, 109 list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
109 list) 110 list)
110 { 111 {
111 DRM_INFO(" %p: %08x\n", obj_priv, 112 DRM_INFO(" %p: %08x\n", obj_priv,
112 obj_priv->last_rendering_seqno); 113 obj_priv->last_rendering_seqno);
113 } 114 }
115 spin_unlock(&dev_priv->mm.active_list_lock);
114 DRM_INFO("}\n"); 116 DRM_INFO("}\n");
115 DRM_INFO("flushing list %s {\n", where); 117 DRM_INFO("flushing list %s {\n", where);
116 list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, 118 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 455ec970b385..a1ac0c5e7307 100644
--- a/drivers/gpu/drm/i915/i915_gem_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c
@@ -69,10 +69,13 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
69 struct drm_device *dev = node->minor->dev; 69 struct drm_device *dev = node->minor->dev;
70 drm_i915_private_t *dev_priv = dev->dev_private; 70 drm_i915_private_t *dev_priv = dev->dev_private;
71 struct drm_i915_gem_object *obj_priv; 71 struct drm_i915_gem_object *obj_priv;
72 spinlock_t *lock = NULL;
72 73
73 switch (list) { 74 switch (list) {
74 case ACTIVE_LIST: 75 case ACTIVE_LIST:
75 seq_printf(m, "Active:\n"); 76 seq_printf(m, "Active:\n");
77 lock = &dev_priv->mm.active_list_lock;
78 spin_lock(lock);
76 head = &dev_priv->mm.active_list; 79 head = &dev_priv->mm.active_list;
77 break; 80 break;
78 case INACTIVE_LIST: 81 case INACTIVE_LIST:
@@ -104,6 +107,9 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
104 seq_printf(m, " (fence: %d\n", obj_priv->fence_reg); 107 seq_printf(m, " (fence: %d\n", obj_priv->fence_reg);
105 seq_printf(m, "\n"); 108 seq_printf(m, "\n");
106 } 109 }
110
111 if (lock)
112 spin_unlock(lock);
107 return 0; 113 return 0;
108} 114}
109 115
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 4cce1aef438e..6be3f927c86a 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -216,6 +216,22 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
216 else 216 else
217 tile_width = 512; 217 tile_width = 512;
218 218
219 /* check maximum stride & object size */
220 if (IS_I965G(dev)) {
221 /* i965 stores the end address of the gtt mapping in the fence
222 * reg, so dont bother to check the size */
223 if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
224 return false;
225 } else if (IS_I9XX(dev)) {
226 if (stride / tile_width > I830_FENCE_MAX_PITCH_VAL ||
227 size > (I830_FENCE_MAX_SIZE_VAL << 20))
228 return false;
229 } else {
230 if (stride / 128 > I830_FENCE_MAX_PITCH_VAL ||
231 size > (I830_FENCE_MAX_SIZE_VAL << 19))
232 return false;
233 }
234
219 /* 965+ just needs multiples of tile width */ 235 /* 965+ just needs multiples of tile width */
220 if (IS_I965G(dev)) { 236 if (IS_I965G(dev)) {
221 if (stride & (tile_width - 1)) 237 if (stride & (tile_width - 1))
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 87b6b603469e..ee7ce7b78cf7 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -48,10 +48,6 @@
48/** Interrupts that we mask and unmask at runtime. */ 48/** Interrupts that we mask and unmask at runtime. */
49#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) 49#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
50 50
51/** These are all of the interrupts used by the driver */
52#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \
53 I915_INTERRUPT_ENABLE_VAR)
54
55#define I915_PIPE_VBLANK_STATUS (PIPE_START_VBLANK_INTERRUPT_STATUS |\ 51#define I915_PIPE_VBLANK_STATUS (PIPE_START_VBLANK_INTERRUPT_STATUS |\
56 PIPE_VBLANK_INTERRUPT_STATUS) 52 PIPE_VBLANK_INTERRUPT_STATUS)
57 53
@@ -187,6 +183,19 @@ u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
187 return I915_READ(reg); 183 return I915_READ(reg);
188} 184}
189 185
186/*
187 * Handle hotplug events outside the interrupt handler proper.
188 */
189static void i915_hotplug_work_func(struct work_struct *work)
190{
191 drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
192 hotplug_work);
193 struct drm_device *dev = dev_priv->dev;
194
195 /* Just fire off a uevent and let userspace tell us what to do */
196 drm_sysfs_hotplug_event(dev);
197}
198
190irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) 199irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
191{ 200{
192 struct drm_device *dev = (struct drm_device *) arg; 201 struct drm_device *dev = (struct drm_device *) arg;
@@ -244,6 +253,20 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
244 253
245 ret = IRQ_HANDLED; 254 ret = IRQ_HANDLED;
246 255
256 /* Consume port. Then clear IIR or we'll miss events */
257 if ((I915_HAS_HOTPLUG(dev)) &&
258 (iir & I915_DISPLAY_PORT_INTERRUPT)) {
259 u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
260
261 DRM_DEBUG("hotplug event received, stat 0x%08x\n",
262 hotplug_status);
263 if (hotplug_status & dev_priv->hotplug_supported_mask)
264 schedule_work(&dev_priv->hotplug_work);
265
266 I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
267 I915_READ(PORT_HOTPLUG_STAT);
268 }
269
247 I915_WRITE(IIR, iir); 270 I915_WRITE(IIR, iir);
248 new_iir = I915_READ(IIR); /* Flush posted writes */ 271 new_iir = I915_READ(IIR); /* Flush posted writes */
249 272
@@ -528,17 +551,24 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
528 551
529 atomic_set(&dev_priv->irq_received, 0); 552 atomic_set(&dev_priv->irq_received, 0);
530 553
554 if (I915_HAS_HOTPLUG(dev)) {
555 I915_WRITE(PORT_HOTPLUG_EN, 0);
556 I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
557 }
558
531 I915_WRITE(HWSTAM, 0xeffe); 559 I915_WRITE(HWSTAM, 0xeffe);
532 I915_WRITE(PIPEASTAT, 0); 560 I915_WRITE(PIPEASTAT, 0);
533 I915_WRITE(PIPEBSTAT, 0); 561 I915_WRITE(PIPEBSTAT, 0);
534 I915_WRITE(IMR, 0xffffffff); 562 I915_WRITE(IMR, 0xffffffff);
535 I915_WRITE(IER, 0x0); 563 I915_WRITE(IER, 0x0);
536 (void) I915_READ(IER); 564 (void) I915_READ(IER);
565 INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
537} 566}
538 567
539int i915_driver_irq_postinstall(struct drm_device *dev) 568int i915_driver_irq_postinstall(struct drm_device *dev)
540{ 569{
541 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 570 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
571 u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
542 572
543 dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; 573 dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
544 574
@@ -550,13 +580,35 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
550 dev_priv->pipestat[0] = 0; 580 dev_priv->pipestat[0] = 0;
551 dev_priv->pipestat[1] = 0; 581 dev_priv->pipestat[1] = 0;
552 582
583 if (I915_HAS_HOTPLUG(dev)) {
584 u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
585
586 /* Leave other bits alone */
587 hotplug_en |= HOTPLUG_EN_MASK;
588 I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
589
590 dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS |
591 TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS |
592 SDVOB_HOTPLUG_INT_STATUS;
593 if (IS_G4X(dev)) {
594 dev_priv->hotplug_supported_mask |=
595 HDMIB_HOTPLUG_INT_STATUS |
596 HDMIC_HOTPLUG_INT_STATUS |
597 HDMID_HOTPLUG_INT_STATUS;
598 }
599 /* Enable in IER... */
600 enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
601 /* and unmask in IMR */
602 i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT);
603 }
604
553 /* Disable pipe interrupt enables, clear pending pipe status */ 605 /* Disable pipe interrupt enables, clear pending pipe status */
554 I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); 606 I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
555 I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); 607 I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
556 /* Clear pending interrupt status */ 608 /* Clear pending interrupt status */
557 I915_WRITE(IIR, I915_READ(IIR)); 609 I915_WRITE(IIR, I915_READ(IIR));
558 610
559 I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK); 611 I915_WRITE(IER, enable_mask);
560 I915_WRITE(IMR, dev_priv->irq_mask_reg); 612 I915_WRITE(IMR, dev_priv->irq_mask_reg);
561 (void) I915_READ(IER); 613 (void) I915_READ(IER);
562 614
@@ -575,6 +627,11 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
575 627
576 dev_priv->vblank_pipe = 0; 628 dev_priv->vblank_pipe = 0;
577 629
630 if (I915_HAS_HOTPLUG(dev)) {
631 I915_WRITE(PORT_HOTPLUG_EN, 0);
632 I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
633 }
634
578 I915_WRITE(HWSTAM, 0xffffffff); 635 I915_WRITE(HWSTAM, 0xffffffff);
579 I915_WRITE(PIPEASTAT, 0); 636 I915_WRITE(PIPEASTAT, 0);
580 I915_WRITE(PIPEBSTAT, 0); 637 I915_WRITE(PIPEBSTAT, 0);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 377cc588f5e9..e805b590ae71 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -190,6 +190,8 @@
190#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) 190#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8)
191#define I830_FENCE_PITCH_SHIFT 4 191#define I830_FENCE_PITCH_SHIFT 4
192#define I830_FENCE_REG_VALID (1<<0) 192#define I830_FENCE_REG_VALID (1<<0)
193#define I830_FENCE_MAX_PITCH_VAL 0x10
194#define I830_FENCE_MAX_SIZE_VAL (1<<8)
193 195
194#define I915_FENCE_START_MASK 0x0ff00000 196#define I915_FENCE_START_MASK 0x0ff00000
195#define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8) 197#define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8)
@@ -198,6 +200,7 @@
198#define I965_FENCE_PITCH_SHIFT 2 200#define I965_FENCE_PITCH_SHIFT 2
199#define I965_FENCE_TILING_Y_SHIFT 1 201#define I965_FENCE_TILING_Y_SHIFT 1
200#define I965_FENCE_REG_VALID (1<<0) 202#define I965_FENCE_REG_VALID (1<<0)
203#define I965_FENCE_MAX_PITCH_VAL 0x0400
201 204
202/* 205/*
203 * Instruction and interrupt control regs 206 * Instruction and interrupt control regs
@@ -648,6 +651,14 @@
648#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) 651#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
649#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) 652#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
650#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */ 653#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
654#define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f
655#define HOTPLUG_EN_MASK (HDMIB_HOTPLUG_INT_EN | \
656 HDMIC_HOTPLUG_INT_EN | \
657 HDMID_HOTPLUG_INT_EN | \
658 SDVOB_HOTPLUG_INT_EN | \
659 SDVOC_HOTPLUG_INT_EN | \
660 TV_HOTPLUG_INT_EN | \
661 CRT_HOTPLUG_INT_EN)
651 662
652 663
653#define PORT_HOTPLUG_STAT 0x61114 664#define PORT_HOTPLUG_STAT 0x61114
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 2b6d44381c31..9bdd959260a5 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -41,7 +41,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
41 41
42 temp = I915_READ(ADPA); 42 temp = I915_READ(ADPA);
43 temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); 43 temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
44 temp &= ~ADPA_DAC_ENABLE; 44 temp |= ADPA_DAC_ENABLE;
45 45
46 switch(mode) { 46 switch(mode) {
47 case DRM_MODE_DPMS_ON: 47 case DRM_MODE_DPMS_ON:
@@ -158,7 +158,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
158 else 158 else
159 tries = 1; 159 tries = 1;
160 hotplug_en = I915_READ(PORT_HOTPLUG_EN); 160 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
161 hotplug_en &= ~(CRT_HOTPLUG_MASK); 161 hotplug_en &= CRT_FORCE_HOTPLUG_MASK;
162 hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; 162 hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
163 163
164 if (IS_GM45(dev)) 164 if (IS_GM45(dev))
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d9c50ff94d76..64773ce52964 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -636,7 +636,7 @@ void
636intel_wait_for_vblank(struct drm_device *dev) 636intel_wait_for_vblank(struct drm_device *dev)
637{ 637{
638 /* Wait for 20ms, i.e. one cycle at 50hz. */ 638 /* Wait for 20ms, i.e. one cycle at 50hz. */
639 udelay(20000); 639 mdelay(20);
640} 640}
641 641
642static int 642static int
@@ -1106,6 +1106,26 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
1106 return -EINVAL; 1106 return -EINVAL;
1107 } 1107 }
1108 1108
1109 /* SDVO TV has fixed PLL values depend on its clock range,
1110 this mirrors vbios setting. */
1111 if (is_sdvo && is_tv) {
1112 if (adjusted_mode->clock >= 100000
1113 && adjusted_mode->clock < 140500) {
1114 clock.p1 = 2;
1115 clock.p2 = 10;
1116 clock.n = 3;
1117 clock.m1 = 16;
1118 clock.m2 = 8;
1119 } else if (adjusted_mode->clock >= 140500
1120 && adjusted_mode->clock <= 200000) {
1121 clock.p1 = 1;
1122 clock.p2 = 10;
1123 clock.n = 6;
1124 clock.m1 = 12;
1125 clock.m2 = 8;
1126 }
1127 }
1128
1109 if (IS_IGD(dev)) 1129 if (IS_IGD(dev))
1110 fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; 1130 fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
1111 else 1131 else
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index e42019e5d661..07d7ec976168 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -76,6 +76,7 @@ int intel_ddc_get_modes(struct intel_output *intel_output)
76 drm_mode_connector_update_edid_property(&intel_output->base, 76 drm_mode_connector_update_edid_property(&intel_output->base,
77 edid); 77 edid);
78 ret = drm_add_edid_modes(&intel_output->base, edid); 78 ret = drm_add_edid_modes(&intel_output->base, edid);
79 intel_output->base.display_info.raw_edid = NULL;
79 kfree(edid); 80 kfree(edid);
80 } 81 }
81 82
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index fbe6f3931b1b..7b31f55f55c8 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -273,20 +273,20 @@ static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd,
273 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; 273 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
274 int i; 274 int i;
275 275
276 DRM_DEBUG("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); 276 printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
277 for (i = 0; i < args_len; i++) 277 for (i = 0; i < args_len; i++)
278 printk("%02X ", ((u8 *)args)[i]); 278 printk(KERN_DEBUG "%02X ", ((u8 *)args)[i]);
279 for (; i < 8; i++) 279 for (; i < 8; i++)
280 printk(" "); 280 printk(KERN_DEBUG " ");
281 for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) { 281 for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) {
282 if (cmd == sdvo_cmd_names[i].cmd) { 282 if (cmd == sdvo_cmd_names[i].cmd) {
283 printk("(%s)", sdvo_cmd_names[i].name); 283 printk(KERN_DEBUG "(%s)", sdvo_cmd_names[i].name);
284 break; 284 break;
285 } 285 }
286 } 286 }
287 if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0])) 287 if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0]))
288 printk("(%02X)",cmd); 288 printk(KERN_DEBUG "(%02X)", cmd);
289 printk("\n"); 289 printk(KERN_DEBUG "\n");
290} 290}
291#else 291#else
292#define intel_sdvo_debug_write(o, c, a, l) 292#define intel_sdvo_debug_write(o, c, a, l)
@@ -323,17 +323,18 @@ static void intel_sdvo_debug_response(struct intel_output *intel_output,
323 u8 status) 323 u8 status)
324{ 324{
325 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; 325 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
326 int i;
326 327
327 DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv)); 328 printk(KERN_DEBUG "%s: R: ", SDVO_NAME(sdvo_priv));
328 for (i = 0; i < response_len; i++) 329 for (i = 0; i < response_len; i++)
329 printk("%02X ", ((u8 *)response)[i]); 330 printk(KERN_DEBUG "%02X ", ((u8 *)response)[i]);
330 for (; i < 8; i++) 331 for (; i < 8; i++)
331 printk(" "); 332 printk(KERN_DEBUG " ");
332 if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) 333 if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
333 printk("(%s)", cmd_status_names[status]); 334 printk(KERN_DEBUG "(%s)", cmd_status_names[status]);
334 else 335 else
335 printk("(??? %d)", status); 336 printk(KERN_DEBUG "(??? %d)", status);
336 printk("\n"); 337 printk(KERN_DEBUG "\n");
337} 338}
338#else 339#else
339#define intel_sdvo_debug_response(o, r, l, s) 340#define intel_sdvo_debug_response(o, r, l, s)
@@ -588,9 +589,12 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output,
588 struct intel_sdvo_preferred_input_timing_args args; 589 struct intel_sdvo_preferred_input_timing_args args;
589 uint8_t status; 590 uint8_t status;
590 591
592 memset(&args, 0, sizeof(args));
591 args.clock = clock; 593 args.clock = clock;
592 args.width = width; 594 args.width = width;
593 args.height = height; 595 args.height = height;
596 args.interlace = 0;
597 args.scaled = 0;
594 intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, 598 intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
595 &args, sizeof(args)); 599 &args, sizeof(args));
596 status = intel_sdvo_read_response(output, NULL, 0); 600 status = intel_sdvo_read_response(output, NULL, 0);
@@ -683,7 +687,7 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
683 dtd->part1.v_high = (((height >> 8) & 0xf) << 4) | 687 dtd->part1.v_high = (((height >> 8) & 0xf) << 4) |
684 ((v_blank_len >> 8) & 0xf); 688 ((v_blank_len >> 8) & 0xf);
685 689
686 dtd->part2.h_sync_off = h_sync_offset; 690 dtd->part2.h_sync_off = h_sync_offset & 0xff;
687 dtd->part2.h_sync_width = h_sync_len & 0xff; 691 dtd->part2.h_sync_width = h_sync_len & 0xff;
688 dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | 692 dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
689 (v_sync_len & 0xf); 693 (v_sync_len & 0xf);
@@ -705,27 +709,10 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
705static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode, 709static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
706 struct intel_sdvo_dtd *dtd) 710 struct intel_sdvo_dtd *dtd)
707{ 711{
708 uint16_t width, height;
709 uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len;
710 uint16_t h_sync_offset, v_sync_offset;
711
712 width = mode->crtc_hdisplay;
713 height = mode->crtc_vdisplay;
714
715 /* do some mode translations */
716 h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start;
717 h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
718
719 v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start;
720 v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
721
722 h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start;
723 v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start;
724
725 mode->hdisplay = dtd->part1.h_active; 712 mode->hdisplay = dtd->part1.h_active;
726 mode->hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8; 713 mode->hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8;
727 mode->hsync_start = mode->hdisplay + dtd->part2.h_sync_off; 714 mode->hsync_start = mode->hdisplay + dtd->part2.h_sync_off;
728 mode->hsync_start += (dtd->part2.sync_off_width_high & 0xa0) << 2; 715 mode->hsync_start += (dtd->part2.sync_off_width_high & 0xc0) << 2;
729 mode->hsync_end = mode->hsync_start + dtd->part2.h_sync_width; 716 mode->hsync_end = mode->hsync_start + dtd->part2.h_sync_width;
730 mode->hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4; 717 mode->hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4;
731 mode->htotal = mode->hdisplay + dtd->part1.h_blank; 718 mode->htotal = mode->hdisplay + dtd->part1.h_blank;
@@ -735,7 +722,7 @@ static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
735 mode->vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8; 722 mode->vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8;
736 mode->vsync_start = mode->vdisplay; 723 mode->vsync_start = mode->vdisplay;
737 mode->vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf; 724 mode->vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf;
738 mode->vsync_start += (dtd->part2.sync_off_width_high & 0x0a) << 2; 725 mode->vsync_start += (dtd->part2.sync_off_width_high & 0x0c) << 2;
739 mode->vsync_start += dtd->part2.v_sync_off_high & 0xc0; 726 mode->vsync_start += dtd->part2.v_sync_off_high & 0xc0;
740 mode->vsync_end = mode->vsync_start + 727 mode->vsync_end = mode->vsync_start +
741 (dtd->part2.v_sync_off_width & 0xf); 728 (dtd->part2.v_sync_off_width & 0xf);
@@ -745,7 +732,7 @@ static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
745 732
746 mode->clock = dtd->part1.clock * 10; 733 mode->clock = dtd->part1.clock * 10;
747 734
748 mode->flags &= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); 735 mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
749 if (dtd->part2.dtd_flags & 0x2) 736 if (dtd->part2.dtd_flags & 0x2)
750 mode->flags |= DRM_MODE_FLAG_PHSYNC; 737 mode->flags |= DRM_MODE_FLAG_PHSYNC;
751 if (dtd->part2.dtd_flags & 0x4) 738 if (dtd->part2.dtd_flags & 0x4)
@@ -924,6 +911,27 @@ static void intel_sdvo_set_avi_infoframe(struct intel_output *output,
924 SDVO_HBUF_TX_VSYNC); 911 SDVO_HBUF_TX_VSYNC);
925} 912}
926 913
914static void intel_sdvo_set_tv_format(struct intel_output *output)
915{
916 struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
917 struct intel_sdvo_tv_format *format, unset;
918 u8 status;
919
920 format = &sdvo_priv->tv_format;
921 memset(&unset, 0, sizeof(unset));
922 if (memcmp(format, &unset, sizeof(*format))) {
923 DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n",
924 SDVO_NAME(sdvo_priv));
925 format->ntsc_m = 1;
926 intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, format,
927 sizeof(*format));
928 status = intel_sdvo_read_response(output, NULL, 0);
929 if (status != SDVO_CMD_STATUS_SUCCESS)
930 DRM_DEBUG("%s: Failed to set TV format\n",
931 SDVO_NAME(sdvo_priv));
932 }
933}
934
927static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, 935static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
928 struct drm_display_mode *mode, 936 struct drm_display_mode *mode,
929 struct drm_display_mode *adjusted_mode) 937 struct drm_display_mode *adjusted_mode)
@@ -968,6 +976,12 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
968 &input_dtd); 976 &input_dtd);
969 intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); 977 intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
970 978
979 drm_mode_set_crtcinfo(adjusted_mode, 0);
980
981 mode->clock = adjusted_mode->clock;
982
983 adjusted_mode->clock *=
984 intel_sdvo_get_pixel_multiplier(mode);
971 } else { 985 } else {
972 return false; 986 return false;
973 } 987 }
@@ -1012,7 +1026,12 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
1012 sdvox |= SDVO_AUDIO_ENABLE; 1026 sdvox |= SDVO_AUDIO_ENABLE;
1013 } 1027 }
1014 1028
1015 intel_sdvo_get_dtd_from_mode(&input_dtd, mode); 1029 /* We have tried to get input timing in mode_fixup, and filled into
1030 adjusted_mode */
1031 if (sdvo_priv->is_tv)
1032 intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
1033 else
1034 intel_sdvo_get_dtd_from_mode(&input_dtd, mode);
1016 1035
1017 /* If it's a TV, we already set the output timing in mode_fixup. 1036 /* If it's a TV, we already set the output timing in mode_fixup.
1018 * Otherwise, the output timing is equal to the input timing. 1037 * Otherwise, the output timing is equal to the input timing.
@@ -1027,6 +1046,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
1027 /* Set the input timing to the screen. Assume always input 0. */ 1046 /* Set the input timing to the screen. Assume always input 0. */
1028 intel_sdvo_set_target_input(output, true, false); 1047 intel_sdvo_set_target_input(output, true, false);
1029 1048
1049 if (sdvo_priv->is_tv)
1050 intel_sdvo_set_tv_format(output);
1051
1030 /* We would like to use intel_sdvo_create_preferred_input_timing() to 1052 /* We would like to use intel_sdvo_create_preferred_input_timing() to
1031 * provide the device with a timing it can support, if it supports that 1053 * provide the device with a timing it can support, if it supports that
1032 * feature. However, presumably we would need to adjust the CRTC to 1054 * feature. However, presumably we would need to adjust the CRTC to
@@ -1395,7 +1417,7 @@ static void
1395intel_sdvo_check_tv_format(struct intel_output *output) 1417intel_sdvo_check_tv_format(struct intel_output *output)
1396{ 1418{
1397 struct intel_sdvo_priv *dev_priv = output->dev_priv; 1419 struct intel_sdvo_priv *dev_priv = output->dev_priv;
1398 struct intel_sdvo_tv_format format, unset; 1420 struct intel_sdvo_tv_format format;
1399 uint8_t status; 1421 uint8_t status;
1400 1422
1401 intel_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0); 1423 intel_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0);
@@ -1403,15 +1425,7 @@ intel_sdvo_check_tv_format(struct intel_output *output)
1403 if (status != SDVO_CMD_STATUS_SUCCESS) 1425 if (status != SDVO_CMD_STATUS_SUCCESS)
1404 return; 1426 return;
1405 1427
1406 memset(&unset, 0, sizeof(unset)); 1428 memcpy(&dev_priv->tv_format, &format, sizeof(format));
1407 if (memcmp(&format, &unset, sizeof(format))) {
1408 DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n",
1409 SDVO_NAME(dev_priv));
1410
1411 format.ntsc_m = true;
1412 intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, NULL, 0);
1413 status = intel_sdvo_read_response(output, NULL, 0);
1414 }
1415} 1429}
1416 1430
1417/* 1431/*
@@ -1420,68 +1434,70 @@ intel_sdvo_check_tv_format(struct intel_output *output)
1420 * XXX: all 60Hz refresh? 1434 * XXX: all 60Hz refresh?
1421 */ 1435 */
1422struct drm_display_mode sdvo_tv_modes[] = { 1436struct drm_display_mode sdvo_tv_modes[] = {
1423 { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815680, 321, 384, 416, 1437 { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815, 320, 321, 384,
1424 200, 0, 232, 201, 233, 4196112, 0, 1438 416, 0, 200, 201, 232, 233, 0,
1425 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1439 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1426 { DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 6814080, 321, 384, 416, 1440 { DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 6814, 320, 321, 384,
1427 240, 0, 272, 241, 273, 4196112, 0, 1441 416, 0, 240, 241, 272, 273, 0,
1428 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1442 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1429 { DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 9910080, 401, 464, 496, 1443 { DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 9910, 400, 401, 464,
1430 300, 0, 332, 301, 333, 4196112, 0, 1444 496, 0, 300, 301, 332, 333, 0,
1431 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1445 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1432 { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 16913280, 641, 704, 736, 1446 { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 16913, 640, 641, 704,
1433 350, 0, 382, 351, 383, 4196112, 0, 1447 736, 0, 350, 351, 382, 383, 0,
1434 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1448 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1435 { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121280, 641, 704, 736, 1449 { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121, 640, 641, 704,
1436 400, 0, 432, 401, 433, 4196112, 0, 1450 736, 0, 400, 401, 432, 433, 0,
1437 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1451 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1438 { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121280, 641, 704, 736, 1452 { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 22654, 640, 641, 704,
1439 400, 0, 432, 401, 433, 4196112, 0, 1453 736, 0, 480, 481, 512, 513, 0,
1440 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1454 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1441 { DRM_MODE("704x480", DRM_MODE_TYPE_DRIVER, 24624000, 705, 768, 800, 1455 { DRM_MODE("704x480", DRM_MODE_TYPE_DRIVER, 24624, 704, 705, 768,
1442 480, 0, 512, 481, 513, 4196112, 0, 1456 800, 0, 480, 481, 512, 513, 0,
1443 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1457 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1444 { DRM_MODE("704x576", DRM_MODE_TYPE_DRIVER, 29232000, 705, 768, 800, 1458 { DRM_MODE("704x576", DRM_MODE_TYPE_DRIVER, 29232, 704, 705, 768,
1445 576, 0, 608, 577, 609, 4196112, 0, 1459 800, 0, 576, 577, 608, 609, 0,
1446 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1460 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1447 { DRM_MODE("720x350", DRM_MODE_TYPE_DRIVER, 18751680, 721, 784, 816, 1461 { DRM_MODE("720x350", DRM_MODE_TYPE_DRIVER, 18751, 720, 721, 784,
1448 350, 0, 382, 351, 383, 4196112, 0, 1462 816, 0, 350, 351, 382, 383, 0,
1449 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1463 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1450 { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 21199680, 721, 784, 816, 1464 { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 21199, 720, 721, 784,
1451 400, 0, 432, 401, 433, 4196112, 0, 1465 816, 0, 400, 401, 432, 433, 0,
1452 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1466 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1453 { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 25116480, 721, 784, 816, 1467 { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 25116, 720, 721, 784,
1454 480, 0, 512, 481, 513, 4196112, 0, 1468 816, 0, 480, 481, 512, 513, 0,
1455 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1469 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1456 { DRM_MODE("720x540", DRM_MODE_TYPE_DRIVER, 28054080, 721, 784, 816, 1470 { DRM_MODE("720x540", DRM_MODE_TYPE_DRIVER, 28054, 720, 721, 784,
1457 540, 0, 572, 541, 573, 4196112, 0, 1471 816, 0, 540, 541, 572, 573, 0,
1458 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1472 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1459 { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 29816640, 721, 784, 816, 1473 { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 29816, 720, 721, 784,
1460 576, 0, 608, 577, 609, 4196112, 0, 1474 816, 0, 576, 577, 608, 609, 0,
1461 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1475 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1462 { DRM_MODE("768x576", DRM_MODE_TYPE_DRIVER, 31570560, 769, 832, 864, 1476 { DRM_MODE("768x576", DRM_MODE_TYPE_DRIVER, 31570, 768, 769, 832,
1463 576, 0, 608, 577, 609, 4196112, 0, 1477 864, 0, 576, 577, 608, 609, 0,
1464 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1478 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1465 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 34030080, 801, 864, 896, 1479 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 34030, 800, 801, 864,
1466 600, 0, 632, 601, 633, 4196112, 0, 1480 896, 0, 600, 601, 632, 633, 0,
1467 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1481 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1468 { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 36581760, 833, 896, 928, 1482 { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 36581, 832, 833, 896,
1469 624, 0, 656, 625, 657, 4196112, 0, 1483 928, 0, 624, 625, 656, 657, 0,
1470 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1484 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1471 { DRM_MODE("920x766", DRM_MODE_TYPE_DRIVER, 48707040, 921, 984, 1016, 1485 { DRM_MODE("920x766", DRM_MODE_TYPE_DRIVER, 48707, 920, 921, 984,
1472 766, 0, 798, 767, 799, 4196112, 0, 1486 1016, 0, 766, 767, 798, 799, 0,
1473 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1487 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1474 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 53827200, 1025, 1088, 1120, 1488 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 53827, 1024, 1025, 1088,
1475 768, 0, 800, 769, 801, 4196112, 0, 1489 1120, 0, 768, 769, 800, 801, 0,
1476 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1490 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1477 { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 87265920, 1281, 1344, 1376, 1491 { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 87265, 1280, 1281, 1344,
1478 1024, 0, 1056, 1025, 1057, 4196112, 0, 1492 1376, 0, 1024, 1025, 1056, 1057, 0,
1479 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 1493 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
1480}; 1494};
1481 1495
1482static void intel_sdvo_get_tv_modes(struct drm_connector *connector) 1496static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
1483{ 1497{
1484 struct intel_output *output = to_intel_output(connector); 1498 struct intel_output *output = to_intel_output(connector);
1499 struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
1500 struct intel_sdvo_sdtv_resolution_request tv_res;
1485 uint32_t reply = 0; 1501 uint32_t reply = 0;
1486 uint8_t status; 1502 uint8_t status;
1487 int i = 0; 1503 int i = 0;
@@ -1491,15 +1507,22 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
1491 /* Read the list of supported input resolutions for the selected TV 1507 /* Read the list of supported input resolutions for the selected TV
1492 * format. 1508 * format.
1493 */ 1509 */
1510 memset(&tv_res, 0, sizeof(tv_res));
1511 memcpy(&tv_res, &sdvo_priv->tv_format, sizeof(tv_res));
1494 intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, 1512 intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
1495 NULL, 0); 1513 &tv_res, sizeof(tv_res));
1496 status = intel_sdvo_read_response(output, &reply, 3); 1514 status = intel_sdvo_read_response(output, &reply, 3);
1497 if (status != SDVO_CMD_STATUS_SUCCESS) 1515 if (status != SDVO_CMD_STATUS_SUCCESS)
1498 return; 1516 return;
1499 1517
1500 for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++) 1518 for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++)
1501 if (reply & (1 << i)) 1519 if (reply & (1 << i)) {
1502 drm_mode_probed_add(connector, &sdvo_tv_modes[i]); 1520 struct drm_display_mode *nmode;
1521 nmode = drm_mode_duplicate(connector->dev,
1522 &sdvo_tv_modes[i]);
1523 if (nmode)
1524 drm_mode_probed_add(connector, nmode);
1525 }
1503} 1526}
1504 1527
1505static int intel_sdvo_get_modes(struct drm_connector *connector) 1528static 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 1117b9c151a6..193938b7d7f9 100644
--- a/drivers/gpu/drm/i915/intel_sdvo_regs.h
+++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h
@@ -100,6 +100,9 @@ struct intel_sdvo_preferred_input_timing_args {
100 u16 clock; 100 u16 clock;
101 u16 width; 101 u16 width;
102 u16 height; 102 u16 height;
103 u8 interlace:1;
104 u8 scaled:1;
105 u8 pad:6;
103} __attribute__((packed)); 106} __attribute__((packed));
104 107
105/* I2C registers for SDVO */ 108/* I2C registers for SDVO */
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index ceca9471a75a..d2c32983242d 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1570,33 +1570,49 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
1570 struct drm_device *dev = connector->dev; 1570 struct drm_device *dev = connector->dev;
1571 struct intel_output *intel_output = to_intel_output(connector); 1571 struct intel_output *intel_output = to_intel_output(connector);
1572 struct intel_tv_priv *tv_priv = intel_output->dev_priv; 1572 struct intel_tv_priv *tv_priv = intel_output->dev_priv;
1573 struct drm_encoder *encoder = &intel_output->enc;
1574 struct drm_crtc *crtc = encoder->crtc;
1573 int ret = 0; 1575 int ret = 0;
1576 bool changed = false;
1574 1577
1575 ret = drm_connector_property_set_value(connector, property, val); 1578 ret = drm_connector_property_set_value(connector, property, val);
1576 if (ret < 0) 1579 if (ret < 0)
1577 goto out; 1580 goto out;
1578 1581
1579 if (property == dev->mode_config.tv_left_margin_property) 1582 if (property == dev->mode_config.tv_left_margin_property &&
1583 tv_priv->margin[TV_MARGIN_LEFT] != val) {
1580 tv_priv->margin[TV_MARGIN_LEFT] = val; 1584 tv_priv->margin[TV_MARGIN_LEFT] = val;
1581 else if (property == dev->mode_config.tv_right_margin_property) 1585 changed = true;
1586 } else if (property == dev->mode_config.tv_right_margin_property &&
1587 tv_priv->margin[TV_MARGIN_RIGHT] != val) {
1582 tv_priv->margin[TV_MARGIN_RIGHT] = val; 1588 tv_priv->margin[TV_MARGIN_RIGHT] = val;
1583 else if (property == dev->mode_config.tv_top_margin_property) 1589 changed = true;
1590 } else if (property == dev->mode_config.tv_top_margin_property &&
1591 tv_priv->margin[TV_MARGIN_TOP] != val) {
1584 tv_priv->margin[TV_MARGIN_TOP] = val; 1592 tv_priv->margin[TV_MARGIN_TOP] = val;
1585 else if (property == dev->mode_config.tv_bottom_margin_property) 1593 changed = true;
1594 } else if (property == dev->mode_config.tv_bottom_margin_property &&
1595 tv_priv->margin[TV_MARGIN_BOTTOM] != val) {
1586 tv_priv->margin[TV_MARGIN_BOTTOM] = val; 1596 tv_priv->margin[TV_MARGIN_BOTTOM] = val;
1587 else if (property == dev->mode_config.tv_mode_property) { 1597 changed = true;
1598 } else if (property == dev->mode_config.tv_mode_property) {
1588 if (val >= NUM_TV_MODES) { 1599 if (val >= NUM_TV_MODES) {
1589 ret = -EINVAL; 1600 ret = -EINVAL;
1590 goto out; 1601 goto out;
1591 } 1602 }
1603 if (!strcmp(tv_priv->tv_format, tv_modes[val].name))
1604 goto out;
1605
1592 tv_priv->tv_format = tv_modes[val].name; 1606 tv_priv->tv_format = tv_modes[val].name;
1593 intel_tv_mode_set(&intel_output->enc, NULL, NULL); 1607 changed = true;
1594 } else { 1608 } else {
1595 ret = -EINVAL; 1609 ret = -EINVAL;
1596 goto out; 1610 goto out;
1597 } 1611 }
1598 1612
1599 intel_tv_mode_set(&intel_output->enc, NULL, NULL); 1613 if (changed && crtc)
1614 drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
1615 crtc->y, crtc->fb);
1600out: 1616out:
1601 return ret; 1617 return ret;
1602} 1618}