diff options
author | Dave Airlie <airlied@redhat.com> | 2009-04-02 20:27:21 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-04-02 20:27:21 -0400 |
commit | 5f3dbedf2770cf6aeb5547b3c56734dee4e5186b (patch) | |
tree | e4930f7f4fe27b06079d2df8072a2bdf6457c666 /drivers | |
parent | 7a1fb5d06d3936c0982e2cf8b53b046244a9aad6 (diff) | |
parent | 1055f9ddad093f54dfd708a0f976582034d4ce1a (diff) |
Merge branch 'drm-intel-next' of ../anholt-2.6 into drm-linus
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/drm_gem.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_sysfs.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 38 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_debug.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_debugfs.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_tiling.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 67 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_modes.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 193 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo_regs.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_tv.c | 30 |
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 | } |
454 | EXPORT_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 | } |
1500 | out: | ||
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 | */ | ||
189 | static 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 | |||
190 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | 199 | irqreturn_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 | ||
539 | int i915_driver_irq_postinstall(struct drm_device *dev) | 568 | int 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 | |||
636 | intel_wait_for_vblank(struct drm_device *dev) | 636 | intel_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 | ||
642 | static int | 642 | static 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, | |||
705 | static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode, | 709 | static 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 | ||
914 | static 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 | |||
927 | static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | 935 | static 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 | |||
1395 | intel_sdvo_check_tv_format(struct intel_output *output) | 1417 | intel_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 | */ |
1422 | struct drm_display_mode sdvo_tv_modes[] = { | 1436 | struct 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 | ||
1482 | static void intel_sdvo_get_tv_modes(struct drm_connector *connector) | 1496 | static 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 | ||
1505 | static int intel_sdvo_get_modes(struct drm_connector *connector) | 1528 | 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 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); | ||
1600 | out: | 1616 | out: |
1601 | return ret; | 1617 | return ret; |
1602 | } | 1618 | } |