diff options
| author | Grant Likely <grant.likely@secretlab.ca> | 2010-02-02 03:05:22 -0500 |
|---|---|---|
| committer | Grant Likely <grant.likely@secretlab.ca> | 2010-02-02 03:05:22 -0500 |
| commit | fb7899b1f0b748ef966071f5dc23c59ebd57d08f (patch) | |
| tree | 2f13f9d8607871a60334608524e8b4e9447f5309 /drivers/gpu/drm/i915 | |
| parent | 212b3c8b8ab94d983c2e0ee1821f17dd5b4e0859 (diff) | |
| parent | abe94c756c08d50566c09a65b9c7fe72f83071c5 (diff) | |
Merge commit 'v2.6.33-rc6' into secretlab/next-spi
Diffstat (limited to 'drivers/gpu/drm/i915')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 107 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 68 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 35 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_bios.h | 40 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 84 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 75 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 50 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 17 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 83 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_tv.c | 2 |
15 files changed, 319 insertions, 261 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9c9998c4dceb..a894ade03093 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
| @@ -290,7 +290,7 @@ static int i915_batchbuffer_info(struct seq_file *m, void *data) | |||
| 290 | list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { | 290 | list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { |
| 291 | obj = obj_priv->obj; | 291 | obj = obj_priv->obj; |
| 292 | if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) { | 292 | if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) { |
| 293 | ret = i915_gem_object_get_pages(obj); | 293 | ret = i915_gem_object_get_pages(obj, 0); |
| 294 | if (ret) { | 294 | if (ret) { |
| 295 | DRM_ERROR("Failed to get pages: %d\n", ret); | 295 | DRM_ERROR("Failed to get pages: %d\n", ret); |
| 296 | spin_unlock(&dev_priv->mm.active_list_lock); | 296 | spin_unlock(&dev_priv->mm.active_list_lock); |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index bbe47812e4b6..e660ac07f3b2 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -134,6 +134,10 @@ static int i915_init_phys_hws(struct drm_device *dev) | |||
| 134 | 134 | ||
| 135 | memset(dev_priv->hw_status_page, 0, PAGE_SIZE); | 135 | memset(dev_priv->hw_status_page, 0, PAGE_SIZE); |
| 136 | 136 | ||
| 137 | if (IS_I965G(dev)) | ||
| 138 | dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & | ||
| 139 | 0xf0; | ||
| 140 | |||
| 137 | I915_WRITE(HWS_PGA, dev_priv->dma_status_page); | 141 | I915_WRITE(HWS_PGA, dev_priv->dma_status_page); |
| 138 | DRM_DEBUG_DRIVER("Enabled hardware status page\n"); | 142 | DRM_DEBUG_DRIVER("Enabled hardware status page\n"); |
| 139 | return 0; | 143 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index be631cc3e4dc..46d88965852a 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -45,6 +45,9 @@ module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); | |||
| 45 | unsigned int i915_powersave = 1; | 45 | unsigned int i915_powersave = 1; |
| 46 | module_param_named(powersave, i915_powersave, int, 0400); | 46 | module_param_named(powersave, i915_powersave, int, 0400); |
| 47 | 47 | ||
| 48 | unsigned int i915_lvds_downclock = 0; | ||
| 49 | module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); | ||
| 50 | |||
| 48 | static struct drm_driver driver; | 51 | static struct drm_driver driver; |
| 49 | 52 | ||
| 50 | #define INTEL_VGA_DEVICE(id, info) { \ | 53 | #define INTEL_VGA_DEVICE(id, info) { \ |
| @@ -464,8 +467,11 @@ static struct drm_driver driver = { | |||
| 464 | .lastclose = i915_driver_lastclose, | 467 | .lastclose = i915_driver_lastclose, |
| 465 | .preclose = i915_driver_preclose, | 468 | .preclose = i915_driver_preclose, |
| 466 | .postclose = i915_driver_postclose, | 469 | .postclose = i915_driver_postclose, |
| 470 | |||
| 471 | /* Used in place of i915_pm_ops for non-DRIVER_MODESET */ | ||
| 467 | .suspend = i915_suspend, | 472 | .suspend = i915_suspend, |
| 468 | .resume = i915_resume, | 473 | .resume = i915_resume, |
| 474 | |||
| 469 | .device_is_agp = i915_driver_device_is_agp, | 475 | .device_is_agp = i915_driver_device_is_agp, |
| 470 | .enable_vblank = i915_enable_vblank, | 476 | .enable_vblank = i915_enable_vblank, |
| 471 | .disable_vblank = i915_disable_vblank, | 477 | .disable_vblank = i915_disable_vblank, |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 29dd67626967..aaf934d96f21 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -283,6 +283,7 @@ typedef struct drm_i915_private { | |||
| 283 | unsigned int lvds_use_ssc:1; | 283 | unsigned int lvds_use_ssc:1; |
| 284 | unsigned int edp_support:1; | 284 | unsigned int edp_support:1; |
| 285 | int lvds_ssc_freq; | 285 | int lvds_ssc_freq; |
| 286 | int edp_bpp; | ||
| 286 | 287 | ||
| 287 | struct notifier_block lid_notifier; | 288 | struct notifier_block lid_notifier; |
| 288 | 289 | ||
| @@ -722,6 +723,7 @@ extern struct drm_ioctl_desc i915_ioctls[]; | |||
| 722 | extern int i915_max_ioctl; | 723 | extern int i915_max_ioctl; |
| 723 | extern unsigned int i915_fbpercrtc; | 724 | extern unsigned int i915_fbpercrtc; |
| 724 | extern unsigned int i915_powersave; | 725 | extern unsigned int i915_powersave; |
| 726 | extern unsigned int i915_lvds_downclock; | ||
| 725 | 727 | ||
| 726 | extern void i915_save_display(struct drm_device *dev); | 728 | extern void i915_save_display(struct drm_device *dev); |
| 727 | extern void i915_restore_display(struct drm_device *dev); | 729 | extern void i915_restore_display(struct drm_device *dev); |
| @@ -864,12 +866,13 @@ int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptib | |||
| 864 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); | 866 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); |
| 865 | int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, | 867 | int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, |
| 866 | int write); | 868 | int write); |
| 869 | int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj); | ||
| 867 | int i915_gem_attach_phys_object(struct drm_device *dev, | 870 | int i915_gem_attach_phys_object(struct drm_device *dev, |
| 868 | struct drm_gem_object *obj, int id); | 871 | struct drm_gem_object *obj, int id); |
| 869 | void i915_gem_detach_phys_object(struct drm_device *dev, | 872 | void i915_gem_detach_phys_object(struct drm_device *dev, |
| 870 | struct drm_gem_object *obj); | 873 | struct drm_gem_object *obj); |
| 871 | void i915_gem_free_all_phys_object(struct drm_device *dev); | 874 | void i915_gem_free_all_phys_object(struct drm_device *dev); |
| 872 | int i915_gem_object_get_pages(struct drm_gem_object *obj); | 875 | int i915_gem_object_get_pages(struct drm_gem_object *obj, gfp_t gfpmask); |
| 873 | void i915_gem_object_put_pages(struct drm_gem_object *obj); | 876 | void i915_gem_object_put_pages(struct drm_gem_object *obj); |
| 874 | void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv); | 877 | void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv); |
| 875 | void i915_gem_object_flush_write_domain(struct drm_gem_object *obj); | 878 | void i915_gem_object_flush_write_domain(struct drm_gem_object *obj); |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2748609f05b3..dda787aafcc6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -277,7 +277,7 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
| 277 | 277 | ||
| 278 | mutex_lock(&dev->struct_mutex); | 278 | mutex_lock(&dev->struct_mutex); |
| 279 | 279 | ||
| 280 | ret = i915_gem_object_get_pages(obj); | 280 | ret = i915_gem_object_get_pages(obj, 0); |
| 281 | if (ret != 0) | 281 | if (ret != 0) |
| 282 | goto fail_unlock; | 282 | goto fail_unlock; |
| 283 | 283 | ||
| @@ -321,40 +321,24 @@ fail_unlock: | |||
| 321 | return ret; | 321 | return ret; |
| 322 | } | 322 | } |
| 323 | 323 | ||
| 324 | static inline gfp_t | ||
| 325 | i915_gem_object_get_page_gfp_mask (struct drm_gem_object *obj) | ||
| 326 | { | ||
| 327 | return mapping_gfp_mask(obj->filp->f_path.dentry->d_inode->i_mapping); | ||
| 328 | } | ||
| 329 | |||
| 330 | static inline void | ||
| 331 | i915_gem_object_set_page_gfp_mask (struct drm_gem_object *obj, gfp_t gfp) | ||
| 332 | { | ||
| 333 | mapping_set_gfp_mask(obj->filp->f_path.dentry->d_inode->i_mapping, gfp); | ||
| 334 | } | ||
| 335 | |||
| 336 | static int | 324 | static int |
| 337 | i915_gem_object_get_pages_or_evict(struct drm_gem_object *obj) | 325 | i915_gem_object_get_pages_or_evict(struct drm_gem_object *obj) |
| 338 | { | 326 | { |
| 339 | int ret; | 327 | int ret; |
| 340 | 328 | ||
| 341 | ret = i915_gem_object_get_pages(obj); | 329 | ret = i915_gem_object_get_pages(obj, __GFP_NORETRY | __GFP_NOWARN); |
| 342 | 330 | ||
| 343 | /* If we've insufficient memory to map in the pages, attempt | 331 | /* If we've insufficient memory to map in the pages, attempt |
| 344 | * to make some space by throwing out some old buffers. | 332 | * to make some space by throwing out some old buffers. |
| 345 | */ | 333 | */ |
| 346 | if (ret == -ENOMEM) { | 334 | if (ret == -ENOMEM) { |
| 347 | struct drm_device *dev = obj->dev; | 335 | struct drm_device *dev = obj->dev; |
| 348 | gfp_t gfp; | ||
| 349 | 336 | ||
| 350 | ret = i915_gem_evict_something(dev, obj->size); | 337 | ret = i915_gem_evict_something(dev, obj->size); |
| 351 | if (ret) | 338 | if (ret) |
| 352 | return ret; | 339 | return ret; |
| 353 | 340 | ||
| 354 | gfp = i915_gem_object_get_page_gfp_mask(obj); | 341 | ret = i915_gem_object_get_pages(obj, 0); |
| 355 | i915_gem_object_set_page_gfp_mask(obj, gfp & ~__GFP_NORETRY); | ||
| 356 | ret = i915_gem_object_get_pages(obj); | ||
| 357 | i915_gem_object_set_page_gfp_mask (obj, gfp); | ||
| 358 | } | 342 | } |
| 359 | 343 | ||
| 360 | return ret; | 344 | return ret; |
| @@ -790,7 +774,7 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
| 790 | 774 | ||
| 791 | mutex_lock(&dev->struct_mutex); | 775 | mutex_lock(&dev->struct_mutex); |
| 792 | 776 | ||
| 793 | ret = i915_gem_object_get_pages(obj); | 777 | ret = i915_gem_object_get_pages(obj, 0); |
| 794 | if (ret != 0) | 778 | if (ret != 0) |
| 795 | goto fail_unlock; | 779 | goto fail_unlock; |
| 796 | 780 | ||
| @@ -2230,7 +2214,8 @@ i915_gem_evict_something(struct drm_device *dev, int min_size) | |||
| 2230 | } | 2214 | } |
| 2231 | 2215 | ||
| 2232 | int | 2216 | int |
| 2233 | i915_gem_object_get_pages(struct drm_gem_object *obj) | 2217 | i915_gem_object_get_pages(struct drm_gem_object *obj, |
| 2218 | gfp_t gfpmask) | ||
| 2234 | { | 2219 | { |
| 2235 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 2220 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 2236 | int page_count, i; | 2221 | int page_count, i; |
| @@ -2256,7 +2241,10 @@ i915_gem_object_get_pages(struct drm_gem_object *obj) | |||
| 2256 | inode = obj->filp->f_path.dentry->d_inode; | 2241 | inode = obj->filp->f_path.dentry->d_inode; |
| 2257 | mapping = inode->i_mapping; | 2242 | mapping = inode->i_mapping; |
| 2258 | for (i = 0; i < page_count; i++) { | 2243 | for (i = 0; i < page_count; i++) { |
| 2259 | page = read_mapping_page(mapping, i, NULL); | 2244 | page = read_cache_page_gfp(mapping, i, |
| 2245 | mapping_gfp_mask (mapping) | | ||
| 2246 | __GFP_COLD | | ||
| 2247 | gfpmask); | ||
| 2260 | if (IS_ERR(page)) { | 2248 | if (IS_ERR(page)) { |
| 2261 | ret = PTR_ERR(page); | 2249 | ret = PTR_ERR(page); |
| 2262 | i915_gem_object_put_pages(obj); | 2250 | i915_gem_object_put_pages(obj); |
| @@ -2579,7 +2567,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
| 2579 | drm_i915_private_t *dev_priv = dev->dev_private; | 2567 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 2580 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 2568 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 2581 | struct drm_mm_node *free_space; | 2569 | struct drm_mm_node *free_space; |
| 2582 | bool retry_alloc = false; | 2570 | gfp_t gfpmask = __GFP_NORETRY | __GFP_NOWARN; |
| 2583 | int ret; | 2571 | int ret; |
| 2584 | 2572 | ||
| 2585 | if (obj_priv->madv != I915_MADV_WILLNEED) { | 2573 | if (obj_priv->madv != I915_MADV_WILLNEED) { |
| @@ -2623,15 +2611,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
| 2623 | DRM_INFO("Binding object of size %zd at 0x%08x\n", | 2611 | DRM_INFO("Binding object of size %zd at 0x%08x\n", |
| 2624 | obj->size, obj_priv->gtt_offset); | 2612 | obj->size, obj_priv->gtt_offset); |
| 2625 | #endif | 2613 | #endif |
| 2626 | if (retry_alloc) { | 2614 | ret = i915_gem_object_get_pages(obj, gfpmask); |
| 2627 | i915_gem_object_set_page_gfp_mask (obj, | ||
| 2628 | i915_gem_object_get_page_gfp_mask (obj) & ~__GFP_NORETRY); | ||
| 2629 | } | ||
| 2630 | ret = i915_gem_object_get_pages(obj); | ||
| 2631 | if (retry_alloc) { | ||
| 2632 | i915_gem_object_set_page_gfp_mask (obj, | ||
| 2633 | i915_gem_object_get_page_gfp_mask (obj) | __GFP_NORETRY); | ||
| 2634 | } | ||
| 2635 | if (ret) { | 2615 | if (ret) { |
| 2636 | drm_mm_put_block(obj_priv->gtt_space); | 2616 | drm_mm_put_block(obj_priv->gtt_space); |
| 2637 | obj_priv->gtt_space = NULL; | 2617 | obj_priv->gtt_space = NULL; |
| @@ -2641,9 +2621,9 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
| 2641 | ret = i915_gem_evict_something(dev, obj->size); | 2621 | ret = i915_gem_evict_something(dev, obj->size); |
| 2642 | if (ret) { | 2622 | if (ret) { |
| 2643 | /* now try to shrink everyone else */ | 2623 | /* now try to shrink everyone else */ |
| 2644 | if (! retry_alloc) { | 2624 | if (gfpmask) { |
| 2645 | retry_alloc = true; | 2625 | gfpmask = 0; |
| 2646 | goto search_free; | 2626 | goto search_free; |
| 2647 | } | 2627 | } |
| 2648 | 2628 | ||
| 2649 | return ret; | 2629 | return ret; |
| @@ -2837,6 +2817,57 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) | |||
| 2837 | return 0; | 2817 | return 0; |
| 2838 | } | 2818 | } |
| 2839 | 2819 | ||
| 2820 | /* | ||
| 2821 | * Prepare buffer for display plane. Use uninterruptible for possible flush | ||
| 2822 | * wait, as in modesetting process we're not supposed to be interrupted. | ||
| 2823 | */ | ||
| 2824 | int | ||
| 2825 | i915_gem_object_set_to_display_plane(struct drm_gem_object *obj) | ||
| 2826 | { | ||
| 2827 | struct drm_device *dev = obj->dev; | ||
| 2828 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
| 2829 | uint32_t old_write_domain, old_read_domains; | ||
| 2830 | int ret; | ||
| 2831 | |||
| 2832 | /* Not valid to be called on unbound objects. */ | ||
| 2833 | if (obj_priv->gtt_space == NULL) | ||
| 2834 | return -EINVAL; | ||
| 2835 | |||
| 2836 | i915_gem_object_flush_gpu_write_domain(obj); | ||
| 2837 | |||
| 2838 | /* Wait on any GPU rendering and flushing to occur. */ | ||
| 2839 | if (obj_priv->active) { | ||
| 2840 | #if WATCH_BUF | ||
| 2841 | DRM_INFO("%s: object %p wait for seqno %08x\n", | ||
| 2842 | __func__, obj, obj_priv->last_rendering_seqno); | ||
| 2843 | #endif | ||
| 2844 | ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0); | ||
| 2845 | if (ret != 0) | ||
| 2846 | return ret; | ||
| 2847 | } | ||
| 2848 | |||
| 2849 | old_write_domain = obj->write_domain; | ||
| 2850 | old_read_domains = obj->read_domains; | ||
| 2851 | |||
| 2852 | obj->read_domains &= I915_GEM_DOMAIN_GTT; | ||
| 2853 | |||
| 2854 | i915_gem_object_flush_cpu_write_domain(obj); | ||
| 2855 | |||
| 2856 | /* It should now be out of any other write domains, and we can update | ||
| 2857 | * the domain values for our changes. | ||
| 2858 | */ | ||
| 2859 | BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); | ||
| 2860 | obj->read_domains |= I915_GEM_DOMAIN_GTT; | ||
| 2861 | obj->write_domain = I915_GEM_DOMAIN_GTT; | ||
| 2862 | obj_priv->dirty = 1; | ||
| 2863 | |||
| 2864 | trace_i915_gem_object_change_domain(obj, | ||
| 2865 | old_read_domains, | ||
| 2866 | old_write_domain); | ||
| 2867 | |||
| 2868 | return 0; | ||
| 2869 | } | ||
| 2870 | |||
| 2840 | /** | 2871 | /** |
| 2841 | * Moves a single object to the CPU read, and possibly write domain. | 2872 | * Moves a single object to the CPU read, and possibly write domain. |
| 2842 | * | 2873 | * |
| @@ -4000,8 +4031,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 4000 | "back to user (%d)\n", | 4031 | "back to user (%d)\n", |
| 4001 | args->buffer_count, ret); | 4032 | args->buffer_count, ret); |
| 4002 | } | 4033 | } |
| 4003 | } else { | ||
| 4004 | DRM_ERROR("i915_gem_do_execbuffer returns %d\n", ret); | ||
| 4005 | } | 4034 | } |
| 4006 | 4035 | ||
| 4007 | drm_free_large(exec_list); | 4036 | drm_free_large(exec_list); |
| @@ -4897,7 +4926,7 @@ void i915_gem_detach_phys_object(struct drm_device *dev, | |||
| 4897 | if (!obj_priv->phys_obj) | 4926 | if (!obj_priv->phys_obj) |
| 4898 | return; | 4927 | return; |
| 4899 | 4928 | ||
| 4900 | ret = i915_gem_object_get_pages(obj); | 4929 | ret = i915_gem_object_get_pages(obj, 0); |
| 4901 | if (ret) | 4930 | if (ret) |
| 4902 | goto out; | 4931 | goto out; |
| 4903 | 4932 | ||
| @@ -4955,7 +4984,7 @@ i915_gem_attach_phys_object(struct drm_device *dev, | |||
| 4955 | obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1]; | 4984 | obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1]; |
| 4956 | obj_priv->phys_obj->cur_obj = obj; | 4985 | obj_priv->phys_obj->cur_obj = obj; |
| 4957 | 4986 | ||
| 4958 | ret = i915_gem_object_get_pages(obj); | 4987 | ret = i915_gem_object_get_pages(obj, 0); |
| 4959 | if (ret) { | 4988 | if (ret) { |
| 4960 | DRM_ERROR("failed to get page list\n"); | 4989 | DRM_ERROR("failed to get page list\n"); |
| 4961 | goto out; | 4990 | goto out; |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7cd8110051b6..89a071a3e6fb 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -274,7 +274,6 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) | |||
| 274 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 274 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 275 | int ret = IRQ_NONE; | 275 | int ret = IRQ_NONE; |
| 276 | u32 de_iir, gt_iir, de_ier, pch_iir; | 276 | u32 de_iir, gt_iir, de_ier, pch_iir; |
| 277 | u32 new_de_iir, new_gt_iir, new_pch_iir; | ||
| 278 | struct drm_i915_master_private *master_priv; | 277 | struct drm_i915_master_private *master_priv; |
| 279 | 278 | ||
| 280 | /* disable master interrupt before clearing iir */ | 279 | /* disable master interrupt before clearing iir */ |
| @@ -286,51 +285,42 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) | |||
| 286 | gt_iir = I915_READ(GTIIR); | 285 | gt_iir = I915_READ(GTIIR); |
| 287 | pch_iir = I915_READ(SDEIIR); | 286 | pch_iir = I915_READ(SDEIIR); |
| 288 | 287 | ||
| 289 | for (;;) { | 288 | if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) |
| 290 | if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) | 289 | goto done; |
| 291 | break; | ||
| 292 | |||
| 293 | ret = IRQ_HANDLED; | ||
| 294 | 290 | ||
| 295 | /* should clear PCH hotplug event before clear CPU irq */ | 291 | ret = IRQ_HANDLED; |
| 296 | I915_WRITE(SDEIIR, pch_iir); | ||
| 297 | new_pch_iir = I915_READ(SDEIIR); | ||
| 298 | 292 | ||
| 299 | I915_WRITE(DEIIR, de_iir); | 293 | if (dev->primary->master) { |
| 300 | new_de_iir = I915_READ(DEIIR); | 294 | master_priv = dev->primary->master->driver_priv; |
| 301 | I915_WRITE(GTIIR, gt_iir); | 295 | if (master_priv->sarea_priv) |
| 302 | new_gt_iir = I915_READ(GTIIR); | 296 | master_priv->sarea_priv->last_dispatch = |
| 303 | 297 | READ_BREADCRUMB(dev_priv); | |
| 304 | if (dev->primary->master) { | 298 | } |
| 305 | master_priv = dev->primary->master->driver_priv; | ||
| 306 | if (master_priv->sarea_priv) | ||
| 307 | master_priv->sarea_priv->last_dispatch = | ||
| 308 | READ_BREADCRUMB(dev_priv); | ||
| 309 | } | ||
| 310 | |||
| 311 | if (gt_iir & GT_USER_INTERRUPT) { | ||
| 312 | u32 seqno = i915_get_gem_seqno(dev); | ||
| 313 | dev_priv->mm.irq_gem_seqno = seqno; | ||
| 314 | trace_i915_gem_request_complete(dev, seqno); | ||
| 315 | DRM_WAKEUP(&dev_priv->irq_queue); | ||
| 316 | dev_priv->hangcheck_count = 0; | ||
| 317 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); | ||
| 318 | } | ||
| 319 | 299 | ||
| 320 | if (de_iir & DE_GSE) | 300 | if (gt_iir & GT_USER_INTERRUPT) { |
| 321 | ironlake_opregion_gse_intr(dev); | 301 | u32 seqno = i915_get_gem_seqno(dev); |
| 302 | dev_priv->mm.irq_gem_seqno = seqno; | ||
| 303 | trace_i915_gem_request_complete(dev, seqno); | ||
| 304 | DRM_WAKEUP(&dev_priv->irq_queue); | ||
| 305 | dev_priv->hangcheck_count = 0; | ||
| 306 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); | ||
| 307 | } | ||
| 322 | 308 | ||
| 323 | /* check event from PCH */ | 309 | if (de_iir & DE_GSE) |
| 324 | if ((de_iir & DE_PCH_EVENT) && | 310 | ironlake_opregion_gse_intr(dev); |
| 325 | (pch_iir & SDE_HOTPLUG_MASK)) { | ||
| 326 | queue_work(dev_priv->wq, &dev_priv->hotplug_work); | ||
| 327 | } | ||
| 328 | 311 | ||
| 329 | de_iir = new_de_iir; | 312 | /* check event from PCH */ |
| 330 | gt_iir = new_gt_iir; | 313 | if ((de_iir & DE_PCH_EVENT) && |
| 331 | pch_iir = new_pch_iir; | 314 | (pch_iir & SDE_HOTPLUG_MASK)) { |
| 315 | queue_work(dev_priv->wq, &dev_priv->hotplug_work); | ||
| 332 | } | 316 | } |
| 333 | 317 | ||
| 318 | /* should clear PCH hotplug event before clear CPU irq */ | ||
| 319 | I915_WRITE(SDEIIR, pch_iir); | ||
| 320 | I915_WRITE(GTIIR, gt_iir); | ||
| 321 | I915_WRITE(DEIIR, de_iir); | ||
| 322 | |||
| 323 | done: | ||
| 334 | I915_WRITE(DEIER, de_ier); | 324 | I915_WRITE(DEIER, de_ier); |
| 335 | (void)I915_READ(DEIER); | 325 | (void)I915_READ(DEIER); |
| 336 | 326 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 149d360d64a3..847006c5218e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -1815,7 +1815,7 @@ | |||
| 1815 | #define DSPFW_PLANEB_SHIFT 8 | 1815 | #define DSPFW_PLANEB_SHIFT 8 |
| 1816 | #define DSPFW2 0x70038 | 1816 | #define DSPFW2 0x70038 |
| 1817 | #define DSPFW_CURSORA_MASK 0x00003f00 | 1817 | #define DSPFW_CURSORA_MASK 0x00003f00 |
| 1818 | #define DSPFW_CURSORA_SHIFT 16 | 1818 | #define DSPFW_CURSORA_SHIFT 8 |
| 1819 | #define DSPFW3 0x7003c | 1819 | #define DSPFW3 0x7003c |
| 1820 | #define DSPFW_HPLL_SR_EN (1<<31) | 1820 | #define DSPFW_HPLL_SR_EN (1<<31) |
| 1821 | #define DSPFW_CURSOR_SR_SHIFT 24 | 1821 | #define DSPFW_CURSOR_SR_SHIFT 24 |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index f27567747580..15fbc1b5a83e 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | #define SLAVE_ADDR1 0x70 | 33 | #define SLAVE_ADDR1 0x70 |
| 34 | #define SLAVE_ADDR2 0x72 | 34 | #define SLAVE_ADDR2 0x72 |
| 35 | 35 | ||
| 36 | static int panel_type; | ||
| 37 | |||
| 36 | static void * | 38 | static void * |
| 37 | find_section(struct bdb_header *bdb, int section_id) | 39 | find_section(struct bdb_header *bdb, int section_id) |
| 38 | { | 40 | { |
| @@ -128,6 +130,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
| 128 | dev_priv->lvds_dither = lvds_options->pixel_dither; | 130 | dev_priv->lvds_dither = lvds_options->pixel_dither; |
| 129 | if (lvds_options->panel_type == 0xff) | 131 | if (lvds_options->panel_type == 0xff) |
| 130 | return; | 132 | return; |
| 133 | panel_type = lvds_options->panel_type; | ||
| 131 | 134 | ||
| 132 | lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); | 135 | lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); |
| 133 | if (!lvds_lfp_data) | 136 | if (!lvds_lfp_data) |
| @@ -197,7 +200,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
| 197 | memset(temp_mode, 0, sizeof(*temp_mode)); | 200 | memset(temp_mode, 0, sizeof(*temp_mode)); |
| 198 | } | 201 | } |
| 199 | kfree(temp_mode); | 202 | kfree(temp_mode); |
| 200 | if (temp_downclock < panel_fixed_mode->clock) { | 203 | if (temp_downclock < panel_fixed_mode->clock && |
| 204 | i915_lvds_downclock) { | ||
| 201 | dev_priv->lvds_downclock_avail = 1; | 205 | dev_priv->lvds_downclock_avail = 1; |
| 202 | dev_priv->lvds_downclock = temp_downclock; | 206 | dev_priv->lvds_downclock = temp_downclock; |
| 203 | DRM_DEBUG_KMS("LVDS downclock is found in VBT. ", | 207 | DRM_DEBUG_KMS("LVDS downclock is found in VBT. ", |
| @@ -405,6 +409,34 @@ parse_driver_features(struct drm_i915_private *dev_priv, | |||
| 405 | } | 409 | } |
| 406 | 410 | ||
| 407 | static void | 411 | static void |
| 412 | parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | ||
| 413 | { | ||
| 414 | struct bdb_edp *edp; | ||
| 415 | |||
| 416 | edp = find_section(bdb, BDB_EDP); | ||
| 417 | if (!edp) { | ||
| 418 | if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) { | ||
| 419 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported,\ | ||
| 420 | assume 18bpp panel color depth.\n"); | ||
| 421 | dev_priv->edp_bpp = 18; | ||
| 422 | } | ||
| 423 | return; | ||
| 424 | } | ||
| 425 | |||
| 426 | switch ((edp->color_depth >> (panel_type * 2)) & 3) { | ||
| 427 | case EDP_18BPP: | ||
| 428 | dev_priv->edp_bpp = 18; | ||
| 429 | break; | ||
| 430 | case EDP_24BPP: | ||
| 431 | dev_priv->edp_bpp = 24; | ||
| 432 | break; | ||
| 433 | case EDP_30BPP: | ||
| 434 | dev_priv->edp_bpp = 30; | ||
| 435 | break; | ||
| 436 | } | ||
| 437 | } | ||
| 438 | |||
| 439 | static void | ||
| 408 | parse_device_mapping(struct drm_i915_private *dev_priv, | 440 | parse_device_mapping(struct drm_i915_private *dev_priv, |
| 409 | struct bdb_header *bdb) | 441 | struct bdb_header *bdb) |
| 410 | { | 442 | { |
| @@ -521,6 +553,7 @@ intel_init_bios(struct drm_device *dev) | |||
| 521 | parse_sdvo_device_mapping(dev_priv, bdb); | 553 | parse_sdvo_device_mapping(dev_priv, bdb); |
| 522 | parse_device_mapping(dev_priv, bdb); | 554 | parse_device_mapping(dev_priv, bdb); |
| 523 | parse_driver_features(dev_priv, bdb); | 555 | parse_driver_features(dev_priv, bdb); |
| 556 | parse_edp(dev_priv, bdb); | ||
| 524 | 557 | ||
| 525 | pci_unmap_rom(pdev, bios); | 558 | pci_unmap_rom(pdev, bios); |
| 526 | 559 | ||
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 425ac9d7f724..4c18514f6f80 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h | |||
| @@ -98,6 +98,7 @@ struct vbios_data { | |||
| 98 | #define BDB_SDVO_LVDS_PNP_IDS 24 | 98 | #define BDB_SDVO_LVDS_PNP_IDS 24 |
| 99 | #define BDB_SDVO_LVDS_POWER_SEQ 25 | 99 | #define BDB_SDVO_LVDS_POWER_SEQ 25 |
| 100 | #define BDB_TV_OPTIONS 26 | 100 | #define BDB_TV_OPTIONS 26 |
| 101 | #define BDB_EDP 27 | ||
| 101 | #define BDB_LVDS_OPTIONS 40 | 102 | #define BDB_LVDS_OPTIONS 40 |
| 102 | #define BDB_LVDS_LFP_DATA_PTRS 41 | 103 | #define BDB_LVDS_LFP_DATA_PTRS 41 |
| 103 | #define BDB_LVDS_LFP_DATA 42 | 104 | #define BDB_LVDS_LFP_DATA 42 |
| @@ -426,6 +427,45 @@ struct bdb_driver_features { | |||
| 426 | u8 custom_vbt_version; | 427 | u8 custom_vbt_version; |
| 427 | } __attribute__((packed)); | 428 | } __attribute__((packed)); |
| 428 | 429 | ||
| 430 | #define EDP_18BPP 0 | ||
| 431 | #define EDP_24BPP 1 | ||
| 432 | #define EDP_30BPP 2 | ||
| 433 | #define EDP_RATE_1_62 0 | ||
| 434 | #define EDP_RATE_2_7 1 | ||
| 435 | #define EDP_LANE_1 0 | ||
| 436 | #define EDP_LANE_2 1 | ||
| 437 | #define EDP_LANE_4 3 | ||
| 438 | #define EDP_PREEMPHASIS_NONE 0 | ||
| 439 | #define EDP_PREEMPHASIS_3_5dB 1 | ||
| 440 | #define EDP_PREEMPHASIS_6dB 2 | ||
| 441 | #define EDP_PREEMPHASIS_9_5dB 3 | ||
| 442 | #define EDP_VSWING_0_4V 0 | ||
| 443 | #define EDP_VSWING_0_6V 1 | ||
| 444 | #define EDP_VSWING_0_8V 2 | ||
| 445 | #define EDP_VSWING_1_2V 3 | ||
| 446 | |||
| 447 | struct edp_power_seq { | ||
| 448 | u16 t3; | ||
| 449 | u16 t7; | ||
| 450 | u16 t9; | ||
| 451 | u16 t10; | ||
| 452 | u16 t12; | ||
| 453 | } __attribute__ ((packed)); | ||
| 454 | |||
| 455 | struct edp_link_params { | ||
| 456 | u8 rate:4; | ||
| 457 | u8 lanes:4; | ||
| 458 | u8 preemphasis:4; | ||
| 459 | u8 vswing:4; | ||
| 460 | } __attribute__ ((packed)); | ||
| 461 | |||
| 462 | struct bdb_edp { | ||
| 463 | struct edp_power_seq power_seqs[16]; | ||
| 464 | u32 color_depth; | ||
| 465 | u32 sdrrs_msa_timing_delay; | ||
| 466 | struct edp_link_params link_params[16]; | ||
| 467 | } __attribute__ ((packed)); | ||
| 468 | |||
| 429 | bool intel_init_bios(struct drm_device *dev); | 469 | bool intel_init_bios(struct drm_device *dev); |
| 430 | 470 | ||
| 431 | /* | 471 | /* |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 002612fae717..45da78ef4a92 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -70,8 +70,6 @@ struct intel_limit { | |||
| 70 | intel_p2_t p2; | 70 | intel_p2_t p2; |
| 71 | bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, | 71 | bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, |
| 72 | int, int, intel_clock_t *); | 72 | int, int, intel_clock_t *); |
| 73 | bool (* find_reduced_pll)(const intel_limit_t *, struct drm_crtc *, | ||
| 74 | int, int, intel_clock_t *); | ||
| 75 | }; | 73 | }; |
| 76 | 74 | ||
| 77 | #define I8XX_DOT_MIN 25000 | 75 | #define I8XX_DOT_MIN 25000 |
| @@ -243,11 +241,11 @@ struct intel_limit { | |||
| 243 | #define IRONLAKE_VCO_MIN 1760000 | 241 | #define IRONLAKE_VCO_MIN 1760000 |
| 244 | #define IRONLAKE_VCO_MAX 3510000 | 242 | #define IRONLAKE_VCO_MAX 3510000 |
| 245 | #define IRONLAKE_N_MIN 1 | 243 | #define IRONLAKE_N_MIN 1 |
| 246 | #define IRONLAKE_N_MAX 5 | 244 | #define IRONLAKE_N_MAX 6 |
| 247 | #define IRONLAKE_M_MIN 79 | 245 | #define IRONLAKE_M_MIN 79 |
| 248 | #define IRONLAKE_M_MAX 118 | 246 | #define IRONLAKE_M_MAX 127 |
| 249 | #define IRONLAKE_M1_MIN 12 | 247 | #define IRONLAKE_M1_MIN 12 |
| 250 | #define IRONLAKE_M1_MAX 23 | 248 | #define IRONLAKE_M1_MAX 22 |
| 251 | #define IRONLAKE_M2_MIN 5 | 249 | #define IRONLAKE_M2_MIN 5 |
| 252 | #define IRONLAKE_M2_MAX 9 | 250 | #define IRONLAKE_M2_MAX 9 |
| 253 | #define IRONLAKE_P_SDVO_DAC_MIN 5 | 251 | #define IRONLAKE_P_SDVO_DAC_MIN 5 |
| @@ -274,9 +272,6 @@ static bool | |||
| 274 | intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 272 | intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
| 275 | int target, int refclk, intel_clock_t *best_clock); | 273 | int target, int refclk, intel_clock_t *best_clock); |
| 276 | static bool | 274 | static bool |
| 277 | intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
| 278 | int target, int refclk, intel_clock_t *best_clock); | ||
| 279 | static bool | ||
| 280 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 275 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
| 281 | int target, int refclk, intel_clock_t *best_clock); | 276 | int target, int refclk, intel_clock_t *best_clock); |
| 282 | 277 | ||
| @@ -299,7 +294,6 @@ static const intel_limit_t intel_limits_i8xx_dvo = { | |||
| 299 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 294 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
| 300 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, | 295 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, |
| 301 | .find_pll = intel_find_best_PLL, | 296 | .find_pll = intel_find_best_PLL, |
| 302 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
| 303 | }; | 297 | }; |
| 304 | 298 | ||
| 305 | static const intel_limit_t intel_limits_i8xx_lvds = { | 299 | static const intel_limit_t intel_limits_i8xx_lvds = { |
| @@ -314,7 +308,6 @@ static const intel_limit_t intel_limits_i8xx_lvds = { | |||
| 314 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 308 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
| 315 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, | 309 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, |
| 316 | .find_pll = intel_find_best_PLL, | 310 | .find_pll = intel_find_best_PLL, |
| 317 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
| 318 | }; | 311 | }; |
| 319 | 312 | ||
| 320 | static const intel_limit_t intel_limits_i9xx_sdvo = { | 313 | static const intel_limit_t intel_limits_i9xx_sdvo = { |
| @@ -329,7 +322,6 @@ static const intel_limit_t intel_limits_i9xx_sdvo = { | |||
| 329 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 322 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
| 330 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 323 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
| 331 | .find_pll = intel_find_best_PLL, | 324 | .find_pll = intel_find_best_PLL, |
| 332 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
| 333 | }; | 325 | }; |
| 334 | 326 | ||
| 335 | static const intel_limit_t intel_limits_i9xx_lvds = { | 327 | static const intel_limit_t intel_limits_i9xx_lvds = { |
| @@ -347,7 +339,6 @@ static const intel_limit_t intel_limits_i9xx_lvds = { | |||
| 347 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 339 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
| 348 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, | 340 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, |
| 349 | .find_pll = intel_find_best_PLL, | 341 | .find_pll = intel_find_best_PLL, |
| 350 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
| 351 | }; | 342 | }; |
| 352 | 343 | ||
| 353 | /* below parameter and function is for G4X Chipset Family*/ | 344 | /* below parameter and function is for G4X Chipset Family*/ |
| @@ -365,7 +356,6 @@ static const intel_limit_t intel_limits_g4x_sdvo = { | |||
| 365 | .p2_fast = G4X_P2_SDVO_FAST | 356 | .p2_fast = G4X_P2_SDVO_FAST |
| 366 | }, | 357 | }, |
| 367 | .find_pll = intel_g4x_find_best_PLL, | 358 | .find_pll = intel_g4x_find_best_PLL, |
| 368 | .find_reduced_pll = intel_g4x_find_best_PLL, | ||
| 369 | }; | 359 | }; |
| 370 | 360 | ||
| 371 | static const intel_limit_t intel_limits_g4x_hdmi = { | 361 | static const intel_limit_t intel_limits_g4x_hdmi = { |
| @@ -382,7 +372,6 @@ static const intel_limit_t intel_limits_g4x_hdmi = { | |||
| 382 | .p2_fast = G4X_P2_HDMI_DAC_FAST | 372 | .p2_fast = G4X_P2_HDMI_DAC_FAST |
| 383 | }, | 373 | }, |
| 384 | .find_pll = intel_g4x_find_best_PLL, | 374 | .find_pll = intel_g4x_find_best_PLL, |
| 385 | .find_reduced_pll = intel_g4x_find_best_PLL, | ||
| 386 | }; | 375 | }; |
| 387 | 376 | ||
| 388 | static const intel_limit_t intel_limits_g4x_single_channel_lvds = { | 377 | static const intel_limit_t intel_limits_g4x_single_channel_lvds = { |
| @@ -407,7 +396,6 @@ static const intel_limit_t intel_limits_g4x_single_channel_lvds = { | |||
| 407 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST | 396 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST |
| 408 | }, | 397 | }, |
| 409 | .find_pll = intel_g4x_find_best_PLL, | 398 | .find_pll = intel_g4x_find_best_PLL, |
| 410 | .find_reduced_pll = intel_g4x_find_best_PLL, | ||
| 411 | }; | 399 | }; |
| 412 | 400 | ||
| 413 | static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { | 401 | static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { |
| @@ -432,7 +420,6 @@ static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { | |||
| 432 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST | 420 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST |
| 433 | }, | 421 | }, |
| 434 | .find_pll = intel_g4x_find_best_PLL, | 422 | .find_pll = intel_g4x_find_best_PLL, |
| 435 | .find_reduced_pll = intel_g4x_find_best_PLL, | ||
| 436 | }; | 423 | }; |
| 437 | 424 | ||
| 438 | static const intel_limit_t intel_limits_g4x_display_port = { | 425 | static const intel_limit_t intel_limits_g4x_display_port = { |
| @@ -470,7 +457,6 @@ static const intel_limit_t intel_limits_pineview_sdvo = { | |||
| 470 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 457 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
| 471 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 458 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
| 472 | .find_pll = intel_find_best_PLL, | 459 | .find_pll = intel_find_best_PLL, |
| 473 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
| 474 | }; | 460 | }; |
| 475 | 461 | ||
| 476 | static const intel_limit_t intel_limits_pineview_lvds = { | 462 | static const intel_limit_t intel_limits_pineview_lvds = { |
| @@ -486,7 +472,6 @@ static const intel_limit_t intel_limits_pineview_lvds = { | |||
| 486 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 472 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
| 487 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, | 473 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, |
| 488 | .find_pll = intel_find_best_PLL, | 474 | .find_pll = intel_find_best_PLL, |
| 489 | .find_reduced_pll = intel_find_best_reduced_PLL, | ||
| 490 | }; | 475 | }; |
| 491 | 476 | ||
| 492 | static const intel_limit_t intel_limits_ironlake_sdvo = { | 477 | static const intel_limit_t intel_limits_ironlake_sdvo = { |
| @@ -768,46 +753,6 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
| 768 | return (err != target); | 753 | return (err != target); |
| 769 | } | 754 | } |
| 770 | 755 | ||
| 771 | |||
| 772 | static bool | ||
| 773 | intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
| 774 | int target, int refclk, intel_clock_t *best_clock) | ||
| 775 | |||
| 776 | { | ||
| 777 | struct drm_device *dev = crtc->dev; | ||
| 778 | intel_clock_t clock; | ||
| 779 | int err = target; | ||
| 780 | bool found = false; | ||
| 781 | |||
| 782 | memcpy(&clock, best_clock, sizeof(intel_clock_t)); | ||
| 783 | |||
| 784 | for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { | ||
| 785 | for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) { | ||
| 786 | /* m1 is always 0 in Pineview */ | ||
| 787 | if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev)) | ||
| 788 | break; | ||
| 789 | for (clock.n = limit->n.min; clock.n <= limit->n.max; | ||
| 790 | clock.n++) { | ||
| 791 | int this_err; | ||
| 792 | |||
| 793 | intel_clock(dev, refclk, &clock); | ||
| 794 | |||
| 795 | if (!intel_PLL_is_valid(crtc, &clock)) | ||
| 796 | continue; | ||
| 797 | |||
| 798 | this_err = abs(clock.dot - target); | ||
| 799 | if (this_err < err) { | ||
| 800 | *best_clock = clock; | ||
| 801 | err = this_err; | ||
| 802 | found = true; | ||
| 803 | } | ||
| 804 | } | ||
| 805 | } | ||
| 806 | } | ||
| 807 | |||
| 808 | return found; | ||
| 809 | } | ||
| 810 | |||
| 811 | static bool | 756 | static bool |
| 812 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 757 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
| 813 | int target, int refclk, intel_clock_t *best_clock) | 758 | int target, int refclk, intel_clock_t *best_clock) |
| @@ -1262,7 +1207,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 1262 | return ret; | 1207 | return ret; |
| 1263 | } | 1208 | } |
| 1264 | 1209 | ||
| 1265 | ret = i915_gem_object_set_to_gtt_domain(obj, 1); | 1210 | ret = i915_gem_object_set_to_display_plane(obj); |
| 1266 | if (ret != 0) { | 1211 | if (ret != 0) { |
| 1267 | i915_gem_object_unpin(obj); | 1212 | i915_gem_object_unpin(obj); |
| 1268 | mutex_unlock(&dev->struct_mutex); | 1213 | mutex_unlock(&dev->struct_mutex); |
| @@ -2910,10 +2855,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 2910 | return -EINVAL; | 2855 | return -EINVAL; |
| 2911 | } | 2856 | } |
| 2912 | 2857 | ||
| 2913 | if (is_lvds && limit->find_reduced_pll && | 2858 | if (is_lvds && dev_priv->lvds_downclock_avail) { |
| 2914 | dev_priv->lvds_downclock_avail) { | 2859 | has_reduced_clock = limit->find_pll(limit, crtc, |
| 2915 | memcpy(&reduced_clock, &clock, sizeof(intel_clock_t)); | ||
| 2916 | has_reduced_clock = limit->find_reduced_pll(limit, crtc, | ||
| 2917 | dev_priv->lvds_downclock, | 2860 | dev_priv->lvds_downclock, |
| 2918 | refclk, | 2861 | refclk, |
| 2919 | &reduced_clock); | 2862 | &reduced_clock); |
| @@ -2981,6 +2924,21 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 2981 | temp |= PIPE_8BPC; | 2924 | temp |= PIPE_8BPC; |
| 2982 | else | 2925 | else |
| 2983 | temp |= PIPE_6BPC; | 2926 | temp |= PIPE_6BPC; |
| 2927 | } else if (is_edp) { | ||
| 2928 | switch (dev_priv->edp_bpp/3) { | ||
| 2929 | case 8: | ||
| 2930 | temp |= PIPE_8BPC; | ||
| 2931 | break; | ||
| 2932 | case 10: | ||
| 2933 | temp |= PIPE_10BPC; | ||
| 2934 | break; | ||
| 2935 | case 6: | ||
| 2936 | temp |= PIPE_6BPC; | ||
| 2937 | break; | ||
| 2938 | case 12: | ||
| 2939 | temp |= PIPE_12BPC; | ||
| 2940 | break; | ||
| 2941 | } | ||
| 2984 | } else | 2942 | } else |
| 2985 | temp |= PIPE_8BPC; | 2943 | temp |= PIPE_8BPC; |
| 2986 | I915_WRITE(pipeconf_reg, temp); | 2944 | I915_WRITE(pipeconf_reg, temp); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1349d9fd01c4..439506cefc14 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -125,9 +125,15 @@ intel_dp_link_clock(uint8_t link_bw) | |||
| 125 | 125 | ||
| 126 | /* I think this is a fiction */ | 126 | /* I think this is a fiction */ |
| 127 | static int | 127 | static int |
| 128 | intel_dp_link_required(int pixel_clock) | 128 | intel_dp_link_required(struct drm_device *dev, |
| 129 | struct intel_output *intel_output, int pixel_clock) | ||
| 129 | { | 130 | { |
| 130 | return pixel_clock * 3; | 131 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 132 | |||
| 133 | if (IS_eDP(intel_output)) | ||
| 134 | return (pixel_clock * dev_priv->edp_bpp) / 8; | ||
| 135 | else | ||
| 136 | return pixel_clock * 3; | ||
| 131 | } | 137 | } |
| 132 | 138 | ||
| 133 | static int | 139 | static int |
| @@ -138,7 +144,8 @@ intel_dp_mode_valid(struct drm_connector *connector, | |||
| 138 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output)); | 144 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output)); |
| 139 | int max_lanes = intel_dp_max_lane_count(intel_output); | 145 | int max_lanes = intel_dp_max_lane_count(intel_output); |
| 140 | 146 | ||
| 141 | if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes) | 147 | if (intel_dp_link_required(connector->dev, intel_output, mode->clock) |
| 148 | > max_link_clock * max_lanes) | ||
| 142 | return MODE_CLOCK_HIGH; | 149 | return MODE_CLOCK_HIGH; |
| 143 | 150 | ||
| 144 | if (mode->clock < 10000) | 151 | if (mode->clock < 10000) |
| @@ -492,7 +499,8 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 492 | for (clock = 0; clock <= max_clock; clock++) { | 499 | for (clock = 0; clock <= max_clock; clock++) { |
| 493 | int link_avail = intel_dp_link_clock(bws[clock]) * lane_count; | 500 | int link_avail = intel_dp_link_clock(bws[clock]) * lane_count; |
| 494 | 501 | ||
| 495 | if (intel_dp_link_required(mode->clock) <= link_avail) { | 502 | if (intel_dp_link_required(encoder->dev, intel_output, mode->clock) |
| 503 | <= link_avail) { | ||
| 496 | dp_priv->link_bw = bws[clock]; | 504 | dp_priv->link_bw = bws[clock]; |
| 497 | dp_priv->lane_count = lane_count; | 505 | dp_priv->lane_count = lane_count; |
| 498 | adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); | 506 | adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); |
| @@ -1289,53 +1297,7 @@ intel_dp_hot_plug(struct intel_output *intel_output) | |||
| 1289 | if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON) | 1297 | if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON) |
| 1290 | intel_dp_check_link_status(intel_output); | 1298 | intel_dp_check_link_status(intel_output); |
| 1291 | } | 1299 | } |
| 1292 | /* | 1300 | |
| 1293 | * Enumerate the child dev array parsed from VBT to check whether | ||
| 1294 | * the given DP is present. | ||
| 1295 | * If it is present, return 1. | ||
| 1296 | * If it is not present, return false. | ||
| 1297 | * If no child dev is parsed from VBT, it is assumed that the given | ||
| 1298 | * DP is present. | ||
| 1299 | */ | ||
| 1300 | static int dp_is_present_in_vbt(struct drm_device *dev, int dp_reg) | ||
| 1301 | { | ||
| 1302 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1303 | struct child_device_config *p_child; | ||
| 1304 | int i, dp_port, ret; | ||
| 1305 | |||
| 1306 | if (!dev_priv->child_dev_num) | ||
| 1307 | return 1; | ||
| 1308 | |||
| 1309 | dp_port = 0; | ||
| 1310 | if (dp_reg == DP_B || dp_reg == PCH_DP_B) | ||
| 1311 | dp_port = PORT_IDPB; | ||
| 1312 | else if (dp_reg == DP_C || dp_reg == PCH_DP_C) | ||
| 1313 | dp_port = PORT_IDPC; | ||
| 1314 | else if (dp_reg == DP_D || dp_reg == PCH_DP_D) | ||
| 1315 | dp_port = PORT_IDPD; | ||
| 1316 | |||
| 1317 | ret = 0; | ||
| 1318 | for (i = 0; i < dev_priv->child_dev_num; i++) { | ||
| 1319 | p_child = dev_priv->child_dev + i; | ||
| 1320 | /* | ||
| 1321 | * If the device type is not DP, continue. | ||
| 1322 | */ | ||
| 1323 | if (p_child->device_type != DEVICE_TYPE_DP && | ||
| 1324 | p_child->device_type != DEVICE_TYPE_eDP) | ||
| 1325 | continue; | ||
| 1326 | /* Find the eDP port */ | ||
| 1327 | if (dp_reg == DP_A && p_child->device_type == DEVICE_TYPE_eDP) { | ||
| 1328 | ret = 1; | ||
| 1329 | break; | ||
| 1330 | } | ||
| 1331 | /* Find the DP port */ | ||
| 1332 | if (p_child->dvo_port == dp_port) { | ||
| 1333 | ret = 1; | ||
| 1334 | break; | ||
| 1335 | } | ||
| 1336 | } | ||
| 1337 | return ret; | ||
| 1338 | } | ||
| 1339 | void | 1301 | void |
| 1340 | intel_dp_init(struct drm_device *dev, int output_reg) | 1302 | intel_dp_init(struct drm_device *dev, int output_reg) |
| 1341 | { | 1303 | { |
| @@ -1345,10 +1307,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
| 1345 | struct intel_dp_priv *dp_priv; | 1307 | struct intel_dp_priv *dp_priv; |
| 1346 | const char *name = NULL; | 1308 | const char *name = NULL; |
| 1347 | 1309 | ||
| 1348 | if (!dp_is_present_in_vbt(dev, output_reg)) { | ||
| 1349 | DRM_DEBUG_KMS("DP is not present. Ignore it\n"); | ||
| 1350 | return; | ||
| 1351 | } | ||
| 1352 | intel_output = kcalloc(sizeof(struct intel_output) + | 1310 | intel_output = kcalloc(sizeof(struct intel_output) + |
| 1353 | sizeof(struct intel_dp_priv), 1, GFP_KERNEL); | 1311 | sizeof(struct intel_dp_priv), 1, GFP_KERNEL); |
| 1354 | if (!intel_output) | 1312 | if (!intel_output) |
| @@ -1373,11 +1331,10 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
| 1373 | else if (output_reg == DP_D || output_reg == PCH_DP_D) | 1331 | else if (output_reg == DP_D || output_reg == PCH_DP_D) |
| 1374 | intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT); | 1332 | intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT); |
| 1375 | 1333 | ||
| 1376 | if (IS_eDP(intel_output)) { | 1334 | if (IS_eDP(intel_output)) |
| 1377 | intel_output->crtc_mask = (1 << 1); | ||
| 1378 | intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT); | 1335 | intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT); |
| 1379 | } else | 1336 | |
| 1380 | intel_output->crtc_mask = (1 << 0) | (1 << 1); | 1337 | intel_output->crtc_mask = (1 << 0) | (1 << 1); |
| 1381 | connector->interlace_allowed = true; | 1338 | connector->interlace_allowed = true; |
| 1382 | connector->doublescan_allowed = 0; | 1339 | connector->doublescan_allowed = 0; |
| 1383 | 1340 | ||
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 06431941b233..0e268deed761 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
| @@ -225,52 +225,6 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { | |||
| 225 | .destroy = intel_hdmi_enc_destroy, | 225 | .destroy = intel_hdmi_enc_destroy, |
| 226 | }; | 226 | }; |
| 227 | 227 | ||
| 228 | /* | ||
| 229 | * Enumerate the child dev array parsed from VBT to check whether | ||
| 230 | * the given HDMI is present. | ||
| 231 | * If it is present, return 1. | ||
| 232 | * If it is not present, return false. | ||
| 233 | * If no child dev is parsed from VBT, it assumes that the given | ||
| 234 | * HDMI is present. | ||
| 235 | */ | ||
| 236 | static int hdmi_is_present_in_vbt(struct drm_device *dev, int hdmi_reg) | ||
| 237 | { | ||
| 238 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 239 | struct child_device_config *p_child; | ||
| 240 | int i, hdmi_port, ret; | ||
| 241 | |||
| 242 | if (!dev_priv->child_dev_num) | ||
| 243 | return 1; | ||
| 244 | |||
| 245 | if (hdmi_reg == SDVOB) | ||
| 246 | hdmi_port = DVO_B; | ||
| 247 | else if (hdmi_reg == SDVOC) | ||
| 248 | hdmi_port = DVO_C; | ||
| 249 | else if (hdmi_reg == HDMIB) | ||
| 250 | hdmi_port = DVO_B; | ||
| 251 | else if (hdmi_reg == HDMIC) | ||
| 252 | hdmi_port = DVO_C; | ||
| 253 | else if (hdmi_reg == HDMID) | ||
| 254 | hdmi_port = DVO_D; | ||
| 255 | else | ||
| 256 | return 0; | ||
| 257 | |||
| 258 | ret = 0; | ||
| 259 | for (i = 0; i < dev_priv->child_dev_num; i++) { | ||
| 260 | p_child = dev_priv->child_dev + i; | ||
| 261 | /* | ||
| 262 | * If the device type is not HDMI, continue. | ||
| 263 | */ | ||
| 264 | if (p_child->device_type != DEVICE_TYPE_HDMI) | ||
| 265 | continue; | ||
| 266 | /* Find the HDMI port */ | ||
| 267 | if (p_child->dvo_port == hdmi_port) { | ||
| 268 | ret = 1; | ||
| 269 | break; | ||
| 270 | } | ||
| 271 | } | ||
| 272 | return ret; | ||
| 273 | } | ||
| 274 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | 228 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) |
| 275 | { | 229 | { |
| 276 | struct drm_i915_private *dev_priv = dev->dev_private; | 230 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -278,10 +232,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
| 278 | struct intel_output *intel_output; | 232 | struct intel_output *intel_output; |
| 279 | struct intel_hdmi_priv *hdmi_priv; | 233 | struct intel_hdmi_priv *hdmi_priv; |
| 280 | 234 | ||
| 281 | if (!hdmi_is_present_in_vbt(dev, sdvox_reg)) { | ||
| 282 | DRM_DEBUG_KMS("HDMI is not present. Ignored it \n"); | ||
| 283 | return; | ||
| 284 | } | ||
| 285 | intel_output = kcalloc(sizeof(struct intel_output) + | 235 | intel_output = kcalloc(sizeof(struct intel_output) + |
| 286 | sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); | 236 | sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); |
| 287 | if (!intel_output) | 237 | if (!intel_output) |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f4b4aa242df1..aa74e59bec61 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -602,6 +602,20 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
| 602 | /* Some lid devices report incorrect lid status, assume they're connected */ | 602 | /* Some lid devices report incorrect lid status, assume they're connected */ |
| 603 | static const struct dmi_system_id bad_lid_status[] = { | 603 | static const struct dmi_system_id bad_lid_status[] = { |
| 604 | { | 604 | { |
| 605 | .ident = "Compaq nx9020", | ||
| 606 | .matches = { | ||
| 607 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 608 | DMI_MATCH(DMI_BOARD_NAME, "3084"), | ||
| 609 | }, | ||
| 610 | }, | ||
| 611 | { | ||
| 612 | .ident = "Samsung SX20S", | ||
| 613 | .matches = { | ||
| 614 | DMI_MATCH(DMI_SYS_VENDOR, "Phoenix Technologies LTD"), | ||
| 615 | DMI_MATCH(DMI_BOARD_NAME, "SX20S"), | ||
| 616 | }, | ||
| 617 | }, | ||
| 618 | { | ||
| 605 | .ident = "Aspire One", | 619 | .ident = "Aspire One", |
| 606 | .matches = { | 620 | .matches = { |
| 607 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 621 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| @@ -912,7 +926,8 @@ static void intel_find_lvds_downclock(struct drm_device *dev, | |||
| 912 | } | 926 | } |
| 913 | } | 927 | } |
| 914 | mutex_unlock(&dev->mode_config.mutex); | 928 | mutex_unlock(&dev->mode_config.mutex); |
| 915 | if (temp_downclock < panel_fixed_mode->clock) { | 929 | if (temp_downclock < panel_fixed_mode->clock && |
| 930 | i915_lvds_downclock) { | ||
| 916 | /* We found the downclock for LVDS. */ | 931 | /* We found the downclock for LVDS. */ |
| 917 | dev_priv->lvds_downclock_avail = 1; | 932 | dev_priv->lvds_downclock_avail = 1; |
| 918 | dev_priv->lvds_downclock = temp_downclock; | 933 | dev_priv->lvds_downclock = temp_downclock; |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index de5144c8c153..eaacfd0920df 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -462,14 +462,63 @@ static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) | |||
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | /** | 464 | /** |
| 465 | * Don't check status code from this as it switches the bus back to the | 465 | * Try to read the response after issuie the DDC switch command. But it |
| 466 | * SDVO chips which defeats the purpose of doing a bus switch in the first | 466 | * is noted that we must do the action of reading response and issuing DDC |
| 467 | * place. | 467 | * switch command in one I2C transaction. Otherwise when we try to start |
| 468 | * another I2C transaction after issuing the DDC bus switch, it will be | ||
| 469 | * switched to the internal SDVO register. | ||
| 468 | */ | 470 | */ |
| 469 | static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output, | 471 | static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output, |
| 470 | u8 target) | 472 | u8 target) |
| 471 | { | 473 | { |
| 472 | intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1); | 474 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; |
| 475 | u8 out_buf[2], cmd_buf[2], ret_value[2], ret; | ||
| 476 | struct i2c_msg msgs[] = { | ||
| 477 | { | ||
| 478 | .addr = sdvo_priv->slave_addr >> 1, | ||
| 479 | .flags = 0, | ||
| 480 | .len = 2, | ||
| 481 | .buf = out_buf, | ||
| 482 | }, | ||
| 483 | /* the following two are to read the response */ | ||
| 484 | { | ||
| 485 | .addr = sdvo_priv->slave_addr >> 1, | ||
| 486 | .flags = 0, | ||
| 487 | .len = 1, | ||
| 488 | .buf = cmd_buf, | ||
| 489 | }, | ||
| 490 | { | ||
| 491 | .addr = sdvo_priv->slave_addr >> 1, | ||
| 492 | .flags = I2C_M_RD, | ||
| 493 | .len = 1, | ||
| 494 | .buf = ret_value, | ||
| 495 | }, | ||
| 496 | }; | ||
| 497 | |||
| 498 | intel_sdvo_debug_write(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, | ||
| 499 | &target, 1); | ||
| 500 | /* write the DDC switch command argument */ | ||
| 501 | intel_sdvo_write_byte(intel_output, SDVO_I2C_ARG_0, target); | ||
| 502 | |||
| 503 | out_buf[0] = SDVO_I2C_OPCODE; | ||
| 504 | out_buf[1] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; | ||
| 505 | cmd_buf[0] = SDVO_I2C_CMD_STATUS; | ||
| 506 | cmd_buf[1] = 0; | ||
| 507 | ret_value[0] = 0; | ||
| 508 | ret_value[1] = 0; | ||
| 509 | |||
| 510 | ret = i2c_transfer(intel_output->i2c_bus, msgs, 3); | ||
| 511 | if (ret != 3) { | ||
| 512 | /* failure in I2C transfer */ | ||
| 513 | DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); | ||
| 514 | return; | ||
| 515 | } | ||
| 516 | if (ret_value[0] != SDVO_CMD_STATUS_SUCCESS) { | ||
| 517 | DRM_DEBUG_KMS("DDC switch command returns response %d\n", | ||
| 518 | ret_value[0]); | ||
| 519 | return; | ||
| 520 | } | ||
| 521 | return; | ||
| 473 | } | 522 | } |
| 474 | 523 | ||
| 475 | static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool target_0, bool target_1) | 524 | static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool target_0, bool target_1) |
| @@ -1579,6 +1628,32 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response) | |||
| 1579 | edid = drm_get_edid(&intel_output->base, | 1628 | edid = drm_get_edid(&intel_output->base, |
| 1580 | intel_output->ddc_bus); | 1629 | intel_output->ddc_bus); |
| 1581 | 1630 | ||
| 1631 | /* This is only applied to SDVO cards with multiple outputs */ | ||
| 1632 | if (edid == NULL && intel_sdvo_multifunc_encoder(intel_output)) { | ||
| 1633 | uint8_t saved_ddc, temp_ddc; | ||
| 1634 | saved_ddc = sdvo_priv->ddc_bus; | ||
| 1635 | temp_ddc = sdvo_priv->ddc_bus >> 1; | ||
| 1636 | /* | ||
| 1637 | * Don't use the 1 as the argument of DDC bus switch to get | ||
| 1638 | * the EDID. It is used for SDVO SPD ROM. | ||
| 1639 | */ | ||
| 1640 | while(temp_ddc > 1) { | ||
| 1641 | sdvo_priv->ddc_bus = temp_ddc; | ||
| 1642 | edid = drm_get_edid(&intel_output->base, | ||
| 1643 | intel_output->ddc_bus); | ||
| 1644 | if (edid) { | ||
| 1645 | /* | ||
| 1646 | * When we can get the EDID, maybe it is the | ||
| 1647 | * correct DDC bus. Update it. | ||
| 1648 | */ | ||
| 1649 | sdvo_priv->ddc_bus = temp_ddc; | ||
| 1650 | break; | ||
| 1651 | } | ||
| 1652 | temp_ddc >>= 1; | ||
| 1653 | } | ||
| 1654 | if (edid == NULL) | ||
| 1655 | sdvo_priv->ddc_bus = saved_ddc; | ||
| 1656 | } | ||
| 1582 | /* when there is no edid and no monitor is connected with VGA | 1657 | /* when there is no edid and no monitor is connected with VGA |
| 1583 | * port, try to use the CRT ddc to read the EDID for DVI-connector | 1658 | * port, try to use the CRT ddc to read the EDID for DVI-connector |
| 1584 | */ | 1659 | */ |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 1d5b9b7b033f..552ec110b741 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
| @@ -1840,8 +1840,6 @@ intel_tv_init(struct drm_device *dev) | |||
| 1840 | drm_connector_attach_property(connector, | 1840 | drm_connector_attach_property(connector, |
| 1841 | dev->mode_config.tv_bottom_margin_property, | 1841 | dev->mode_config.tv_bottom_margin_property, |
| 1842 | tv_priv->margin[TV_MARGIN_BOTTOM]); | 1842 | tv_priv->margin[TV_MARGIN_BOTTOM]); |
| 1843 | |||
| 1844 | dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS; | ||
| 1845 | out: | 1843 | out: |
| 1846 | drm_sysfs_connector_add(connector); | 1844 | drm_sysfs_connector_add(connector); |
| 1847 | } | 1845 | } |
