diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 720 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_evict.c | 8 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_suspend.c | 44 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_acpi.c | 34 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 159 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 165 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 173 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_i2c.c | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 133 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_opregion.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_overlay.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 159 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 84 |
19 files changed, 1032 insertions, 682 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 7a26f4dd21ae..e6800819bca8 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -767,6 +767,9 @@ static int i915_getparam(struct drm_device *dev, void *data, | |||
| 767 | case I915_PARAM_HAS_BLT: | 767 | case I915_PARAM_HAS_BLT: |
| 768 | value = HAS_BLT(dev); | 768 | value = HAS_BLT(dev); |
| 769 | break; | 769 | break; |
| 770 | case I915_PARAM_HAS_COHERENT_RINGS: | ||
| 771 | value = 1; | ||
| 772 | break; | ||
| 770 | default: | 773 | default: |
| 771 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", | 774 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", |
| 772 | param->param); | 775 | param->param); |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3467dd420760..f737960712e6 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -44,7 +44,7 @@ unsigned int i915_fbpercrtc = 0; | |||
| 44 | module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); | 44 | module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); |
| 45 | 45 | ||
| 46 | unsigned int i915_powersave = 1; | 46 | unsigned int i915_powersave = 1; |
| 47 | module_param_named(powersave, i915_powersave, int, 0400); | 47 | module_param_named(powersave, i915_powersave, int, 0600); |
| 48 | 48 | ||
| 49 | unsigned int i915_lvds_downclock = 0; | 49 | unsigned int i915_lvds_downclock = 0; |
| 50 | module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); | 50 | module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); |
| @@ -150,7 +150,8 @@ static const struct intel_device_info intel_ironlake_d_info = { | |||
| 150 | 150 | ||
| 151 | static const struct intel_device_info intel_ironlake_m_info = { | 151 | static const struct intel_device_info intel_ironlake_m_info = { |
| 152 | .gen = 5, .is_mobile = 1, | 152 | .gen = 5, .is_mobile = 1, |
| 153 | .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, | 153 | .need_gfx_hws = 1, .has_rc6 = 1, .has_hotplug = 1, |
| 154 | .has_fbc = 0, /* disabled due to buggy hardware */ | ||
| 154 | .has_bsd_ring = 1, | 155 | .has_bsd_ring = 1, |
| 155 | }; | 156 | }; |
| 156 | 157 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2c2c19b6285e..409826da3099 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -1045,6 +1045,8 @@ void i915_gem_clflush_object(struct drm_gem_object *obj); | |||
| 1045 | int i915_gem_object_set_domain(struct drm_gem_object *obj, | 1045 | int i915_gem_object_set_domain(struct drm_gem_object *obj, |
| 1046 | uint32_t read_domains, | 1046 | uint32_t read_domains, |
| 1047 | uint32_t write_domain); | 1047 | uint32_t write_domain); |
| 1048 | int i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj, | ||
| 1049 | bool interruptible); | ||
| 1048 | int i915_gem_init_ringbuffer(struct drm_device *dev); | 1050 | int i915_gem_init_ringbuffer(struct drm_device *dev); |
| 1049 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); | 1051 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); |
| 1050 | int i915_gem_do_init(struct drm_device *dev, unsigned long start, | 1052 | int i915_gem_do_init(struct drm_device *dev, unsigned long start, |
| @@ -1321,6 +1323,7 @@ static inline void i915_write(struct drm_i915_private *dev_priv, u32 reg, | |||
| 1321 | 1323 | ||
| 1322 | #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) | 1324 | #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) |
| 1323 | #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) | 1325 | #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) |
| 1326 | #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) | ||
| 1324 | 1327 | ||
| 1325 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) | 1328 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) |
| 1326 | 1329 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8eb8453208b5..275ec6ed43ae 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -38,8 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); | 39 | static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); |
| 40 | 40 | ||
| 41 | static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, | 41 | static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); |
| 42 | bool pipelined); | ||
| 43 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); | 42 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); |
| 44 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); | 43 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); |
| 45 | static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, | 44 | static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, |
| @@ -547,6 +546,19 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
| 547 | struct drm_i915_gem_object *obj_priv; | 546 | struct drm_i915_gem_object *obj_priv; |
| 548 | int ret = 0; | 547 | int ret = 0; |
| 549 | 548 | ||
| 549 | if (args->size == 0) | ||
| 550 | return 0; | ||
| 551 | |||
| 552 | if (!access_ok(VERIFY_WRITE, | ||
| 553 | (char __user *)(uintptr_t)args->data_ptr, | ||
| 554 | args->size)) | ||
| 555 | return -EFAULT; | ||
| 556 | |||
| 557 | ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr, | ||
| 558 | args->size); | ||
| 559 | if (ret) | ||
| 560 | return -EFAULT; | ||
| 561 | |||
| 550 | ret = i915_mutex_lock_interruptible(dev); | 562 | ret = i915_mutex_lock_interruptible(dev); |
| 551 | if (ret) | 563 | if (ret) |
| 552 | return ret; | 564 | return ret; |
| @@ -564,23 +576,6 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
| 564 | goto out; | 576 | goto out; |
| 565 | } | 577 | } |
| 566 | 578 | ||
| 567 | if (args->size == 0) | ||
| 568 | goto out; | ||
| 569 | |||
| 570 | if (!access_ok(VERIFY_WRITE, | ||
| 571 | (char __user *)(uintptr_t)args->data_ptr, | ||
| 572 | args->size)) { | ||
| 573 | ret = -EFAULT; | ||
| 574 | goto out; | ||
| 575 | } | ||
| 576 | |||
| 577 | ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr, | ||
| 578 | args->size); | ||
| 579 | if (ret) { | ||
| 580 | ret = -EFAULT; | ||
| 581 | goto out; | ||
| 582 | } | ||
| 583 | |||
| 584 | ret = i915_gem_object_get_pages_or_evict(obj); | 579 | ret = i915_gem_object_get_pages_or_evict(obj); |
| 585 | if (ret) | 580 | if (ret) |
| 586 | goto out; | 581 | goto out; |
| @@ -981,7 +976,20 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
| 981 | struct drm_i915_gem_pwrite *args = data; | 976 | struct drm_i915_gem_pwrite *args = data; |
| 982 | struct drm_gem_object *obj; | 977 | struct drm_gem_object *obj; |
| 983 | struct drm_i915_gem_object *obj_priv; | 978 | struct drm_i915_gem_object *obj_priv; |
| 984 | int ret = 0; | 979 | int ret; |
| 980 | |||
| 981 | if (args->size == 0) | ||
| 982 | return 0; | ||
| 983 | |||
| 984 | if (!access_ok(VERIFY_READ, | ||
| 985 | (char __user *)(uintptr_t)args->data_ptr, | ||
| 986 | args->size)) | ||
| 987 | return -EFAULT; | ||
| 988 | |||
| 989 | ret = fault_in_pages_readable((char __user *)(uintptr_t)args->data_ptr, | ||
| 990 | args->size); | ||
| 991 | if (ret) | ||
| 992 | return -EFAULT; | ||
| 985 | 993 | ||
| 986 | ret = i915_mutex_lock_interruptible(dev); | 994 | ret = i915_mutex_lock_interruptible(dev); |
| 987 | if (ret) | 995 | if (ret) |
| @@ -994,30 +1002,12 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
| 994 | } | 1002 | } |
| 995 | obj_priv = to_intel_bo(obj); | 1003 | obj_priv = to_intel_bo(obj); |
| 996 | 1004 | ||
| 997 | |||
| 998 | /* Bounds check destination. */ | 1005 | /* Bounds check destination. */ |
| 999 | if (args->offset > obj->size || args->size > obj->size - args->offset) { | 1006 | if (args->offset > obj->size || args->size > obj->size - args->offset) { |
| 1000 | ret = -EINVAL; | 1007 | ret = -EINVAL; |
| 1001 | goto out; | 1008 | goto out; |
| 1002 | } | 1009 | } |
| 1003 | 1010 | ||
| 1004 | if (args->size == 0) | ||
| 1005 | goto out; | ||
| 1006 | |||
| 1007 | if (!access_ok(VERIFY_READ, | ||
| 1008 | (char __user *)(uintptr_t)args->data_ptr, | ||
| 1009 | args->size)) { | ||
| 1010 | ret = -EFAULT; | ||
| 1011 | goto out; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | ret = fault_in_pages_readable((char __user *)(uintptr_t)args->data_ptr, | ||
| 1015 | args->size); | ||
| 1016 | if (ret) { | ||
| 1017 | ret = -EFAULT; | ||
| 1018 | goto out; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | /* We can only do the GTT pwrite on untiled buffers, as otherwise | 1011 | /* We can only do the GTT pwrite on untiled buffers, as otherwise |
| 1022 | * it would end up going through the fenced access, and we'll get | 1012 | * it would end up going through the fenced access, and we'll get |
| 1023 | * different detiling behavior between reading and writing. | 1013 | * different detiling behavior between reading and writing. |
| @@ -2172,7 +2162,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj) | |||
| 2172 | static int i915_ring_idle(struct drm_device *dev, | 2162 | static int i915_ring_idle(struct drm_device *dev, |
| 2173 | struct intel_ring_buffer *ring) | 2163 | struct intel_ring_buffer *ring) |
| 2174 | { | 2164 | { |
| 2175 | if (list_empty(&ring->gpu_write_list)) | 2165 | if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list)) |
| 2176 | return 0; | 2166 | return 0; |
| 2177 | 2167 | ||
| 2178 | i915_gem_flush_ring(dev, NULL, ring, | 2168 | i915_gem_flush_ring(dev, NULL, ring, |
| @@ -2190,9 +2180,7 @@ i915_gpu_idle(struct drm_device *dev) | |||
| 2190 | int ret; | 2180 | int ret; |
| 2191 | 2181 | ||
| 2192 | lists_empty = (list_empty(&dev_priv->mm.flushing_list) && | 2182 | lists_empty = (list_empty(&dev_priv->mm.flushing_list) && |
| 2193 | list_empty(&dev_priv->render_ring.active_list) && | 2183 | list_empty(&dev_priv->mm.active_list)); |
| 2194 | list_empty(&dev_priv->bsd_ring.active_list) && | ||
| 2195 | list_empty(&dev_priv->blt_ring.active_list)); | ||
| 2196 | if (lists_empty) | 2184 | if (lists_empty) |
| 2197 | return 0; | 2185 | return 0; |
| 2198 | 2186 | ||
| @@ -2605,7 +2593,7 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj, | |||
| 2605 | if (reg->gpu) { | 2593 | if (reg->gpu) { |
| 2606 | int ret; | 2594 | int ret; |
| 2607 | 2595 | ||
| 2608 | ret = i915_gem_object_flush_gpu_write_domain(obj, true); | 2596 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 2609 | if (ret) | 2597 | if (ret) |
| 2610 | return ret; | 2598 | return ret; |
| 2611 | 2599 | ||
| @@ -2753,8 +2741,7 @@ i915_gem_clflush_object(struct drm_gem_object *obj) | |||
| 2753 | 2741 | ||
| 2754 | /** Flushes any GPU write domain for the object if it's dirty. */ | 2742 | /** Flushes any GPU write domain for the object if it's dirty. */ |
| 2755 | static int | 2743 | static int |
| 2756 | i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, | 2744 | i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj) |
| 2757 | bool pipelined) | ||
| 2758 | { | 2745 | { |
| 2759 | struct drm_device *dev = obj->dev; | 2746 | struct drm_device *dev = obj->dev; |
| 2760 | uint32_t old_write_domain; | 2747 | uint32_t old_write_domain; |
| @@ -2773,10 +2760,7 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, | |||
| 2773 | obj->read_domains, | 2760 | obj->read_domains, |
| 2774 | old_write_domain); | 2761 | old_write_domain); |
| 2775 | 2762 | ||
| 2776 | if (pipelined) | 2763 | return 0; |
| 2777 | return 0; | ||
| 2778 | |||
| 2779 | return i915_gem_object_wait_rendering(obj, true); | ||
| 2780 | } | 2764 | } |
| 2781 | 2765 | ||
| 2782 | /** Flushes the GTT write domain for the object if it's dirty. */ | 2766 | /** Flushes the GTT write domain for the object if it's dirty. */ |
| @@ -2837,18 +2821,15 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) | |||
| 2837 | if (obj_priv->gtt_space == NULL) | 2821 | if (obj_priv->gtt_space == NULL) |
| 2838 | return -EINVAL; | 2822 | return -EINVAL; |
| 2839 | 2823 | ||
| 2840 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); | 2824 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 2841 | if (ret != 0) | 2825 | if (ret != 0) |
| 2842 | return ret; | 2826 | return ret; |
| 2827 | ret = i915_gem_object_wait_rendering(obj, true); | ||
| 2828 | if (ret) | ||
| 2829 | return ret; | ||
| 2843 | 2830 | ||
| 2844 | i915_gem_object_flush_cpu_write_domain(obj); | 2831 | i915_gem_object_flush_cpu_write_domain(obj); |
| 2845 | 2832 | ||
| 2846 | if (write) { | ||
| 2847 | ret = i915_gem_object_wait_rendering(obj, true); | ||
| 2848 | if (ret) | ||
| 2849 | return ret; | ||
| 2850 | } | ||
| 2851 | |||
| 2852 | old_write_domain = obj->write_domain; | 2833 | old_write_domain = obj->write_domain; |
| 2853 | old_read_domains = obj->read_domains; | 2834 | old_read_domains = obj->read_domains; |
| 2854 | 2835 | ||
| @@ -2886,7 +2867,7 @@ i915_gem_object_set_to_display_plane(struct drm_gem_object *obj, | |||
| 2886 | if (obj_priv->gtt_space == NULL) | 2867 | if (obj_priv->gtt_space == NULL) |
| 2887 | return -EINVAL; | 2868 | return -EINVAL; |
| 2888 | 2869 | ||
| 2889 | ret = i915_gem_object_flush_gpu_write_domain(obj, true); | 2870 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 2890 | if (ret) | 2871 | if (ret) |
| 2891 | return ret; | 2872 | return ret; |
| 2892 | 2873 | ||
| @@ -2909,6 +2890,20 @@ i915_gem_object_set_to_display_plane(struct drm_gem_object *obj, | |||
| 2909 | return 0; | 2890 | return 0; |
| 2910 | } | 2891 | } |
| 2911 | 2892 | ||
| 2893 | int | ||
| 2894 | i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj, | ||
| 2895 | bool interruptible) | ||
| 2896 | { | ||
| 2897 | if (!obj->active) | ||
| 2898 | return 0; | ||
| 2899 | |||
| 2900 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) | ||
| 2901 | i915_gem_flush_ring(obj->base.dev, NULL, obj->ring, | ||
| 2902 | 0, obj->base.write_domain); | ||
| 2903 | |||
| 2904 | return i915_gem_object_wait_rendering(&obj->base, interruptible); | ||
| 2905 | } | ||
| 2906 | |||
| 2912 | /** | 2907 | /** |
| 2913 | * Moves a single object to the CPU read, and possibly write domain. | 2908 | * Moves a single object to the CPU read, and possibly write domain. |
| 2914 | * | 2909 | * |
| @@ -2921,9 +2916,12 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
| 2921 | uint32_t old_write_domain, old_read_domains; | 2916 | uint32_t old_write_domain, old_read_domains; |
| 2922 | int ret; | 2917 | int ret; |
| 2923 | 2918 | ||
| 2924 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); | 2919 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 2925 | if (ret != 0) | 2920 | if (ret != 0) |
| 2926 | return ret; | 2921 | return ret; |
| 2922 | ret = i915_gem_object_wait_rendering(obj, true); | ||
| 2923 | if (ret) | ||
| 2924 | return ret; | ||
| 2927 | 2925 | ||
| 2928 | i915_gem_object_flush_gtt_write_domain(obj); | 2926 | i915_gem_object_flush_gtt_write_domain(obj); |
| 2929 | 2927 | ||
| @@ -2932,12 +2930,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
| 2932 | */ | 2930 | */ |
| 2933 | i915_gem_object_set_to_full_cpu_read_domain(obj); | 2931 | i915_gem_object_set_to_full_cpu_read_domain(obj); |
| 2934 | 2932 | ||
| 2935 | if (write) { | ||
| 2936 | ret = i915_gem_object_wait_rendering(obj, true); | ||
| 2937 | if (ret) | ||
| 2938 | return ret; | ||
| 2939 | } | ||
| 2940 | |||
| 2941 | old_write_domain = obj->write_domain; | 2933 | old_write_domain = obj->write_domain; |
| 2942 | old_read_domains = obj->read_domains; | 2934 | old_read_domains = obj->read_domains; |
| 2943 | 2935 | ||
| @@ -3108,7 +3100,8 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | |||
| 3108 | * write domain | 3100 | * write domain |
| 3109 | */ | 3101 | */ |
| 3110 | if (obj->write_domain && | 3102 | if (obj->write_domain && |
| 3111 | obj->write_domain != obj->pending_read_domains) { | 3103 | (obj->write_domain != obj->pending_read_domains || |
| 3104 | obj_priv->ring != ring)) { | ||
| 3112 | flush_domains |= obj->write_domain; | 3105 | flush_domains |= obj->write_domain; |
| 3113 | invalidate_domains |= | 3106 | invalidate_domains |= |
| 3114 | obj->pending_read_domains & ~obj->write_domain; | 3107 | obj->pending_read_domains & ~obj->write_domain; |
| @@ -3201,9 +3194,13 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
| 3201 | if (offset == 0 && size == obj->size) | 3194 | if (offset == 0 && size == obj->size) |
| 3202 | return i915_gem_object_set_to_cpu_domain(obj, 0); | 3195 | return i915_gem_object_set_to_cpu_domain(obj, 0); |
| 3203 | 3196 | ||
| 3204 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); | 3197 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 3205 | if (ret != 0) | 3198 | if (ret != 0) |
| 3206 | return ret; | 3199 | return ret; |
| 3200 | ret = i915_gem_object_wait_rendering(obj, true); | ||
| 3201 | if (ret) | ||
| 3202 | return ret; | ||
| 3203 | |||
| 3207 | i915_gem_object_flush_gtt_write_domain(obj); | 3204 | i915_gem_object_flush_gtt_write_domain(obj); |
| 3208 | 3205 | ||
| 3209 | /* If we're already fully in the CPU read domain, we're done. */ | 3206 | /* If we're already fully in the CPU read domain, we're done. */ |
| @@ -3250,192 +3247,230 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
| 3250 | return 0; | 3247 | return 0; |
| 3251 | } | 3248 | } |
| 3252 | 3249 | ||
| 3253 | /** | ||
| 3254 | * Pin an object to the GTT and evaluate the relocations landing in it. | ||
| 3255 | */ | ||
| 3256 | static int | 3250 | static int |
| 3257 | i915_gem_execbuffer_relocate(struct drm_i915_gem_object *obj, | 3251 | i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, |
| 3258 | struct drm_file *file_priv, | 3252 | struct drm_file *file_priv, |
| 3259 | struct drm_i915_gem_exec_object2 *entry) | 3253 | struct drm_i915_gem_exec_object2 *entry, |
| 3254 | struct drm_i915_gem_relocation_entry *reloc) | ||
| 3260 | { | 3255 | { |
| 3261 | struct drm_device *dev = obj->base.dev; | 3256 | struct drm_device *dev = obj->base.dev; |
| 3262 | drm_i915_private_t *dev_priv = dev->dev_private; | 3257 | struct drm_gem_object *target_obj; |
| 3263 | struct drm_i915_gem_relocation_entry __user *user_relocs; | 3258 | uint32_t target_offset; |
| 3264 | struct drm_gem_object *target_obj = NULL; | 3259 | int ret = -EINVAL; |
| 3265 | uint32_t target_handle = 0; | ||
| 3266 | int i, ret = 0; | ||
| 3267 | 3260 | ||
| 3268 | user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; | 3261 | target_obj = drm_gem_object_lookup(dev, file_priv, |
| 3269 | for (i = 0; i < entry->relocation_count; i++) { | 3262 | reloc->target_handle); |
| 3270 | struct drm_i915_gem_relocation_entry reloc; | 3263 | if (target_obj == NULL) |
| 3271 | uint32_t target_offset; | 3264 | return -ENOENT; |
| 3272 | 3265 | ||
| 3273 | if (__copy_from_user_inatomic(&reloc, | 3266 | target_offset = to_intel_bo(target_obj)->gtt_offset; |
| 3274 | user_relocs+i, | ||
| 3275 | sizeof(reloc))) { | ||
| 3276 | ret = -EFAULT; | ||
| 3277 | break; | ||
| 3278 | } | ||
| 3279 | 3267 | ||
| 3280 | if (reloc.target_handle != target_handle) { | 3268 | #if WATCH_RELOC |
| 3281 | drm_gem_object_unreference(target_obj); | 3269 | DRM_INFO("%s: obj %p offset %08x target %d " |
| 3270 | "read %08x write %08x gtt %08x " | ||
| 3271 | "presumed %08x delta %08x\n", | ||
| 3272 | __func__, | ||
| 3273 | obj, | ||
| 3274 | (int) reloc->offset, | ||
| 3275 | (int) reloc->target_handle, | ||
| 3276 | (int) reloc->read_domains, | ||
| 3277 | (int) reloc->write_domain, | ||
| 3278 | (int) target_offset, | ||
| 3279 | (int) reloc->presumed_offset, | ||
| 3280 | reloc->delta); | ||
| 3281 | #endif | ||
| 3282 | 3282 | ||
| 3283 | target_obj = drm_gem_object_lookup(dev, file_priv, | 3283 | /* The target buffer should have appeared before us in the |
| 3284 | reloc.target_handle); | 3284 | * exec_object list, so it should have a GTT space bound by now. |
| 3285 | if (target_obj == NULL) { | 3285 | */ |
| 3286 | ret = -ENOENT; | 3286 | if (target_offset == 0) { |
| 3287 | break; | 3287 | DRM_ERROR("No GTT space found for object %d\n", |
| 3288 | } | 3288 | reloc->target_handle); |
| 3289 | goto err; | ||
| 3290 | } | ||
| 3289 | 3291 | ||
| 3290 | target_handle = reloc.target_handle; | 3292 | /* Validate that the target is in a valid r/w GPU domain */ |
| 3291 | } | 3293 | if (reloc->write_domain & (reloc->write_domain - 1)) { |
| 3292 | target_offset = to_intel_bo(target_obj)->gtt_offset; | 3294 | DRM_ERROR("reloc with multiple write domains: " |
| 3295 | "obj %p target %d offset %d " | ||
| 3296 | "read %08x write %08x", | ||
| 3297 | obj, reloc->target_handle, | ||
| 3298 | (int) reloc->offset, | ||
| 3299 | reloc->read_domains, | ||
| 3300 | reloc->write_domain); | ||
| 3301 | goto err; | ||
| 3302 | } | ||
| 3303 | if (reloc->write_domain & I915_GEM_DOMAIN_CPU || | ||
| 3304 | reloc->read_domains & I915_GEM_DOMAIN_CPU) { | ||
| 3305 | DRM_ERROR("reloc with read/write CPU domains: " | ||
| 3306 | "obj %p target %d offset %d " | ||
| 3307 | "read %08x write %08x", | ||
| 3308 | obj, reloc->target_handle, | ||
| 3309 | (int) reloc->offset, | ||
| 3310 | reloc->read_domains, | ||
| 3311 | reloc->write_domain); | ||
| 3312 | goto err; | ||
| 3313 | } | ||
| 3314 | if (reloc->write_domain && target_obj->pending_write_domain && | ||
| 3315 | reloc->write_domain != target_obj->pending_write_domain) { | ||
| 3316 | DRM_ERROR("Write domain conflict: " | ||
| 3317 | "obj %p target %d offset %d " | ||
| 3318 | "new %08x old %08x\n", | ||
| 3319 | obj, reloc->target_handle, | ||
| 3320 | (int) reloc->offset, | ||
| 3321 | reloc->write_domain, | ||
| 3322 | target_obj->pending_write_domain); | ||
| 3323 | goto err; | ||
| 3324 | } | ||
| 3293 | 3325 | ||
| 3294 | #if WATCH_RELOC | 3326 | target_obj->pending_read_domains |= reloc->read_domains; |
| 3295 | DRM_INFO("%s: obj %p offset %08x target %d " | 3327 | target_obj->pending_write_domain |= reloc->write_domain; |
| 3296 | "read %08x write %08x gtt %08x " | ||
| 3297 | "presumed %08x delta %08x\n", | ||
| 3298 | __func__, | ||
| 3299 | obj, | ||
| 3300 | (int) reloc.offset, | ||
| 3301 | (int) reloc.target_handle, | ||
| 3302 | (int) reloc.read_domains, | ||
| 3303 | (int) reloc.write_domain, | ||
| 3304 | (int) target_offset, | ||
| 3305 | (int) reloc.presumed_offset, | ||
| 3306 | reloc.delta); | ||
| 3307 | #endif | ||
| 3308 | 3328 | ||
| 3309 | /* The target buffer should have appeared before us in the | 3329 | /* If the relocation already has the right value in it, no |
| 3310 | * exec_object list, so it should have a GTT space bound by now. | 3330 | * more work needs to be done. |
| 3311 | */ | 3331 | */ |
| 3312 | if (target_offset == 0) { | 3332 | if (target_offset == reloc->presumed_offset) |
| 3313 | DRM_ERROR("No GTT space found for object %d\n", | 3333 | goto out; |
| 3314 | reloc.target_handle); | ||
| 3315 | ret = -EINVAL; | ||
| 3316 | break; | ||
| 3317 | } | ||
| 3318 | 3334 | ||
| 3319 | /* Validate that the target is in a valid r/w GPU domain */ | 3335 | /* Check that the relocation address is valid... */ |
| 3320 | if (reloc.write_domain & (reloc.write_domain - 1)) { | 3336 | if (reloc->offset > obj->base.size - 4) { |
| 3321 | DRM_ERROR("reloc with multiple write domains: " | 3337 | DRM_ERROR("Relocation beyond object bounds: " |
| 3322 | "obj %p target %d offset %d " | 3338 | "obj %p target %d offset %d size %d.\n", |
| 3323 | "read %08x write %08x", | 3339 | obj, reloc->target_handle, |
| 3324 | obj, reloc.target_handle, | 3340 | (int) reloc->offset, |
| 3325 | (int) reloc.offset, | 3341 | (int) obj->base.size); |
| 3326 | reloc.read_domains, | 3342 | goto err; |
| 3327 | reloc.write_domain); | 3343 | } |
| 3328 | ret = -EINVAL; | 3344 | if (reloc->offset & 3) { |
| 3329 | break; | 3345 | DRM_ERROR("Relocation not 4-byte aligned: " |
| 3330 | } | 3346 | "obj %p target %d offset %d.\n", |
| 3331 | if (reloc.write_domain & I915_GEM_DOMAIN_CPU || | 3347 | obj, reloc->target_handle, |
| 3332 | reloc.read_domains & I915_GEM_DOMAIN_CPU) { | 3348 | (int) reloc->offset); |
| 3333 | DRM_ERROR("reloc with read/write CPU domains: " | 3349 | goto err; |
| 3334 | "obj %p target %d offset %d " | 3350 | } |
| 3335 | "read %08x write %08x", | ||
| 3336 | obj, reloc.target_handle, | ||
| 3337 | (int) reloc.offset, | ||
| 3338 | reloc.read_domains, | ||
| 3339 | reloc.write_domain); | ||
| 3340 | ret = -EINVAL; | ||
| 3341 | break; | ||
| 3342 | } | ||
| 3343 | if (reloc.write_domain && target_obj->pending_write_domain && | ||
| 3344 | reloc.write_domain != target_obj->pending_write_domain) { | ||
| 3345 | DRM_ERROR("Write domain conflict: " | ||
| 3346 | "obj %p target %d offset %d " | ||
| 3347 | "new %08x old %08x\n", | ||
| 3348 | obj, reloc.target_handle, | ||
| 3349 | (int) reloc.offset, | ||
| 3350 | reloc.write_domain, | ||
| 3351 | target_obj->pending_write_domain); | ||
| 3352 | ret = -EINVAL; | ||
| 3353 | break; | ||
| 3354 | } | ||
| 3355 | 3351 | ||
| 3356 | target_obj->pending_read_domains |= reloc.read_domains; | 3352 | /* and points to somewhere within the target object. */ |
| 3357 | target_obj->pending_write_domain |= reloc.write_domain; | 3353 | if (reloc->delta >= target_obj->size) { |
| 3354 | DRM_ERROR("Relocation beyond target object bounds: " | ||
| 3355 | "obj %p target %d delta %d size %d.\n", | ||
| 3356 | obj, reloc->target_handle, | ||
| 3357 | (int) reloc->delta, | ||
| 3358 | (int) target_obj->size); | ||
| 3359 | goto err; | ||
| 3360 | } | ||
| 3358 | 3361 | ||
| 3359 | /* If the relocation already has the right value in it, no | 3362 | reloc->delta += target_offset; |
| 3360 | * more work needs to be done. | 3363 | if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { |
| 3361 | */ | 3364 | uint32_t page_offset = reloc->offset & ~PAGE_MASK; |
| 3362 | if (target_offset == reloc.presumed_offset) | 3365 | char *vaddr; |
| 3363 | continue; | ||
| 3364 | 3366 | ||
| 3365 | /* Check that the relocation address is valid... */ | 3367 | vaddr = kmap_atomic(obj->pages[reloc->offset >> PAGE_SHIFT]); |
| 3366 | if (reloc.offset > obj->base.size - 4) { | 3368 | *(uint32_t *)(vaddr + page_offset) = reloc->delta; |
| 3367 | DRM_ERROR("Relocation beyond object bounds: " | 3369 | kunmap_atomic(vaddr); |
| 3368 | "obj %p target %d offset %d size %d.\n", | 3370 | } else { |
| 3369 | obj, reloc.target_handle, | 3371 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3370 | (int) reloc.offset, (int) obj->base.size); | 3372 | uint32_t __iomem *reloc_entry; |
| 3371 | ret = -EINVAL; | 3373 | void __iomem *reloc_page; |
| 3372 | break; | ||
| 3373 | } | ||
| 3374 | if (reloc.offset & 3) { | ||
| 3375 | DRM_ERROR("Relocation not 4-byte aligned: " | ||
| 3376 | "obj %p target %d offset %d.\n", | ||
| 3377 | obj, reloc.target_handle, | ||
| 3378 | (int) reloc.offset); | ||
| 3379 | ret = -EINVAL; | ||
| 3380 | break; | ||
| 3381 | } | ||
| 3382 | 3374 | ||
| 3383 | /* and points to somewhere within the target object. */ | 3375 | ret = i915_gem_object_set_to_gtt_domain(&obj->base, 1); |
| 3384 | if (reloc.delta >= target_obj->size) { | 3376 | if (ret) |
| 3385 | DRM_ERROR("Relocation beyond target object bounds: " | 3377 | goto err; |
| 3386 | "obj %p target %d delta %d size %d.\n", | ||
| 3387 | obj, reloc.target_handle, | ||
| 3388 | (int) reloc.delta, (int) target_obj->size); | ||
| 3389 | ret = -EINVAL; | ||
| 3390 | break; | ||
| 3391 | } | ||
| 3392 | 3378 | ||
| 3393 | reloc.delta += target_offset; | 3379 | /* Map the page containing the relocation we're going to perform. */ |
| 3394 | if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { | 3380 | reloc->offset += obj->gtt_offset; |
| 3395 | uint32_t page_offset = reloc.offset & ~PAGE_MASK; | 3381 | reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, |
| 3396 | char *vaddr; | 3382 | reloc->offset & PAGE_MASK); |
| 3383 | reloc_entry = (uint32_t __iomem *) | ||
| 3384 | (reloc_page + (reloc->offset & ~PAGE_MASK)); | ||
| 3385 | iowrite32(reloc->delta, reloc_entry); | ||
| 3386 | io_mapping_unmap_atomic(reloc_page); | ||
| 3387 | } | ||
| 3397 | 3388 | ||
| 3398 | vaddr = kmap_atomic(obj->pages[reloc.offset >> PAGE_SHIFT]); | 3389 | /* and update the user's relocation entry */ |
| 3399 | *(uint32_t *)(vaddr + page_offset) = reloc.delta; | 3390 | reloc->presumed_offset = target_offset; |
| 3400 | kunmap_atomic(vaddr); | ||
| 3401 | } else { | ||
| 3402 | uint32_t __iomem *reloc_entry; | ||
| 3403 | void __iomem *reloc_page; | ||
| 3404 | 3391 | ||
| 3405 | ret = i915_gem_object_set_to_gtt_domain(&obj->base, 1); | 3392 | out: |
| 3406 | if (ret) | 3393 | ret = 0; |
| 3407 | break; | 3394 | err: |
| 3395 | drm_gem_object_unreference(target_obj); | ||
| 3396 | return ret; | ||
| 3397 | } | ||
| 3408 | 3398 | ||
| 3409 | /* Map the page containing the relocation we're going to perform. */ | 3399 | static int |
| 3410 | reloc.offset += obj->gtt_offset; | 3400 | i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, |
| 3411 | reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | 3401 | struct drm_file *file_priv, |
| 3412 | reloc.offset & PAGE_MASK); | 3402 | struct drm_i915_gem_exec_object2 *entry) |
| 3413 | reloc_entry = (uint32_t __iomem *) | 3403 | { |
| 3414 | (reloc_page + (reloc.offset & ~PAGE_MASK)); | 3404 | struct drm_i915_gem_relocation_entry __user *user_relocs; |
| 3415 | iowrite32(reloc.delta, reloc_entry); | 3405 | int i, ret; |
| 3416 | io_mapping_unmap_atomic(reloc_page); | 3406 | |
| 3417 | } | 3407 | user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; |
| 3408 | for (i = 0; i < entry->relocation_count; i++) { | ||
| 3409 | struct drm_i915_gem_relocation_entry reloc; | ||
| 3410 | |||
| 3411 | if (__copy_from_user_inatomic(&reloc, | ||
| 3412 | user_relocs+i, | ||
| 3413 | sizeof(reloc))) | ||
| 3414 | return -EFAULT; | ||
| 3415 | |||
| 3416 | ret = i915_gem_execbuffer_relocate_entry(obj, file_priv, entry, &reloc); | ||
| 3417 | if (ret) | ||
| 3418 | return ret; | ||
| 3418 | 3419 | ||
| 3419 | /* and update the user's relocation entry */ | ||
| 3420 | reloc.presumed_offset = target_offset; | ||
| 3421 | if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset, | 3420 | if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset, |
| 3422 | &reloc.presumed_offset, | 3421 | &reloc.presumed_offset, |
| 3423 | sizeof(reloc.presumed_offset))) { | 3422 | sizeof(reloc.presumed_offset))) |
| 3424 | ret = -EFAULT; | 3423 | return -EFAULT; |
| 3425 | break; | ||
| 3426 | } | ||
| 3427 | } | 3424 | } |
| 3428 | 3425 | ||
| 3429 | drm_gem_object_unreference(target_obj); | 3426 | return 0; |
| 3430 | return ret; | 3427 | } |
| 3428 | |||
| 3429 | static int | ||
| 3430 | i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj, | ||
| 3431 | struct drm_file *file_priv, | ||
| 3432 | struct drm_i915_gem_exec_object2 *entry, | ||
| 3433 | struct drm_i915_gem_relocation_entry *relocs) | ||
| 3434 | { | ||
| 3435 | int i, ret; | ||
| 3436 | |||
| 3437 | for (i = 0; i < entry->relocation_count; i++) { | ||
| 3438 | ret = i915_gem_execbuffer_relocate_entry(obj, file_priv, entry, &relocs[i]); | ||
| 3439 | if (ret) | ||
| 3440 | return ret; | ||
| 3441 | } | ||
| 3442 | |||
| 3443 | return 0; | ||
| 3431 | } | 3444 | } |
| 3432 | 3445 | ||
| 3433 | static int | 3446 | static int |
| 3434 | i915_gem_execbuffer_pin(struct drm_device *dev, | 3447 | i915_gem_execbuffer_relocate(struct drm_device *dev, |
| 3435 | struct drm_file *file, | 3448 | struct drm_file *file, |
| 3436 | struct drm_gem_object **object_list, | 3449 | struct drm_gem_object **object_list, |
| 3437 | struct drm_i915_gem_exec_object2 *exec_list, | 3450 | struct drm_i915_gem_exec_object2 *exec_list, |
| 3438 | int count) | 3451 | int count) |
| 3452 | { | ||
| 3453 | int i, ret; | ||
| 3454 | |||
| 3455 | for (i = 0; i < count; i++) { | ||
| 3456 | struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); | ||
| 3457 | obj->base.pending_read_domains = 0; | ||
| 3458 | obj->base.pending_write_domain = 0; | ||
| 3459 | ret = i915_gem_execbuffer_relocate_object(obj, file, | ||
| 3460 | &exec_list[i]); | ||
| 3461 | if (ret) | ||
| 3462 | return ret; | ||
| 3463 | } | ||
| 3464 | |||
| 3465 | return 0; | ||
| 3466 | } | ||
| 3467 | |||
| 3468 | static int | ||
| 3469 | i915_gem_execbuffer_reserve(struct drm_device *dev, | ||
| 3470 | struct drm_file *file, | ||
| 3471 | struct drm_gem_object **object_list, | ||
| 3472 | struct drm_i915_gem_exec_object2 *exec_list, | ||
| 3473 | int count) | ||
| 3439 | { | 3474 | { |
| 3440 | struct drm_i915_private *dev_priv = dev->dev_private; | 3475 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3441 | int ret, i, retry; | 3476 | int ret, i, retry; |
| @@ -3497,6 +3532,133 @@ i915_gem_execbuffer_pin(struct drm_device *dev, | |||
| 3497 | return 0; | 3532 | return 0; |
| 3498 | } | 3533 | } |
| 3499 | 3534 | ||
| 3535 | static int | ||
| 3536 | i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | ||
| 3537 | struct drm_file *file, | ||
| 3538 | struct drm_gem_object **object_list, | ||
| 3539 | struct drm_i915_gem_exec_object2 *exec_list, | ||
| 3540 | int count) | ||
| 3541 | { | ||
| 3542 | struct drm_i915_gem_relocation_entry *reloc; | ||
| 3543 | int i, total, ret; | ||
| 3544 | |||
| 3545 | for (i = 0; i < count; i++) { | ||
| 3546 | struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); | ||
| 3547 | obj->in_execbuffer = false; | ||
| 3548 | } | ||
| 3549 | |||
| 3550 | mutex_unlock(&dev->struct_mutex); | ||
| 3551 | |||
| 3552 | total = 0; | ||
| 3553 | for (i = 0; i < count; i++) | ||
| 3554 | total += exec_list[i].relocation_count; | ||
| 3555 | |||
| 3556 | reloc = drm_malloc_ab(total, sizeof(*reloc)); | ||
| 3557 | if (reloc == NULL) { | ||
| 3558 | mutex_lock(&dev->struct_mutex); | ||
| 3559 | return -ENOMEM; | ||
| 3560 | } | ||
| 3561 | |||
| 3562 | total = 0; | ||
| 3563 | for (i = 0; i < count; i++) { | ||
| 3564 | struct drm_i915_gem_relocation_entry __user *user_relocs; | ||
| 3565 | |||
| 3566 | user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; | ||
| 3567 | |||
| 3568 | if (copy_from_user(reloc+total, user_relocs, | ||
| 3569 | exec_list[i].relocation_count * | ||
| 3570 | sizeof(*reloc))) { | ||
| 3571 | ret = -EFAULT; | ||
| 3572 | mutex_lock(&dev->struct_mutex); | ||
| 3573 | goto err; | ||
| 3574 | } | ||
| 3575 | |||
| 3576 | total += exec_list[i].relocation_count; | ||
| 3577 | } | ||
| 3578 | |||
| 3579 | ret = i915_mutex_lock_interruptible(dev); | ||
| 3580 | if (ret) { | ||
| 3581 | mutex_lock(&dev->struct_mutex); | ||
| 3582 | goto err; | ||
| 3583 | } | ||
| 3584 | |||
| 3585 | ret = i915_gem_execbuffer_reserve(dev, file, | ||
| 3586 | object_list, exec_list, | ||
| 3587 | count); | ||
| 3588 | if (ret) | ||
| 3589 | goto err; | ||
| 3590 | |||
| 3591 | total = 0; | ||
| 3592 | for (i = 0; i < count; i++) { | ||
| 3593 | struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); | ||
| 3594 | obj->base.pending_read_domains = 0; | ||
| 3595 | obj->base.pending_write_domain = 0; | ||
| 3596 | ret = i915_gem_execbuffer_relocate_object_slow(obj, file, | ||
| 3597 | &exec_list[i], | ||
| 3598 | reloc + total); | ||
| 3599 | if (ret) | ||
| 3600 | goto err; | ||
| 3601 | |||
| 3602 | total += exec_list[i].relocation_count; | ||
| 3603 | } | ||
| 3604 | |||
| 3605 | /* Leave the user relocations as are, this is the painfully slow path, | ||
| 3606 | * and we want to avoid the complication of dropping the lock whilst | ||
| 3607 | * having buffers reserved in the aperture and so causing spurious | ||
| 3608 | * ENOSPC for random operations. | ||
| 3609 | */ | ||
| 3610 | |||
| 3611 | err: | ||
| 3612 | drm_free_large(reloc); | ||
| 3613 | return ret; | ||
| 3614 | } | ||
| 3615 | |||
| 3616 | static int | ||
| 3617 | i915_gem_execbuffer_move_to_gpu(struct drm_device *dev, | ||
| 3618 | struct drm_file *file, | ||
| 3619 | struct intel_ring_buffer *ring, | ||
| 3620 | struct drm_gem_object **objects, | ||
| 3621 | int count) | ||
| 3622 | { | ||
| 3623 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 3624 | int ret, i; | ||
| 3625 | |||
| 3626 | /* Zero the global flush/invalidate flags. These | ||
| 3627 | * will be modified as new domains are computed | ||
| 3628 | * for each object | ||
| 3629 | */ | ||
| 3630 | dev->invalidate_domains = 0; | ||
| 3631 | dev->flush_domains = 0; | ||
| 3632 | dev_priv->mm.flush_rings = 0; | ||
| 3633 | for (i = 0; i < count; i++) | ||
| 3634 | i915_gem_object_set_to_gpu_domain(objects[i], ring); | ||
| 3635 | |||
| 3636 | if (dev->invalidate_domains | dev->flush_domains) { | ||
| 3637 | #if WATCH_EXEC | ||
| 3638 | DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", | ||
| 3639 | __func__, | ||
| 3640 | dev->invalidate_domains, | ||
| 3641 | dev->flush_domains); | ||
| 3642 | #endif | ||
| 3643 | i915_gem_flush(dev, file, | ||
| 3644 | dev->invalidate_domains, | ||
| 3645 | dev->flush_domains, | ||
| 3646 | dev_priv->mm.flush_rings); | ||
| 3647 | } | ||
| 3648 | |||
| 3649 | for (i = 0; i < count; i++) { | ||
| 3650 | struct drm_i915_gem_object *obj = to_intel_bo(objects[i]); | ||
| 3651 | /* XXX replace with semaphores */ | ||
| 3652 | if (obj->ring && ring != obj->ring) { | ||
| 3653 | ret = i915_gem_object_wait_rendering(&obj->base, true); | ||
| 3654 | if (ret) | ||
| 3655 | return ret; | ||
| 3656 | } | ||
| 3657 | } | ||
| 3658 | |||
| 3659 | return 0; | ||
| 3660 | } | ||
| 3661 | |||
| 3500 | /* Throttle our rendering by waiting until the ring has completed our requests | 3662 | /* Throttle our rendering by waiting until the ring has completed our requests |
| 3501 | * emitted over 20 msec ago. | 3663 | * emitted over 20 msec ago. |
| 3502 | * | 3664 | * |
| @@ -3580,8 +3742,15 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, | |||
| 3580 | 3742 | ||
| 3581 | for (i = 0; i < count; i++) { | 3743 | for (i = 0; i < count; i++) { |
| 3582 | char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; | 3744 | char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; |
| 3583 | size_t length = exec[i].relocation_count * sizeof(struct drm_i915_gem_relocation_entry); | 3745 | int length; /* limited by fault_in_pages_readable() */ |
| 3746 | |||
| 3747 | /* First check for malicious input causing overflow */ | ||
| 3748 | if (exec[i].relocation_count > | ||
| 3749 | INT_MAX / sizeof(struct drm_i915_gem_relocation_entry)) | ||
| 3750 | return -EINVAL; | ||
| 3584 | 3751 | ||
| 3752 | length = exec[i].relocation_count * | ||
| 3753 | sizeof(struct drm_i915_gem_relocation_entry); | ||
| 3585 | if (!access_ok(VERIFY_READ, ptr, length)) | 3754 | if (!access_ok(VERIFY_READ, ptr, length)) |
| 3586 | return -EFAULT; | 3755 | return -EFAULT; |
| 3587 | 3756 | ||
| @@ -3724,18 +3893,24 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 3724 | } | 3893 | } |
| 3725 | 3894 | ||
| 3726 | /* Move the objects en-masse into the GTT, evicting if necessary. */ | 3895 | /* Move the objects en-masse into the GTT, evicting if necessary. */ |
| 3727 | ret = i915_gem_execbuffer_pin(dev, file, | 3896 | ret = i915_gem_execbuffer_reserve(dev, file, |
| 3728 | object_list, exec_list, | 3897 | object_list, exec_list, |
| 3729 | args->buffer_count); | 3898 | args->buffer_count); |
| 3730 | if (ret) | 3899 | if (ret) |
| 3731 | goto err; | 3900 | goto err; |
| 3732 | 3901 | ||
| 3733 | /* The objects are in their final locations, apply the relocations. */ | 3902 | /* The objects are in their final locations, apply the relocations. */ |
| 3734 | for (i = 0; i < args->buffer_count; i++) { | 3903 | ret = i915_gem_execbuffer_relocate(dev, file, |
| 3735 | struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); | 3904 | object_list, exec_list, |
| 3736 | obj->base.pending_read_domains = 0; | 3905 | args->buffer_count); |
| 3737 | obj->base.pending_write_domain = 0; | 3906 | if (ret) { |
| 3738 | ret = i915_gem_execbuffer_relocate(obj, file, &exec_list[i]); | 3907 | if (ret == -EFAULT) { |
| 3908 | ret = i915_gem_execbuffer_relocate_slow(dev, file, | ||
| 3909 | object_list, | ||
| 3910 | exec_list, | ||
| 3911 | args->buffer_count); | ||
| 3912 | BUG_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
| 3913 | } | ||
| 3739 | if (ret) | 3914 | if (ret) |
| 3740 | goto err; | 3915 | goto err; |
| 3741 | } | 3916 | } |
| @@ -3757,33 +3932,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 3757 | goto err; | 3932 | goto err; |
| 3758 | } | 3933 | } |
| 3759 | 3934 | ||
| 3760 | /* Zero the global flush/invalidate flags. These | 3935 | ret = i915_gem_execbuffer_move_to_gpu(dev, file, ring, |
| 3761 | * will be modified as new domains are computed | 3936 | object_list, args->buffer_count); |
| 3762 | * for each object | 3937 | if (ret) |
| 3763 | */ | 3938 | goto err; |
| 3764 | dev->invalidate_domains = 0; | ||
| 3765 | dev->flush_domains = 0; | ||
| 3766 | dev_priv->mm.flush_rings = 0; | ||
| 3767 | |||
| 3768 | for (i = 0; i < args->buffer_count; i++) { | ||
| 3769 | struct drm_gem_object *obj = object_list[i]; | ||
| 3770 | |||
| 3771 | /* Compute new gpu domains and update invalidate/flush */ | ||
| 3772 | i915_gem_object_set_to_gpu_domain(obj, ring); | ||
| 3773 | } | ||
| 3774 | |||
| 3775 | if (dev->invalidate_domains | dev->flush_domains) { | ||
| 3776 | #if WATCH_EXEC | ||
| 3777 | DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", | ||
| 3778 | __func__, | ||
| 3779 | dev->invalidate_domains, | ||
| 3780 | dev->flush_domains); | ||
| 3781 | #endif | ||
| 3782 | i915_gem_flush(dev, file, | ||
| 3783 | dev->invalidate_domains, | ||
| 3784 | dev->flush_domains, | ||
| 3785 | dev_priv->mm.flush_rings); | ||
| 3786 | } | ||
| 3787 | 3939 | ||
| 3788 | for (i = 0; i < args->buffer_count; i++) { | 3940 | for (i = 0; i < args->buffer_count; i++) { |
| 3789 | struct drm_gem_object *obj = object_list[i]; | 3941 | struct drm_gem_object *obj = object_list[i]; |
| @@ -4043,8 +4195,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | |||
| 4043 | alignment = i915_gem_get_gtt_alignment(obj); | 4195 | alignment = i915_gem_get_gtt_alignment(obj); |
| 4044 | if (obj_priv->gtt_offset & (alignment - 1)) { | 4196 | if (obj_priv->gtt_offset & (alignment - 1)) { |
| 4045 | WARN(obj_priv->pin_count, | 4197 | WARN(obj_priv->pin_count, |
| 4046 | "bo is already pinned with incorrect alignment:" | 4198 | "bo is already pinned with incorrect alignment: offset=%x, req.alignment=%x\n", |
| 4047 | " offset=%x, req.alignment=%x\n", | ||
| 4048 | obj_priv->gtt_offset, alignment); | 4199 | obj_priv->gtt_offset, alignment); |
| 4049 | ret = i915_gem_object_unbind(obj); | 4200 | ret = i915_gem_object_unbind(obj); |
| 4050 | if (ret) | 4201 | if (ret) |
| @@ -4223,10 +4374,20 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
| 4223 | * use this buffer rather sooner than later, so issuing the required | 4374 | * use this buffer rather sooner than later, so issuing the required |
| 4224 | * flush earlier is beneficial. | 4375 | * flush earlier is beneficial. |
| 4225 | */ | 4376 | */ |
| 4226 | if (obj->write_domain & I915_GEM_GPU_DOMAINS) | 4377 | if (obj->write_domain & I915_GEM_GPU_DOMAINS) { |
| 4227 | i915_gem_flush_ring(dev, file_priv, | 4378 | i915_gem_flush_ring(dev, file_priv, |
| 4228 | obj_priv->ring, | 4379 | obj_priv->ring, |
| 4229 | 0, obj->write_domain); | 4380 | 0, obj->write_domain); |
| 4381 | } else if (obj_priv->ring->outstanding_lazy_request) { | ||
| 4382 | /* This ring is not being cleared by active usage, | ||
| 4383 | * so emit a request to do so. | ||
| 4384 | */ | ||
| 4385 | u32 seqno = i915_add_request(dev, | ||
| 4386 | NULL, NULL, | ||
| 4387 | obj_priv->ring); | ||
| 4388 | if (seqno == 0) | ||
| 4389 | ret = -ENOMEM; | ||
| 4390 | } | ||
| 4230 | 4391 | ||
| 4231 | /* Update the active list for the hardware's current position. | 4392 | /* Update the active list for the hardware's current position. |
| 4232 | * Otherwise this only updates on a delayed timer or when irqs | 4393 | * Otherwise this only updates on a delayed timer or when irqs |
| @@ -4856,17 +5017,24 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | |||
| 4856 | struct drm_file *file_priv) | 5017 | struct drm_file *file_priv) |
| 4857 | { | 5018 | { |
| 4858 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 5019 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
| 4859 | void *obj_addr; | 5020 | void *vaddr = obj_priv->phys_obj->handle->vaddr + args->offset; |
| 4860 | int ret; | 5021 | char __user *user_data = (char __user *) (uintptr_t) args->data_ptr; |
| 4861 | char __user *user_data; | ||
| 4862 | 5022 | ||
| 4863 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 5023 | DRM_DEBUG_DRIVER("vaddr %p, %lld\n", vaddr, args->size); |
| 4864 | obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; | ||
| 4865 | 5024 | ||
| 4866 | DRM_DEBUG_DRIVER("obj_addr %p, %lld\n", obj_addr, args->size); | 5025 | if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) { |
| 4867 | ret = copy_from_user(obj_addr, user_data, args->size); | 5026 | unsigned long unwritten; |
| 4868 | if (ret) | 5027 | |
| 4869 | return -EFAULT; | 5028 | /* The physical object once assigned is fixed for the lifetime |
| 5029 | * of the obj, so we can safely drop the lock and continue | ||
| 5030 | * to access vaddr. | ||
| 5031 | */ | ||
| 5032 | mutex_unlock(&dev->struct_mutex); | ||
| 5033 | unwritten = copy_from_user(vaddr, user_data, args->size); | ||
| 5034 | mutex_lock(&dev->struct_mutex); | ||
| 5035 | if (unwritten) | ||
| 5036 | return -EFAULT; | ||
| 5037 | } | ||
| 4870 | 5038 | ||
| 4871 | drm_agp_chipset_flush(dev); | 5039 | drm_agp_chipset_flush(dev); |
| 4872 | return 0; | 5040 | return 0; |
| @@ -4900,9 +5068,7 @@ i915_gpu_is_active(struct drm_device *dev) | |||
| 4900 | int lists_empty; | 5068 | int lists_empty; |
| 4901 | 5069 | ||
| 4902 | lists_empty = list_empty(&dev_priv->mm.flushing_list) && | 5070 | lists_empty = list_empty(&dev_priv->mm.flushing_list) && |
| 4903 | list_empty(&dev_priv->render_ring.active_list) && | 5071 | list_empty(&dev_priv->mm.active_list); |
| 4904 | list_empty(&dev_priv->bsd_ring.active_list) && | ||
| 4905 | list_empty(&dev_priv->blt_ring.active_list); | ||
| 4906 | 5072 | ||
| 4907 | return !lists_empty; | 5073 | return !lists_empty; |
| 4908 | } | 5074 | } |
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 43a4013f53fa..d8ae7d1d0cc6 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
| @@ -165,9 +165,7 @@ i915_gem_evict_everything(struct drm_device *dev) | |||
| 165 | 165 | ||
| 166 | lists_empty = (list_empty(&dev_priv->mm.inactive_list) && | 166 | lists_empty = (list_empty(&dev_priv->mm.inactive_list) && |
| 167 | list_empty(&dev_priv->mm.flushing_list) && | 167 | list_empty(&dev_priv->mm.flushing_list) && |
| 168 | list_empty(&dev_priv->render_ring.active_list) && | 168 | list_empty(&dev_priv->mm.active_list)); |
| 169 | list_empty(&dev_priv->bsd_ring.active_list) && | ||
| 170 | list_empty(&dev_priv->blt_ring.active_list)); | ||
| 171 | if (lists_empty) | 169 | if (lists_empty) |
| 172 | return -ENOSPC; | 170 | return -ENOSPC; |
| 173 | 171 | ||
| @@ -184,9 +182,7 @@ i915_gem_evict_everything(struct drm_device *dev) | |||
| 184 | 182 | ||
| 185 | lists_empty = (list_empty(&dev_priv->mm.inactive_list) && | 183 | lists_empty = (list_empty(&dev_priv->mm.inactive_list) && |
| 186 | list_empty(&dev_priv->mm.flushing_list) && | 184 | list_empty(&dev_priv->mm.flushing_list) && |
| 187 | list_empty(&dev_priv->render_ring.active_list) && | 185 | list_empty(&dev_priv->mm.active_list)); |
| 188 | list_empty(&dev_priv->bsd_ring.active_list) && | ||
| 189 | list_empty(&dev_priv->blt_ring.active_list)); | ||
| 190 | BUG_ON(!lists_empty); | 186 | BUG_ON(!lists_empty); |
| 191 | 187 | ||
| 192 | return 0; | 188 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 25ed911a3112..878fc766a12c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -3033,6 +3033,7 @@ | |||
| 3033 | #define TRANS_DP_10BPC (1<<9) | 3033 | #define TRANS_DP_10BPC (1<<9) |
| 3034 | #define TRANS_DP_6BPC (2<<9) | 3034 | #define TRANS_DP_6BPC (2<<9) |
| 3035 | #define TRANS_DP_12BPC (3<<9) | 3035 | #define TRANS_DP_12BPC (3<<9) |
| 3036 | #define TRANS_DP_BPC_MASK (3<<9) | ||
| 3036 | #define TRANS_DP_VSYNC_ACTIVE_HIGH (1<<4) | 3037 | #define TRANS_DP_VSYNC_ACTIVE_HIGH (1<<4) |
| 3037 | #define TRANS_DP_VSYNC_ACTIVE_LOW 0 | 3038 | #define TRANS_DP_VSYNC_ACTIVE_LOW 0 |
| 3038 | #define TRANS_DP_HSYNC_ACTIVE_HIGH (1<<3) | 3039 | #define TRANS_DP_HSYNC_ACTIVE_HIGH (1<<3) |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 989c19d2d959..42729d25da58 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
| @@ -239,6 +239,16 @@ static void i915_save_modeset_reg(struct drm_device *dev) | |||
| 239 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | 239 | if (drm_core_check_feature(dev, DRIVER_MODESET)) |
| 240 | return; | 240 | return; |
| 241 | 241 | ||
| 242 | /* Cursor state */ | ||
| 243 | dev_priv->saveCURACNTR = I915_READ(CURACNTR); | ||
| 244 | dev_priv->saveCURAPOS = I915_READ(CURAPOS); | ||
| 245 | dev_priv->saveCURABASE = I915_READ(CURABASE); | ||
| 246 | dev_priv->saveCURBCNTR = I915_READ(CURBCNTR); | ||
| 247 | dev_priv->saveCURBPOS = I915_READ(CURBPOS); | ||
| 248 | dev_priv->saveCURBBASE = I915_READ(CURBBASE); | ||
| 249 | if (IS_GEN2(dev)) | ||
| 250 | dev_priv->saveCURSIZE = I915_READ(CURSIZE); | ||
| 251 | |||
| 242 | if (HAS_PCH_SPLIT(dev)) { | 252 | if (HAS_PCH_SPLIT(dev)) { |
| 243 | dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL); | 253 | dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL); |
| 244 | dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL); | 254 | dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL); |
| @@ -529,6 +539,16 @@ static void i915_restore_modeset_reg(struct drm_device *dev) | |||
| 529 | I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); | 539 | I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); |
| 530 | I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); | 540 | I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); |
| 531 | 541 | ||
| 542 | /* Cursor state */ | ||
| 543 | I915_WRITE(CURAPOS, dev_priv->saveCURAPOS); | ||
| 544 | I915_WRITE(CURACNTR, dev_priv->saveCURACNTR); | ||
| 545 | I915_WRITE(CURABASE, dev_priv->saveCURABASE); | ||
| 546 | I915_WRITE(CURBPOS, dev_priv->saveCURBPOS); | ||
| 547 | I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR); | ||
| 548 | I915_WRITE(CURBBASE, dev_priv->saveCURBBASE); | ||
| 549 | if (IS_GEN2(dev)) | ||
| 550 | I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); | ||
| 551 | |||
| 532 | return; | 552 | return; |
| 533 | } | 553 | } |
| 534 | 554 | ||
| @@ -543,16 +563,6 @@ void i915_save_display(struct drm_device *dev) | |||
| 543 | /* Don't save them in KMS mode */ | 563 | /* Don't save them in KMS mode */ |
| 544 | i915_save_modeset_reg(dev); | 564 | i915_save_modeset_reg(dev); |
| 545 | 565 | ||
| 546 | /* Cursor state */ | ||
| 547 | dev_priv->saveCURACNTR = I915_READ(CURACNTR); | ||
| 548 | dev_priv->saveCURAPOS = I915_READ(CURAPOS); | ||
| 549 | dev_priv->saveCURABASE = I915_READ(CURABASE); | ||
| 550 | dev_priv->saveCURBCNTR = I915_READ(CURBCNTR); | ||
| 551 | dev_priv->saveCURBPOS = I915_READ(CURBPOS); | ||
| 552 | dev_priv->saveCURBBASE = I915_READ(CURBBASE); | ||
| 553 | if (IS_GEN2(dev)) | ||
| 554 | dev_priv->saveCURSIZE = I915_READ(CURSIZE); | ||
| 555 | |||
| 556 | /* CRT state */ | 566 | /* CRT state */ |
| 557 | if (HAS_PCH_SPLIT(dev)) { | 567 | if (HAS_PCH_SPLIT(dev)) { |
| 558 | dev_priv->saveADPA = I915_READ(PCH_ADPA); | 568 | dev_priv->saveADPA = I915_READ(PCH_ADPA); |
| @@ -657,16 +667,6 @@ void i915_restore_display(struct drm_device *dev) | |||
| 657 | /* Don't restore them in KMS mode */ | 667 | /* Don't restore them in KMS mode */ |
| 658 | i915_restore_modeset_reg(dev); | 668 | i915_restore_modeset_reg(dev); |
| 659 | 669 | ||
| 660 | /* Cursor state */ | ||
| 661 | I915_WRITE(CURAPOS, dev_priv->saveCURAPOS); | ||
| 662 | I915_WRITE(CURACNTR, dev_priv->saveCURACNTR); | ||
| 663 | I915_WRITE(CURABASE, dev_priv->saveCURABASE); | ||
| 664 | I915_WRITE(CURBPOS, dev_priv->saveCURBPOS); | ||
| 665 | I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR); | ||
| 666 | I915_WRITE(CURBBASE, dev_priv->saveCURBBASE); | ||
| 667 | if (IS_GEN2(dev)) | ||
| 668 | I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); | ||
| 669 | |||
| 670 | /* CRT state */ | 670 | /* CRT state */ |
| 671 | if (HAS_PCH_SPLIT(dev)) | 671 | if (HAS_PCH_SPLIT(dev)) |
| 672 | I915_WRITE(PCH_ADPA, dev_priv->saveADPA); | 672 | I915_WRITE(PCH_ADPA, dev_priv->saveADPA); |
| @@ -862,8 +862,10 @@ int i915_restore_state(struct drm_device *dev) | |||
| 862 | /* Clock gating state */ | 862 | /* Clock gating state */ |
| 863 | intel_init_clock_gating(dev); | 863 | intel_init_clock_gating(dev); |
| 864 | 864 | ||
| 865 | if (HAS_PCH_SPLIT(dev)) | 865 | if (HAS_PCH_SPLIT(dev)) { |
| 866 | ironlake_enable_drps(dev); | 866 | ironlake_enable_drps(dev); |
| 867 | intel_init_emon(dev); | ||
| 868 | } | ||
| 867 | 869 | ||
| 868 | /* Cache mode state */ | 870 | /* Cache mode state */ |
| 869 | I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); | 871 | I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); |
diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index 65c88f9ba12c..2cb8e0b9f1ee 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c | |||
| @@ -190,37 +190,6 @@ out: | |||
| 190 | kfree(output.pointer); | 190 | kfree(output.pointer); |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | static int intel_dsm_switchto(enum vga_switcheroo_client_id id) | ||
| 194 | { | ||
| 195 | return 0; | ||
| 196 | } | ||
| 197 | |||
| 198 | static int intel_dsm_power_state(enum vga_switcheroo_client_id id, | ||
| 199 | enum vga_switcheroo_state state) | ||
| 200 | { | ||
| 201 | return 0; | ||
| 202 | } | ||
| 203 | |||
| 204 | static int intel_dsm_init(void) | ||
| 205 | { | ||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | static int intel_dsm_get_client_id(struct pci_dev *pdev) | ||
| 210 | { | ||
| 211 | if (intel_dsm_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev)) | ||
| 212 | return VGA_SWITCHEROO_IGD; | ||
| 213 | else | ||
| 214 | return VGA_SWITCHEROO_DIS; | ||
| 215 | } | ||
| 216 | |||
| 217 | static struct vga_switcheroo_handler intel_dsm_handler = { | ||
| 218 | .switchto = intel_dsm_switchto, | ||
| 219 | .power_state = intel_dsm_power_state, | ||
| 220 | .init = intel_dsm_init, | ||
| 221 | .get_client_id = intel_dsm_get_client_id, | ||
| 222 | }; | ||
| 223 | |||
| 224 | static bool intel_dsm_pci_probe(struct pci_dev *pdev) | 193 | static bool intel_dsm_pci_probe(struct pci_dev *pdev) |
| 225 | { | 194 | { |
| 226 | acpi_handle dhandle, intel_handle; | 195 | acpi_handle dhandle, intel_handle; |
| @@ -276,11 +245,8 @@ void intel_register_dsm_handler(void) | |||
| 276 | { | 245 | { |
| 277 | if (!intel_dsm_detect()) | 246 | if (!intel_dsm_detect()) |
| 278 | return; | 247 | return; |
| 279 | |||
| 280 | vga_switcheroo_register_handler(&intel_dsm_handler); | ||
| 281 | } | 248 | } |
| 282 | 249 | ||
| 283 | void intel_unregister_dsm_handler(void) | 250 | void intel_unregister_dsm_handler(void) |
| 284 | { | 251 | { |
| 285 | vga_switcheroo_unregister_handler(); | ||
| 286 | } | 252 | } |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index c55c77043357..8df574316063 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
| @@ -34,6 +34,25 @@ | |||
| 34 | #include "i915_drm.h" | 34 | #include "i915_drm.h" |
| 35 | #include "i915_drv.h" | 35 | #include "i915_drv.h" |
| 36 | 36 | ||
| 37 | /* Here's the desired hotplug mode */ | ||
| 38 | #define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \ | ||
| 39 | ADPA_CRT_HOTPLUG_WARMUP_10MS | \ | ||
| 40 | ADPA_CRT_HOTPLUG_SAMPLE_4S | \ | ||
| 41 | ADPA_CRT_HOTPLUG_VOLTAGE_50 | \ | ||
| 42 | ADPA_CRT_HOTPLUG_VOLREF_325MV | \ | ||
| 43 | ADPA_CRT_HOTPLUG_ENABLE) | ||
| 44 | |||
| 45 | struct intel_crt { | ||
| 46 | struct intel_encoder base; | ||
| 47 | bool force_hotplug_required; | ||
| 48 | }; | ||
| 49 | |||
| 50 | static struct intel_crt *intel_attached_crt(struct drm_connector *connector) | ||
| 51 | { | ||
| 52 | return container_of(intel_attached_encoder(connector), | ||
| 53 | struct intel_crt, base); | ||
| 54 | } | ||
| 55 | |||
| 37 | static void intel_crt_dpms(struct drm_encoder *encoder, int mode) | 56 | static void intel_crt_dpms(struct drm_encoder *encoder, int mode) |
| 38 | { | 57 | { |
| 39 | struct drm_device *dev = encoder->dev; | 58 | struct drm_device *dev = encoder->dev; |
| @@ -129,7 +148,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
| 129 | dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); | 148 | dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); |
| 130 | } | 149 | } |
| 131 | 150 | ||
| 132 | adpa = 0; | 151 | adpa = ADPA_HOTPLUG_BITS; |
| 133 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) | 152 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
| 134 | adpa |= ADPA_HSYNC_ACTIVE_HIGH; | 153 | adpa |= ADPA_HSYNC_ACTIVE_HIGH; |
| 135 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) | 154 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
| @@ -157,53 +176,44 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
| 157 | static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) | 176 | static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) |
| 158 | { | 177 | { |
| 159 | struct drm_device *dev = connector->dev; | 178 | struct drm_device *dev = connector->dev; |
| 179 | struct intel_crt *crt = intel_attached_crt(connector); | ||
| 160 | struct drm_i915_private *dev_priv = dev->dev_private; | 180 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 161 | u32 adpa, temp; | 181 | u32 adpa; |
| 162 | bool ret; | 182 | bool ret; |
| 163 | bool turn_off_dac = false; | ||
| 164 | 183 | ||
| 165 | temp = adpa = I915_READ(PCH_ADPA); | 184 | /* The first time through, trigger an explicit detection cycle */ |
| 185 | if (crt->force_hotplug_required) { | ||
| 186 | bool turn_off_dac = HAS_PCH_SPLIT(dev); | ||
| 187 | u32 save_adpa; | ||
| 166 | 188 | ||
| 167 | if (HAS_PCH_SPLIT(dev)) | 189 | crt->force_hotplug_required = 0; |
| 168 | turn_off_dac = true; | 190 | |
| 169 | 191 | save_adpa = adpa = I915_READ(PCH_ADPA); | |
| 170 | adpa &= ~ADPA_CRT_HOTPLUG_MASK; | 192 | DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa); |
| 171 | if (turn_off_dac) | 193 | |
| 172 | adpa &= ~ADPA_DAC_ENABLE; | 194 | adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER; |
| 173 | 195 | if (turn_off_dac) | |
| 174 | /* disable HPD first */ | 196 | adpa &= ~ADPA_DAC_ENABLE; |
| 175 | I915_WRITE(PCH_ADPA, adpa); | 197 | |
| 176 | (void)I915_READ(PCH_ADPA); | 198 | I915_WRITE(PCH_ADPA, adpa); |
| 177 | 199 | ||
| 178 | adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 | | 200 | if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, |
| 179 | ADPA_CRT_HOTPLUG_WARMUP_10MS | | 201 | 1000)) |
| 180 | ADPA_CRT_HOTPLUG_SAMPLE_4S | | 202 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); |
| 181 | ADPA_CRT_HOTPLUG_VOLTAGE_50 | /* default */ | 203 | |
| 182 | ADPA_CRT_HOTPLUG_VOLREF_325MV | | 204 | if (turn_off_dac) { |
| 183 | ADPA_CRT_HOTPLUG_ENABLE | | 205 | I915_WRITE(PCH_ADPA, save_adpa); |
| 184 | ADPA_CRT_HOTPLUG_FORCE_TRIGGER); | 206 | POSTING_READ(PCH_ADPA); |
| 185 | 207 | } | |
| 186 | DRM_DEBUG_KMS("pch crt adpa 0x%x", adpa); | ||
| 187 | I915_WRITE(PCH_ADPA, adpa); | ||
| 188 | |||
| 189 | if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, | ||
| 190 | 1000)) | ||
| 191 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); | ||
| 192 | |||
| 193 | if (turn_off_dac) { | ||
| 194 | /* Make sure hotplug is enabled */ | ||
| 195 | I915_WRITE(PCH_ADPA, temp | ADPA_CRT_HOTPLUG_ENABLE); | ||
| 196 | (void)I915_READ(PCH_ADPA); | ||
| 197 | } | 208 | } |
| 198 | 209 | ||
| 199 | /* Check the status to see if both blue and green are on now */ | 210 | /* Check the status to see if both blue and green are on now */ |
| 200 | adpa = I915_READ(PCH_ADPA); | 211 | adpa = I915_READ(PCH_ADPA); |
| 201 | adpa &= ADPA_CRT_HOTPLUG_MONITOR_MASK; | 212 | if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0) |
| 202 | if ((adpa == ADPA_CRT_HOTPLUG_MONITOR_COLOR) || | ||
| 203 | (adpa == ADPA_CRT_HOTPLUG_MONITOR_MONO)) | ||
| 204 | ret = true; | 213 | ret = true; |
| 205 | else | 214 | else |
| 206 | ret = false; | 215 | ret = false; |
| 216 | DRM_DEBUG_KMS("ironlake hotplug adpa=0x%x, result %d\n", adpa, ret); | ||
| 207 | 217 | ||
| 208 | return ret; | 218 | return ret; |
| 209 | } | 219 | } |
| @@ -277,13 +287,12 @@ static bool intel_crt_ddc_probe(struct drm_i915_private *dev_priv, int ddc_bus) | |||
| 277 | return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1; | 287 | return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1; |
| 278 | } | 288 | } |
| 279 | 289 | ||
| 280 | static bool intel_crt_detect_ddc(struct drm_encoder *encoder) | 290 | static bool intel_crt_detect_ddc(struct intel_crt *crt) |
| 281 | { | 291 | { |
| 282 | struct intel_encoder *intel_encoder = to_intel_encoder(encoder); | 292 | struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private; |
| 283 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
| 284 | 293 | ||
| 285 | /* CRT should always be at 0, but check anyway */ | 294 | /* CRT should always be at 0, but check anyway */ |
| 286 | if (intel_encoder->type != INTEL_OUTPUT_ANALOG) | 295 | if (crt->base.type != INTEL_OUTPUT_ANALOG) |
| 287 | return false; | 296 | return false; |
| 288 | 297 | ||
| 289 | if (intel_crt_ddc_probe(dev_priv, dev_priv->crt_ddc_pin)) { | 298 | if (intel_crt_ddc_probe(dev_priv, dev_priv->crt_ddc_pin)) { |
| @@ -291,7 +300,7 @@ static bool intel_crt_detect_ddc(struct drm_encoder *encoder) | |||
| 291 | return true; | 300 | return true; |
| 292 | } | 301 | } |
| 293 | 302 | ||
| 294 | if (intel_ddc_probe(intel_encoder, dev_priv->crt_ddc_pin)) { | 303 | if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) { |
| 295 | DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n"); | 304 | DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n"); |
| 296 | return true; | 305 | return true; |
| 297 | } | 306 | } |
| @@ -300,9 +309,9 @@ static bool intel_crt_detect_ddc(struct drm_encoder *encoder) | |||
| 300 | } | 309 | } |
| 301 | 310 | ||
| 302 | static enum drm_connector_status | 311 | static enum drm_connector_status |
| 303 | intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder) | 312 | intel_crt_load_detect(struct drm_crtc *crtc, struct intel_crt *crt) |
| 304 | { | 313 | { |
| 305 | struct drm_encoder *encoder = &intel_encoder->base; | 314 | struct drm_encoder *encoder = &crt->base.base; |
| 306 | struct drm_device *dev = encoder->dev; | 315 | struct drm_device *dev = encoder->dev; |
| 307 | struct drm_i915_private *dev_priv = dev->dev_private; | 316 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 308 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 317 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| @@ -434,7 +443,7 @@ static enum drm_connector_status | |||
| 434 | intel_crt_detect(struct drm_connector *connector, bool force) | 443 | intel_crt_detect(struct drm_connector *connector, bool force) |
| 435 | { | 444 | { |
| 436 | struct drm_device *dev = connector->dev; | 445 | struct drm_device *dev = connector->dev; |
| 437 | struct intel_encoder *encoder = intel_attached_encoder(connector); | 446 | struct intel_crt *crt = intel_attached_crt(connector); |
| 438 | struct drm_crtc *crtc; | 447 | struct drm_crtc *crtc; |
| 439 | int dpms_mode; | 448 | int dpms_mode; |
| 440 | enum drm_connector_status status; | 449 | enum drm_connector_status status; |
| @@ -443,28 +452,31 @@ intel_crt_detect(struct drm_connector *connector, bool force) | |||
| 443 | if (intel_crt_detect_hotplug(connector)) { | 452 | if (intel_crt_detect_hotplug(connector)) { |
| 444 | DRM_DEBUG_KMS("CRT detected via hotplug\n"); | 453 | DRM_DEBUG_KMS("CRT detected via hotplug\n"); |
| 445 | return connector_status_connected; | 454 | return connector_status_connected; |
| 446 | } else | 455 | } else { |
| 456 | DRM_DEBUG_KMS("CRT not detected via hotplug\n"); | ||
| 447 | return connector_status_disconnected; | 457 | return connector_status_disconnected; |
| 458 | } | ||
| 448 | } | 459 | } |
| 449 | 460 | ||
| 450 | if (intel_crt_detect_ddc(&encoder->base)) | 461 | if (intel_crt_detect_ddc(crt)) |
| 451 | return connector_status_connected; | 462 | return connector_status_connected; |
| 452 | 463 | ||
| 453 | if (!force) | 464 | if (!force) |
| 454 | return connector->status; | 465 | return connector->status; |
| 455 | 466 | ||
| 456 | /* for pre-945g platforms use load detect */ | 467 | /* for pre-945g platforms use load detect */ |
| 457 | if (encoder->base.crtc && encoder->base.crtc->enabled) { | 468 | crtc = crt->base.base.crtc; |
| 458 | status = intel_crt_load_detect(encoder->base.crtc, encoder); | 469 | if (crtc && crtc->enabled) { |
| 470 | status = intel_crt_load_detect(crtc, crt); | ||
| 459 | } else { | 471 | } else { |
| 460 | crtc = intel_get_load_detect_pipe(encoder, connector, | 472 | crtc = intel_get_load_detect_pipe(&crt->base, connector, |
| 461 | NULL, &dpms_mode); | 473 | NULL, &dpms_mode); |
| 462 | if (crtc) { | 474 | if (crtc) { |
| 463 | if (intel_crt_detect_ddc(&encoder->base)) | 475 | if (intel_crt_detect_ddc(crt)) |
| 464 | status = connector_status_connected; | 476 | status = connector_status_connected; |
| 465 | else | 477 | else |
| 466 | status = intel_crt_load_detect(crtc, encoder); | 478 | status = intel_crt_load_detect(crtc, crt); |
| 467 | intel_release_load_detect_pipe(encoder, | 479 | intel_release_load_detect_pipe(&crt->base, |
| 468 | connector, dpms_mode); | 480 | connector, dpms_mode); |
| 469 | } else | 481 | } else |
| 470 | status = connector_status_unknown; | 482 | status = connector_status_unknown; |
| @@ -536,17 +548,17 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = { | |||
| 536 | void intel_crt_init(struct drm_device *dev) | 548 | void intel_crt_init(struct drm_device *dev) |
| 537 | { | 549 | { |
| 538 | struct drm_connector *connector; | 550 | struct drm_connector *connector; |
| 539 | struct intel_encoder *intel_encoder; | 551 | struct intel_crt *crt; |
| 540 | struct intel_connector *intel_connector; | 552 | struct intel_connector *intel_connector; |
| 541 | struct drm_i915_private *dev_priv = dev->dev_private; | 553 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 542 | 554 | ||
| 543 | intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL); | 555 | crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL); |
| 544 | if (!intel_encoder) | 556 | if (!crt) |
| 545 | return; | 557 | return; |
| 546 | 558 | ||
| 547 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); | 559 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); |
| 548 | if (!intel_connector) { | 560 | if (!intel_connector) { |
| 549 | kfree(intel_encoder); | 561 | kfree(crt); |
| 550 | return; | 562 | return; |
| 551 | } | 563 | } |
| 552 | 564 | ||
| @@ -554,20 +566,20 @@ void intel_crt_init(struct drm_device *dev) | |||
| 554 | drm_connector_init(dev, &intel_connector->base, | 566 | drm_connector_init(dev, &intel_connector->base, |
| 555 | &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); | 567 | &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); |
| 556 | 568 | ||
| 557 | drm_encoder_init(dev, &intel_encoder->base, &intel_crt_enc_funcs, | 569 | drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs, |
| 558 | DRM_MODE_ENCODER_DAC); | 570 | DRM_MODE_ENCODER_DAC); |
| 559 | 571 | ||
| 560 | intel_connector_attach_encoder(intel_connector, intel_encoder); | 572 | intel_connector_attach_encoder(intel_connector, &crt->base); |
| 561 | 573 | ||
| 562 | intel_encoder->type = INTEL_OUTPUT_ANALOG; | 574 | crt->base.type = INTEL_OUTPUT_ANALOG; |
| 563 | intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | | 575 | crt->base.clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT | |
| 564 | (1 << INTEL_ANALOG_CLONE_BIT) | | 576 | 1 << INTEL_ANALOG_CLONE_BIT | |
| 565 | (1 << INTEL_SDVO_LVDS_CLONE_BIT); | 577 | 1 << INTEL_SDVO_LVDS_CLONE_BIT); |
| 566 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); | 578 | crt->base.crtc_mask = (1 << 0) | (1 << 1); |
| 567 | connector->interlace_allowed = 1; | 579 | connector->interlace_allowed = 1; |
| 568 | connector->doublescan_allowed = 0; | 580 | connector->doublescan_allowed = 0; |
| 569 | 581 | ||
| 570 | drm_encoder_helper_add(&intel_encoder->base, &intel_crt_helper_funcs); | 582 | drm_encoder_helper_add(&crt->base.base, &intel_crt_helper_funcs); |
| 571 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); | 583 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); |
| 572 | 584 | ||
| 573 | drm_sysfs_connector_add(connector); | 585 | drm_sysfs_connector_add(connector); |
| @@ -577,5 +589,22 @@ void intel_crt_init(struct drm_device *dev) | |||
| 577 | else | 589 | else |
| 578 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | 590 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; |
| 579 | 591 | ||
| 592 | /* | ||
| 593 | * Configure the automatic hotplug detection stuff | ||
| 594 | */ | ||
| 595 | crt->force_hotplug_required = 0; | ||
| 596 | if (HAS_PCH_SPLIT(dev)) { | ||
| 597 | u32 adpa; | ||
| 598 | |||
| 599 | adpa = I915_READ(PCH_ADPA); | ||
| 600 | adpa &= ~ADPA_CRT_HOTPLUG_MASK; | ||
| 601 | adpa |= ADPA_HOTPLUG_BITS; | ||
| 602 | I915_WRITE(PCH_ADPA, adpa); | ||
| 603 | POSTING_READ(PCH_ADPA); | ||
| 604 | |||
| 605 | DRM_DEBUG_KMS("pch crt adpa set to 0x%x\n", adpa); | ||
| 606 | crt->force_hotplug_required = 1; | ||
| 607 | } | ||
| 608 | |||
| 580 | dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; | 609 | dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; |
| 581 | } | 610 | } |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 990f065374b2..d9b7092439ef 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -1611,6 +1611,18 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 1611 | 1611 | ||
| 1612 | wait_event(dev_priv->pending_flip_queue, | 1612 | wait_event(dev_priv->pending_flip_queue, |
| 1613 | atomic_read(&obj_priv->pending_flip) == 0); | 1613 | atomic_read(&obj_priv->pending_flip) == 0); |
| 1614 | |||
| 1615 | /* Big Hammer, we also need to ensure that any pending | ||
| 1616 | * MI_WAIT_FOR_EVENT inside a user batch buffer on the | ||
| 1617 | * current scanout is retired before unpinning the old | ||
| 1618 | * framebuffer. | ||
| 1619 | */ | ||
| 1620 | ret = i915_gem_object_flush_gpu(obj_priv, false); | ||
| 1621 | if (ret) { | ||
| 1622 | i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); | ||
| 1623 | mutex_unlock(&dev->struct_mutex); | ||
| 1624 | return ret; | ||
| 1625 | } | ||
| 1614 | } | 1626 | } |
| 1615 | 1627 | ||
| 1616 | ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y, | 1628 | ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y, |
| @@ -1681,6 +1693,37 @@ static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock) | |||
| 1681 | udelay(500); | 1693 | udelay(500); |
| 1682 | } | 1694 | } |
| 1683 | 1695 | ||
| 1696 | static void intel_fdi_normal_train(struct drm_crtc *crtc) | ||
| 1697 | { | ||
| 1698 | struct drm_device *dev = crtc->dev; | ||
| 1699 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1700 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 1701 | int pipe = intel_crtc->pipe; | ||
| 1702 | u32 reg, temp; | ||
| 1703 | |||
| 1704 | /* enable normal train */ | ||
| 1705 | reg = FDI_TX_CTL(pipe); | ||
| 1706 | temp = I915_READ(reg); | ||
| 1707 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
| 1708 | temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; | ||
| 1709 | I915_WRITE(reg, temp); | ||
| 1710 | |||
| 1711 | reg = FDI_RX_CTL(pipe); | ||
| 1712 | temp = I915_READ(reg); | ||
| 1713 | if (HAS_PCH_CPT(dev)) { | ||
| 1714 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
| 1715 | temp |= FDI_LINK_TRAIN_NORMAL_CPT; | ||
| 1716 | } else { | ||
| 1717 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
| 1718 | temp |= FDI_LINK_TRAIN_NONE; | ||
| 1719 | } | ||
| 1720 | I915_WRITE(reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); | ||
| 1721 | |||
| 1722 | /* wait one idle pattern time */ | ||
| 1723 | POSTING_READ(reg); | ||
| 1724 | udelay(1000); | ||
| 1725 | } | ||
| 1726 | |||
| 1684 | /* The FDI link training functions for ILK/Ibexpeak. */ | 1727 | /* The FDI link training functions for ILK/Ibexpeak. */ |
| 1685 | static void ironlake_fdi_link_train(struct drm_crtc *crtc) | 1728 | static void ironlake_fdi_link_train(struct drm_crtc *crtc) |
| 1686 | { | 1729 | { |
| @@ -1767,27 +1810,6 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) | |||
| 1767 | 1810 | ||
| 1768 | DRM_DEBUG_KMS("FDI train done\n"); | 1811 | DRM_DEBUG_KMS("FDI train done\n"); |
| 1769 | 1812 | ||
| 1770 | /* enable normal train */ | ||
| 1771 | reg = FDI_TX_CTL(pipe); | ||
| 1772 | temp = I915_READ(reg); | ||
| 1773 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
| 1774 | temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; | ||
| 1775 | I915_WRITE(reg, temp); | ||
| 1776 | |||
| 1777 | reg = FDI_RX_CTL(pipe); | ||
| 1778 | temp = I915_READ(reg); | ||
| 1779 | if (HAS_PCH_CPT(dev)) { | ||
| 1780 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
| 1781 | temp |= FDI_LINK_TRAIN_NORMAL_CPT; | ||
| 1782 | } else { | ||
| 1783 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
| 1784 | temp |= FDI_LINK_TRAIN_NONE; | ||
| 1785 | } | ||
| 1786 | I915_WRITE(reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); | ||
| 1787 | |||
| 1788 | /* wait one idle pattern time */ | ||
| 1789 | POSTING_READ(reg); | ||
| 1790 | udelay(1000); | ||
| 1791 | } | 1813 | } |
| 1792 | 1814 | ||
| 1793 | static const int const snb_b_fdi_train_param [] = { | 1815 | static const int const snb_b_fdi_train_param [] = { |
| @@ -2090,15 +2112,19 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) | |||
| 2090 | I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe))); | 2112 | I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe))); |
| 2091 | I915_WRITE(TRANS_VSYNC(pipe), I915_READ(VSYNC(pipe))); | 2113 | I915_WRITE(TRANS_VSYNC(pipe), I915_READ(VSYNC(pipe))); |
| 2092 | 2114 | ||
| 2115 | intel_fdi_normal_train(crtc); | ||
| 2116 | |||
| 2093 | /* For PCH DP, enable TRANS_DP_CTL */ | 2117 | /* For PCH DP, enable TRANS_DP_CTL */ |
| 2094 | if (HAS_PCH_CPT(dev) && | 2118 | if (HAS_PCH_CPT(dev) && |
| 2095 | intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { | 2119 | intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { |
| 2096 | reg = TRANS_DP_CTL(pipe); | 2120 | reg = TRANS_DP_CTL(pipe); |
| 2097 | temp = I915_READ(reg); | 2121 | temp = I915_READ(reg); |
| 2098 | temp &= ~(TRANS_DP_PORT_SEL_MASK | | 2122 | temp &= ~(TRANS_DP_PORT_SEL_MASK | |
| 2099 | TRANS_DP_SYNC_MASK); | 2123 | TRANS_DP_SYNC_MASK | |
| 2124 | TRANS_DP_BPC_MASK); | ||
| 2100 | temp |= (TRANS_DP_OUTPUT_ENABLE | | 2125 | temp |= (TRANS_DP_OUTPUT_ENABLE | |
| 2101 | TRANS_DP_ENH_FRAMING); | 2126 | TRANS_DP_ENH_FRAMING); |
| 2127 | temp |= TRANS_DP_8BPC; | ||
| 2102 | 2128 | ||
| 2103 | if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) | 2129 | if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) |
| 2104 | temp |= TRANS_DP_HSYNC_ACTIVE_HIGH; | 2130 | temp |= TRANS_DP_HSYNC_ACTIVE_HIGH; |
| @@ -2200,9 +2226,10 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) | |||
| 2200 | udelay(100); | 2226 | udelay(100); |
| 2201 | 2227 | ||
| 2202 | /* Ironlake workaround, disable clock pointer after downing FDI */ | 2228 | /* Ironlake workaround, disable clock pointer after downing FDI */ |
| 2203 | I915_WRITE(FDI_RX_CHICKEN(pipe), | 2229 | if (HAS_PCH_IBX(dev)) |
| 2204 | I915_READ(FDI_RX_CHICKEN(pipe) & | 2230 | I915_WRITE(FDI_RX_CHICKEN(pipe), |
| 2205 | ~FDI_RX_PHASE_SYNC_POINTER_ENABLE)); | 2231 | I915_READ(FDI_RX_CHICKEN(pipe) & |
| 2232 | ~FDI_RX_PHASE_SYNC_POINTER_ENABLE)); | ||
| 2206 | 2233 | ||
| 2207 | /* still set train pattern 1 */ | 2234 | /* still set train pattern 1 */ |
| 2208 | reg = FDI_TX_CTL(pipe); | 2235 | reg = FDI_TX_CTL(pipe); |
| @@ -2687,27 +2714,19 @@ fdi_reduce_ratio(u32 *num, u32 *den) | |||
| 2687 | } | 2714 | } |
| 2688 | } | 2715 | } |
| 2689 | 2716 | ||
| 2690 | #define DATA_N 0x800000 | ||
| 2691 | #define LINK_N 0x80000 | ||
| 2692 | |||
| 2693 | static void | 2717 | static void |
| 2694 | ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock, | 2718 | ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock, |
| 2695 | int link_clock, struct fdi_m_n *m_n) | 2719 | int link_clock, struct fdi_m_n *m_n) |
| 2696 | { | 2720 | { |
| 2697 | u64 temp; | ||
| 2698 | |||
| 2699 | m_n->tu = 64; /* default size */ | 2721 | m_n->tu = 64; /* default size */ |
| 2700 | 2722 | ||
| 2701 | temp = (u64) DATA_N * pixel_clock; | 2723 | /* BUG_ON(pixel_clock > INT_MAX / 36); */ |
| 2702 | temp = div_u64(temp, link_clock); | 2724 | m_n->gmch_m = bits_per_pixel * pixel_clock; |
| 2703 | m_n->gmch_m = div_u64(temp * bits_per_pixel, nlanes); | 2725 | m_n->gmch_n = link_clock * nlanes * 8; |
| 2704 | m_n->gmch_m >>= 3; /* convert to bytes_per_pixel */ | ||
| 2705 | m_n->gmch_n = DATA_N; | ||
| 2706 | fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); | 2726 | fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); |
| 2707 | 2727 | ||
| 2708 | temp = (u64) LINK_N * pixel_clock; | 2728 | m_n->link_m = pixel_clock; |
| 2709 | m_n->link_m = div_u64(temp, link_clock); | 2729 | m_n->link_n = link_clock; |
| 2710 | m_n->link_n = LINK_N; | ||
| 2711 | fdi_reduce_ratio(&m_n->link_m, &m_n->link_n); | 2730 | fdi_reduce_ratio(&m_n->link_m, &m_n->link_n); |
| 2712 | } | 2731 | } |
| 2713 | 2732 | ||
| @@ -3691,6 +3710,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 3691 | 3710 | ||
| 3692 | /* FDI link */ | 3711 | /* FDI link */ |
| 3693 | if (HAS_PCH_SPLIT(dev)) { | 3712 | if (HAS_PCH_SPLIT(dev)) { |
| 3713 | int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); | ||
| 3694 | int lane = 0, link_bw, bpp; | 3714 | int lane = 0, link_bw, bpp; |
| 3695 | /* CPU eDP doesn't require FDI link, so just set DP M/N | 3715 | /* CPU eDP doesn't require FDI link, so just set DP M/N |
| 3696 | according to current link config */ | 3716 | according to current link config */ |
| @@ -3774,6 +3794,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 3774 | 3794 | ||
| 3775 | intel_crtc->fdi_lanes = lane; | 3795 | intel_crtc->fdi_lanes = lane; |
| 3776 | 3796 | ||
| 3797 | if (pixel_multiplier > 1) | ||
| 3798 | link_bw *= pixel_multiplier; | ||
| 3777 | ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); | 3799 | ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); |
| 3778 | } | 3800 | } |
| 3779 | 3801 | ||
| @@ -5211,6 +5233,55 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { | |||
| 5211 | .page_flip = intel_crtc_page_flip, | 5233 | .page_flip = intel_crtc_page_flip, |
| 5212 | }; | 5234 | }; |
| 5213 | 5235 | ||
| 5236 | static void intel_sanitize_modesetting(struct drm_device *dev, | ||
| 5237 | int pipe, int plane) | ||
| 5238 | { | ||
| 5239 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 5240 | u32 reg, val; | ||
| 5241 | |||
| 5242 | if (HAS_PCH_SPLIT(dev)) | ||
| 5243 | return; | ||
| 5244 | |||
| 5245 | /* Who knows what state these registers were left in by the BIOS or | ||
| 5246 | * grub? | ||
| 5247 | * | ||
| 5248 | * If we leave the registers in a conflicting state (e.g. with the | ||
| 5249 | * display plane reading from the other pipe than the one we intend | ||
| 5250 | * to use) then when we attempt to teardown the active mode, we will | ||
| 5251 | * not disable the pipes and planes in the correct order -- leaving | ||
| 5252 | * a plane reading from a disabled pipe and possibly leading to | ||
| 5253 | * undefined behaviour. | ||
| 5254 | */ | ||
| 5255 | |||
| 5256 | reg = DSPCNTR(plane); | ||
| 5257 | val = I915_READ(reg); | ||
| 5258 | |||
| 5259 | if ((val & DISPLAY_PLANE_ENABLE) == 0) | ||
| 5260 | return; | ||
| 5261 | if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe) | ||
| 5262 | return; | ||
| 5263 | |||
| 5264 | /* This display plane is active and attached to the other CPU pipe. */ | ||
| 5265 | pipe = !pipe; | ||
| 5266 | |||
| 5267 | /* Disable the plane and wait for it to stop reading from the pipe. */ | ||
| 5268 | I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE); | ||
| 5269 | intel_flush_display_plane(dev, plane); | ||
| 5270 | |||
| 5271 | if (IS_GEN2(dev)) | ||
| 5272 | intel_wait_for_vblank(dev, pipe); | ||
| 5273 | |||
| 5274 | if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) | ||
| 5275 | return; | ||
| 5276 | |||
| 5277 | /* Switch off the pipe. */ | ||
| 5278 | reg = PIPECONF(pipe); | ||
| 5279 | val = I915_READ(reg); | ||
| 5280 | if (val & PIPECONF_ENABLE) { | ||
| 5281 | I915_WRITE(reg, val & ~PIPECONF_ENABLE); | ||
| 5282 | intel_wait_for_pipe_off(dev, pipe); | ||
| 5283 | } | ||
| 5284 | } | ||
| 5214 | 5285 | ||
| 5215 | static void intel_crtc_init(struct drm_device *dev, int pipe) | 5286 | static void intel_crtc_init(struct drm_device *dev, int pipe) |
| 5216 | { | 5287 | { |
| @@ -5262,6 +5333,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
| 5262 | 5333 | ||
| 5263 | setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer, | 5334 | setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer, |
| 5264 | (unsigned long)intel_crtc); | 5335 | (unsigned long)intel_crtc); |
| 5336 | |||
| 5337 | intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane); | ||
| 5265 | } | 5338 | } |
| 5266 | 5339 | ||
| 5267 | int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, | 5340 | int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, |
| @@ -5311,9 +5384,14 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 5311 | struct drm_i915_private *dev_priv = dev->dev_private; | 5384 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 5312 | struct intel_encoder *encoder; | 5385 | struct intel_encoder *encoder; |
| 5313 | bool dpd_is_edp = false; | 5386 | bool dpd_is_edp = false; |
| 5387 | bool has_lvds = false; | ||
| 5314 | 5388 | ||
| 5315 | if (IS_MOBILE(dev) && !IS_I830(dev)) | 5389 | if (IS_MOBILE(dev) && !IS_I830(dev)) |
| 5316 | intel_lvds_init(dev); | 5390 | has_lvds = intel_lvds_init(dev); |
| 5391 | if (!has_lvds && !HAS_PCH_SPLIT(dev)) { | ||
| 5392 | /* disable the panel fitter on everything but LVDS */ | ||
| 5393 | I915_WRITE(PFIT_CONTROL, 0); | ||
| 5394 | } | ||
| 5317 | 5395 | ||
| 5318 | if (HAS_PCH_SPLIT(dev)) { | 5396 | if (HAS_PCH_SPLIT(dev)) { |
| 5319 | dpd_is_edp = intel_dpd_is_edp(dev); | 5397 | dpd_is_edp = intel_dpd_is_edp(dev); |
| @@ -5581,20 +5659,19 @@ void ironlake_enable_drps(struct drm_device *dev) | |||
| 5581 | fmin = (rgvmodectl & MEMMODE_FMIN_MASK); | 5659 | fmin = (rgvmodectl & MEMMODE_FMIN_MASK); |
| 5582 | fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >> | 5660 | fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >> |
| 5583 | MEMMODE_FSTART_SHIFT; | 5661 | MEMMODE_FSTART_SHIFT; |
| 5584 | fstart = fmax; | ||
| 5585 | 5662 | ||
| 5586 | vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >> | 5663 | vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >> |
| 5587 | PXVFREQ_PX_SHIFT; | 5664 | PXVFREQ_PX_SHIFT; |
| 5588 | 5665 | ||
| 5589 | dev_priv->fmax = fstart; /* IPS callback will increase this */ | 5666 | dev_priv->fmax = fmax; /* IPS callback will increase this */ |
| 5590 | dev_priv->fstart = fstart; | 5667 | dev_priv->fstart = fstart; |
| 5591 | 5668 | ||
| 5592 | dev_priv->max_delay = fmax; | 5669 | dev_priv->max_delay = fstart; |
| 5593 | dev_priv->min_delay = fmin; | 5670 | dev_priv->min_delay = fmin; |
| 5594 | dev_priv->cur_delay = fstart; | 5671 | dev_priv->cur_delay = fstart; |
| 5595 | 5672 | ||
| 5596 | DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", fmax, fmin, | 5673 | DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", |
| 5597 | fstart); | 5674 | fmax, fmin, fstart); |
| 5598 | 5675 | ||
| 5599 | I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN); | 5676 | I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN); |
| 5600 | 5677 | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 891f4f1d63b1..df648cb4c296 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -584,17 +584,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 584 | mode->clock = dev_priv->panel_fixed_mode->clock; | 584 | mode->clock = dev_priv->panel_fixed_mode->clock; |
| 585 | } | 585 | } |
| 586 | 586 | ||
| 587 | /* Just use VBT values for eDP */ | ||
| 588 | if (is_edp(intel_dp)) { | ||
| 589 | intel_dp->lane_count = dev_priv->edp.lanes; | ||
| 590 | intel_dp->link_bw = dev_priv->edp.rate; | ||
| 591 | adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw); | ||
| 592 | DRM_DEBUG_KMS("eDP link bw %02x lane count %d clock %d\n", | ||
| 593 | intel_dp->link_bw, intel_dp->lane_count, | ||
| 594 | adjusted_mode->clock); | ||
| 595 | return true; | ||
| 596 | } | ||
| 597 | |||
| 598 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { | 587 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { |
| 599 | for (clock = 0; clock <= max_clock; clock++) { | 588 | for (clock = 0; clock <= max_clock; clock++) { |
| 600 | int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); | 589 | int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); |
| @@ -613,6 +602,19 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 613 | } | 602 | } |
| 614 | } | 603 | } |
| 615 | 604 | ||
| 605 | if (is_edp(intel_dp)) { | ||
| 606 | /* okay we failed just pick the highest */ | ||
| 607 | intel_dp->lane_count = max_lane_count; | ||
| 608 | intel_dp->link_bw = bws[max_clock]; | ||
| 609 | adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw); | ||
| 610 | DRM_DEBUG_KMS("Force picking display port link bw %02x lane " | ||
| 611 | "count %d clock %d\n", | ||
| 612 | intel_dp->link_bw, intel_dp->lane_count, | ||
| 613 | adjusted_mode->clock); | ||
| 614 | |||
| 615 | return true; | ||
| 616 | } | ||
| 617 | |||
| 616 | return false; | 618 | return false; |
| 617 | } | 619 | } |
| 618 | 620 | ||
| @@ -1087,21 +1089,11 @@ intel_get_adjust_train(struct intel_dp *intel_dp) | |||
| 1087 | } | 1089 | } |
| 1088 | 1090 | ||
| 1089 | static uint32_t | 1091 | static uint32_t |
| 1090 | intel_dp_signal_levels(struct intel_dp *intel_dp) | 1092 | intel_dp_signal_levels(uint8_t train_set, int lane_count) |
| 1091 | { | 1093 | { |
| 1092 | struct drm_device *dev = intel_dp->base.base.dev; | 1094 | uint32_t signal_levels = 0; |
| 1093 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1094 | uint32_t signal_levels = 0; | ||
| 1095 | u8 train_set = intel_dp->train_set[0]; | ||
| 1096 | u32 vswing = train_set & DP_TRAIN_VOLTAGE_SWING_MASK; | ||
| 1097 | u32 preemphasis = train_set & DP_TRAIN_PRE_EMPHASIS_MASK; | ||
| 1098 | 1095 | ||
| 1099 | if (is_edp(intel_dp)) { | 1096 | switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { |
| 1100 | vswing = dev_priv->edp.vswing; | ||
| 1101 | preemphasis = dev_priv->edp.preemphasis; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | switch (vswing) { | ||
| 1105 | case DP_TRAIN_VOLTAGE_SWING_400: | 1097 | case DP_TRAIN_VOLTAGE_SWING_400: |
| 1106 | default: | 1098 | default: |
| 1107 | signal_levels |= DP_VOLTAGE_0_4; | 1099 | signal_levels |= DP_VOLTAGE_0_4; |
| @@ -1116,7 +1108,7 @@ intel_dp_signal_levels(struct intel_dp *intel_dp) | |||
| 1116 | signal_levels |= DP_VOLTAGE_1_2; | 1108 | signal_levels |= DP_VOLTAGE_1_2; |
| 1117 | break; | 1109 | break; |
| 1118 | } | 1110 | } |
| 1119 | switch (preemphasis) { | 1111 | switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { |
| 1120 | case DP_TRAIN_PRE_EMPHASIS_0: | 1112 | case DP_TRAIN_PRE_EMPHASIS_0: |
| 1121 | default: | 1113 | default: |
| 1122 | signal_levels |= DP_PRE_EMPHASIS_0; | 1114 | signal_levels |= DP_PRE_EMPHASIS_0; |
| @@ -1203,18 +1195,6 @@ intel_channel_eq_ok(struct intel_dp *intel_dp) | |||
| 1203 | } | 1195 | } |
| 1204 | 1196 | ||
| 1205 | static bool | 1197 | static bool |
| 1206 | intel_dp_aux_handshake_required(struct intel_dp *intel_dp) | ||
| 1207 | { | ||
| 1208 | struct drm_device *dev = intel_dp->base.base.dev; | ||
| 1209 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1210 | |||
| 1211 | if (is_edp(intel_dp) && dev_priv->no_aux_handshake) | ||
| 1212 | return false; | ||
| 1213 | |||
| 1214 | return true; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | static bool | ||
| 1218 | intel_dp_set_link_train(struct intel_dp *intel_dp, | 1198 | intel_dp_set_link_train(struct intel_dp *intel_dp, |
| 1219 | uint32_t dp_reg_value, | 1199 | uint32_t dp_reg_value, |
| 1220 | uint8_t dp_train_pat) | 1200 | uint8_t dp_train_pat) |
| @@ -1226,9 +1206,6 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
| 1226 | I915_WRITE(intel_dp->output_reg, dp_reg_value); | 1206 | I915_WRITE(intel_dp->output_reg, dp_reg_value); |
| 1227 | POSTING_READ(intel_dp->output_reg); | 1207 | POSTING_READ(intel_dp->output_reg); |
| 1228 | 1208 | ||
| 1229 | if (!intel_dp_aux_handshake_required(intel_dp)) | ||
| 1230 | return true; | ||
| 1231 | |||
| 1232 | intel_dp_aux_native_write_1(intel_dp, | 1209 | intel_dp_aux_native_write_1(intel_dp, |
| 1233 | DP_TRAINING_PATTERN_SET, | 1210 | DP_TRAINING_PATTERN_SET, |
| 1234 | dp_train_pat); | 1211 | dp_train_pat); |
| @@ -1261,11 +1238,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
| 1261 | POSTING_READ(intel_dp->output_reg); | 1238 | POSTING_READ(intel_dp->output_reg); |
| 1262 | intel_wait_for_vblank(dev, intel_crtc->pipe); | 1239 | intel_wait_for_vblank(dev, intel_crtc->pipe); |
| 1263 | 1240 | ||
| 1264 | if (intel_dp_aux_handshake_required(intel_dp)) | 1241 | /* Write the link configuration data */ |
| 1265 | /* Write the link configuration data */ | 1242 | intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, |
| 1266 | intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, | 1243 | intel_dp->link_configuration, |
| 1267 | intel_dp->link_configuration, | 1244 | DP_LINK_CONFIGURATION_SIZE); |
| 1268 | DP_LINK_CONFIGURATION_SIZE); | ||
| 1269 | 1245 | ||
| 1270 | DP |= DP_PORT_EN; | 1246 | DP |= DP_PORT_EN; |
| 1271 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) | 1247 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) |
| @@ -1283,7 +1259,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
| 1283 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); | 1259 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); |
| 1284 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | 1260 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; |
| 1285 | } else { | 1261 | } else { |
| 1286 | signal_levels = intel_dp_signal_levels(intel_dp); | 1262 | signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); |
| 1287 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | 1263 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; |
| 1288 | } | 1264 | } |
| 1289 | 1265 | ||
| @@ -1297,37 +1273,33 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
| 1297 | break; | 1273 | break; |
| 1298 | /* Set training pattern 1 */ | 1274 | /* Set training pattern 1 */ |
| 1299 | 1275 | ||
| 1300 | udelay(500); | 1276 | udelay(100); |
| 1301 | if (intel_dp_aux_handshake_required(intel_dp)) { | 1277 | if (!intel_dp_get_link_status(intel_dp)) |
| 1302 | break; | 1278 | break; |
| 1303 | } else { | ||
| 1304 | if (!intel_dp_get_link_status(intel_dp)) | ||
| 1305 | break; | ||
| 1306 | 1279 | ||
| 1307 | if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { | 1280 | if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { |
| 1308 | clock_recovery = true; | 1281 | clock_recovery = true; |
| 1309 | break; | 1282 | break; |
| 1310 | } | 1283 | } |
| 1311 | 1284 | ||
| 1312 | /* Check to see if we've tried the max voltage */ | 1285 | /* Check to see if we've tried the max voltage */ |
| 1313 | for (i = 0; i < intel_dp->lane_count; i++) | 1286 | for (i = 0; i < intel_dp->lane_count; i++) |
| 1314 | if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) | 1287 | if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) |
| 1315 | break; | ||
| 1316 | if (i == intel_dp->lane_count) | ||
| 1317 | break; | 1288 | break; |
| 1289 | if (i == intel_dp->lane_count) | ||
| 1290 | break; | ||
| 1318 | 1291 | ||
| 1319 | /* Check to see if we've tried the same voltage 5 times */ | 1292 | /* Check to see if we've tried the same voltage 5 times */ |
| 1320 | if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { | 1293 | if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { |
| 1321 | ++tries; | 1294 | ++tries; |
| 1322 | if (tries == 5) | 1295 | if (tries == 5) |
| 1323 | break; | 1296 | break; |
| 1324 | } else | 1297 | } else |
| 1325 | tries = 0; | 1298 | tries = 0; |
| 1326 | voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; | 1299 | voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; |
| 1327 | 1300 | ||
| 1328 | /* Compute new intel_dp->train_set as requested by target */ | 1301 | /* Compute new intel_dp->train_set as requested by target */ |
| 1329 | intel_get_adjust_train(intel_dp); | 1302 | intel_get_adjust_train(intel_dp); |
| 1330 | } | ||
| 1331 | } | 1303 | } |
| 1332 | 1304 | ||
| 1333 | intel_dp->DP = DP; | 1305 | intel_dp->DP = DP; |
| @@ -1354,7 +1326,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
| 1354 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); | 1326 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); |
| 1355 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | 1327 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; |
| 1356 | } else { | 1328 | } else { |
| 1357 | signal_levels = intel_dp_signal_levels(intel_dp); | 1329 | signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); |
| 1358 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | 1330 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; |
| 1359 | } | 1331 | } |
| 1360 | 1332 | ||
| @@ -1368,28 +1340,24 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
| 1368 | DP_TRAINING_PATTERN_2)) | 1340 | DP_TRAINING_PATTERN_2)) |
| 1369 | break; | 1341 | break; |
| 1370 | 1342 | ||
| 1371 | udelay(500); | 1343 | udelay(400); |
| 1372 | 1344 | if (!intel_dp_get_link_status(intel_dp)) | |
| 1373 | if (!intel_dp_aux_handshake_required(intel_dp)) { | ||
| 1374 | break; | 1345 | break; |
| 1375 | } else { | ||
| 1376 | if (!intel_dp_get_link_status(intel_dp)) | ||
| 1377 | break; | ||
| 1378 | 1346 | ||
| 1379 | if (intel_channel_eq_ok(intel_dp)) { | 1347 | if (intel_channel_eq_ok(intel_dp)) { |
| 1380 | channel_eq = true; | 1348 | channel_eq = true; |
| 1381 | break; | 1349 | break; |
| 1382 | } | 1350 | } |
| 1383 | 1351 | ||
| 1384 | /* Try 5 times */ | 1352 | /* Try 5 times */ |
| 1385 | if (tries > 5) | 1353 | if (tries > 5) |
| 1386 | break; | 1354 | break; |
| 1387 | 1355 | ||
| 1388 | /* Compute new intel_dp->train_set as requested by target */ | 1356 | /* Compute new intel_dp->train_set as requested by target */ |
| 1389 | intel_get_adjust_train(intel_dp); | 1357 | intel_get_adjust_train(intel_dp); |
| 1390 | ++tries; | 1358 | ++tries; |
| 1391 | } | ||
| 1392 | } | 1359 | } |
| 1360 | |||
| 1393 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) | 1361 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) |
| 1394 | reg = DP | DP_LINK_TRAIN_OFF_CPT; | 1362 | reg = DP | DP_LINK_TRAIN_OFF_CPT; |
| 1395 | else | 1363 | else |
| @@ -1408,6 +1376,9 @@ intel_dp_link_down(struct intel_dp *intel_dp) | |||
| 1408 | struct drm_i915_private *dev_priv = dev->dev_private; | 1376 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 1409 | uint32_t DP = intel_dp->DP; | 1377 | uint32_t DP = intel_dp->DP; |
| 1410 | 1378 | ||
| 1379 | if ((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0) | ||
| 1380 | return; | ||
| 1381 | |||
| 1411 | DRM_DEBUG_KMS("\n"); | 1382 | DRM_DEBUG_KMS("\n"); |
| 1412 | 1383 | ||
| 1413 | if (is_edp(intel_dp)) { | 1384 | if (is_edp(intel_dp)) { |
| @@ -1430,6 +1401,28 @@ intel_dp_link_down(struct intel_dp *intel_dp) | |||
| 1430 | 1401 | ||
| 1431 | if (is_edp(intel_dp)) | 1402 | if (is_edp(intel_dp)) |
| 1432 | DP |= DP_LINK_TRAIN_OFF; | 1403 | DP |= DP_LINK_TRAIN_OFF; |
| 1404 | |||
| 1405 | if (!HAS_PCH_CPT(dev) && | ||
| 1406 | I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { | ||
| 1407 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc); | ||
| 1408 | /* Hardware workaround: leaving our transcoder select | ||
| 1409 | * set to transcoder B while it's off will prevent the | ||
| 1410 | * corresponding HDMI output on transcoder A. | ||
| 1411 | * | ||
| 1412 | * Combine this with another hardware workaround: | ||
| 1413 | * transcoder select bit can only be cleared while the | ||
| 1414 | * port is enabled. | ||
| 1415 | */ | ||
| 1416 | DP &= ~DP_PIPEB_SELECT; | ||
| 1417 | I915_WRITE(intel_dp->output_reg, DP); | ||
| 1418 | |||
| 1419 | /* Changes to enable or select take place the vblank | ||
| 1420 | * after being written. | ||
| 1421 | */ | ||
| 1422 | intel_wait_for_vblank(intel_dp->base.base.dev, | ||
| 1423 | intel_crtc->pipe); | ||
| 1424 | } | ||
| 1425 | |||
| 1433 | I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); | 1426 | I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); |
| 1434 | POSTING_READ(intel_dp->output_reg); | 1427 | POSTING_READ(intel_dp->output_reg); |
| 1435 | } | 1428 | } |
| @@ -1517,7 +1510,7 @@ g4x_dp_detect(struct intel_dp *intel_dp) | |||
| 1517 | status = connector_status_connected; | 1510 | status = connector_status_connected; |
| 1518 | } | 1511 | } |
| 1519 | 1512 | ||
| 1520 | return bit; | 1513 | return status; |
| 1521 | } | 1514 | } |
| 1522 | 1515 | ||
| 1523 | /** | 1516 | /** |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9af9f86a8765..e52c6125bb1f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -237,7 +237,7 @@ extern bool intel_sdvo_init(struct drm_device *dev, int output_device); | |||
| 237 | extern void intel_dvo_init(struct drm_device *dev); | 237 | extern void intel_dvo_init(struct drm_device *dev); |
| 238 | extern void intel_tv_init(struct drm_device *dev); | 238 | extern void intel_tv_init(struct drm_device *dev); |
| 239 | extern void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj); | 239 | extern void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj); |
| 240 | extern void intel_lvds_init(struct drm_device *dev); | 240 | extern bool intel_lvds_init(struct drm_device *dev); |
| 241 | extern void intel_dp_init(struct drm_device *dev, int dp_reg); | 241 | extern void intel_dp_init(struct drm_device *dev, int dp_reg); |
| 242 | void | 242 | void |
| 243 | intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | 243 | intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, |
| @@ -296,6 +296,7 @@ extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
| 296 | extern void intel_init_clock_gating(struct drm_device *dev); | 296 | extern void intel_init_clock_gating(struct drm_device *dev); |
| 297 | extern void ironlake_enable_drps(struct drm_device *dev); | 297 | extern void ironlake_enable_drps(struct drm_device *dev); |
| 298 | extern void ironlake_disable_drps(struct drm_device *dev); | 298 | extern void ironlake_disable_drps(struct drm_device *dev); |
| 299 | extern void intel_init_emon(struct drm_device *dev); | ||
| 299 | 300 | ||
| 300 | extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, | 301 | extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, |
| 301 | struct drm_gem_object *obj, | 302 | struct drm_gem_object *obj, |
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 2be4f728ed0c..3dba086e7eea 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
| @@ -160,7 +160,7 @@ intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin) | |||
| 160 | }; | 160 | }; |
| 161 | struct intel_gpio *gpio; | 161 | struct intel_gpio *gpio; |
| 162 | 162 | ||
| 163 | if (pin < 1 || pin > 7) | 163 | if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin]) |
| 164 | return NULL; | 164 | return NULL; |
| 165 | 165 | ||
| 166 | gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL); | 166 | gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL); |
| @@ -172,7 +172,8 @@ intel_gpio_create(struct drm_i915_private *dev_priv, u32 pin) | |||
| 172 | gpio->reg += PCH_GPIOA - GPIOA; | 172 | gpio->reg += PCH_GPIOA - GPIOA; |
| 173 | gpio->dev_priv = dev_priv; | 173 | gpio->dev_priv = dev_priv; |
| 174 | 174 | ||
| 175 | snprintf(gpio->adapter.name, I2C_NAME_SIZE, "GPIO%c", "?BACDEF?"[pin]); | 175 | snprintf(gpio->adapter.name, sizeof(gpio->adapter.name), |
| 176 | "i915 GPIO%c", "?BACDE?F"[pin]); | ||
| 176 | gpio->adapter.owner = THIS_MODULE; | 177 | gpio->adapter.owner = THIS_MODULE; |
| 177 | gpio->adapter.algo_data = &gpio->algo; | 178 | gpio->adapter.algo_data = &gpio->algo; |
| 178 | gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev; | 179 | gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev; |
| @@ -349,7 +350,7 @@ int intel_setup_gmbus(struct drm_device *dev) | |||
| 349 | "panel", | 350 | "panel", |
| 350 | "dpc", | 351 | "dpc", |
| 351 | "dpb", | 352 | "dpb", |
| 352 | "reserved" | 353 | "reserved", |
| 353 | "dpd", | 354 | "dpd", |
| 354 | }; | 355 | }; |
| 355 | struct drm_i915_private *dev_priv = dev->dev_private; | 356 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -366,8 +367,8 @@ int intel_setup_gmbus(struct drm_device *dev) | |||
| 366 | bus->adapter.owner = THIS_MODULE; | 367 | bus->adapter.owner = THIS_MODULE; |
| 367 | bus->adapter.class = I2C_CLASS_DDC; | 368 | bus->adapter.class = I2C_CLASS_DDC; |
| 368 | snprintf(bus->adapter.name, | 369 | snprintf(bus->adapter.name, |
| 369 | I2C_NAME_SIZE, | 370 | sizeof(bus->adapter.name), |
| 370 | "gmbus %s", | 371 | "i915 gmbus %s", |
| 371 | names[i]); | 372 | names[i]); |
| 372 | 373 | ||
| 373 | bus->adapter.dev.parent = &dev->pdev->dev; | 374 | bus->adapter.dev.parent = &dev->pdev->dev; |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f1a649990ea9..25bcedf386fd 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -68,7 +68,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector) | |||
| 68 | /** | 68 | /** |
| 69 | * Sets the power state for the panel. | 69 | * Sets the power state for the panel. |
| 70 | */ | 70 | */ |
| 71 | static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on) | 71 | static void intel_lvds_enable(struct intel_lvds *intel_lvds) |
| 72 | { | 72 | { |
| 73 | struct drm_device *dev = intel_lvds->base.base.dev; | 73 | struct drm_device *dev = intel_lvds->base.base.dev; |
| 74 | struct drm_i915_private *dev_priv = dev->dev_private; | 74 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -82,26 +82,61 @@ static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on) | |||
| 82 | lvds_reg = LVDS; | 82 | lvds_reg = LVDS; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | if (on) { | 85 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN); |
| 86 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN); | ||
| 87 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON); | ||
| 88 | intel_panel_set_backlight(dev, dev_priv->backlight_level); | ||
| 89 | } else { | ||
| 90 | dev_priv->backlight_level = intel_panel_get_backlight(dev); | ||
| 91 | |||
| 92 | intel_panel_set_backlight(dev, 0); | ||
| 93 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON); | ||
| 94 | 86 | ||
| 95 | if (intel_lvds->pfit_control) { | 87 | if (intel_lvds->pfit_dirty) { |
| 96 | if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) | 88 | /* |
| 97 | DRM_ERROR("timed out waiting for panel to power off\n"); | 89 | * Enable automatic panel scaling so that non-native modes |
| 98 | I915_WRITE(PFIT_CONTROL, 0); | 90 | * fill the screen. The panel fitter should only be |
| 99 | intel_lvds->pfit_control = 0; | 91 | * adjusted whilst the pipe is disabled, according to |
| 92 | * register description and PRM. | ||
| 93 | */ | ||
| 94 | DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n", | ||
| 95 | intel_lvds->pfit_control, | ||
| 96 | intel_lvds->pfit_pgm_ratios); | ||
| 97 | if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) { | ||
| 98 | DRM_ERROR("timed out waiting for panel to power off\n"); | ||
| 99 | } else { | ||
| 100 | I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios); | ||
| 101 | I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control); | ||
| 100 | intel_lvds->pfit_dirty = false; | 102 | intel_lvds->pfit_dirty = false; |
| 101 | } | 103 | } |
| 104 | } | ||
| 105 | |||
| 106 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON); | ||
| 107 | POSTING_READ(lvds_reg); | ||
| 108 | |||
| 109 | intel_panel_set_backlight(dev, dev_priv->backlight_level); | ||
| 110 | } | ||
| 111 | |||
| 112 | static void intel_lvds_disable(struct intel_lvds *intel_lvds) | ||
| 113 | { | ||
| 114 | struct drm_device *dev = intel_lvds->base.base.dev; | ||
| 115 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 116 | u32 ctl_reg, lvds_reg; | ||
| 117 | |||
| 118 | if (HAS_PCH_SPLIT(dev)) { | ||
| 119 | ctl_reg = PCH_PP_CONTROL; | ||
| 120 | lvds_reg = PCH_LVDS; | ||
| 121 | } else { | ||
| 122 | ctl_reg = PP_CONTROL; | ||
| 123 | lvds_reg = LVDS; | ||
| 124 | } | ||
| 125 | |||
| 126 | dev_priv->backlight_level = intel_panel_get_backlight(dev); | ||
| 127 | intel_panel_set_backlight(dev, 0); | ||
| 102 | 128 | ||
| 103 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN); | 129 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON); |
| 130 | |||
| 131 | if (intel_lvds->pfit_control) { | ||
| 132 | if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) | ||
| 133 | DRM_ERROR("timed out waiting for panel to power off\n"); | ||
| 134 | |||
| 135 | I915_WRITE(PFIT_CONTROL, 0); | ||
| 136 | intel_lvds->pfit_dirty = true; | ||
| 104 | } | 137 | } |
| 138 | |||
| 139 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN); | ||
| 105 | POSTING_READ(lvds_reg); | 140 | POSTING_READ(lvds_reg); |
| 106 | } | 141 | } |
| 107 | 142 | ||
| @@ -110,9 +145,9 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode) | |||
| 110 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); | 145 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); |
| 111 | 146 | ||
| 112 | if (mode == DRM_MODE_DPMS_ON) | 147 | if (mode == DRM_MODE_DPMS_ON) |
| 113 | intel_lvds_set_power(intel_lvds, true); | 148 | intel_lvds_enable(intel_lvds); |
| 114 | else | 149 | else |
| 115 | intel_lvds_set_power(intel_lvds, false); | 150 | intel_lvds_disable(intel_lvds); |
| 116 | 151 | ||
| 117 | /* XXX: We never power down the LVDS pairs. */ | 152 | /* XXX: We never power down the LVDS pairs. */ |
| 118 | } | 153 | } |
| @@ -411,43 +446,18 @@ static void intel_lvds_commit(struct drm_encoder *encoder) | |||
| 411 | /* Always do a full power on as we do not know what state | 446 | /* Always do a full power on as we do not know what state |
| 412 | * we were left in. | 447 | * we were left in. |
| 413 | */ | 448 | */ |
| 414 | intel_lvds_set_power(intel_lvds, true); | 449 | intel_lvds_enable(intel_lvds); |
| 415 | } | 450 | } |
| 416 | 451 | ||
| 417 | static void intel_lvds_mode_set(struct drm_encoder *encoder, | 452 | static void intel_lvds_mode_set(struct drm_encoder *encoder, |
| 418 | struct drm_display_mode *mode, | 453 | struct drm_display_mode *mode, |
| 419 | struct drm_display_mode *adjusted_mode) | 454 | struct drm_display_mode *adjusted_mode) |
| 420 | { | 455 | { |
| 421 | struct drm_device *dev = encoder->dev; | ||
| 422 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 423 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); | ||
| 424 | |||
| 425 | /* | 456 | /* |
| 426 | * The LVDS pin pair will already have been turned on in the | 457 | * The LVDS pin pair will already have been turned on in the |
| 427 | * intel_crtc_mode_set since it has a large impact on the DPLL | 458 | * intel_crtc_mode_set since it has a large impact on the DPLL |
| 428 | * settings. | 459 | * settings. |
| 429 | */ | 460 | */ |
| 430 | |||
| 431 | if (HAS_PCH_SPLIT(dev)) | ||
| 432 | return; | ||
| 433 | |||
| 434 | if (!intel_lvds->pfit_dirty) | ||
| 435 | return; | ||
| 436 | |||
| 437 | /* | ||
| 438 | * Enable automatic panel scaling so that non-native modes fill the | ||
| 439 | * screen. Should be enabled before the pipe is enabled, according to | ||
| 440 | * register description and PRM. | ||
| 441 | */ | ||
| 442 | DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n", | ||
| 443 | intel_lvds->pfit_control, | ||
| 444 | intel_lvds->pfit_pgm_ratios); | ||
| 445 | if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000)) | ||
| 446 | DRM_ERROR("timed out waiting for panel to power off\n"); | ||
| 447 | |||
| 448 | I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios); | ||
| 449 | I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control); | ||
| 450 | intel_lvds->pfit_dirty = false; | ||
| 451 | } | 461 | } |
| 452 | 462 | ||
| 453 | /** | 463 | /** |
| @@ -481,11 +491,8 @@ static int intel_lvds_get_modes(struct drm_connector *connector) | |||
| 481 | struct drm_device *dev = connector->dev; | 491 | struct drm_device *dev = connector->dev; |
| 482 | struct drm_display_mode *mode; | 492 | struct drm_display_mode *mode; |
| 483 | 493 | ||
| 484 | if (intel_lvds->edid) { | 494 | if (intel_lvds->edid) |
| 485 | drm_mode_connector_update_edid_property(connector, | ||
| 486 | intel_lvds->edid); | ||
| 487 | return drm_add_edid_modes(connector, intel_lvds->edid); | 495 | return drm_add_edid_modes(connector, intel_lvds->edid); |
| 488 | } | ||
| 489 | 496 | ||
| 490 | mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode); | 497 | mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode); |
| 491 | if (mode == 0) | 498 | if (mode == 0) |
| @@ -840,7 +847,7 @@ static bool intel_lvds_ddc_probe(struct drm_device *dev, u8 pin) | |||
| 840 | * Create the connector, register the LVDS DDC bus, and try to figure out what | 847 | * Create the connector, register the LVDS DDC bus, and try to figure out what |
| 841 | * modes we can display on the LVDS panel (if present). | 848 | * modes we can display on the LVDS panel (if present). |
| 842 | */ | 849 | */ |
| 843 | void intel_lvds_init(struct drm_device *dev) | 850 | bool intel_lvds_init(struct drm_device *dev) |
| 844 | { | 851 | { |
| 845 | struct drm_i915_private *dev_priv = dev->dev_private; | 852 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 846 | struct intel_lvds *intel_lvds; | 853 | struct intel_lvds *intel_lvds; |
| @@ -856,37 +863,37 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 856 | 863 | ||
| 857 | /* Skip init on machines we know falsely report LVDS */ | 864 | /* Skip init on machines we know falsely report LVDS */ |
| 858 | if (dmi_check_system(intel_no_lvds)) | 865 | if (dmi_check_system(intel_no_lvds)) |
| 859 | return; | 866 | return false; |
| 860 | 867 | ||
| 861 | pin = GMBUS_PORT_PANEL; | 868 | pin = GMBUS_PORT_PANEL; |
| 862 | if (!lvds_is_present_in_vbt(dev, &pin)) { | 869 | if (!lvds_is_present_in_vbt(dev, &pin)) { |
| 863 | DRM_DEBUG_KMS("LVDS is not present in VBT\n"); | 870 | DRM_DEBUG_KMS("LVDS is not present in VBT\n"); |
| 864 | return; | 871 | return false; |
| 865 | } | 872 | } |
| 866 | 873 | ||
| 867 | if (HAS_PCH_SPLIT(dev)) { | 874 | if (HAS_PCH_SPLIT(dev)) { |
| 868 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) | 875 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) |
| 869 | return; | 876 | return false; |
| 870 | if (dev_priv->edp.support) { | 877 | if (dev_priv->edp.support) { |
| 871 | DRM_DEBUG_KMS("disable LVDS for eDP support\n"); | 878 | DRM_DEBUG_KMS("disable LVDS for eDP support\n"); |
| 872 | return; | 879 | return false; |
| 873 | } | 880 | } |
| 874 | } | 881 | } |
| 875 | 882 | ||
| 876 | if (!intel_lvds_ddc_probe(dev, pin)) { | 883 | if (!intel_lvds_ddc_probe(dev, pin)) { |
| 877 | DRM_DEBUG_KMS("LVDS did not respond to DDC probe\n"); | 884 | DRM_DEBUG_KMS("LVDS did not respond to DDC probe\n"); |
| 878 | return; | 885 | return false; |
| 879 | } | 886 | } |
| 880 | 887 | ||
| 881 | intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL); | 888 | intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL); |
| 882 | if (!intel_lvds) { | 889 | if (!intel_lvds) { |
| 883 | return; | 890 | return false; |
| 884 | } | 891 | } |
| 885 | 892 | ||
| 886 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); | 893 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); |
| 887 | if (!intel_connector) { | 894 | if (!intel_connector) { |
| 888 | kfree(intel_lvds); | 895 | kfree(intel_lvds); |
| 889 | return; | 896 | return false; |
| 890 | } | 897 | } |
| 891 | 898 | ||
| 892 | if (!HAS_PCH_SPLIT(dev)) { | 899 | if (!HAS_PCH_SPLIT(dev)) { |
| @@ -939,7 +946,16 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 939 | */ | 946 | */ |
| 940 | intel_lvds->edid = drm_get_edid(connector, | 947 | intel_lvds->edid = drm_get_edid(connector, |
| 941 | &dev_priv->gmbus[pin].adapter); | 948 | &dev_priv->gmbus[pin].adapter); |
| 942 | 949 | if (intel_lvds->edid) { | |
| 950 | if (drm_add_edid_modes(connector, | ||
| 951 | intel_lvds->edid)) { | ||
| 952 | drm_mode_connector_update_edid_property(connector, | ||
| 953 | intel_lvds->edid); | ||
| 954 | } else { | ||
| 955 | kfree(intel_lvds->edid); | ||
| 956 | intel_lvds->edid = NULL; | ||
| 957 | } | ||
| 958 | } | ||
| 943 | if (!intel_lvds->edid) { | 959 | if (!intel_lvds->edid) { |
| 944 | /* Didn't get an EDID, so | 960 | /* Didn't get an EDID, so |
| 945 | * Set wide sync ranges so we get all modes | 961 | * Set wide sync ranges so we get all modes |
| @@ -1020,7 +1036,7 @@ out: | |||
| 1020 | /* keep the LVDS connector */ | 1036 | /* keep the LVDS connector */ |
| 1021 | dev_priv->int_lvds_connector = connector; | 1037 | dev_priv->int_lvds_connector = connector; |
| 1022 | drm_sysfs_connector_add(connector); | 1038 | drm_sysfs_connector_add(connector); |
| 1023 | return; | 1039 | return true; |
| 1024 | 1040 | ||
| 1025 | failed: | 1041 | failed: |
| 1026 | DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); | 1042 | DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); |
| @@ -1028,4 +1044,5 @@ failed: | |||
| 1028 | drm_encoder_cleanup(encoder); | 1044 | drm_encoder_cleanup(encoder); |
| 1029 | kfree(intel_lvds); | 1045 | kfree(intel_lvds); |
| 1030 | kfree(intel_connector); | 1046 | kfree(intel_connector); |
| 1047 | return false; | ||
| 1031 | } | 1048 | } |
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 917c7dc3cd6b..9b0d9a867aea 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c | |||
| @@ -512,6 +512,6 @@ int intel_opregion_setup(struct drm_device *dev) | |||
| 512 | return 0; | 512 | return 0; |
| 513 | 513 | ||
| 514 | err_out: | 514 | err_out: |
| 515 | iounmap(opregion->header); | 515 | iounmap(base); |
| 516 | return err; | 516 | return err; |
| 517 | } | 517 | } |
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index afb96d25219a..02ff0a481f47 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
| @@ -946,7 +946,9 @@ static int check_overlay_src(struct drm_device *dev, | |||
| 946 | { | 946 | { |
| 947 | int uv_hscale = uv_hsubsampling(rec->flags); | 947 | int uv_hscale = uv_hsubsampling(rec->flags); |
| 948 | int uv_vscale = uv_vsubsampling(rec->flags); | 948 | int uv_vscale = uv_vsubsampling(rec->flags); |
| 949 | u32 stride_mask, depth, tmp; | 949 | u32 stride_mask; |
| 950 | int depth; | ||
| 951 | u32 tmp; | ||
| 950 | 952 | ||
| 951 | /* check src dimensions */ | 953 | /* check src dimensions */ |
| 952 | if (IS_845G(dev) || IS_I830(dev)) { | 954 | if (IS_845G(dev) || IS_I830(dev)) { |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 09f2dc353ae2..89a65be8a3f3 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
| @@ -156,28 +156,30 @@ static int init_ring_common(struct drm_device *dev, | |||
| 156 | 156 | ||
| 157 | /* G45 ring initialization fails to reset head to zero */ | 157 | /* G45 ring initialization fails to reset head to zero */ |
| 158 | if (head != 0) { | 158 | if (head != 0) { |
| 159 | DRM_ERROR("%s head not reset to zero " | 159 | DRM_DEBUG_KMS("%s head not reset to zero " |
| 160 | "ctl %08x head %08x tail %08x start %08x\n", | 160 | "ctl %08x head %08x tail %08x start %08x\n", |
| 161 | ring->name, | 161 | ring->name, |
| 162 | I915_READ_CTL(ring), | 162 | I915_READ_CTL(ring), |
| 163 | I915_READ_HEAD(ring), | 163 | I915_READ_HEAD(ring), |
| 164 | I915_READ_TAIL(ring), | 164 | I915_READ_TAIL(ring), |
| 165 | I915_READ_START(ring)); | 165 | I915_READ_START(ring)); |
| 166 | 166 | ||
| 167 | I915_WRITE_HEAD(ring, 0); | 167 | I915_WRITE_HEAD(ring, 0); |
| 168 | 168 | ||
| 169 | DRM_ERROR("%s head forced to zero " | 169 | if (I915_READ_HEAD(ring) & HEAD_ADDR) { |
| 170 | "ctl %08x head %08x tail %08x start %08x\n", | 170 | DRM_ERROR("failed to set %s head to zero " |
| 171 | ring->name, | 171 | "ctl %08x head %08x tail %08x start %08x\n", |
| 172 | I915_READ_CTL(ring), | 172 | ring->name, |
| 173 | I915_READ_HEAD(ring), | 173 | I915_READ_CTL(ring), |
| 174 | I915_READ_TAIL(ring), | 174 | I915_READ_HEAD(ring), |
| 175 | I915_READ_START(ring)); | 175 | I915_READ_TAIL(ring), |
| 176 | I915_READ_START(ring)); | ||
| 177 | } | ||
| 176 | } | 178 | } |
| 177 | 179 | ||
| 178 | I915_WRITE_CTL(ring, | 180 | I915_WRITE_CTL(ring, |
| 179 | ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES) | 181 | ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES) |
| 180 | | RING_NO_REPORT | RING_VALID); | 182 | | RING_REPORT_64K | RING_VALID); |
| 181 | 183 | ||
| 182 | head = I915_READ_HEAD(ring) & HEAD_ADDR; | 184 | head = I915_READ_HEAD(ring) & HEAD_ADDR; |
| 183 | /* If the head is still not zero, the ring is dead */ | 185 | /* If the head is still not zero, the ring is dead */ |
| @@ -654,6 +656,10 @@ void intel_cleanup_ring_buffer(struct drm_device *dev, | |||
| 654 | i915_gem_object_unpin(ring->gem_object); | 656 | i915_gem_object_unpin(ring->gem_object); |
| 655 | drm_gem_object_unreference(ring->gem_object); | 657 | drm_gem_object_unreference(ring->gem_object); |
| 656 | ring->gem_object = NULL; | 658 | ring->gem_object = NULL; |
| 659 | |||
| 660 | if (ring->cleanup) | ||
| 661 | ring->cleanup(ring); | ||
| 662 | |||
| 657 | cleanup_status_page(dev, ring); | 663 | cleanup_status_page(dev, ring); |
| 658 | } | 664 | } |
| 659 | 665 | ||
| @@ -688,6 +694,17 @@ int intel_wait_ring_buffer(struct drm_device *dev, | |||
| 688 | { | 694 | { |
| 689 | unsigned long end; | 695 | unsigned long end; |
| 690 | drm_i915_private_t *dev_priv = dev->dev_private; | 696 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 697 | u32 head; | ||
| 698 | |||
| 699 | head = intel_read_status_page(ring, 4); | ||
| 700 | if (head) { | ||
| 701 | ring->head = head & HEAD_ADDR; | ||
| 702 | ring->space = ring->head - (ring->tail + 8); | ||
| 703 | if (ring->space < 0) | ||
| 704 | ring->space += ring->size; | ||
| 705 | if (ring->space >= n) | ||
| 706 | return 0; | ||
| 707 | } | ||
| 691 | 708 | ||
| 692 | trace_i915_ring_wait_begin (dev); | 709 | trace_i915_ring_wait_begin (dev); |
| 693 | end = jiffies + 3 * HZ; | 710 | end = jiffies + 3 * HZ; |
| @@ -854,19 +871,125 @@ blt_ring_put_user_irq(struct drm_device *dev, | |||
| 854 | /* do nothing */ | 871 | /* do nothing */ |
| 855 | } | 872 | } |
| 856 | 873 | ||
| 874 | |||
| 875 | /* Workaround for some stepping of SNB, | ||
| 876 | * each time when BLT engine ring tail moved, | ||
| 877 | * the first command in the ring to be parsed | ||
| 878 | * should be MI_BATCH_BUFFER_START | ||
| 879 | */ | ||
| 880 | #define NEED_BLT_WORKAROUND(dev) \ | ||
| 881 | (IS_GEN6(dev) && (dev->pdev->revision < 8)) | ||
| 882 | |||
| 883 | static inline struct drm_i915_gem_object * | ||
| 884 | to_blt_workaround(struct intel_ring_buffer *ring) | ||
| 885 | { | ||
| 886 | return ring->private; | ||
| 887 | } | ||
| 888 | |||
| 889 | static int blt_ring_init(struct drm_device *dev, | ||
| 890 | struct intel_ring_buffer *ring) | ||
| 891 | { | ||
| 892 | if (NEED_BLT_WORKAROUND(dev)) { | ||
| 893 | struct drm_i915_gem_object *obj; | ||
| 894 | u32 __iomem *ptr; | ||
| 895 | int ret; | ||
| 896 | |||
| 897 | obj = to_intel_bo(i915_gem_alloc_object(dev, 4096)); | ||
| 898 | if (obj == NULL) | ||
| 899 | return -ENOMEM; | ||
| 900 | |||
| 901 | ret = i915_gem_object_pin(&obj->base, 4096); | ||
| 902 | if (ret) { | ||
| 903 | drm_gem_object_unreference(&obj->base); | ||
| 904 | return ret; | ||
| 905 | } | ||
| 906 | |||
| 907 | ptr = kmap(obj->pages[0]); | ||
| 908 | iowrite32(MI_BATCH_BUFFER_END, ptr); | ||
| 909 | iowrite32(MI_NOOP, ptr+1); | ||
| 910 | kunmap(obj->pages[0]); | ||
| 911 | |||
| 912 | ret = i915_gem_object_set_to_gtt_domain(&obj->base, false); | ||
| 913 | if (ret) { | ||
| 914 | i915_gem_object_unpin(&obj->base); | ||
| 915 | drm_gem_object_unreference(&obj->base); | ||
| 916 | return ret; | ||
| 917 | } | ||
| 918 | |||
| 919 | ring->private = obj; | ||
| 920 | } | ||
| 921 | |||
| 922 | return init_ring_common(dev, ring); | ||
| 923 | } | ||
| 924 | |||
| 925 | static void blt_ring_begin(struct drm_device *dev, | ||
| 926 | struct intel_ring_buffer *ring, | ||
| 927 | int num_dwords) | ||
| 928 | { | ||
| 929 | if (ring->private) { | ||
| 930 | intel_ring_begin(dev, ring, num_dwords+2); | ||
| 931 | intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START); | ||
| 932 | intel_ring_emit(dev, ring, to_blt_workaround(ring)->gtt_offset); | ||
| 933 | } else | ||
| 934 | intel_ring_begin(dev, ring, 4); | ||
| 935 | } | ||
| 936 | |||
| 937 | static void blt_ring_flush(struct drm_device *dev, | ||
| 938 | struct intel_ring_buffer *ring, | ||
| 939 | u32 invalidate_domains, | ||
| 940 | u32 flush_domains) | ||
| 941 | { | ||
| 942 | blt_ring_begin(dev, ring, 4); | ||
| 943 | intel_ring_emit(dev, ring, MI_FLUSH_DW); | ||
| 944 | intel_ring_emit(dev, ring, 0); | ||
| 945 | intel_ring_emit(dev, ring, 0); | ||
| 946 | intel_ring_emit(dev, ring, 0); | ||
| 947 | intel_ring_advance(dev, ring); | ||
| 948 | } | ||
| 949 | |||
| 950 | static u32 | ||
| 951 | blt_ring_add_request(struct drm_device *dev, | ||
| 952 | struct intel_ring_buffer *ring, | ||
| 953 | u32 flush_domains) | ||
| 954 | { | ||
| 955 | u32 seqno = i915_gem_get_seqno(dev); | ||
| 956 | |||
| 957 | blt_ring_begin(dev, ring, 4); | ||
| 958 | intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX); | ||
| 959 | intel_ring_emit(dev, ring, | ||
| 960 | I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); | ||
| 961 | intel_ring_emit(dev, ring, seqno); | ||
| 962 | intel_ring_emit(dev, ring, MI_USER_INTERRUPT); | ||
| 963 | intel_ring_advance(dev, ring); | ||
| 964 | |||
| 965 | DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno); | ||
| 966 | return seqno; | ||
| 967 | } | ||
| 968 | |||
| 969 | static void blt_ring_cleanup(struct intel_ring_buffer *ring) | ||
| 970 | { | ||
| 971 | if (!ring->private) | ||
| 972 | return; | ||
| 973 | |||
| 974 | i915_gem_object_unpin(ring->private); | ||
| 975 | drm_gem_object_unreference(ring->private); | ||
| 976 | ring->private = NULL; | ||
| 977 | } | ||
| 978 | |||
| 857 | static const struct intel_ring_buffer gen6_blt_ring = { | 979 | static const struct intel_ring_buffer gen6_blt_ring = { |
| 858 | .name = "blt ring", | 980 | .name = "blt ring", |
| 859 | .id = RING_BLT, | 981 | .id = RING_BLT, |
| 860 | .mmio_base = BLT_RING_BASE, | 982 | .mmio_base = BLT_RING_BASE, |
| 861 | .size = 32 * PAGE_SIZE, | 983 | .size = 32 * PAGE_SIZE, |
| 862 | .init = init_ring_common, | 984 | .init = blt_ring_init, |
| 863 | .write_tail = ring_write_tail, | 985 | .write_tail = ring_write_tail, |
| 864 | .flush = gen6_ring_flush, | 986 | .flush = blt_ring_flush, |
| 865 | .add_request = ring_add_request, | 987 | .add_request = blt_ring_add_request, |
| 866 | .get_seqno = ring_status_page_get_seqno, | 988 | .get_seqno = ring_status_page_get_seqno, |
| 867 | .user_irq_get = blt_ring_get_user_irq, | 989 | .user_irq_get = blt_ring_get_user_irq, |
| 868 | .user_irq_put = blt_ring_put_user_irq, | 990 | .user_irq_put = blt_ring_put_user_irq, |
| 869 | .dispatch_gem_execbuffer = gen6_ring_dispatch_gem_execbuffer, | 991 | .dispatch_gem_execbuffer = gen6_ring_dispatch_gem_execbuffer, |
| 992 | .cleanup = blt_ring_cleanup, | ||
| 870 | }; | 993 | }; |
| 871 | 994 | ||
| 872 | int intel_init_render_ring_buffer(struct drm_device *dev) | 995 | int intel_init_render_ring_buffer(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index a05aff0e5764..3126c2681983 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
| @@ -63,6 +63,7 @@ struct intel_ring_buffer { | |||
| 63 | struct drm_i915_gem_execbuffer2 *exec, | 63 | struct drm_i915_gem_execbuffer2 *exec, |
| 64 | struct drm_clip_rect *cliprects, | 64 | struct drm_clip_rect *cliprects, |
| 65 | uint64_t exec_offset); | 65 | uint64_t exec_offset); |
| 66 | void (*cleanup)(struct intel_ring_buffer *ring); | ||
| 66 | 67 | ||
| 67 | /** | 68 | /** |
| 68 | * List of objects currently involved in rendering from the | 69 | * List of objects currently involved in rendering from the |
| @@ -98,6 +99,8 @@ struct intel_ring_buffer { | |||
| 98 | 99 | ||
| 99 | wait_queue_head_t irq_queue; | 100 | wait_queue_head_t irq_queue; |
| 100 | drm_local_map_t map; | 101 | drm_local_map_t map; |
| 102 | |||
| 103 | void *private; | ||
| 101 | }; | 104 | }; |
| 102 | 105 | ||
| 103 | static inline u32 | 106 | static inline u32 |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index de158b76bcd5..d97e6cb52d34 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -107,7 +107,8 @@ struct intel_sdvo { | |||
| 107 | * This is set if we treat the device as HDMI, instead of DVI. | 107 | * This is set if we treat the device as HDMI, instead of DVI. |
| 108 | */ | 108 | */ |
| 109 | bool is_hdmi; | 109 | bool is_hdmi; |
| 110 | bool has_audio; | 110 | bool has_hdmi_monitor; |
| 111 | bool has_hdmi_audio; | ||
| 111 | 112 | ||
| 112 | /** | 113 | /** |
| 113 | * This is set if we detect output of sdvo device as LVDS and | 114 | * This is set if we detect output of sdvo device as LVDS and |
| @@ -1023,7 +1024,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1023 | if (!intel_sdvo_set_target_input(intel_sdvo)) | 1024 | if (!intel_sdvo_set_target_input(intel_sdvo)) |
| 1024 | return; | 1025 | return; |
| 1025 | 1026 | ||
| 1026 | if (intel_sdvo->is_hdmi && | 1027 | if (intel_sdvo->has_hdmi_monitor && |
| 1027 | !intel_sdvo_set_avi_infoframe(intel_sdvo)) | 1028 | !intel_sdvo_set_avi_infoframe(intel_sdvo)) |
| 1028 | return; | 1029 | return; |
| 1029 | 1030 | ||
| @@ -1063,7 +1064,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1063 | } | 1064 | } |
| 1064 | if (intel_crtc->pipe == 1) | 1065 | if (intel_crtc->pipe == 1) |
| 1065 | sdvox |= SDVO_PIPE_B_SELECT; | 1066 | sdvox |= SDVO_PIPE_B_SELECT; |
| 1066 | if (intel_sdvo->has_audio) | 1067 | if (intel_sdvo->has_hdmi_audio) |
| 1067 | sdvox |= SDVO_AUDIO_ENABLE; | 1068 | sdvox |= SDVO_AUDIO_ENABLE; |
| 1068 | 1069 | ||
| 1069 | if (INTEL_INFO(dev)->gen >= 4) { | 1070 | if (INTEL_INFO(dev)->gen >= 4) { |
| @@ -1295,55 +1296,14 @@ intel_sdvo_get_edid(struct drm_connector *connector) | |||
| 1295 | return drm_get_edid(connector, &sdvo->ddc); | 1296 | return drm_get_edid(connector, &sdvo->ddc); |
| 1296 | } | 1297 | } |
| 1297 | 1298 | ||
| 1298 | static struct drm_connector * | ||
| 1299 | intel_find_analog_connector(struct drm_device *dev) | ||
| 1300 | { | ||
| 1301 | struct drm_connector *connector; | ||
| 1302 | struct intel_sdvo *encoder; | ||
| 1303 | |||
| 1304 | list_for_each_entry(encoder, | ||
| 1305 | &dev->mode_config.encoder_list, | ||
| 1306 | base.base.head) { | ||
| 1307 | if (encoder->base.type == INTEL_OUTPUT_ANALOG) { | ||
| 1308 | list_for_each_entry(connector, | ||
| 1309 | &dev->mode_config.connector_list, | ||
| 1310 | head) { | ||
| 1311 | if (&encoder->base == | ||
| 1312 | intel_attached_encoder(connector)) | ||
| 1313 | return connector; | ||
| 1314 | } | ||
| 1315 | } | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | return NULL; | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | static int | ||
| 1322 | intel_analog_is_connected(struct drm_device *dev) | ||
| 1323 | { | ||
| 1324 | struct drm_connector *analog_connector; | ||
| 1325 | |||
| 1326 | analog_connector = intel_find_analog_connector(dev); | ||
| 1327 | if (!analog_connector) | ||
| 1328 | return false; | ||
| 1329 | |||
| 1330 | if (analog_connector->funcs->detect(analog_connector, false) == | ||
| 1331 | connector_status_disconnected) | ||
| 1332 | return false; | ||
| 1333 | |||
| 1334 | return true; | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | /* Mac mini hack -- use the same DDC as the analog connector */ | 1299 | /* Mac mini hack -- use the same DDC as the analog connector */ |
| 1338 | static struct edid * | 1300 | static struct edid * |
| 1339 | intel_sdvo_get_analog_edid(struct drm_connector *connector) | 1301 | intel_sdvo_get_analog_edid(struct drm_connector *connector) |
| 1340 | { | 1302 | { |
| 1341 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | 1303 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
| 1342 | 1304 | ||
| 1343 | if (!intel_analog_is_connected(connector->dev)) | 1305 | return drm_get_edid(connector, |
| 1344 | return NULL; | 1306 | &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); |
| 1345 | |||
| 1346 | return drm_get_edid(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); | ||
| 1347 | } | 1307 | } |
| 1348 | 1308 | ||
| 1349 | enum drm_connector_status | 1309 | enum drm_connector_status |
| @@ -1388,8 +1348,10 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
| 1388 | /* DDC bus is shared, match EDID to connector type */ | 1348 | /* DDC bus is shared, match EDID to connector type */ |
| 1389 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { | 1349 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
| 1390 | status = connector_status_connected; | 1350 | status = connector_status_connected; |
| 1391 | intel_sdvo->is_hdmi = drm_detect_hdmi_monitor(edid); | 1351 | if (intel_sdvo->is_hdmi) { |
| 1392 | intel_sdvo->has_audio = drm_detect_monitor_audio(edid); | 1352 | intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid); |
| 1353 | intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid); | ||
| 1354 | } | ||
| 1393 | } | 1355 | } |
| 1394 | connector->display_info.raw_edid = NULL; | 1356 | connector->display_info.raw_edid = NULL; |
| 1395 | kfree(edid); | 1357 | kfree(edid); |
| @@ -1398,7 +1360,7 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
| 1398 | if (status == connector_status_connected) { | 1360 | if (status == connector_status_connected) { |
| 1399 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); | 1361 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); |
| 1400 | if (intel_sdvo_connector->force_audio) | 1362 | if (intel_sdvo_connector->force_audio) |
| 1401 | intel_sdvo->has_audio = intel_sdvo_connector->force_audio > 0; | 1363 | intel_sdvo->has_hdmi_audio = intel_sdvo_connector->force_audio > 0; |
| 1402 | } | 1364 | } |
| 1403 | 1365 | ||
| 1404 | return status; | 1366 | return status; |
| @@ -1415,10 +1377,12 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) | |||
| 1415 | if (!intel_sdvo_write_cmd(intel_sdvo, | 1377 | if (!intel_sdvo_write_cmd(intel_sdvo, |
| 1416 | SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0)) | 1378 | SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0)) |
| 1417 | return connector_status_unknown; | 1379 | return connector_status_unknown; |
| 1418 | if (intel_sdvo->is_tv) { | 1380 | |
| 1419 | /* add 30ms delay when the output type is SDVO-TV */ | 1381 | /* add 30ms delay when the output type might be TV */ |
| 1382 | if (intel_sdvo->caps.output_flags & | ||
| 1383 | (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_CVBS0)) | ||
| 1420 | mdelay(30); | 1384 | mdelay(30); |
| 1421 | } | 1385 | |
| 1422 | if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) | 1386 | if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) |
| 1423 | return connector_status_unknown; | 1387 | return connector_status_unknown; |
| 1424 | 1388 | ||
| @@ -1472,8 +1436,10 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) | |||
| 1472 | edid = intel_sdvo_get_analog_edid(connector); | 1436 | edid = intel_sdvo_get_analog_edid(connector); |
| 1473 | 1437 | ||
| 1474 | if (edid != NULL) { | 1438 | if (edid != NULL) { |
| 1475 | drm_mode_connector_update_edid_property(connector, edid); | 1439 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
| 1476 | drm_add_edid_modes(connector, edid); | 1440 | drm_mode_connector_update_edid_property(connector, edid); |
| 1441 | drm_add_edid_modes(connector, edid); | ||
| 1442 | } | ||
| 1477 | connector->display_info.raw_edid = NULL; | 1443 | connector->display_info.raw_edid = NULL; |
| 1478 | kfree(edid); | 1444 | kfree(edid); |
| 1479 | } | 1445 | } |
| @@ -1713,12 +1679,12 @@ intel_sdvo_set_property(struct drm_connector *connector, | |||
| 1713 | 1679 | ||
| 1714 | intel_sdvo_connector->force_audio = val; | 1680 | intel_sdvo_connector->force_audio = val; |
| 1715 | 1681 | ||
| 1716 | if (val > 0 && intel_sdvo->has_audio) | 1682 | if (val > 0 && intel_sdvo->has_hdmi_audio) |
| 1717 | return 0; | 1683 | return 0; |
| 1718 | if (val < 0 && !intel_sdvo->has_audio) | 1684 | if (val < 0 && !intel_sdvo->has_hdmi_audio) |
| 1719 | return 0; | 1685 | return 0; |
| 1720 | 1686 | ||
| 1721 | intel_sdvo->has_audio = val > 0; | 1687 | intel_sdvo->has_hdmi_audio = val > 0; |
| 1722 | goto done; | 1688 | goto done; |
| 1723 | } | 1689 | } |
| 1724 | 1690 | ||
| @@ -2070,6 +2036,8 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | |||
| 2070 | intel_sdvo_set_colorimetry(intel_sdvo, | 2036 | intel_sdvo_set_colorimetry(intel_sdvo, |
| 2071 | SDVO_COLORIMETRY_RGB256); | 2037 | SDVO_COLORIMETRY_RGB256); |
| 2072 | connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; | 2038 | connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; |
| 2039 | |||
| 2040 | intel_sdvo_add_hdmi_properties(intel_sdvo_connector); | ||
| 2073 | intel_sdvo->is_hdmi = true; | 2041 | intel_sdvo->is_hdmi = true; |
| 2074 | } | 2042 | } |
| 2075 | intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | | 2043 | intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | |
| @@ -2077,8 +2045,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | |||
| 2077 | 2045 | ||
| 2078 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); | 2046 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); |
| 2079 | 2047 | ||
| 2080 | intel_sdvo_add_hdmi_properties(intel_sdvo_connector); | ||
| 2081 | |||
| 2082 | return true; | 2048 | return true; |
| 2083 | } | 2049 | } |
| 2084 | 2050 | ||
