diff options
46 files changed, 880 insertions, 397 deletions
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 0761a03cdbb2..2bf9670ba29b 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
| @@ -184,19 +184,27 @@ EXPORT_SYMBOL(drm_mm_get_block_generic); | |||
| 184 | * -ENOSPC if no suitable free area is available. The preallocated memory node | 184 | * -ENOSPC if no suitable free area is available. The preallocated memory node |
| 185 | * must be cleared. | 185 | * must be cleared. |
| 186 | */ | 186 | */ |
| 187 | int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, | 187 | int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node, |
| 188 | unsigned long size, unsigned alignment) | 188 | unsigned long size, unsigned alignment, |
| 189 | unsigned long color) | ||
| 189 | { | 190 | { |
| 190 | struct drm_mm_node *hole_node; | 191 | struct drm_mm_node *hole_node; |
| 191 | 192 | ||
| 192 | hole_node = drm_mm_search_free(mm, size, alignment, false); | 193 | hole_node = drm_mm_search_free_generic(mm, size, alignment, |
| 194 | color, 0); | ||
| 193 | if (!hole_node) | 195 | if (!hole_node) |
| 194 | return -ENOSPC; | 196 | return -ENOSPC; |
| 195 | 197 | ||
| 196 | drm_mm_insert_helper(hole_node, node, size, alignment, 0); | 198 | drm_mm_insert_helper(hole_node, node, size, alignment, color); |
| 197 | |||
| 198 | return 0; | 199 | return 0; |
| 199 | } | 200 | } |
| 201 | EXPORT_SYMBOL(drm_mm_insert_node_generic); | ||
| 202 | |||
| 203 | int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, | ||
| 204 | unsigned long size, unsigned alignment) | ||
| 205 | { | ||
| 206 | return drm_mm_insert_node_generic(mm, node, size, alignment, 0); | ||
| 207 | } | ||
| 200 | EXPORT_SYMBOL(drm_mm_insert_node); | 208 | EXPORT_SYMBOL(drm_mm_insert_node); |
| 201 | 209 | ||
| 202 | static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, | 210 | static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, |
| @@ -275,22 +283,31 @@ EXPORT_SYMBOL(drm_mm_get_block_range_generic); | |||
| 275 | * -ENOSPC if no suitable free area is available. This is for range | 283 | * -ENOSPC if no suitable free area is available. This is for range |
| 276 | * restricted allocations. The preallocated memory node must be cleared. | 284 | * restricted allocations. The preallocated memory node must be cleared. |
| 277 | */ | 285 | */ |
| 278 | int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node, | 286 | int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node, |
| 279 | unsigned long size, unsigned alignment, | 287 | unsigned long size, unsigned alignment, unsigned long color, |
| 280 | unsigned long start, unsigned long end) | 288 | unsigned long start, unsigned long end) |
| 281 | { | 289 | { |
| 282 | struct drm_mm_node *hole_node; | 290 | struct drm_mm_node *hole_node; |
| 283 | 291 | ||
| 284 | hole_node = drm_mm_search_free_in_range(mm, size, alignment, | 292 | hole_node = drm_mm_search_free_in_range_generic(mm, |
| 285 | start, end, false); | 293 | size, alignment, color, |
| 294 | start, end, 0); | ||
| 286 | if (!hole_node) | 295 | if (!hole_node) |
| 287 | return -ENOSPC; | 296 | return -ENOSPC; |
| 288 | 297 | ||
| 289 | drm_mm_insert_helper_range(hole_node, node, size, alignment, 0, | 298 | drm_mm_insert_helper_range(hole_node, node, |
| 299 | size, alignment, color, | ||
| 290 | start, end); | 300 | start, end); |
| 291 | |||
| 292 | return 0; | 301 | return 0; |
| 293 | } | 302 | } |
| 303 | EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic); | ||
| 304 | |||
| 305 | int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node, | ||
| 306 | unsigned long size, unsigned alignment, | ||
| 307 | unsigned long start, unsigned long end) | ||
| 308 | { | ||
| 309 | return drm_mm_insert_node_in_range_generic(mm, node, size, alignment, 0, start, end); | ||
| 310 | } | ||
| 294 | EXPORT_SYMBOL(drm_mm_insert_node_in_range); | 311 | EXPORT_SYMBOL(drm_mm_insert_node_in_range); |
| 295 | 312 | ||
| 296 | /** | 313 | /** |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 8f63cd5de4b4..99daa896105d 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -989,6 +989,9 @@ static int i915_getparam(struct drm_device *dev, void *data, | |||
| 989 | case I915_PARAM_HAS_SECURE_BATCHES: | 989 | case I915_PARAM_HAS_SECURE_BATCHES: |
| 990 | value = capable(CAP_SYS_ADMIN); | 990 | value = capable(CAP_SYS_ADMIN); |
| 991 | break; | 991 | break; |
| 992 | case I915_PARAM_HAS_PINNED_BATCHES: | ||
| 993 | value = 1; | ||
| 994 | break; | ||
| 992 | default: | 995 | default: |
| 993 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", | 996 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", |
| 994 | param->param); | 997 | param->param); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 557843dd4b2e..ed3059575576 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -780,6 +780,7 @@ typedef struct drm_i915_private { | |||
| 780 | struct i915_hw_ppgtt *aliasing_ppgtt; | 780 | struct i915_hw_ppgtt *aliasing_ppgtt; |
| 781 | 781 | ||
| 782 | struct shrinker inactive_shrinker; | 782 | struct shrinker inactive_shrinker; |
| 783 | bool shrinker_no_lock_stealing; | ||
| 783 | 784 | ||
| 784 | /** | 785 | /** |
| 785 | * List of objects currently involved in rendering. | 786 | * List of objects currently involved in rendering. |
| @@ -1100,6 +1101,7 @@ struct drm_i915_gem_object { | |||
| 1100 | */ | 1101 | */ |
| 1101 | atomic_t pending_flip; | 1102 | atomic_t pending_flip; |
| 1102 | }; | 1103 | }; |
| 1104 | #define to_gem_object(obj) (&((struct drm_i915_gem_object *)(obj))->base) | ||
| 1103 | 1105 | ||
| 1104 | #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base) | 1106 | #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base) |
| 1105 | 1107 | ||
| @@ -1166,6 +1168,9 @@ struct drm_i915_file_private { | |||
| 1166 | #define IS_IVB_GT1(dev) ((dev)->pci_device == 0x0156 || \ | 1168 | #define IS_IVB_GT1(dev) ((dev)->pci_device == 0x0156 || \ |
| 1167 | (dev)->pci_device == 0x0152 || \ | 1169 | (dev)->pci_device == 0x0152 || \ |
| 1168 | (dev)->pci_device == 0x015a) | 1170 | (dev)->pci_device == 0x015a) |
| 1171 | #define IS_SNB_GT1(dev) ((dev)->pci_device == 0x0102 || \ | ||
| 1172 | (dev)->pci_device == 0x0106 || \ | ||
| 1173 | (dev)->pci_device == 0x010A) | ||
| 1169 | #define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview) | 1174 | #define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview) |
| 1170 | #define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell) | 1175 | #define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell) |
| 1171 | #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) | 1176 | #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) |
| @@ -1196,6 +1201,9 @@ struct drm_i915_file_private { | |||
| 1196 | #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) | 1201 | #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) |
| 1197 | #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) | 1202 | #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) |
| 1198 | 1203 | ||
| 1204 | /* Early gen2 have a totally busted CS tlb and require pinned batches. */ | ||
| 1205 | #define HAS_BROKEN_CS_TLB(dev) (IS_I830(dev) || IS_845G(dev)) | ||
| 1206 | |||
| 1199 | /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte | 1207 | /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte |
| 1200 | * rows, which changed the alignment requirements and fence programming. | 1208 | * rows, which changed the alignment requirements and fence programming. |
| 1201 | */ | 1209 | */ |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 742206e45103..da3c82e301b1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -1517,9 +1517,11 @@ static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj) | |||
| 1517 | if (obj->base.map_list.map) | 1517 | if (obj->base.map_list.map) |
| 1518 | return 0; | 1518 | return 0; |
| 1519 | 1519 | ||
| 1520 | dev_priv->mm.shrinker_no_lock_stealing = true; | ||
| 1521 | |||
| 1520 | ret = drm_gem_create_mmap_offset(&obj->base); | 1522 | ret = drm_gem_create_mmap_offset(&obj->base); |
| 1521 | if (ret != -ENOSPC) | 1523 | if (ret != -ENOSPC) |
| 1522 | return ret; | 1524 | goto out; |
| 1523 | 1525 | ||
| 1524 | /* Badly fragmented mmap space? The only way we can recover | 1526 | /* Badly fragmented mmap space? The only way we can recover |
| 1525 | * space is by destroying unwanted objects. We can't randomly release | 1527 | * space is by destroying unwanted objects. We can't randomly release |
| @@ -1531,10 +1533,14 @@ static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj) | |||
| 1531 | i915_gem_purge(dev_priv, obj->base.size >> PAGE_SHIFT); | 1533 | i915_gem_purge(dev_priv, obj->base.size >> PAGE_SHIFT); |
| 1532 | ret = drm_gem_create_mmap_offset(&obj->base); | 1534 | ret = drm_gem_create_mmap_offset(&obj->base); |
| 1533 | if (ret != -ENOSPC) | 1535 | if (ret != -ENOSPC) |
| 1534 | return ret; | 1536 | goto out; |
| 1535 | 1537 | ||
| 1536 | i915_gem_shrink_all(dev_priv); | 1538 | i915_gem_shrink_all(dev_priv); |
| 1537 | return drm_gem_create_mmap_offset(&obj->base); | 1539 | ret = drm_gem_create_mmap_offset(&obj->base); |
| 1540 | out: | ||
| 1541 | dev_priv->mm.shrinker_no_lock_stealing = false; | ||
| 1542 | |||
| 1543 | return ret; | ||
| 1538 | } | 1544 | } |
| 1539 | 1545 | ||
| 1540 | static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj) | 1546 | static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj) |
| @@ -2890,7 +2896,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, | |||
| 2890 | { | 2896 | { |
| 2891 | struct drm_device *dev = obj->base.dev; | 2897 | struct drm_device *dev = obj->base.dev; |
| 2892 | drm_i915_private_t *dev_priv = dev->dev_private; | 2898 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 2893 | struct drm_mm_node *free_space; | 2899 | struct drm_mm_node *node; |
| 2894 | u32 size, fence_size, fence_alignment, unfenced_alignment; | 2900 | u32 size, fence_size, fence_alignment, unfenced_alignment; |
| 2895 | bool mappable, fenceable; | 2901 | bool mappable, fenceable; |
| 2896 | int ret; | 2902 | int ret; |
| @@ -2936,66 +2942,54 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, | |||
| 2936 | 2942 | ||
| 2937 | i915_gem_object_pin_pages(obj); | 2943 | i915_gem_object_pin_pages(obj); |
| 2938 | 2944 | ||
| 2945 | node = kzalloc(sizeof(*node), GFP_KERNEL); | ||
| 2946 | if (node == NULL) { | ||
| 2947 | i915_gem_object_unpin_pages(obj); | ||
| 2948 | return -ENOMEM; | ||
| 2949 | } | ||
| 2950 | |||
| 2939 | search_free: | 2951 | search_free: |
| 2940 | if (map_and_fenceable) | 2952 | if (map_and_fenceable) |
| 2941 | free_space = drm_mm_search_free_in_range_color(&dev_priv->mm.gtt_space, | 2953 | ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node, |
| 2942 | size, alignment, obj->cache_level, | 2954 | size, alignment, obj->cache_level, |
| 2943 | 0, dev_priv->mm.gtt_mappable_end, | 2955 | 0, dev_priv->mm.gtt_mappable_end); |
| 2944 | false); | ||
| 2945 | else | 2956 | else |
| 2946 | free_space = drm_mm_search_free_color(&dev_priv->mm.gtt_space, | 2957 | ret = drm_mm_insert_node_generic(&dev_priv->mm.gtt_space, node, |
| 2947 | size, alignment, obj->cache_level, | 2958 | size, alignment, obj->cache_level); |
| 2948 | false); | 2959 | if (ret) { |
| 2949 | |||
| 2950 | if (free_space != NULL) { | ||
| 2951 | if (map_and_fenceable) | ||
| 2952 | free_space = | ||
| 2953 | drm_mm_get_block_range_generic(free_space, | ||
| 2954 | size, alignment, obj->cache_level, | ||
| 2955 | 0, dev_priv->mm.gtt_mappable_end, | ||
| 2956 | false); | ||
| 2957 | else | ||
| 2958 | free_space = | ||
| 2959 | drm_mm_get_block_generic(free_space, | ||
| 2960 | size, alignment, obj->cache_level, | ||
| 2961 | false); | ||
| 2962 | } | ||
| 2963 | if (free_space == NULL) { | ||
| 2964 | ret = i915_gem_evict_something(dev, size, alignment, | 2960 | ret = i915_gem_evict_something(dev, size, alignment, |
| 2965 | obj->cache_level, | 2961 | obj->cache_level, |
| 2966 | map_and_fenceable, | 2962 | map_and_fenceable, |
| 2967 | nonblocking); | 2963 | nonblocking); |
| 2968 | if (ret) { | 2964 | if (ret == 0) |
| 2969 | i915_gem_object_unpin_pages(obj); | 2965 | goto search_free; |
| 2970 | return ret; | ||
| 2971 | } | ||
| 2972 | 2966 | ||
| 2973 | goto search_free; | 2967 | i915_gem_object_unpin_pages(obj); |
| 2968 | kfree(node); | ||
| 2969 | return ret; | ||
| 2974 | } | 2970 | } |
| 2975 | if (WARN_ON(!i915_gem_valid_gtt_space(dev, | 2971 | if (WARN_ON(!i915_gem_valid_gtt_space(dev, node, obj->cache_level))) { |
| 2976 | free_space, | ||
| 2977 | obj->cache_level))) { | ||
| 2978 | i915_gem_object_unpin_pages(obj); | 2972 | i915_gem_object_unpin_pages(obj); |
| 2979 | drm_mm_put_block(free_space); | 2973 | drm_mm_put_block(node); |
| 2980 | return -EINVAL; | 2974 | return -EINVAL; |
| 2981 | } | 2975 | } |
| 2982 | 2976 | ||
| 2983 | ret = i915_gem_gtt_prepare_object(obj); | 2977 | ret = i915_gem_gtt_prepare_object(obj); |
| 2984 | if (ret) { | 2978 | if (ret) { |
| 2985 | i915_gem_object_unpin_pages(obj); | 2979 | i915_gem_object_unpin_pages(obj); |
| 2986 | drm_mm_put_block(free_space); | 2980 | drm_mm_put_block(node); |
| 2987 | return ret; | 2981 | return ret; |
| 2988 | } | 2982 | } |
| 2989 | 2983 | ||
| 2990 | list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list); | 2984 | list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list); |
| 2991 | list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list); | 2985 | list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list); |
| 2992 | 2986 | ||
| 2993 | obj->gtt_space = free_space; | 2987 | obj->gtt_space = node; |
| 2994 | obj->gtt_offset = free_space->start; | 2988 | obj->gtt_offset = node->start; |
| 2995 | 2989 | ||
| 2996 | fenceable = | 2990 | fenceable = |
| 2997 | free_space->size == fence_size && | 2991 | node->size == fence_size && |
| 2998 | (free_space->start & (fence_alignment - 1)) == 0; | 2992 | (node->start & (fence_alignment - 1)) == 0; |
| 2999 | 2993 | ||
| 3000 | mappable = | 2994 | mappable = |
| 3001 | obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end; | 2995 | obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end; |
| @@ -4392,6 +4386,9 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) | |||
| 4392 | if (!mutex_is_locked_by(&dev->struct_mutex, current)) | 4386 | if (!mutex_is_locked_by(&dev->struct_mutex, current)) |
| 4393 | return 0; | 4387 | return 0; |
| 4394 | 4388 | ||
| 4389 | if (dev_priv->mm.shrinker_no_lock_stealing) | ||
| 4390 | return 0; | ||
| 4391 | |||
| 4395 | unlock = false; | 4392 | unlock = false; |
| 4396 | } | 4393 | } |
| 4397 | 4394 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 773ef77b6c22..7be4241e8242 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c | |||
| @@ -226,7 +226,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev, | |||
| 226 | { | 226 | { |
| 227 | struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); | 227 | struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); |
| 228 | 228 | ||
| 229 | return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, 0600); | 229 | return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, flags); |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) | 232 | static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index ee8f97f0539e..d6a994a07393 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
| @@ -808,6 +808,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 808 | 808 | ||
| 809 | flags |= I915_DISPATCH_SECURE; | 809 | flags |= I915_DISPATCH_SECURE; |
| 810 | } | 810 | } |
| 811 | if (args->flags & I915_EXEC_IS_PINNED) | ||
| 812 | flags |= I915_DISPATCH_PINNED; | ||
| 811 | 813 | ||
| 812 | switch (args->flags & I915_EXEC_RING_MASK) { | 814 | switch (args->flags & I915_EXEC_RING_MASK) { |
| 813 | case I915_EXEC_DEFAULT: | 815 | case I915_EXEC_DEFAULT: |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a4dc97f8b9f0..2220dec3e5d9 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -1087,6 +1087,18 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv, | |||
| 1087 | if (!ring->get_seqno) | 1087 | if (!ring->get_seqno) |
| 1088 | return NULL; | 1088 | return NULL; |
| 1089 | 1089 | ||
| 1090 | if (HAS_BROKEN_CS_TLB(dev_priv->dev)) { | ||
| 1091 | u32 acthd = I915_READ(ACTHD); | ||
| 1092 | |||
| 1093 | if (WARN_ON(ring->id != RCS)) | ||
| 1094 | return NULL; | ||
| 1095 | |||
| 1096 | obj = ring->private; | ||
| 1097 | if (acthd >= obj->gtt_offset && | ||
| 1098 | acthd < obj->gtt_offset + obj->base.size) | ||
| 1099 | return i915_error_object_create(dev_priv, obj); | ||
| 1100 | } | ||
| 1101 | |||
| 1090 | seqno = ring->get_seqno(ring, false); | 1102 | seqno = ring->get_seqno(ring, false); |
| 1091 | list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) { | 1103 | list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) { |
| 1092 | if (obj->ring != ring) | 1104 | if (obj->ring != ring) |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3f75cfaf1c3f..186ee5c85b51 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -517,6 +517,7 @@ | |||
| 517 | * the enables for writing to the corresponding low bit. | 517 | * the enables for writing to the corresponding low bit. |
| 518 | */ | 518 | */ |
| 519 | #define _3D_CHICKEN 0x02084 | 519 | #define _3D_CHICKEN 0x02084 |
| 520 | #define _3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB (1 << 10) | ||
| 520 | #define _3D_CHICKEN2 0x0208c | 521 | #define _3D_CHICKEN2 0x0208c |
| 521 | /* Disables pipelining of read flushes past the SF-WIZ interface. | 522 | /* Disables pipelining of read flushes past the SF-WIZ interface. |
| 522 | * Required on all Ironlake steppings according to the B-Spec, but the | 523 | * Required on all Ironlake steppings according to the B-Spec, but the |
| @@ -532,7 +533,8 @@ | |||
| 532 | # define MI_FLUSH_ENABLE (1 << 12) | 533 | # define MI_FLUSH_ENABLE (1 << 12) |
| 533 | 534 | ||
| 534 | #define GEN6_GT_MODE 0x20d0 | 535 | #define GEN6_GT_MODE 0x20d0 |
| 535 | #define GEN6_GT_MODE_HI (1 << 9) | 536 | #define GEN6_GT_MODE_HI (1 << 9) |
| 537 | #define GEN6_TD_FOUR_ROW_DISPATCH_DISABLE (1 << 5) | ||
| 536 | 538 | ||
| 537 | #define GFX_MODE 0x02520 | 539 | #define GFX_MODE 0x02520 |
| 538 | #define GFX_MODE_GEN7 0x0229c | 540 | #define GFX_MODE_GEN7 0x0229c |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5d127e068950..a9fb046b94a1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -8144,10 +8144,6 @@ intel_modeset_stage_output_state(struct drm_device *dev, | |||
| 8144 | DRM_DEBUG_KMS("encoder changed, full mode switch\n"); | 8144 | DRM_DEBUG_KMS("encoder changed, full mode switch\n"); |
| 8145 | config->mode_changed = true; | 8145 | config->mode_changed = true; |
| 8146 | } | 8146 | } |
| 8147 | |||
| 8148 | /* Disable all disconnected encoders. */ | ||
| 8149 | if (connector->base.status == connector_status_disconnected) | ||
| 8150 | connector->new_encoder = NULL; | ||
| 8151 | } | 8147 | } |
| 8152 | /* connector->new_encoder is now updated for all connectors. */ | 8148 | /* connector->new_encoder is now updated for all connectors. */ |
| 8153 | 8149 | ||
| @@ -9167,6 +9163,23 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) | |||
| 9167 | * the crtc fixup. */ | 9163 | * the crtc fixup. */ |
| 9168 | } | 9164 | } |
| 9169 | 9165 | ||
| 9166 | static void i915_redisable_vga(struct drm_device *dev) | ||
| 9167 | { | ||
| 9168 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 9169 | u32 vga_reg; | ||
| 9170 | |||
| 9171 | if (HAS_PCH_SPLIT(dev)) | ||
| 9172 | vga_reg = CPU_VGACNTRL; | ||
| 9173 | else | ||
| 9174 | vga_reg = VGACNTRL; | ||
| 9175 | |||
| 9176 | if (I915_READ(vga_reg) != VGA_DISP_DISABLE) { | ||
| 9177 | DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); | ||
| 9178 | I915_WRITE(vga_reg, VGA_DISP_DISABLE); | ||
| 9179 | POSTING_READ(vga_reg); | ||
| 9180 | } | ||
| 9181 | } | ||
| 9182 | |||
| 9170 | /* Scan out the current hw modeset state, sanitizes it and maps it into the drm | 9183 | /* Scan out the current hw modeset state, sanitizes it and maps it into the drm |
| 9171 | * and i915 state tracking structures. */ | 9184 | * and i915 state tracking structures. */ |
| 9172 | void intel_modeset_setup_hw_state(struct drm_device *dev, | 9185 | void intel_modeset_setup_hw_state(struct drm_device *dev, |
| @@ -9275,6 +9288,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, | |||
| 9275 | intel_set_mode(&crtc->base, &crtc->base.mode, | 9288 | intel_set_mode(&crtc->base, &crtc->base.mode, |
| 9276 | crtc->base.x, crtc->base.y, crtc->base.fb); | 9289 | crtc->base.x, crtc->base.y, crtc->base.fb); |
| 9277 | } | 9290 | } |
| 9291 | |||
| 9292 | i915_redisable_vga(dev); | ||
| 9278 | } else { | 9293 | } else { |
| 9279 | intel_modeset_update_staged_output_state(dev); | 9294 | intel_modeset_update_staged_output_state(dev); |
| 9280 | } | 9295 | } |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 496caa73eb70..e6f54ffab3ba 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -405,7 +405,7 @@ void intel_update_fbc(struct drm_device *dev) | |||
| 405 | * - going to an unsupported config (interlace, pixel multiply, etc.) | 405 | * - going to an unsupported config (interlace, pixel multiply, etc.) |
| 406 | */ | 406 | */ |
| 407 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { | 407 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { |
| 408 | if (tmp_crtc->enabled && | 408 | if (to_intel_crtc(tmp_crtc)->active && |
| 409 | !to_intel_crtc(tmp_crtc)->primary_disabled && | 409 | !to_intel_crtc(tmp_crtc)->primary_disabled && |
| 410 | tmp_crtc->fb) { | 410 | tmp_crtc->fb) { |
| 411 | if (crtc) { | 411 | if (crtc) { |
| @@ -992,7 +992,7 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) | |||
| 992 | struct drm_crtc *crtc, *enabled = NULL; | 992 | struct drm_crtc *crtc, *enabled = NULL; |
| 993 | 993 | ||
| 994 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 994 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
| 995 | if (crtc->enabled && crtc->fb) { | 995 | if (to_intel_crtc(crtc)->active && crtc->fb) { |
| 996 | if (enabled) | 996 | if (enabled) |
| 997 | return NULL; | 997 | return NULL; |
| 998 | enabled = crtc; | 998 | enabled = crtc; |
| @@ -1086,7 +1086,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, | |||
| 1086 | int entries, tlb_miss; | 1086 | int entries, tlb_miss; |
| 1087 | 1087 | ||
| 1088 | crtc = intel_get_crtc_for_plane(dev, plane); | 1088 | crtc = intel_get_crtc_for_plane(dev, plane); |
| 1089 | if (crtc->fb == NULL || !crtc->enabled) { | 1089 | if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) { |
| 1090 | *cursor_wm = cursor->guard_size; | 1090 | *cursor_wm = cursor->guard_size; |
| 1091 | *plane_wm = display->guard_size; | 1091 | *plane_wm = display->guard_size; |
| 1092 | return false; | 1092 | return false; |
| @@ -1215,7 +1215,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, | |||
| 1215 | int entries; | 1215 | int entries; |
| 1216 | 1216 | ||
| 1217 | crtc = intel_get_crtc_for_plane(dev, plane); | 1217 | crtc = intel_get_crtc_for_plane(dev, plane); |
| 1218 | if (crtc->fb == NULL || !crtc->enabled) | 1218 | if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) |
| 1219 | return false; | 1219 | return false; |
| 1220 | 1220 | ||
| 1221 | clock = crtc->mode.clock; /* VESA DOT Clock */ | 1221 | clock = crtc->mode.clock; /* VESA DOT Clock */ |
| @@ -1286,6 +1286,7 @@ static void valleyview_update_wm(struct drm_device *dev) | |||
| 1286 | struct drm_i915_private *dev_priv = dev->dev_private; | 1286 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 1287 | int planea_wm, planeb_wm, cursora_wm, cursorb_wm; | 1287 | int planea_wm, planeb_wm, cursora_wm, cursorb_wm; |
| 1288 | int plane_sr, cursor_sr; | 1288 | int plane_sr, cursor_sr; |
| 1289 | int ignore_plane_sr, ignore_cursor_sr; | ||
| 1289 | unsigned int enabled = 0; | 1290 | unsigned int enabled = 0; |
| 1290 | 1291 | ||
| 1291 | vlv_update_drain_latency(dev); | 1292 | vlv_update_drain_latency(dev); |
| @@ -1302,17 +1303,23 @@ static void valleyview_update_wm(struct drm_device *dev) | |||
| 1302 | &planeb_wm, &cursorb_wm)) | 1303 | &planeb_wm, &cursorb_wm)) |
| 1303 | enabled |= 2; | 1304 | enabled |= 2; |
| 1304 | 1305 | ||
| 1305 | plane_sr = cursor_sr = 0; | ||
| 1306 | if (single_plane_enabled(enabled) && | 1306 | if (single_plane_enabled(enabled) && |
| 1307 | g4x_compute_srwm(dev, ffs(enabled) - 1, | 1307 | g4x_compute_srwm(dev, ffs(enabled) - 1, |
| 1308 | sr_latency_ns, | 1308 | sr_latency_ns, |
| 1309 | &valleyview_wm_info, | 1309 | &valleyview_wm_info, |
| 1310 | &valleyview_cursor_wm_info, | 1310 | &valleyview_cursor_wm_info, |
| 1311 | &plane_sr, &cursor_sr)) | 1311 | &plane_sr, &ignore_cursor_sr) && |
| 1312 | g4x_compute_srwm(dev, ffs(enabled) - 1, | ||
| 1313 | 2*sr_latency_ns, | ||
| 1314 | &valleyview_wm_info, | ||
| 1315 | &valleyview_cursor_wm_info, | ||
| 1316 | &ignore_plane_sr, &cursor_sr)) { | ||
| 1312 | I915_WRITE(FW_BLC_SELF_VLV, FW_CSPWRDWNEN); | 1317 | I915_WRITE(FW_BLC_SELF_VLV, FW_CSPWRDWNEN); |
| 1313 | else | 1318 | } else { |
| 1314 | I915_WRITE(FW_BLC_SELF_VLV, | 1319 | I915_WRITE(FW_BLC_SELF_VLV, |
| 1315 | I915_READ(FW_BLC_SELF_VLV) & ~FW_CSPWRDWNEN); | 1320 | I915_READ(FW_BLC_SELF_VLV) & ~FW_CSPWRDWNEN); |
| 1321 | plane_sr = cursor_sr = 0; | ||
| 1322 | } | ||
| 1316 | 1323 | ||
| 1317 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", | 1324 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", |
| 1318 | planea_wm, cursora_wm, | 1325 | planea_wm, cursora_wm, |
| @@ -1352,17 +1359,18 @@ static void g4x_update_wm(struct drm_device *dev) | |||
| 1352 | &planeb_wm, &cursorb_wm)) | 1359 | &planeb_wm, &cursorb_wm)) |
| 1353 | enabled |= 2; | 1360 | enabled |= 2; |
| 1354 | 1361 | ||
| 1355 | plane_sr = cursor_sr = 0; | ||
| 1356 | if (single_plane_enabled(enabled) && | 1362 | if (single_plane_enabled(enabled) && |
| 1357 | g4x_compute_srwm(dev, ffs(enabled) - 1, | 1363 | g4x_compute_srwm(dev, ffs(enabled) - 1, |
| 1358 | sr_latency_ns, | 1364 | sr_latency_ns, |
| 1359 | &g4x_wm_info, | 1365 | &g4x_wm_info, |
| 1360 | &g4x_cursor_wm_info, | 1366 | &g4x_cursor_wm_info, |
| 1361 | &plane_sr, &cursor_sr)) | 1367 | &plane_sr, &cursor_sr)) { |
| 1362 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); | 1368 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); |
| 1363 | else | 1369 | } else { |
| 1364 | I915_WRITE(FW_BLC_SELF, | 1370 | I915_WRITE(FW_BLC_SELF, |
| 1365 | I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN); | 1371 | I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN); |
| 1372 | plane_sr = cursor_sr = 0; | ||
| 1373 | } | ||
| 1366 | 1374 | ||
| 1367 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", | 1375 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", |
| 1368 | planea_wm, cursora_wm, | 1376 | planea_wm, cursora_wm, |
| @@ -1468,7 +1476,7 @@ static void i9xx_update_wm(struct drm_device *dev) | |||
| 1468 | 1476 | ||
| 1469 | fifo_size = dev_priv->display.get_fifo_size(dev, 0); | 1477 | fifo_size = dev_priv->display.get_fifo_size(dev, 0); |
| 1470 | crtc = intel_get_crtc_for_plane(dev, 0); | 1478 | crtc = intel_get_crtc_for_plane(dev, 0); |
| 1471 | if (crtc->enabled && crtc->fb) { | 1479 | if (to_intel_crtc(crtc)->active && crtc->fb) { |
| 1472 | int cpp = crtc->fb->bits_per_pixel / 8; | 1480 | int cpp = crtc->fb->bits_per_pixel / 8; |
| 1473 | if (IS_GEN2(dev)) | 1481 | if (IS_GEN2(dev)) |
| 1474 | cpp = 4; | 1482 | cpp = 4; |
| @@ -1482,7 +1490,7 @@ static void i9xx_update_wm(struct drm_device *dev) | |||
| 1482 | 1490 | ||
| 1483 | fifo_size = dev_priv->display.get_fifo_size(dev, 1); | 1491 | fifo_size = dev_priv->display.get_fifo_size(dev, 1); |
| 1484 | crtc = intel_get_crtc_for_plane(dev, 1); | 1492 | crtc = intel_get_crtc_for_plane(dev, 1); |
| 1485 | if (crtc->enabled && crtc->fb) { | 1493 | if (to_intel_crtc(crtc)->active && crtc->fb) { |
| 1486 | int cpp = crtc->fb->bits_per_pixel / 8; | 1494 | int cpp = crtc->fb->bits_per_pixel / 8; |
| 1487 | if (IS_GEN2(dev)) | 1495 | if (IS_GEN2(dev)) |
| 1488 | cpp = 4; | 1496 | cpp = 4; |
| @@ -1811,8 +1819,110 @@ static void sandybridge_update_wm(struct drm_device *dev) | |||
| 1811 | enabled |= 2; | 1819 | enabled |= 2; |
| 1812 | } | 1820 | } |
| 1813 | 1821 | ||
| 1814 | if ((dev_priv->num_pipe == 3) && | 1822 | /* |
| 1815 | g4x_compute_wm0(dev, 2, | 1823 | * Calculate and update the self-refresh watermark only when one |
| 1824 | * display plane is used. | ||
| 1825 | * | ||
| 1826 | * SNB support 3 levels of watermark. | ||
| 1827 | * | ||
| 1828 | * WM1/WM2/WM2 watermarks have to be enabled in the ascending order, | ||
| 1829 | * and disabled in the descending order | ||
| 1830 | * | ||
| 1831 | */ | ||
| 1832 | I915_WRITE(WM3_LP_ILK, 0); | ||
| 1833 | I915_WRITE(WM2_LP_ILK, 0); | ||
| 1834 | I915_WRITE(WM1_LP_ILK, 0); | ||
| 1835 | |||
| 1836 | if (!single_plane_enabled(enabled) || | ||
| 1837 | dev_priv->sprite_scaling_enabled) | ||
| 1838 | return; | ||
| 1839 | enabled = ffs(enabled) - 1; | ||
| 1840 | |||
| 1841 | /* WM1 */ | ||
| 1842 | if (!ironlake_compute_srwm(dev, 1, enabled, | ||
| 1843 | SNB_READ_WM1_LATENCY() * 500, | ||
| 1844 | &sandybridge_display_srwm_info, | ||
| 1845 | &sandybridge_cursor_srwm_info, | ||
| 1846 | &fbc_wm, &plane_wm, &cursor_wm)) | ||
| 1847 | return; | ||
| 1848 | |||
| 1849 | I915_WRITE(WM1_LP_ILK, | ||
| 1850 | WM1_LP_SR_EN | | ||
| 1851 | (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) | | ||
| 1852 | (fbc_wm << WM1_LP_FBC_SHIFT) | | ||
| 1853 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
| 1854 | cursor_wm); | ||
| 1855 | |||
| 1856 | /* WM2 */ | ||
| 1857 | if (!ironlake_compute_srwm(dev, 2, enabled, | ||
| 1858 | SNB_READ_WM2_LATENCY() * 500, | ||
| 1859 | &sandybridge_display_srwm_info, | ||
| 1860 | &sandybridge_cursor_srwm_info, | ||
| 1861 | &fbc_wm, &plane_wm, &cursor_wm)) | ||
| 1862 | return; | ||
| 1863 | |||
| 1864 | I915_WRITE(WM2_LP_ILK, | ||
| 1865 | WM2_LP_EN | | ||
| 1866 | (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) | | ||
| 1867 | (fbc_wm << WM1_LP_FBC_SHIFT) | | ||
| 1868 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
| 1869 | cursor_wm); | ||
| 1870 | |||
| 1871 | /* WM3 */ | ||
| 1872 | if (!ironlake_compute_srwm(dev, 3, enabled, | ||
| 1873 | SNB_READ_WM3_LATENCY() * 500, | ||
| 1874 | &sandybridge_display_srwm_info, | ||
| 1875 | &sandybridge_cursor_srwm_info, | ||
| 1876 | &fbc_wm, &plane_wm, &cursor_wm)) | ||
| 1877 | return; | ||
| 1878 | |||
| 1879 | I915_WRITE(WM3_LP_ILK, | ||
| 1880 | WM3_LP_EN | | ||
| 1881 | (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) | | ||
| 1882 | (fbc_wm << WM1_LP_FBC_SHIFT) | | ||
| 1883 | (plane_wm << WM1_LP_SR_SHIFT) | | ||
| 1884 | cursor_wm); | ||
| 1885 | } | ||
| 1886 | |||
| 1887 | static void ivybridge_update_wm(struct drm_device *dev) | ||
| 1888 | { | ||
| 1889 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1890 | int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ | ||
| 1891 | u32 val; | ||
| 1892 | int fbc_wm, plane_wm, cursor_wm; | ||
| 1893 | int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm; | ||
| 1894 | unsigned int enabled; | ||
| 1895 | |||
| 1896 | enabled = 0; | ||
| 1897 | if (g4x_compute_wm0(dev, 0, | ||
| 1898 | &sandybridge_display_wm_info, latency, | ||
| 1899 | &sandybridge_cursor_wm_info, latency, | ||
| 1900 | &plane_wm, &cursor_wm)) { | ||
| 1901 | val = I915_READ(WM0_PIPEA_ILK); | ||
| 1902 | val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); | ||
| 1903 | I915_WRITE(WM0_PIPEA_ILK, val | | ||
| 1904 | ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); | ||
| 1905 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" | ||
| 1906 | " plane %d, " "cursor: %d\n", | ||
| 1907 | plane_wm, cursor_wm); | ||
| 1908 | enabled |= 1; | ||
| 1909 | } | ||
| 1910 | |||
| 1911 | if (g4x_compute_wm0(dev, 1, | ||
| 1912 | &sandybridge_display_wm_info, latency, | ||
| 1913 | &sandybridge_cursor_wm_info, latency, | ||
| 1914 | &plane_wm, &cursor_wm)) { | ||
| 1915 | val = I915_READ(WM0_PIPEB_ILK); | ||
| 1916 | val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); | ||
| 1917 | I915_WRITE(WM0_PIPEB_ILK, val | | ||
| 1918 | ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); | ||
| 1919 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" | ||
| 1920 | " plane %d, cursor: %d\n", | ||
| 1921 | plane_wm, cursor_wm); | ||
| 1922 | enabled |= 2; | ||
| 1923 | } | ||
| 1924 | |||
| 1925 | if (g4x_compute_wm0(dev, 2, | ||
| 1816 | &sandybridge_display_wm_info, latency, | 1926 | &sandybridge_display_wm_info, latency, |
| 1817 | &sandybridge_cursor_wm_info, latency, | 1927 | &sandybridge_cursor_wm_info, latency, |
| 1818 | &plane_wm, &cursor_wm)) { | 1928 | &plane_wm, &cursor_wm)) { |
| @@ -1875,12 +1985,17 @@ static void sandybridge_update_wm(struct drm_device *dev) | |||
| 1875 | (plane_wm << WM1_LP_SR_SHIFT) | | 1985 | (plane_wm << WM1_LP_SR_SHIFT) | |
| 1876 | cursor_wm); | 1986 | cursor_wm); |
| 1877 | 1987 | ||
| 1878 | /* WM3 */ | 1988 | /* WM3, note we have to correct the cursor latency */ |
| 1879 | if (!ironlake_compute_srwm(dev, 3, enabled, | 1989 | if (!ironlake_compute_srwm(dev, 3, enabled, |
| 1880 | SNB_READ_WM3_LATENCY() * 500, | 1990 | SNB_READ_WM3_LATENCY() * 500, |
| 1881 | &sandybridge_display_srwm_info, | 1991 | &sandybridge_display_srwm_info, |
| 1882 | &sandybridge_cursor_srwm_info, | 1992 | &sandybridge_cursor_srwm_info, |
| 1883 | &fbc_wm, &plane_wm, &cursor_wm)) | 1993 | &fbc_wm, &plane_wm, &ignore_cursor_wm) || |
| 1994 | !ironlake_compute_srwm(dev, 3, enabled, | ||
| 1995 | 2 * SNB_READ_WM3_LATENCY() * 500, | ||
| 1996 | &sandybridge_display_srwm_info, | ||
| 1997 | &sandybridge_cursor_srwm_info, | ||
| 1998 | &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm)) | ||
| 1884 | return; | 1999 | return; |
| 1885 | 2000 | ||
| 1886 | I915_WRITE(WM3_LP_ILK, | 2001 | I915_WRITE(WM3_LP_ILK, |
| @@ -1929,7 +2044,7 @@ sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, | |||
| 1929 | int entries, tlb_miss; | 2044 | int entries, tlb_miss; |
| 1930 | 2045 | ||
| 1931 | crtc = intel_get_crtc_for_plane(dev, plane); | 2046 | crtc = intel_get_crtc_for_plane(dev, plane); |
| 1932 | if (crtc->fb == NULL || !crtc->enabled) { | 2047 | if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) { |
| 1933 | *sprite_wm = display->guard_size; | 2048 | *sprite_wm = display->guard_size; |
| 1934 | return false; | 2049 | return false; |
| 1935 | } | 2050 | } |
| @@ -3471,6 +3586,15 @@ static void gen6_init_clock_gating(struct drm_device *dev) | |||
| 3471 | I915_READ(ILK_DISPLAY_CHICKEN2) | | 3586 | I915_READ(ILK_DISPLAY_CHICKEN2) | |
| 3472 | ILK_ELPIN_409_SELECT); | 3587 | ILK_ELPIN_409_SELECT); |
| 3473 | 3588 | ||
| 3589 | /* WaDisableHiZPlanesWhenMSAAEnabled */ | ||
| 3590 | I915_WRITE(_3D_CHICKEN, | ||
| 3591 | _MASKED_BIT_ENABLE(_3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB)); | ||
| 3592 | |||
| 3593 | /* WaSetupGtModeTdRowDispatch */ | ||
| 3594 | if (IS_SNB_GT1(dev)) | ||
| 3595 | I915_WRITE(GEN6_GT_MODE, | ||
| 3596 | _MASKED_BIT_ENABLE(GEN6_TD_FOUR_ROW_DISPATCH_DISABLE)); | ||
| 3597 | |||
| 3474 | I915_WRITE(WM3_LP_ILK, 0); | 3598 | I915_WRITE(WM3_LP_ILK, 0); |
| 3475 | I915_WRITE(WM2_LP_ILK, 0); | 3599 | I915_WRITE(WM2_LP_ILK, 0); |
| 3476 | I915_WRITE(WM1_LP_ILK, 0); | 3600 | I915_WRITE(WM1_LP_ILK, 0); |
| @@ -3999,7 +4123,7 @@ void intel_init_pm(struct drm_device *dev) | |||
| 3999 | } else if (IS_IVYBRIDGE(dev)) { | 4123 | } else if (IS_IVYBRIDGE(dev)) { |
| 4000 | /* FIXME: detect B0+ stepping and use auto training */ | 4124 | /* FIXME: detect B0+ stepping and use auto training */ |
| 4001 | if (SNB_READ_WM0_LATENCY()) { | 4125 | if (SNB_READ_WM0_LATENCY()) { |
| 4002 | dev_priv->display.update_wm = sandybridge_update_wm; | 4126 | dev_priv->display.update_wm = ivybridge_update_wm; |
| 4003 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; | 4127 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; |
| 4004 | } else { | 4128 | } else { |
| 4005 | DRM_DEBUG_KMS("Failed to read display plane latency. " | 4129 | DRM_DEBUG_KMS("Failed to read display plane latency. " |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 2346b920bd86..ae253e04c391 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
| @@ -547,9 +547,14 @@ static int init_render_ring(struct intel_ring_buffer *ring) | |||
| 547 | 547 | ||
| 548 | static void render_ring_cleanup(struct intel_ring_buffer *ring) | 548 | static void render_ring_cleanup(struct intel_ring_buffer *ring) |
| 549 | { | 549 | { |
| 550 | struct drm_device *dev = ring->dev; | ||
| 551 | |||
| 550 | if (!ring->private) | 552 | if (!ring->private) |
| 551 | return; | 553 | return; |
| 552 | 554 | ||
| 555 | if (HAS_BROKEN_CS_TLB(dev)) | ||
| 556 | drm_gem_object_unreference(to_gem_object(ring->private)); | ||
| 557 | |||
| 553 | cleanup_pipe_control(ring); | 558 | cleanup_pipe_control(ring); |
| 554 | } | 559 | } |
| 555 | 560 | ||
| @@ -969,6 +974,8 @@ i965_dispatch_execbuffer(struct intel_ring_buffer *ring, | |||
| 969 | return 0; | 974 | return 0; |
| 970 | } | 975 | } |
| 971 | 976 | ||
| 977 | /* Just userspace ABI convention to limit the wa batch bo to a resonable size */ | ||
| 978 | #define I830_BATCH_LIMIT (256*1024) | ||
| 972 | static int | 979 | static int |
| 973 | i830_dispatch_execbuffer(struct intel_ring_buffer *ring, | 980 | i830_dispatch_execbuffer(struct intel_ring_buffer *ring, |
| 974 | u32 offset, u32 len, | 981 | u32 offset, u32 len, |
| @@ -976,15 +983,47 @@ i830_dispatch_execbuffer(struct intel_ring_buffer *ring, | |||
| 976 | { | 983 | { |
| 977 | int ret; | 984 | int ret; |
| 978 | 985 | ||
| 979 | ret = intel_ring_begin(ring, 4); | 986 | if (flags & I915_DISPATCH_PINNED) { |
| 980 | if (ret) | 987 | ret = intel_ring_begin(ring, 4); |
| 981 | return ret; | 988 | if (ret) |
| 989 | return ret; | ||
| 982 | 990 | ||
| 983 | intel_ring_emit(ring, MI_BATCH_BUFFER); | 991 | intel_ring_emit(ring, MI_BATCH_BUFFER); |
| 984 | intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); | 992 | intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); |
| 985 | intel_ring_emit(ring, offset + len - 8); | 993 | intel_ring_emit(ring, offset + len - 8); |
| 986 | intel_ring_emit(ring, 0); | 994 | intel_ring_emit(ring, MI_NOOP); |
| 987 | intel_ring_advance(ring); | 995 | intel_ring_advance(ring); |
| 996 | } else { | ||
| 997 | struct drm_i915_gem_object *obj = ring->private; | ||
| 998 | u32 cs_offset = obj->gtt_offset; | ||
| 999 | |||
| 1000 | if (len > I830_BATCH_LIMIT) | ||
| 1001 | return -ENOSPC; | ||
| 1002 | |||
| 1003 | ret = intel_ring_begin(ring, 9+3); | ||
| 1004 | if (ret) | ||
| 1005 | return ret; | ||
| 1006 | /* Blit the batch (which has now all relocs applied) to the stable batch | ||
| 1007 | * scratch bo area (so that the CS never stumbles over its tlb | ||
| 1008 | * invalidation bug) ... */ | ||
| 1009 | intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD | | ||
| 1010 | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||
| 1011 | XY_SRC_COPY_BLT_WRITE_RGB); | ||
| 1012 | intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | 4096); | ||
| 1013 | intel_ring_emit(ring, 0); | ||
| 1014 | intel_ring_emit(ring, (DIV_ROUND_UP(len, 4096) << 16) | 1024); | ||
| 1015 | intel_ring_emit(ring, cs_offset); | ||
| 1016 | intel_ring_emit(ring, 0); | ||
| 1017 | intel_ring_emit(ring, 4096); | ||
| 1018 | intel_ring_emit(ring, offset); | ||
| 1019 | intel_ring_emit(ring, MI_FLUSH); | ||
| 1020 | |||
| 1021 | /* ... and execute it. */ | ||
| 1022 | intel_ring_emit(ring, MI_BATCH_BUFFER); | ||
| 1023 | intel_ring_emit(ring, cs_offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE)); | ||
| 1024 | intel_ring_emit(ring, cs_offset + len - 8); | ||
| 1025 | intel_ring_advance(ring); | ||
| 1026 | } | ||
| 988 | 1027 | ||
| 989 | return 0; | 1028 | return 0; |
| 990 | } | 1029 | } |
| @@ -1596,6 +1635,27 @@ int intel_init_render_ring_buffer(struct drm_device *dev) | |||
| 1596 | ring->init = init_render_ring; | 1635 | ring->init = init_render_ring; |
| 1597 | ring->cleanup = render_ring_cleanup; | 1636 | ring->cleanup = render_ring_cleanup; |
| 1598 | 1637 | ||
| 1638 | /* Workaround batchbuffer to combat CS tlb bug. */ | ||
| 1639 | if (HAS_BROKEN_CS_TLB(dev)) { | ||
| 1640 | struct drm_i915_gem_object *obj; | ||
| 1641 | int ret; | ||
| 1642 | |||
| 1643 | obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT); | ||
| 1644 | if (obj == NULL) { | ||
| 1645 | DRM_ERROR("Failed to allocate batch bo\n"); | ||
| 1646 | return -ENOMEM; | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | ret = i915_gem_object_pin(obj, 0, true, false); | ||
| 1650 | if (ret != 0) { | ||
| 1651 | drm_gem_object_unreference(&obj->base); | ||
| 1652 | DRM_ERROR("Failed to ping batch bo\n"); | ||
| 1653 | return ret; | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | ring->private = obj; | ||
| 1657 | } | ||
| 1658 | |||
| 1599 | return intel_init_ring_buffer(dev, ring); | 1659 | return intel_init_ring_buffer(dev, ring); |
| 1600 | } | 1660 | } |
| 1601 | 1661 | ||
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 526182ed0c6d..6af87cd05725 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
| @@ -94,6 +94,7 @@ struct intel_ring_buffer { | |||
| 94 | u32 offset, u32 length, | 94 | u32 offset, u32 length, |
| 95 | unsigned flags); | 95 | unsigned flags); |
| 96 | #define I915_DISPATCH_SECURE 0x1 | 96 | #define I915_DISPATCH_SECURE 0x1 |
| 97 | #define I915_DISPATCH_PINNED 0x2 | ||
| 97 | void (*cleanup)(struct intel_ring_buffer *ring); | 98 | void (*cleanup)(struct intel_ring_buffer *ring); |
| 98 | int (*sync_to)(struct intel_ring_buffer *ring, | 99 | int (*sync_to)(struct intel_ring_buffer *ring, |
| 99 | struct intel_ring_buffer *to, | 100 | struct intel_ring_buffer *to, |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc index 7b715fda2763..62ab231cd6b6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc | |||
| @@ -57,6 +57,11 @@ chipsets: | |||
| 57 | .b16 #nve4_gpc_mmio_tail | 57 | .b16 #nve4_gpc_mmio_tail |
| 58 | .b16 #nve4_tpc_mmio_head | 58 | .b16 #nve4_tpc_mmio_head |
| 59 | .b16 #nve4_tpc_mmio_tail | 59 | .b16 #nve4_tpc_mmio_tail |
| 60 | .b8 0xe6 0 0 0 | ||
| 61 | .b16 #nve4_gpc_mmio_head | ||
| 62 | .b16 #nve4_gpc_mmio_tail | ||
| 63 | .b16 #nve4_tpc_mmio_head | ||
| 64 | .b16 #nve4_tpc_mmio_tail | ||
| 60 | .b8 0 0 0 0 | 65 | .b8 0 0 0 0 |
| 61 | 66 | ||
| 62 | // GPC mmio lists | 67 | // GPC mmio lists |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h index 26c2165bad0f..09ee4702c8b2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h | |||
| @@ -34,13 +34,16 @@ uint32_t nve0_grgpc_data[] = { | |||
| 34 | 0x00000000, | 34 | 0x00000000, |
| 35 | /* 0x0064: chipsets */ | 35 | /* 0x0064: chipsets */ |
| 36 | 0x000000e4, | 36 | 0x000000e4, |
| 37 | 0x01040080, | 37 | 0x0110008c, |
| 38 | 0x014c0104, | 38 | 0x01580110, |
| 39 | 0x000000e7, | 39 | 0x000000e7, |
| 40 | 0x01040080, | 40 | 0x0110008c, |
| 41 | 0x014c0104, | 41 | 0x01580110, |
| 42 | 0x000000e6, | ||
| 43 | 0x0110008c, | ||
| 44 | 0x01580110, | ||
| 42 | 0x00000000, | 45 | 0x00000000, |
| 43 | /* 0x0080: nve4_gpc_mmio_head */ | 46 | /* 0x008c: nve4_gpc_mmio_head */ |
| 44 | 0x00000380, | 47 | 0x00000380, |
| 45 | 0x04000400, | 48 | 0x04000400, |
| 46 | 0x0800040c, | 49 | 0x0800040c, |
| @@ -74,8 +77,8 @@ uint32_t nve0_grgpc_data[] = { | |||
| 74 | 0x14003100, | 77 | 0x14003100, |
| 75 | 0x000031d0, | 78 | 0x000031d0, |
| 76 | 0x040031e0, | 79 | 0x040031e0, |
| 77 | /* 0x0104: nve4_gpc_mmio_tail */ | 80 | /* 0x0110: nve4_gpc_mmio_tail */ |
| 78 | /* 0x0104: nve4_tpc_mmio_head */ | 81 | /* 0x0110: nve4_tpc_mmio_head */ |
| 79 | 0x00000048, | 82 | 0x00000048, |
| 80 | 0x00000064, | 83 | 0x00000064, |
| 81 | 0x00000088, | 84 | 0x00000088, |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc index acfc457654bd..0bcfa4d447e5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc | |||
| @@ -754,6 +754,16 @@ ctx_mmio_exec: | |||
| 754 | // on load it means: "a save preceeded this load" | 754 | // on load it means: "a save preceeded this load" |
| 755 | // | 755 | // |
| 756 | ctx_xfer: | 756 | ctx_xfer: |
| 757 | // according to mwk, some kind of wait for idle | ||
| 758 | mov $r15 0xc00 | ||
| 759 | shl b32 $r15 6 | ||
| 760 | mov $r14 4 | ||
| 761 | iowr I[$r15 + 0x200] $r14 | ||
| 762 | ctx_xfer_idle: | ||
| 763 | iord $r14 I[$r15 + 0x000] | ||
| 764 | and $r14 0x2000 | ||
| 765 | bra ne #ctx_xfer_idle | ||
| 766 | |||
| 757 | bra not $p1 #ctx_xfer_pre | 767 | bra not $p1 #ctx_xfer_pre |
| 758 | bra $p2 #ctx_xfer_pre_load | 768 | bra $p2 #ctx_xfer_pre_load |
| 759 | ctx_xfer_pre: | 769 | ctx_xfer_pre: |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h index 85a8d556f484..bb03d2a1d57b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h | |||
| @@ -799,79 +799,80 @@ uint32_t nvc0_grhub_code[] = { | |||
| 799 | 0x01fa0613, | 799 | 0x01fa0613, |
| 800 | 0xf803f806, | 800 | 0xf803f806, |
| 801 | /* 0x0829: ctx_xfer */ | 801 | /* 0x0829: ctx_xfer */ |
| 802 | 0x0611f400, | 802 | 0x00f7f100, |
| 803 | /* 0x082f: ctx_xfer_pre */ | 803 | 0x06f4b60c, |
| 804 | 0xf01102f4, | 804 | 0xd004e7f0, |
| 805 | 0x21f510f7, | 805 | /* 0x0836: ctx_xfer_idle */ |
| 806 | 0x21f50698, | 806 | 0xfecf80fe, |
| 807 | 0x11f40631, | 807 | 0x00e4f100, |
| 808 | /* 0x083d: ctx_xfer_pre_load */ | 808 | 0xf91bf420, |
| 809 | 0x02f7f01c, | 809 | 0xf40611f4, |
| 810 | 0x065721f5, | 810 | /* 0x0846: ctx_xfer_pre */ |
| 811 | 0x066621f5, | 811 | 0xf7f01102, |
| 812 | 0x067821f5, | 812 | 0x9821f510, |
| 813 | 0x21f5f4bd, | 813 | 0x3121f506, |
| 814 | 0x21f50657, | 814 | 0x1c11f406, |
| 815 | /* 0x0856: ctx_xfer_exec */ | 815 | /* 0x0854: ctx_xfer_pre_load */ |
| 816 | 0x019806b8, | 816 | 0xf502f7f0, |
| 817 | 0x1427f116, | 817 | 0xf5065721, |
| 818 | 0x0624b604, | 818 | 0xf5066621, |
| 819 | 0xf10020d0, | 819 | 0xbd067821, |
| 820 | 0xf0a500e7, | 820 | 0x5721f5f4, |
| 821 | 0x1fb941e3, | 821 | 0xb821f506, |
| 822 | 0x8d21f402, | 822 | /* 0x086d: ctx_xfer_exec */ |
| 823 | 0xf004e0b6, | 823 | 0x16019806, |
| 824 | 0x2cf001fc, | 824 | 0x041427f1, |
| 825 | 0x0124b602, | 825 | 0xd00624b6, |
| 826 | 0xf405f2fd, | 826 | 0xe7f10020, |
| 827 | 0x17f18d21, | 827 | 0xe3f0a500, |
| 828 | 0x13f04afc, | 828 | 0x021fb941, |
| 829 | 0x0c27f002, | 829 | 0xb68d21f4, |
| 830 | 0xf50012d0, | 830 | 0xfcf004e0, |
| 831 | 0xf1020721, | 831 | 0x022cf001, |
| 832 | 0xf047fc27, | 832 | 0xfd0124b6, |
| 833 | 0x20d00223, | 833 | 0x21f405f2, |
| 834 | 0x012cf000, | 834 | 0xfc17f18d, |
| 835 | 0xd00320b6, | 835 | 0x0213f04a, |
| 836 | 0xacf00012, | 836 | 0xd00c27f0, |
| 837 | 0x06a5f001, | 837 | 0x21f50012, |
| 838 | 0x9800b7f0, | 838 | 0x27f10207, |
| 839 | 0x0d98140c, | 839 | 0x23f047fc, |
| 840 | 0x00e7f015, | 840 | 0x0020d002, |
| 841 | 0x015c21f5, | 841 | 0xb6012cf0, |
| 842 | 0xf508a7f0, | 842 | 0x12d00320, |
| 843 | 0xf5010321, | 843 | 0x01acf000, |
| 844 | 0xf4020721, | 844 | 0xf006a5f0, |
| 845 | 0xa7f02201, | 845 | 0x0c9800b7, |
| 846 | 0xc921f40c, | 846 | 0x150d9814, |
| 847 | 0x0a1017f1, | 847 | 0xf500e7f0, |
| 848 | 0xf00614b6, | 848 | 0xf0015c21, |
| 849 | 0x12d00527, | 849 | 0x21f508a7, |
| 850 | /* 0x08dd: ctx_xfer_post_save_wait */ | 850 | 0x21f50103, |
| 851 | 0x0012cf00, | 851 | 0x01f40207, |
| 852 | 0xf40522fd, | 852 | 0x0ca7f022, |
| 853 | 0x02f4fa1b, | 853 | 0xf1c921f4, |
| 854 | /* 0x08e9: ctx_xfer_post */ | 854 | 0xb60a1017, |
| 855 | 0x02f7f032, | 855 | 0x27f00614, |
| 856 | 0x065721f5, | 856 | 0x0012d005, |
| 857 | 0x21f5f4bd, | 857 | /* 0x08f4: ctx_xfer_post_save_wait */ |
| 858 | 0x21f50698, | 858 | 0xfd0012cf, |
| 859 | 0x21f50226, | 859 | 0x1bf40522, |
| 860 | 0xf4bd0666, | 860 | 0x3202f4fa, |
| 861 | 0x065721f5, | 861 | /* 0x0900: ctx_xfer_post */ |
| 862 | 0x981011f4, | 862 | 0xf502f7f0, |
| 863 | 0x11fd8001, | 863 | 0xbd065721, |
| 864 | 0x070bf405, | 864 | 0x9821f5f4, |
| 865 | 0x07df21f5, | 865 | 0x2621f506, |
| 866 | /* 0x0914: ctx_xfer_no_post_mmio */ | 866 | 0x6621f502, |
| 867 | 0x064921f5, | 867 | 0xf5f4bd06, |
| 868 | /* 0x0918: ctx_xfer_done */ | 868 | 0xf4065721, |
| 869 | 0x000000f8, | 869 | 0x01981011, |
| 870 | 0x00000000, | 870 | 0x0511fd80, |
| 871 | 0x00000000, | 871 | 0xf5070bf4, |
| 872 | 0x00000000, | 872 | /* 0x092b: ctx_xfer_no_post_mmio */ |
| 873 | 0x00000000, | 873 | 0xf507df21, |
| 874 | 0x00000000, | 874 | /* 0x092f: ctx_xfer_done */ |
| 875 | 0xf8064921, | ||
| 875 | 0x00000000, | 876 | 0x00000000, |
| 876 | 0x00000000, | 877 | 0x00000000, |
| 877 | 0x00000000, | 878 | 0x00000000, |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc index 138eeaa28665..7fe9d7cf486b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc | |||
| @@ -44,6 +44,9 @@ chipsets: | |||
| 44 | .b8 0xe7 0 0 0 | 44 | .b8 0xe7 0 0 0 |
| 45 | .b16 #nve4_hub_mmio_head | 45 | .b16 #nve4_hub_mmio_head |
| 46 | .b16 #nve4_hub_mmio_tail | 46 | .b16 #nve4_hub_mmio_tail |
| 47 | .b8 0xe6 0 0 0 | ||
| 48 | .b16 #nve4_hub_mmio_head | ||
| 49 | .b16 #nve4_hub_mmio_tail | ||
| 47 | .b8 0 0 0 0 | 50 | .b8 0 0 0 0 |
| 48 | 51 | ||
| 49 | nve4_hub_mmio_head: | 52 | nve4_hub_mmio_head: |
| @@ -680,6 +683,16 @@ ctx_mmio_exec: | |||
| 680 | // on load it means: "a save preceeded this load" | 683 | // on load it means: "a save preceeded this load" |
| 681 | // | 684 | // |
| 682 | ctx_xfer: | 685 | ctx_xfer: |
| 686 | // according to mwk, some kind of wait for idle | ||
| 687 | mov $r15 0xc00 | ||
| 688 | shl b32 $r15 6 | ||
| 689 | mov $r14 4 | ||
| 690 | iowr I[$r15 + 0x200] $r14 | ||
| 691 | ctx_xfer_idle: | ||
| 692 | iord $r14 I[$r15 + 0x000] | ||
| 693 | and $r14 0x2000 | ||
| 694 | bra ne #ctx_xfer_idle | ||
| 695 | |||
| 683 | bra not $p1 #ctx_xfer_pre | 696 | bra not $p1 #ctx_xfer_pre |
| 684 | bra $p2 #ctx_xfer_pre_load | 697 | bra $p2 #ctx_xfer_pre_load |
| 685 | ctx_xfer_pre: | 698 | ctx_xfer_pre: |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h index decf0c60ca3b..e3421af68ab9 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h | |||
| @@ -30,11 +30,13 @@ uint32_t nve0_grhub_data[] = { | |||
| 30 | 0x00000000, | 30 | 0x00000000, |
| 31 | /* 0x005c: chipsets */ | 31 | /* 0x005c: chipsets */ |
| 32 | 0x000000e4, | 32 | 0x000000e4, |
| 33 | 0x013c0070, | 33 | 0x01440078, |
| 34 | 0x000000e7, | 34 | 0x000000e7, |
| 35 | 0x013c0070, | 35 | 0x01440078, |
| 36 | 0x000000e6, | ||
| 37 | 0x01440078, | ||
| 36 | 0x00000000, | 38 | 0x00000000, |
| 37 | /* 0x0070: nve4_hub_mmio_head */ | 39 | /* 0x0078: nve4_hub_mmio_head */ |
| 38 | 0x0417e91c, | 40 | 0x0417e91c, |
| 39 | 0x04400204, | 41 | 0x04400204, |
| 40 | 0x18404010, | 42 | 0x18404010, |
| @@ -86,9 +88,7 @@ uint32_t nve0_grhub_data[] = { | |||
| 86 | 0x00408840, | 88 | 0x00408840, |
| 87 | 0x08408900, | 89 | 0x08408900, |
| 88 | 0x00408980, | 90 | 0x00408980, |
| 89 | /* 0x013c: nve4_hub_mmio_tail */ | 91 | /* 0x0144: nve4_hub_mmio_tail */ |
| 90 | 0x00000000, | ||
| 91 | 0x00000000, | ||
| 92 | 0x00000000, | 92 | 0x00000000, |
| 93 | 0x00000000, | 93 | 0x00000000, |
| 94 | 0x00000000, | 94 | 0x00000000, |
| @@ -781,77 +781,78 @@ uint32_t nve0_grhub_code[] = { | |||
| 781 | 0x0613f002, | 781 | 0x0613f002, |
| 782 | 0xf80601fa, | 782 | 0xf80601fa, |
| 783 | /* 0x07fb: ctx_xfer */ | 783 | /* 0x07fb: ctx_xfer */ |
| 784 | 0xf400f803, | 784 | 0xf100f803, |
| 785 | 0x02f40611, | 785 | 0xb60c00f7, |
| 786 | /* 0x0801: ctx_xfer_pre */ | 786 | 0xe7f006f4, |
| 787 | 0x10f7f00d, | 787 | 0x80fed004, |
| 788 | 0x067221f5, | 788 | /* 0x0808: ctx_xfer_idle */ |
| 789 | /* 0x080b: ctx_xfer_pre_load */ | 789 | 0xf100fecf, |
| 790 | 0xf01c11f4, | 790 | 0xf42000e4, |
| 791 | 0x21f502f7, | 791 | 0x11f4f91b, |
| 792 | 0x21f50631, | 792 | 0x0d02f406, |
| 793 | 0x21f50640, | 793 | /* 0x0818: ctx_xfer_pre */ |
| 794 | 0xf4bd0652, | 794 | 0xf510f7f0, |
| 795 | 0x063121f5, | 795 | 0xf4067221, |
| 796 | 0x069221f5, | 796 | /* 0x0822: ctx_xfer_pre_load */ |
| 797 | /* 0x0824: ctx_xfer_exec */ | 797 | 0xf7f01c11, |
| 798 | 0xf1160198, | 798 | 0x3121f502, |
| 799 | 0xb6041427, | 799 | 0x4021f506, |
| 800 | 0x20d00624, | 800 | 0x5221f506, |
| 801 | 0x00e7f100, | 801 | 0xf5f4bd06, |
| 802 | 0x41e3f0a5, | 802 | 0xf5063121, |
| 803 | 0xf4021fb9, | 803 | /* 0x083b: ctx_xfer_exec */ |
| 804 | 0xe0b68d21, | 804 | 0x98069221, |
| 805 | 0x01fcf004, | 805 | 0x27f11601, |
| 806 | 0xb6022cf0, | 806 | 0x24b60414, |
| 807 | 0xf2fd0124, | 807 | 0x0020d006, |
| 808 | 0x8d21f405, | 808 | 0xa500e7f1, |
| 809 | 0x4afc17f1, | 809 | 0xb941e3f0, |
| 810 | 0xf00213f0, | 810 | 0x21f4021f, |
| 811 | 0x12d00c27, | 811 | 0x04e0b68d, |
| 812 | 0x0721f500, | 812 | 0xf001fcf0, |
| 813 | 0xfc27f102, | 813 | 0x24b6022c, |
| 814 | 0x0223f047, | 814 | 0x05f2fd01, |
| 815 | 0xf00020d0, | 815 | 0xf18d21f4, |
| 816 | 0x20b6012c, | 816 | 0xf04afc17, |
| 817 | 0x0012d003, | 817 | 0x27f00213, |
| 818 | 0xf001acf0, | 818 | 0x0012d00c, |
| 819 | 0xb7f006a5, | 819 | 0x020721f5, |
| 820 | 0x140c9800, | 820 | 0x47fc27f1, |
| 821 | 0xf0150d98, | 821 | 0xd00223f0, |
| 822 | 0x21f500e7, | 822 | 0x2cf00020, |
| 823 | 0xa7f0015c, | 823 | 0x0320b601, |
| 824 | 0x0321f508, | 824 | 0xf00012d0, |
| 825 | 0x0721f501, | 825 | 0xa5f001ac, |
| 826 | 0x2201f402, | 826 | 0x00b7f006, |
| 827 | 0xf40ca7f0, | 827 | 0x98140c98, |
| 828 | 0x17f1c921, | 828 | 0xe7f0150d, |
| 829 | 0x14b60a10, | 829 | 0x5c21f500, |
| 830 | 0x0527f006, | 830 | 0x08a7f001, |
| 831 | /* 0x08ab: ctx_xfer_post_save_wait */ | 831 | 0x010321f5, |
| 832 | 0xcf0012d0, | 832 | 0x020721f5, |
| 833 | 0x22fd0012, | 833 | 0xf02201f4, |
| 834 | 0xfa1bf405, | 834 | 0x21f40ca7, |
| 835 | /* 0x08b7: ctx_xfer_post */ | 835 | 0x1017f1c9, |
| 836 | 0xf02e02f4, | 836 | 0x0614b60a, |
| 837 | 0x21f502f7, | 837 | 0xd00527f0, |
| 838 | 0xf4bd0631, | 838 | /* 0x08c2: ctx_xfer_post_save_wait */ |
| 839 | 0x067221f5, | 839 | 0x12cf0012, |
| 840 | 0x022621f5, | 840 | 0x0522fd00, |
| 841 | 0x064021f5, | 841 | 0xf4fa1bf4, |
| 842 | 0x21f5f4bd, | 842 | /* 0x08ce: ctx_xfer_post */ |
| 843 | 0x11f40631, | 843 | 0xf7f02e02, |
| 844 | 0x80019810, | 844 | 0x3121f502, |
| 845 | 0xf40511fd, | 845 | 0xf5f4bd06, |
| 846 | 0x21f5070b, | 846 | 0xf5067221, |
| 847 | /* 0x08e2: ctx_xfer_no_post_mmio */ | 847 | 0xf5022621, |
| 848 | /* 0x08e2: ctx_xfer_done */ | 848 | 0xbd064021, |
| 849 | 0x00f807b1, | 849 | 0x3121f5f4, |
| 850 | 0x00000000, | 850 | 0x1011f406, |
| 851 | 0x00000000, | 851 | 0xfd800198, |
| 852 | 0x00000000, | 852 | 0x0bf40511, |
| 853 | 0x00000000, | 853 | 0xb121f507, |
| 854 | 0x00000000, | 854 | /* 0x08f9: ctx_xfer_no_post_mmio */ |
| 855 | 0x00000000, | 855 | /* 0x08f9: ctx_xfer_done */ |
| 856 | 0x0000f807, | ||
| 856 | 0x00000000, | 857 | 0x00000000, |
| 857 | }; | 858 | }; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 47a02081d708..45aff5f5085a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | |||
| @@ -516,18 +516,9 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 516 | { | 516 | { |
| 517 | struct nouveau_device *device = nv_device(parent); | 517 | struct nouveau_device *device = nv_device(parent); |
| 518 | struct nvc0_graph_priv *priv; | 518 | struct nvc0_graph_priv *priv; |
| 519 | bool enable = true; | ||
| 520 | int ret, i; | 519 | int ret, i; |
| 521 | 520 | ||
| 522 | switch (device->chipset) { | 521 | ret = nouveau_graph_create(parent, engine, oclass, true, &priv); |
| 523 | case 0xd9: /* known broken without binary driver firmware */ | ||
| 524 | enable = false; | ||
| 525 | break; | ||
| 526 | default: | ||
| 527 | break; | ||
| 528 | } | ||
| 529 | |||
| 530 | ret = nouveau_graph_create(parent, engine, oclass, enable, &priv); | ||
| 531 | *pobject = nv_object(priv); | 522 | *pobject = nv_object(priv); |
| 532 | if (ret) | 523 | if (ret) |
| 533 | return ret; | 524 | return ret; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index 18d2210e12eb..a1e78de46456 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h | |||
| @@ -121,6 +121,7 @@ nvc0_graph_class(void *obj) | |||
| 121 | return 0x9297; | 121 | return 0x9297; |
| 122 | case 0xe4: | 122 | case 0xe4: |
| 123 | case 0xe7: | 123 | case 0xe7: |
| 124 | case 0xe6: | ||
| 124 | return 0xa097; | 125 | return 0xa097; |
| 125 | default: | 126 | default: |
| 126 | return 0; | 127 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 539d4c72f192..9f82e9702b46 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | |||
| @@ -203,7 +203,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 203 | struct nvc0_graph_priv *priv; | 203 | struct nvc0_graph_priv *priv; |
| 204 | int ret, i; | 204 | int ret, i; |
| 205 | 205 | ||
| 206 | ret = nouveau_graph_create(parent, engine, oclass, false, &priv); | 206 | ret = nouveau_graph_create(parent, engine, oclass, true, &priv); |
| 207 | *pobject = nv_object(priv); | 207 | *pobject = nv_object(priv); |
| 208 | if (ret) | 208 | if (ret) |
| 209 | return ret; | 209 | return ret; |
| @@ -252,6 +252,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 252 | priv->magic_not_rop_nr = 1; | 252 | priv->magic_not_rop_nr = 1; |
| 253 | break; | 253 | break; |
| 254 | case 0xe7: | 254 | case 0xe7: |
| 255 | case 0xe6: | ||
| 255 | priv->magic_not_rop_nr = 1; | 256 | priv->magic_not_rop_nr = 1; |
| 256 | break; | 257 | break; |
| 257 | default: | 258 | default: |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios.h index d145b25e6be4..5bd1ca8cd20d 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios.h | |||
| @@ -17,6 +17,7 @@ struct nouveau_bios { | |||
| 17 | u8 chip; | 17 | u8 chip; |
| 18 | u8 minor; | 18 | u8 minor; |
| 19 | u8 micro; | 19 | u8 micro; |
| 20 | u8 patch; | ||
| 20 | } version; | 21 | } version; |
| 21 | }; | 22 | }; |
| 22 | 23 | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h index 2bf178082a36..e6563b5cb08e 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h | |||
| @@ -25,9 +25,11 @@ struct dcb_gpio_func { | |||
| 25 | u8 param; | 25 | u8 param; |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | u16 dcb_gpio_table(struct nouveau_bios *); | 28 | u16 dcb_gpio_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); |
| 29 | u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver); | 29 | u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len); |
| 30 | int dcb_gpio_parse(struct nouveau_bios *, int idx, u8 func, u8 line, | 30 | u16 dcb_gpio_parse(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len, |
| 31 | struct dcb_gpio_func *); | 31 | struct dcb_gpio_func *); |
| 32 | u16 dcb_gpio_match(struct nouveau_bios *, int idx, u8 func, u8 line, | ||
| 33 | u8 *ver, u8 *len, struct dcb_gpio_func *); | ||
| 32 | 34 | ||
| 33 | #endif | 35 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h index e69a8bdc6e97..ca2f6bf37f46 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h | |||
| @@ -13,6 +13,7 @@ struct nvbios_init { | |||
| 13 | u32 nested; | 13 | u32 nested; |
| 14 | u16 repeat; | 14 | u16 repeat; |
| 15 | u16 repend; | 15 | u16 repend; |
| 16 | u32 ramcfg; | ||
| 16 | }; | 17 | }; |
| 17 | 18 | ||
| 18 | int nvbios_exec(struct nvbios_init *); | 19 | int nvbios_exec(struct nvbios_init *); |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h index 9ea2b12cc15d..b75e8f18e52c 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h | |||
| @@ -11,7 +11,7 @@ struct nouveau_gpio { | |||
| 11 | struct nouveau_subdev base; | 11 | struct nouveau_subdev base; |
| 12 | 12 | ||
| 13 | /* hardware interfaces */ | 13 | /* hardware interfaces */ |
| 14 | void (*reset)(struct nouveau_gpio *); | 14 | void (*reset)(struct nouveau_gpio *, u8 func); |
| 15 | int (*drive)(struct nouveau_gpio *, int line, int dir, int out); | 15 | int (*drive)(struct nouveau_gpio *, int line, int dir, int out); |
| 16 | int (*sense)(struct nouveau_gpio *, int line); | 16 | int (*sense)(struct nouveau_gpio *, int line); |
| 17 | void (*irq_enable)(struct nouveau_gpio *, int line, bool); | 17 | void (*irq_enable)(struct nouveau_gpio *, int line, bool); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index dd111947eb86..f621f69fa1a2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c | |||
| @@ -447,6 +447,7 @@ nouveau_bios_ctor(struct nouveau_object *parent, | |||
| 447 | bios->version.chip = nv_ro08(bios, bit_i.offset + 2); | 447 | bios->version.chip = nv_ro08(bios, bit_i.offset + 2); |
| 448 | bios->version.minor = nv_ro08(bios, bit_i.offset + 1); | 448 | bios->version.minor = nv_ro08(bios, bit_i.offset + 1); |
| 449 | bios->version.micro = nv_ro08(bios, bit_i.offset + 0); | 449 | bios->version.micro = nv_ro08(bios, bit_i.offset + 0); |
| 450 | bios->version.patch = nv_ro08(bios, bit_i.offset + 4); | ||
| 450 | } else | 451 | } else |
| 451 | if (bmp_version(bios)) { | 452 | if (bmp_version(bios)) { |
| 452 | bios->version.major = nv_ro08(bios, bios->bmp_offset + 13); | 453 | bios->version.major = nv_ro08(bios, bios->bmp_offset + 13); |
| @@ -455,9 +456,9 @@ nouveau_bios_ctor(struct nouveau_object *parent, | |||
| 455 | bios->version.micro = nv_ro08(bios, bios->bmp_offset + 10); | 456 | bios->version.micro = nv_ro08(bios, bios->bmp_offset + 10); |
| 456 | } | 457 | } |
| 457 | 458 | ||
| 458 | nv_info(bios, "version %02x.%02x.%02x.%02x\n", | 459 | nv_info(bios, "version %02x.%02x.%02x.%02x.%02x\n", |
| 459 | bios->version.major, bios->version.chip, | 460 | bios->version.major, bios->version.chip, |
| 460 | bios->version.minor, bios->version.micro); | 461 | bios->version.minor, bios->version.micro, bios->version.patch); |
| 461 | 462 | ||
| 462 | return 0; | 463 | return 0; |
| 463 | } | 464 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c index c90d4aa3ae4f..c84e93fa6d95 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c | |||
| @@ -27,84 +27,105 @@ | |||
| 27 | #include <subdev/bios/gpio.h> | 27 | #include <subdev/bios/gpio.h> |
| 28 | 28 | ||
| 29 | u16 | 29 | u16 |
| 30 | dcb_gpio_table(struct nouveau_bios *bios) | 30 | dcb_gpio_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) |
| 31 | { | 31 | { |
| 32 | u8 ver, hdr, cnt, len; | 32 | u16 data = 0x0000; |
| 33 | u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len); | 33 | u16 dcb = dcb_table(bios, ver, hdr, cnt, len); |
| 34 | if (dcb) { | 34 | if (dcb) { |
| 35 | if (ver >= 0x30 && hdr >= 0x0c) | 35 | if (*ver >= 0x30 && *hdr >= 0x0c) |
| 36 | return nv_ro16(bios, dcb + 0x0a); | 36 | data = nv_ro16(bios, dcb + 0x0a); |
| 37 | if (ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13) | 37 | else |
| 38 | return nv_ro16(bios, dcb - 0x0f); | 38 | if (*ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13) |
| 39 | data = nv_ro16(bios, dcb - 0x0f); | ||
| 40 | |||
| 41 | if (data) { | ||
| 42 | *ver = nv_ro08(bios, data + 0x00); | ||
| 43 | if (*ver < 0x30) { | ||
| 44 | *hdr = 3; | ||
| 45 | *cnt = nv_ro08(bios, data + 0x02); | ||
| 46 | *len = nv_ro08(bios, data + 0x01); | ||
| 47 | } else | ||
| 48 | if (*ver <= 0x41) { | ||
| 49 | *hdr = nv_ro08(bios, data + 0x01); | ||
| 50 | *cnt = nv_ro08(bios, data + 0x02); | ||
| 51 | *len = nv_ro08(bios, data + 0x03); | ||
| 52 | } else { | ||
| 53 | data = 0x0000; | ||
| 54 | } | ||
| 55 | } | ||
| 39 | } | 56 | } |
| 40 | return 0x0000; | 57 | return data; |
| 41 | } | 58 | } |
| 42 | 59 | ||
| 43 | u16 | 60 | u16 |
| 44 | dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver) | 61 | dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len) |
| 45 | { | 62 | { |
| 46 | u16 gpio = dcb_gpio_table(bios); | 63 | u8 hdr, cnt; |
| 47 | if (gpio) { | 64 | u16 gpio = !idx ? dcb_gpio_table(bios, ver, &hdr, &cnt, len) : 0x0000; |
| 48 | *ver = nv_ro08(bios, gpio); | 65 | if (gpio && ent < cnt) |
| 49 | if (*ver < 0x30 && ent < nv_ro08(bios, gpio + 2)) | 66 | return gpio + hdr + (ent * *len); |
| 50 | return gpio + 3 + (ent * nv_ro08(bios, gpio + 1)); | ||
| 51 | else if (ent < nv_ro08(bios, gpio + 2)) | ||
| 52 | return gpio + nv_ro08(bios, gpio + 1) + | ||
| 53 | (ent * nv_ro08(bios, gpio + 3)); | ||
| 54 | } | ||
| 55 | return 0x0000; | 67 | return 0x0000; |
| 56 | } | 68 | } |
| 57 | 69 | ||
| 58 | int | 70 | u16 |
| 59 | dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, | 71 | dcb_gpio_parse(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len, |
| 60 | struct dcb_gpio_func *gpio) | 72 | struct dcb_gpio_func *gpio) |
| 61 | { | 73 | { |
| 62 | u8 ver, hdr, cnt, len; | 74 | u16 data = dcb_gpio_entry(bios, idx, ent, ver, len); |
| 63 | u16 entry; | 75 | if (data) { |
| 64 | int i = -1; | 76 | if (*ver < 0x40) { |
| 65 | 77 | u16 info = nv_ro16(bios, data); | |
| 66 | while ((entry = dcb_gpio_entry(bios, idx, ++i, &ver))) { | ||
| 67 | if (ver < 0x40) { | ||
| 68 | u16 data = nv_ro16(bios, entry); | ||
| 69 | *gpio = (struct dcb_gpio_func) { | 78 | *gpio = (struct dcb_gpio_func) { |
| 70 | .line = (data & 0x001f) >> 0, | 79 | .line = (info & 0x001f) >> 0, |
| 71 | .func = (data & 0x07e0) >> 5, | 80 | .func = (info & 0x07e0) >> 5, |
| 72 | .log[0] = (data & 0x1800) >> 11, | 81 | .log[0] = (info & 0x1800) >> 11, |
| 73 | .log[1] = (data & 0x6000) >> 13, | 82 | .log[1] = (info & 0x6000) >> 13, |
| 74 | .param = !!(data & 0x8000), | 83 | .param = !!(info & 0x8000), |
| 75 | }; | 84 | }; |
| 76 | } else | 85 | } else |
| 77 | if (ver < 0x41) { | 86 | if (*ver < 0x41) { |
| 78 | u32 data = nv_ro32(bios, entry); | 87 | u32 info = nv_ro32(bios, data); |
| 79 | *gpio = (struct dcb_gpio_func) { | 88 | *gpio = (struct dcb_gpio_func) { |
| 80 | .line = (data & 0x0000001f) >> 0, | 89 | .line = (info & 0x0000001f) >> 0, |
| 81 | .func = (data & 0x0000ff00) >> 8, | 90 | .func = (info & 0x0000ff00) >> 8, |
| 82 | .log[0] = (data & 0x18000000) >> 27, | 91 | .log[0] = (info & 0x18000000) >> 27, |
| 83 | .log[1] = (data & 0x60000000) >> 29, | 92 | .log[1] = (info & 0x60000000) >> 29, |
| 84 | .param = !!(data & 0x80000000), | 93 | .param = !!(info & 0x80000000), |
| 85 | }; | 94 | }; |
| 86 | } else { | 95 | } else { |
| 87 | u32 data = nv_ro32(bios, entry + 0); | 96 | u32 info = nv_ro32(bios, data + 0); |
| 88 | u8 data1 = nv_ro32(bios, entry + 4); | 97 | u8 info1 = nv_ro32(bios, data + 4); |
| 89 | *gpio = (struct dcb_gpio_func) { | 98 | *gpio = (struct dcb_gpio_func) { |
| 90 | .line = (data & 0x0000003f) >> 0, | 99 | .line = (info & 0x0000003f) >> 0, |
| 91 | .func = (data & 0x0000ff00) >> 8, | 100 | .func = (info & 0x0000ff00) >> 8, |
| 92 | .log[0] = (data1 & 0x30) >> 4, | 101 | .log[0] = (info1 & 0x30) >> 4, |
| 93 | .log[1] = (data1 & 0xc0) >> 6, | 102 | .log[1] = (info1 & 0xc0) >> 6, |
| 94 | .param = !!(data & 0x80000000), | 103 | .param = !!(info & 0x80000000), |
| 95 | }; | 104 | }; |
| 96 | } | 105 | } |
| 106 | } | ||
| 107 | |||
| 108 | return data; | ||
| 109 | } | ||
| 97 | 110 | ||
| 111 | u16 | ||
| 112 | dcb_gpio_match(struct nouveau_bios *bios, int idx, u8 func, u8 line, | ||
| 113 | u8 *ver, u8 *len, struct dcb_gpio_func *gpio) | ||
| 114 | { | ||
| 115 | u8 hdr, cnt, i = 0; | ||
| 116 | u16 data; | ||
| 117 | |||
| 118 | while ((data = dcb_gpio_parse(bios, idx, i++, ver, len, gpio))) { | ||
| 98 | if ((line == 0xff || line == gpio->line) && | 119 | if ((line == 0xff || line == gpio->line) && |
| 99 | (func == 0xff || func == gpio->func)) | 120 | (func == 0xff || func == gpio->func)) |
| 100 | return 0; | 121 | return data; |
| 101 | } | 122 | } |
| 102 | 123 | ||
| 103 | /* DCB 2.2, fixed TVDAC GPIO data */ | 124 | /* DCB 2.2, fixed TVDAC GPIO data */ |
| 104 | if ((entry = dcb_table(bios, &ver, &hdr, &cnt, &len))) { | 125 | if ((data = dcb_table(bios, ver, &hdr, &cnt, len))) { |
| 105 | if (ver >= 0x22 && ver < 0x30 && func == DCB_GPIO_TVDAC0) { | 126 | if (*ver >= 0x22 && *ver < 0x30 && func == DCB_GPIO_TVDAC0) { |
| 106 | u8 conf = nv_ro08(bios, entry - 5); | 127 | u8 conf = nv_ro08(bios, data - 5); |
| 107 | u8 addr = nv_ro08(bios, entry - 4); | 128 | u8 addr = nv_ro08(bios, data - 4); |
| 108 | if (conf & 0x01) { | 129 | if (conf & 0x01) { |
| 109 | *gpio = (struct dcb_gpio_func) { | 130 | *gpio = (struct dcb_gpio_func) { |
| 110 | .func = DCB_GPIO_TVDAC0, | 131 | .func = DCB_GPIO_TVDAC0, |
| @@ -112,10 +133,11 @@ dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, | |||
| 112 | .log[0] = !!(conf & 0x02), | 133 | .log[0] = !!(conf & 0x02), |
| 113 | .log[1] = !(conf & 0x02), | 134 | .log[1] = !(conf & 0x02), |
| 114 | }; | 135 | }; |
| 115 | return 0; | 136 | *ver = 0x00; |
| 137 | return data; | ||
| 116 | } | 138 | } |
| 117 | } | 139 | } |
| 118 | } | 140 | } |
| 119 | 141 | ||
| 120 | return -EINVAL; | 142 | return 0x0000; |
| 121 | } | 143 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index ae168bbb86d8..2917d552689b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c | |||
| @@ -2,11 +2,12 @@ | |||
| 2 | #include <core/device.h> | 2 | #include <core/device.h> |
| 3 | 3 | ||
| 4 | #include <subdev/bios.h> | 4 | #include <subdev/bios.h> |
| 5 | #include <subdev/bios/conn.h> | ||
| 6 | #include <subdev/bios/bmp.h> | 5 | #include <subdev/bios/bmp.h> |
| 7 | #include <subdev/bios/bit.h> | 6 | #include <subdev/bios/bit.h> |
| 7 | #include <subdev/bios/conn.h> | ||
| 8 | #include <subdev/bios/dcb.h> | 8 | #include <subdev/bios/dcb.h> |
| 9 | #include <subdev/bios/dp.h> | 9 | #include <subdev/bios/dp.h> |
| 10 | #include <subdev/bios/gpio.h> | ||
| 10 | #include <subdev/bios/init.h> | 11 | #include <subdev/bios/init.h> |
| 11 | #include <subdev/devinit.h> | 12 | #include <subdev/devinit.h> |
| 12 | #include <subdev/clock.h> | 13 | #include <subdev/clock.h> |
| @@ -410,9 +411,25 @@ init_ram_restrict_group_count(struct nvbios_init *init) | |||
| 410 | } | 411 | } |
| 411 | 412 | ||
| 412 | static u8 | 413 | static u8 |
| 414 | init_ram_restrict_strap(struct nvbios_init *init) | ||
| 415 | { | ||
| 416 | /* This appears to be the behaviour of the VBIOS parser, and *is* | ||
| 417 | * important to cache the NV_PEXTDEV_BOOT0 on later chipsets to | ||
| 418 | * avoid fucking up the memory controller (somehow) by reading it | ||
| 419 | * on every INIT_RAM_RESTRICT_ZM_GROUP opcode. | ||
| 420 | * | ||
| 421 | * Preserving the non-caching behaviour on earlier chipsets just | ||
| 422 | * in case *not* re-reading the strap causes similar breakage. | ||
| 423 | */ | ||
| 424 | if (!init->ramcfg || init->bios->version.major < 0x70) | ||
| 425 | init->ramcfg = init_rd32(init, 0x101000); | ||
| 426 | return (init->ramcfg & 0x00000003c) >> 2; | ||
| 427 | } | ||
| 428 | |||
| 429 | static u8 | ||
| 413 | init_ram_restrict(struct nvbios_init *init) | 430 | init_ram_restrict(struct nvbios_init *init) |
| 414 | { | 431 | { |
| 415 | u32 strap = (init_rd32(init, 0x101000) & 0x0000003c) >> 2; | 432 | u8 strap = init_ram_restrict_strap(init); |
| 416 | u16 table = init_ram_restrict_table(init); | 433 | u16 table = init_ram_restrict_table(init); |
| 417 | if (table) | 434 | if (table) |
| 418 | return nv_ro08(init->bios, table + strap); | 435 | return nv_ro08(init->bios, table + strap); |
| @@ -1781,7 +1798,7 @@ init_gpio(struct nvbios_init *init) | |||
| 1781 | init->offset += 1; | 1798 | init->offset += 1; |
| 1782 | 1799 | ||
| 1783 | if (init_exec(init) && gpio && gpio->reset) | 1800 | if (init_exec(init) && gpio && gpio->reset) |
| 1784 | gpio->reset(gpio); | 1801 | gpio->reset(gpio, DCB_GPIO_UNUSED); |
| 1785 | } | 1802 | } |
| 1786 | 1803 | ||
| 1787 | /** | 1804 | /** |
| @@ -1995,6 +2012,47 @@ init_i2c_long_if(struct nvbios_init *init) | |||
| 1995 | init_exec_set(init, false); | 2012 | init_exec_set(init, false); |
| 1996 | } | 2013 | } |
| 1997 | 2014 | ||
| 2015 | /** | ||
| 2016 | * INIT_GPIO_NE - opcode 0xa9 | ||
| 2017 | * | ||
| 2018 | */ | ||
| 2019 | static void | ||
| 2020 | init_gpio_ne(struct nvbios_init *init) | ||
| 2021 | { | ||
| 2022 | struct nouveau_bios *bios = init->bios; | ||
| 2023 | struct nouveau_gpio *gpio = nouveau_gpio(bios); | ||
| 2024 | struct dcb_gpio_func func; | ||
| 2025 | u8 count = nv_ro08(bios, init->offset + 1); | ||
| 2026 | u8 idx = 0, ver, len; | ||
| 2027 | u16 data, i; | ||
| 2028 | |||
| 2029 | trace("GPIO_NE\t"); | ||
| 2030 | init->offset += 2; | ||
| 2031 | |||
| 2032 | for (i = init->offset; i < init->offset + count; i++) | ||
| 2033 | cont("0x%02x ", nv_ro08(bios, i)); | ||
| 2034 | cont("\n"); | ||
| 2035 | |||
| 2036 | while ((data = dcb_gpio_parse(bios, 0, idx++, &ver, &len, &func))) { | ||
| 2037 | if (func.func != DCB_GPIO_UNUSED) { | ||
| 2038 | for (i = init->offset; i < init->offset + count; i++) { | ||
| 2039 | if (func.func == nv_ro08(bios, i)) | ||
| 2040 | break; | ||
| 2041 | } | ||
| 2042 | |||
| 2043 | trace("\tFUNC[0x%02x]", func.func); | ||
| 2044 | if (i == (init->offset + count)) { | ||
| 2045 | cont(" *"); | ||
| 2046 | if (init_exec(init) && gpio && gpio->reset) | ||
| 2047 | gpio->reset(gpio, func.func); | ||
| 2048 | } | ||
| 2049 | cont("\n"); | ||
| 2050 | } | ||
| 2051 | } | ||
| 2052 | |||
| 2053 | init->offset += count; | ||
| 2054 | } | ||
| 2055 | |||
| 1998 | static struct nvbios_init_opcode { | 2056 | static struct nvbios_init_opcode { |
| 1999 | void (*exec)(struct nvbios_init *); | 2057 | void (*exec)(struct nvbios_init *); |
| 2000 | } init_opcode[] = { | 2058 | } init_opcode[] = { |
| @@ -2059,6 +2117,7 @@ static struct nvbios_init_opcode { | |||
| 2059 | [0x98] = { init_auxch }, | 2117 | [0x98] = { init_auxch }, |
| 2060 | [0x99] = { init_zm_auxch }, | 2118 | [0x99] = { init_zm_auxch }, |
| 2061 | [0x9a] = { init_i2c_long_if }, | 2119 | [0x9a] = { init_i2c_long_if }, |
| 2120 | [0xa9] = { init_gpio_ne }, | ||
| 2062 | }; | 2121 | }; |
| 2063 | 2122 | ||
| 2064 | #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) | 2123 | #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 9b7881e76634..03a652876e73 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | |||
| @@ -109,6 +109,34 @@ nve0_identify(struct nouveau_device *device) | |||
| 109 | device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; | 109 | device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; |
| 110 | device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; | 110 | device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; |
| 111 | break; | 111 | break; |
| 112 | case 0xe6: | ||
| 113 | device->cname = "GK106"; | ||
| 114 | device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; | ||
| 115 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; | ||
| 116 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | ||
| 117 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | ||
| 118 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
| 119 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | ||
| 120 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | ||
| 121 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | ||
| 122 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | ||
| 123 | device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; | ||
| 124 | device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; | ||
| 125 | device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass; | ||
| 126 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | ||
| 127 | device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; | ||
| 128 | device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; | ||
| 129 | device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; | ||
| 130 | device->oclass[NVDEV_ENGINE_FIFO ] = &nve0_fifo_oclass; | ||
| 131 | device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; | ||
| 132 | device->oclass[NVDEV_ENGINE_GR ] = &nve0_graph_oclass; | ||
| 133 | device->oclass[NVDEV_ENGINE_DISP ] = &nve0_disp_oclass; | ||
| 134 | device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass; | ||
| 135 | device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass; | ||
| 136 | device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass; | ||
| 137 | device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; | ||
| 138 | device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; | ||
| 139 | break; | ||
| 112 | default: | 140 | default: |
| 113 | nv_fatal(device, "unknown Kepler chipset\n"); | 141 | nv_fatal(device, "unknown Kepler chipset\n"); |
| 114 | return -EINVAL; | 142 | return -EINVAL; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c index acf818c58bf0..9fb0f9b92d49 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c | |||
| @@ -43,10 +43,15 @@ static int | |||
| 43 | nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, | 43 | nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, |
| 44 | struct dcb_gpio_func *func) | 44 | struct dcb_gpio_func *func) |
| 45 | { | 45 | { |
| 46 | struct nouveau_bios *bios = nouveau_bios(gpio); | ||
| 47 | u8 ver, len; | ||
| 48 | u16 data; | ||
| 49 | |||
| 46 | if (line == 0xff && tag == 0xff) | 50 | if (line == 0xff && tag == 0xff) |
| 47 | return -EINVAL; | 51 | return -EINVAL; |
| 48 | 52 | ||
| 49 | if (!dcb_gpio_parse(nouveau_bios(gpio), idx, tag, line, func)) | 53 | data = dcb_gpio_match(bios, idx, tag, line, &ver, &len, func); |
| 54 | if (data) | ||
| 50 | return 0; | 55 | return 0; |
| 51 | 56 | ||
| 52 | /* Apple iMac G4 NV18 */ | 57 | /* Apple iMac G4 NV18 */ |
| @@ -265,7 +270,7 @@ nouveau_gpio_init(struct nouveau_gpio *gpio) | |||
| 265 | int ret = nouveau_subdev_init(&gpio->base); | 270 | int ret = nouveau_subdev_init(&gpio->base); |
| 266 | if (ret == 0 && gpio->reset) { | 271 | if (ret == 0 && gpio->reset) { |
| 267 | if (dmi_check_system(gpio_reset_ids)) | 272 | if (dmi_check_system(gpio_reset_ids)) |
| 268 | gpio->reset(gpio); | 273 | gpio->reset(gpio, DCB_GPIO_UNUSED); |
| 269 | } | 274 | } |
| 270 | return ret; | 275 | return ret; |
| 271 | } | 276 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c index f3502c961cd9..bf13a1200f26 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c | |||
| @@ -29,15 +29,15 @@ struct nv50_gpio_priv { | |||
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | static void | 31 | static void |
| 32 | nv50_gpio_reset(struct nouveau_gpio *gpio) | 32 | nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match) |
| 33 | { | 33 | { |
| 34 | struct nouveau_bios *bios = nouveau_bios(gpio); | 34 | struct nouveau_bios *bios = nouveau_bios(gpio); |
| 35 | struct nv50_gpio_priv *priv = (void *)gpio; | 35 | struct nv50_gpio_priv *priv = (void *)gpio; |
| 36 | u8 ver, len; | ||
| 36 | u16 entry; | 37 | u16 entry; |
| 37 | u8 ver; | ||
| 38 | int ent = -1; | 38 | int ent = -1; |
| 39 | 39 | ||
| 40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) { | 40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) { |
| 41 | static const u32 regs[] = { 0xe100, 0xe28c }; | 41 | static const u32 regs[] = { 0xe100, 0xe28c }; |
| 42 | u32 data = nv_ro32(bios, entry); | 42 | u32 data = nv_ro32(bios, entry); |
| 43 | u8 line = (data & 0x0000001f); | 43 | u8 line = (data & 0x0000001f); |
| @@ -48,7 +48,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio) | |||
| 48 | u32 val = (unk1 << 16) | unk0; | 48 | u32 val = (unk1 << 16) | unk0; |
| 49 | u32 reg = regs[line >> 4]; line &= 0x0f; | 49 | u32 reg = regs[line >> 4]; line &= 0x0f; |
| 50 | 50 | ||
| 51 | if (func == 0xff) | 51 | if ( func == DCB_GPIO_UNUSED || |
| 52 | (match != DCB_GPIO_UNUSED && match != func)) | ||
| 52 | continue; | 53 | continue; |
| 53 | 54 | ||
| 54 | gpio->set(gpio, 0, func, line, defs); | 55 | gpio->set(gpio, 0, func, line, defs); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c index 8d18fcad26e0..83e8b8f16e6a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c | |||
| @@ -29,15 +29,15 @@ struct nvd0_gpio_priv { | |||
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | static void | 31 | static void |
| 32 | nvd0_gpio_reset(struct nouveau_gpio *gpio) | 32 | nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match) |
| 33 | { | 33 | { |
| 34 | struct nouveau_bios *bios = nouveau_bios(gpio); | 34 | struct nouveau_bios *bios = nouveau_bios(gpio); |
| 35 | struct nvd0_gpio_priv *priv = (void *)gpio; | 35 | struct nvd0_gpio_priv *priv = (void *)gpio; |
| 36 | u8 ver, len; | ||
| 36 | u16 entry; | 37 | u16 entry; |
| 37 | u8 ver; | ||
| 38 | int ent = -1; | 38 | int ent = -1; |
| 39 | 39 | ||
| 40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) { | 40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) { |
| 41 | u32 data = nv_ro32(bios, entry); | 41 | u32 data = nv_ro32(bios, entry); |
| 42 | u8 line = (data & 0x0000003f); | 42 | u8 line = (data & 0x0000003f); |
| 43 | u8 defs = !!(data & 0x00000080); | 43 | u8 defs = !!(data & 0x00000080); |
| @@ -45,7 +45,8 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio) | |||
| 45 | u8 unk0 = (data & 0x00ff0000) >> 16; | 45 | u8 unk0 = (data & 0x00ff0000) >> 16; |
| 46 | u8 unk1 = (data & 0x1f000000) >> 24; | 46 | u8 unk1 = (data & 0x1f000000) >> 24; |
| 47 | 47 | ||
| 48 | if (func == 0xff) | 48 | if ( func == DCB_GPIO_UNUSED || |
| 49 | (match != DCB_GPIO_UNUSED && match != func)) | ||
| 49 | continue; | 50 | continue; |
| 50 | 51 | ||
| 51 | gpio->set(gpio, 0, func, line, defs); | 52 | gpio->set(gpio, 0, func, line, defs); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c index 93e3ddf7303a..e286e132c7e7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c | |||
| @@ -260,7 +260,7 @@ nouveau_mxm_create_(struct nouveau_object *parent, | |||
| 260 | 260 | ||
| 261 | data = mxm_table(bios, &ver, &len); | 261 | data = mxm_table(bios, &ver, &len); |
| 262 | if (!data || !(ver = nv_ro08(bios, data))) { | 262 | if (!data || !(ver = nv_ro08(bios, data))) { |
| 263 | nv_info(mxm, "no VBIOS data, nothing to do\n"); | 263 | nv_debug(mxm, "no VBIOS data, nothing to do\n"); |
| 264 | return 0; | 264 | return 0; |
| 265 | } | 265 | } |
| 266 | 266 | ||
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 74c6b42d2597..7a445666e71f 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c | |||
| @@ -2654,6 +2654,35 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
| 2654 | ib[idx+4] = upper_32_bits(offset) & 0xff; | 2654 | ib[idx+4] = upper_32_bits(offset) & 0xff; |
| 2655 | } | 2655 | } |
| 2656 | break; | 2656 | break; |
| 2657 | case PACKET3_MEM_WRITE: | ||
| 2658 | { | ||
| 2659 | u64 offset; | ||
| 2660 | |||
| 2661 | if (pkt->count != 3) { | ||
| 2662 | DRM_ERROR("bad MEM_WRITE (invalid count)\n"); | ||
| 2663 | return -EINVAL; | ||
| 2664 | } | ||
| 2665 | r = evergreen_cs_packet_next_reloc(p, &reloc); | ||
| 2666 | if (r) { | ||
| 2667 | DRM_ERROR("bad MEM_WRITE (missing reloc)\n"); | ||
| 2668 | return -EINVAL; | ||
| 2669 | } | ||
| 2670 | offset = radeon_get_ib_value(p, idx+0); | ||
| 2671 | offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL; | ||
| 2672 | if (offset & 0x7) { | ||
| 2673 | DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n"); | ||
| 2674 | return -EINVAL; | ||
| 2675 | } | ||
| 2676 | if ((offset + 8) > radeon_bo_size(reloc->robj)) { | ||
| 2677 | DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n", | ||
| 2678 | offset + 8, radeon_bo_size(reloc->robj)); | ||
| 2679 | return -EINVAL; | ||
| 2680 | } | ||
| 2681 | offset += reloc->lobj.gpu_offset; | ||
| 2682 | ib[idx+0] = offset; | ||
| 2683 | ib[idx+1] = upper_32_bits(offset) & 0xff; | ||
| 2684 | break; | ||
| 2685 | } | ||
| 2657 | case PACKET3_COPY_DW: | 2686 | case PACKET3_COPY_DW: |
| 2658 | if (pkt->count != 4) { | 2687 | if (pkt->count != 4) { |
| 2659 | DRM_ERROR("bad COPY_DW (invalid count)\n"); | 2688 | DRM_ERROR("bad COPY_DW (invalid count)\n"); |
| @@ -3287,6 +3316,7 @@ static bool evergreen_vm_reg_valid(u32 reg) | |||
| 3287 | 3316 | ||
| 3288 | /* check config regs */ | 3317 | /* check config regs */ |
| 3289 | switch (reg) { | 3318 | switch (reg) { |
| 3319 | case WAIT_UNTIL: | ||
| 3290 | case GRBM_GFX_INDEX: | 3320 | case GRBM_GFX_INDEX: |
| 3291 | case CP_STRMOUT_CNTL: | 3321 | case CP_STRMOUT_CNTL: |
| 3292 | case CP_COHER_CNTL: | 3322 | case CP_COHER_CNTL: |
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 0be768be530c..9ea13d07cc55 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
| @@ -2294,6 +2294,35 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
| 2294 | ib[idx+4] = upper_32_bits(offset) & 0xff; | 2294 | ib[idx+4] = upper_32_bits(offset) & 0xff; |
| 2295 | } | 2295 | } |
| 2296 | break; | 2296 | break; |
| 2297 | case PACKET3_MEM_WRITE: | ||
| 2298 | { | ||
| 2299 | u64 offset; | ||
| 2300 | |||
| 2301 | if (pkt->count != 3) { | ||
| 2302 | DRM_ERROR("bad MEM_WRITE (invalid count)\n"); | ||
| 2303 | return -EINVAL; | ||
| 2304 | } | ||
| 2305 | r = r600_cs_packet_next_reloc(p, &reloc); | ||
| 2306 | if (r) { | ||
| 2307 | DRM_ERROR("bad MEM_WRITE (missing reloc)\n"); | ||
| 2308 | return -EINVAL; | ||
| 2309 | } | ||
| 2310 | offset = radeon_get_ib_value(p, idx+0); | ||
| 2311 | offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL; | ||
| 2312 | if (offset & 0x7) { | ||
| 2313 | DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n"); | ||
| 2314 | return -EINVAL; | ||
| 2315 | } | ||
| 2316 | if ((offset + 8) > radeon_bo_size(reloc->robj)) { | ||
| 2317 | DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n", | ||
| 2318 | offset + 8, radeon_bo_size(reloc->robj)); | ||
| 2319 | return -EINVAL; | ||
| 2320 | } | ||
| 2321 | offset += reloc->lobj.gpu_offset; | ||
| 2322 | ib[idx+0] = offset; | ||
| 2323 | ib[idx+1] = upper_32_bits(offset) & 0xff; | ||
| 2324 | break; | ||
| 2325 | } | ||
| 2297 | case PACKET3_COPY_DW: | 2326 | case PACKET3_COPY_DW: |
| 2298 | if (pkt->count != 4) { | 2327 | if (pkt->count != 4) { |
| 2299 | DRM_ERROR("bad COPY_DW (invalid count)\n"); | 2328 | DRM_ERROR("bad COPY_DW (invalid count)\n"); |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5dc744d43d12..9b9422c4403a 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -225,12 +225,13 @@ struct radeon_fence { | |||
| 225 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); | 225 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); |
| 226 | int radeon_fence_driver_init(struct radeon_device *rdev); | 226 | int radeon_fence_driver_init(struct radeon_device *rdev); |
| 227 | void radeon_fence_driver_fini(struct radeon_device *rdev); | 227 | void radeon_fence_driver_fini(struct radeon_device *rdev); |
| 228 | void radeon_fence_driver_force_completion(struct radeon_device *rdev); | ||
| 228 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); | 229 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); |
| 229 | void radeon_fence_process(struct radeon_device *rdev, int ring); | 230 | void radeon_fence_process(struct radeon_device *rdev, int ring); |
| 230 | bool radeon_fence_signaled(struct radeon_fence *fence); | 231 | bool radeon_fence_signaled(struct radeon_fence *fence); |
| 231 | int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); | 232 | int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); |
| 232 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); | 233 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); |
| 233 | void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); | 234 | int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); |
| 234 | int radeon_fence_wait_any(struct radeon_device *rdev, | 235 | int radeon_fence_wait_any(struct radeon_device *rdev, |
| 235 | struct radeon_fence **fences, | 236 | struct radeon_fence **fences, |
| 236 | bool intr); | 237 | bool intr); |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 49b06590001e..cd756262924d 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -1164,6 +1164,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
| 1164 | struct drm_crtc *crtc; | 1164 | struct drm_crtc *crtc; |
| 1165 | struct drm_connector *connector; | 1165 | struct drm_connector *connector; |
| 1166 | int i, r; | 1166 | int i, r; |
| 1167 | bool force_completion = false; | ||
| 1167 | 1168 | ||
| 1168 | if (dev == NULL || dev->dev_private == NULL) { | 1169 | if (dev == NULL || dev->dev_private == NULL) { |
| 1169 | return -ENODEV; | 1170 | return -ENODEV; |
| @@ -1206,8 +1207,16 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
| 1206 | 1207 | ||
| 1207 | mutex_lock(&rdev->ring_lock); | 1208 | mutex_lock(&rdev->ring_lock); |
| 1208 | /* wait for gpu to finish processing current batch */ | 1209 | /* wait for gpu to finish processing current batch */ |
| 1209 | for (i = 0; i < RADEON_NUM_RINGS; i++) | 1210 | for (i = 0; i < RADEON_NUM_RINGS; i++) { |
| 1210 | radeon_fence_wait_empty_locked(rdev, i); | 1211 | r = radeon_fence_wait_empty_locked(rdev, i); |
| 1212 | if (r) { | ||
| 1213 | /* delay GPU reset to resume */ | ||
| 1214 | force_completion = true; | ||
| 1215 | } | ||
| 1216 | } | ||
| 1217 | if (force_completion) { | ||
| 1218 | radeon_fence_driver_force_completion(rdev); | ||
| 1219 | } | ||
| 1211 | mutex_unlock(&rdev->ring_lock); | 1220 | mutex_unlock(&rdev->ring_lock); |
| 1212 | 1221 | ||
| 1213 | radeon_save_bios_scratch_regs(rdev); | 1222 | radeon_save_bios_scratch_regs(rdev); |
| @@ -1338,7 +1347,6 @@ retry: | |||
| 1338 | } | 1347 | } |
| 1339 | 1348 | ||
| 1340 | radeon_restore_bios_scratch_regs(rdev); | 1349 | radeon_restore_bios_scratch_regs(rdev); |
| 1341 | drm_helper_resume_force_mode(rdev->ddev); | ||
| 1342 | 1350 | ||
| 1343 | if (!r) { | 1351 | if (!r) { |
| 1344 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 1352 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
| @@ -1358,11 +1366,14 @@ retry: | |||
| 1358 | } | 1366 | } |
| 1359 | } | 1367 | } |
| 1360 | } else { | 1368 | } else { |
| 1369 | radeon_fence_driver_force_completion(rdev); | ||
| 1361 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 1370 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
| 1362 | kfree(ring_data[i]); | 1371 | kfree(ring_data[i]); |
| 1363 | } | 1372 | } |
| 1364 | } | 1373 | } |
| 1365 | 1374 | ||
| 1375 | drm_helper_resume_force_mode(rdev->ddev); | ||
| 1376 | |||
| 1366 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); | 1377 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); |
| 1367 | if (r) { | 1378 | if (r) { |
| 1368 | /* bad news, how to tell it to userspace ? */ | 1379 | /* bad news, how to tell it to userspace ? */ |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 9b1a727d3c9e..ff7593498a74 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -68,9 +68,10 @@ | |||
| 68 | * 2.25.0 - eg+: new info request for num SE and num SH | 68 | * 2.25.0 - eg+: new info request for num SE and num SH |
| 69 | * 2.26.0 - r600-eg: fix htile size computation | 69 | * 2.26.0 - r600-eg: fix htile size computation |
| 70 | * 2.27.0 - r600-SI: Add CS ioctl support for async DMA | 70 | * 2.27.0 - r600-SI: Add CS ioctl support for async DMA |
| 71 | * 2.28.0 - r600-eg: Add MEM_WRITE packet support | ||
| 71 | */ | 72 | */ |
| 72 | #define KMS_DRIVER_MAJOR 2 | 73 | #define KMS_DRIVER_MAJOR 2 |
| 73 | #define KMS_DRIVER_MINOR 27 | 74 | #define KMS_DRIVER_MINOR 28 |
| 74 | #define KMS_DRIVER_PATCHLEVEL 0 | 75 | #define KMS_DRIVER_PATCHLEVEL 0 |
| 75 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); | 76 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); |
| 76 | int radeon_driver_unload_kms(struct drm_device *dev); | 77 | int radeon_driver_unload_kms(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 410a975a8eec..34356252567a 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
| @@ -609,26 +609,20 @@ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) | |||
| 609 | * Returns 0 if the fences have passed, error for all other cases. | 609 | * Returns 0 if the fences have passed, error for all other cases. |
| 610 | * Caller must hold ring lock. | 610 | * Caller must hold ring lock. |
| 611 | */ | 611 | */ |
| 612 | void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) | 612 | int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) |
| 613 | { | 613 | { |
| 614 | uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; | 614 | uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; |
| 615 | int r; | ||
| 615 | 616 | ||
| 616 | while(1) { | 617 | r = radeon_fence_wait_seq(rdev, seq, ring, false, false); |
| 617 | int r; | 618 | if (r) { |
| 618 | r = radeon_fence_wait_seq(rdev, seq, ring, false, false); | ||
| 619 | if (r == -EDEADLK) { | 619 | if (r == -EDEADLK) { |
| 620 | mutex_unlock(&rdev->ring_lock); | 620 | return -EDEADLK; |
| 621 | r = radeon_gpu_reset(rdev); | ||
| 622 | mutex_lock(&rdev->ring_lock); | ||
| 623 | if (!r) | ||
| 624 | continue; | ||
| 625 | } | ||
| 626 | if (r) { | ||
| 627 | dev_err(rdev->dev, "error waiting for ring to become" | ||
| 628 | " idle (%d)\n", r); | ||
| 629 | } | 621 | } |
| 630 | return; | 622 | dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%d)\n", |
| 623 | ring, r); | ||
| 631 | } | 624 | } |
| 625 | return 0; | ||
| 632 | } | 626 | } |
| 633 | 627 | ||
| 634 | /** | 628 | /** |
| @@ -854,13 +848,17 @@ int radeon_fence_driver_init(struct radeon_device *rdev) | |||
| 854 | */ | 848 | */ |
| 855 | void radeon_fence_driver_fini(struct radeon_device *rdev) | 849 | void radeon_fence_driver_fini(struct radeon_device *rdev) |
| 856 | { | 850 | { |
| 857 | int ring; | 851 | int ring, r; |
| 858 | 852 | ||
| 859 | mutex_lock(&rdev->ring_lock); | 853 | mutex_lock(&rdev->ring_lock); |
| 860 | for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { | 854 | for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { |
| 861 | if (!rdev->fence_drv[ring].initialized) | 855 | if (!rdev->fence_drv[ring].initialized) |
| 862 | continue; | 856 | continue; |
| 863 | radeon_fence_wait_empty_locked(rdev, ring); | 857 | r = radeon_fence_wait_empty_locked(rdev, ring); |
| 858 | if (r) { | ||
| 859 | /* no need to trigger GPU reset as we are unloading */ | ||
| 860 | radeon_fence_driver_force_completion(rdev); | ||
| 861 | } | ||
| 864 | wake_up_all(&rdev->fence_queue); | 862 | wake_up_all(&rdev->fence_queue); |
| 865 | radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); | 863 | radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); |
| 866 | rdev->fence_drv[ring].initialized = false; | 864 | rdev->fence_drv[ring].initialized = false; |
| @@ -868,6 +866,25 @@ void radeon_fence_driver_fini(struct radeon_device *rdev) | |||
| 868 | mutex_unlock(&rdev->ring_lock); | 866 | mutex_unlock(&rdev->ring_lock); |
| 869 | } | 867 | } |
| 870 | 868 | ||
| 869 | /** | ||
| 870 | * radeon_fence_driver_force_completion - force all fence waiter to complete | ||
| 871 | * | ||
| 872 | * @rdev: radeon device pointer | ||
| 873 | * | ||
| 874 | * In case of GPU reset failure make sure no process keep waiting on fence | ||
| 875 | * that will never complete. | ||
| 876 | */ | ||
| 877 | void radeon_fence_driver_force_completion(struct radeon_device *rdev) | ||
| 878 | { | ||
| 879 | int ring; | ||
| 880 | |||
| 881 | for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { | ||
| 882 | if (!rdev->fence_drv[ring].initialized) | ||
| 883 | continue; | ||
| 884 | radeon_fence_write(rdev, rdev->fence_drv[ring].sync_seq[ring], ring); | ||
| 885 | } | ||
| 886 | } | ||
| 887 | |||
| 871 | 888 | ||
| 872 | /* | 889 | /* |
| 873 | * Fence debugfs | 890 | * Fence debugfs |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index aa14dbb7e4fb..0bfa656aa87d 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
| @@ -234,7 +234,7 @@ static void radeon_set_power_state(struct radeon_device *rdev) | |||
| 234 | 234 | ||
| 235 | static void radeon_pm_set_clocks(struct radeon_device *rdev) | 235 | static void radeon_pm_set_clocks(struct radeon_device *rdev) |
| 236 | { | 236 | { |
| 237 | int i; | 237 | int i, r; |
| 238 | 238 | ||
| 239 | /* no need to take locks, etc. if nothing's going to change */ | 239 | /* no need to take locks, etc. if nothing's going to change */ |
| 240 | if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && | 240 | if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && |
| @@ -248,8 +248,17 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) | |||
| 248 | /* wait for the rings to drain */ | 248 | /* wait for the rings to drain */ |
| 249 | for (i = 0; i < RADEON_NUM_RINGS; i++) { | 249 | for (i = 0; i < RADEON_NUM_RINGS; i++) { |
| 250 | struct radeon_ring *ring = &rdev->ring[i]; | 250 | struct radeon_ring *ring = &rdev->ring[i]; |
| 251 | if (ring->ready) | 251 | if (!ring->ready) { |
| 252 | radeon_fence_wait_empty_locked(rdev, i); | 252 | continue; |
| 253 | } | ||
| 254 | r = radeon_fence_wait_empty_locked(rdev, i); | ||
| 255 | if (r) { | ||
| 256 | /* needs a GPU reset dont reset here */ | ||
| 257 | mutex_unlock(&rdev->ring_lock); | ||
| 258 | up_write(&rdev->pm.mclk_lock); | ||
| 259 | mutex_unlock(&rdev->ddev->struct_mutex); | ||
| 260 | return; | ||
| 261 | } | ||
| 253 | } | 262 | } |
| 254 | 263 | ||
| 255 | radeon_unmap_vram_bos(rdev); | 264 | radeon_unmap_vram_bos(rdev); |
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 074410371e2a..656b2e3334a6 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
| @@ -102,12 +102,12 @@ static int tegra_dc_set_timings(struct tegra_dc *dc, | |||
| 102 | ((mode->hsync_end - mode->hsync_start) << 0); | 102 | ((mode->hsync_end - mode->hsync_start) << 0); |
| 103 | tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH); | 103 | tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH); |
| 104 | 104 | ||
| 105 | value = ((mode->vsync_start - mode->vdisplay) << 16) | | ||
| 106 | ((mode->hsync_start - mode->hdisplay) << 0); | ||
| 107 | tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH); | ||
| 108 | |||
| 109 | value = ((mode->vtotal - mode->vsync_end) << 16) | | 105 | value = ((mode->vtotal - mode->vsync_end) << 16) | |
| 110 | ((mode->htotal - mode->hsync_end) << 0); | 106 | ((mode->htotal - mode->hsync_end) << 0); |
| 107 | tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH); | ||
| 108 | |||
| 109 | value = ((mode->vsync_start - mode->vdisplay) << 16) | | ||
| 110 | ((mode->hsync_start - mode->hdisplay) << 0); | ||
| 111 | tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH); | 111 | tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH); |
| 112 | 112 | ||
| 113 | value = (mode->vdisplay << 16) | mode->hdisplay; | 113 | value = (mode->vdisplay << 16) | mode->hdisplay; |
| @@ -221,8 +221,7 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc, | |||
| 221 | win.stride = crtc->fb->pitches[0]; | 221 | win.stride = crtc->fb->pitches[0]; |
| 222 | 222 | ||
| 223 | /* program window registers */ | 223 | /* program window registers */ |
| 224 | value = tegra_dc_readl(dc, DC_CMD_DISPLAY_WINDOW_HEADER); | 224 | value = WINDOW_A_SELECT; |
| 225 | value |= WINDOW_A_SELECT; | ||
| 226 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); | 225 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); |
| 227 | 226 | ||
| 228 | tegra_dc_writel(dc, win.fmt, DC_WIN_COLOR_DEPTH); | 227 | tegra_dc_writel(dc, win.fmt, DC_WIN_COLOR_DEPTH); |
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 3a843a77ddc7..741b5dc2742c 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h | |||
| @@ -204,24 +204,6 @@ extern int tegra_output_parse_dt(struct tegra_output *output); | |||
| 204 | extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output); | 204 | extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output); |
| 205 | extern int tegra_output_exit(struct tegra_output *output); | 205 | extern int tegra_output_exit(struct tegra_output *output); |
| 206 | 206 | ||
| 207 | /* from gem.c */ | ||
| 208 | extern struct tegra_gem_object *tegra_gem_alloc(struct drm_device *drm, | ||
| 209 | size_t size); | ||
| 210 | extern int tegra_gem_handle_create(struct drm_device *drm, | ||
| 211 | struct drm_file *file, size_t size, | ||
| 212 | unsigned long flags, uint32_t *handle); | ||
| 213 | extern int tegra_gem_dumb_create(struct drm_file *file, struct drm_device *drm, | ||
| 214 | struct drm_mode_create_dumb *args); | ||
| 215 | extern int tegra_gem_dumb_map_offset(struct drm_file *file, | ||
| 216 | struct drm_device *drm, uint32_t handle, | ||
| 217 | uint64_t *offset); | ||
| 218 | extern int tegra_gem_dumb_destroy(struct drm_file *file, | ||
| 219 | struct drm_device *drm, uint32_t handle); | ||
| 220 | extern int tegra_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); | ||
| 221 | extern int tegra_gem_init_object(struct drm_gem_object *obj); | ||
| 222 | extern void tegra_gem_free_object(struct drm_gem_object *obj); | ||
| 223 | extern struct vm_operations_struct tegra_gem_vm_ops; | ||
| 224 | |||
| 225 | /* from fb.c */ | 207 | /* from fb.c */ |
| 226 | extern int tegra_drm_fb_init(struct drm_device *drm); | 208 | extern int tegra_drm_fb_init(struct drm_device *drm); |
| 227 | extern void tegra_drm_fb_exit(struct drm_device *drm); | 209 | extern void tegra_drm_fb_exit(struct drm_device *drm); |
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index ab4016412bbf..e060c7e6434d 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c | |||
| @@ -149,7 +149,7 @@ struct tmds_config { | |||
| 149 | }; | 149 | }; |
| 150 | 150 | ||
| 151 | static const struct tmds_config tegra2_tmds_config[] = { | 151 | static const struct tmds_config tegra2_tmds_config[] = { |
| 152 | { /* 480p modes */ | 152 | { /* slow pixel clock modes */ |
| 153 | .pclk = 27000000, | 153 | .pclk = 27000000, |
| 154 | .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | | 154 | .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | |
| 155 | SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) | | 155 | SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(0) | |
| @@ -163,21 +163,8 @@ static const struct tmds_config tegra2_tmds_config[] = { | |||
| 163 | DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) | | 163 | DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) | |
| 164 | DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) | | 164 | DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) | |
| 165 | DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA), | 165 | DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA), |
| 166 | }, { /* 720p modes */ | 166 | }, |
| 167 | .pclk = 74250000, | 167 | { /* high pixel clock modes */ |
| 168 | .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | | ||
| 169 | SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) | | ||
| 170 | SOR_PLL_TX_REG_LOAD(3), | ||
| 171 | .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN, | ||
| 172 | .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) | | ||
| 173 | PE_CURRENT1(PE_CURRENT_6_0_mA) | | ||
| 174 | PE_CURRENT2(PE_CURRENT_6_0_mA) | | ||
| 175 | PE_CURRENT3(PE_CURRENT_6_0_mA), | ||
| 176 | .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) | | ||
| 177 | DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) | | ||
| 178 | DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) | | ||
| 179 | DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA), | ||
| 180 | }, { /* 1080p modes */ | ||
| 181 | .pclk = UINT_MAX, | 168 | .pclk = UINT_MAX, |
| 182 | .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | | 169 | .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | |
| 183 | SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) | | 170 | SOR_PLL_RESISTORSEL | SOR_PLL_VCOCAP(1) | |
| @@ -479,7 +466,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi, | |||
| 479 | return; | 466 | return; |
| 480 | } | 467 | } |
| 481 | 468 | ||
| 482 | h_front_porch = mode->htotal - mode->hsync_end; | 469 | h_front_porch = mode->hsync_start - mode->hdisplay; |
| 483 | memset(&frame, 0, sizeof(frame)); | 470 | memset(&frame, 0, sizeof(frame)); |
| 484 | frame.r = HDMI_AVI_R_SAME; | 471 | frame.r = HDMI_AVI_R_SAME; |
| 485 | 472 | ||
| @@ -634,8 +621,8 @@ static int tegra_output_hdmi_enable(struct tegra_output *output) | |||
| 634 | 621 | ||
| 635 | pclk = mode->clock * 1000; | 622 | pclk = mode->clock * 1000; |
| 636 | h_sync_width = mode->hsync_end - mode->hsync_start; | 623 | h_sync_width = mode->hsync_end - mode->hsync_start; |
| 637 | h_front_porch = mode->htotal - mode->hsync_end; | 624 | h_back_porch = mode->htotal - mode->hsync_end; |
| 638 | h_back_porch = mode->hsync_start - mode->hdisplay; | 625 | h_front_porch = mode->hsync_start - mode->hdisplay; |
| 639 | 626 | ||
| 640 | err = regulator_enable(hdmi->vdd); | 627 | err = regulator_enable(hdmi->vdd); |
| 641 | if (err < 0) { | 628 | if (err < 0) { |
diff --git a/drivers/gpu/drm/tegra/host1x.c b/drivers/gpu/drm/tegra/host1x.c index bdb97a564d82..5d17b113a6fc 100644 --- a/drivers/gpu/drm/tegra/host1x.c +++ b/drivers/gpu/drm/tegra/host1x.c | |||
| @@ -239,6 +239,8 @@ int host1x_register_client(struct host1x *host1x, struct host1x_client *client) | |||
| 239 | } | 239 | } |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | client->host1x = host1x; | ||
| 243 | |||
| 242 | return 0; | 244 | return 0; |
| 243 | } | 245 | } |
| 244 | 246 | ||
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 06d7f798a08c..0f4a366f6fa6 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h | |||
| @@ -158,12 +158,29 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic_range( | |||
| 158 | return drm_mm_get_block_range_generic(parent, size, alignment, 0, | 158 | return drm_mm_get_block_range_generic(parent, size, alignment, 0, |
| 159 | start, end, 1); | 159 | start, end, 1); |
| 160 | } | 160 | } |
| 161 | extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, | 161 | |
| 162 | unsigned long size, unsigned alignment); | 162 | extern int drm_mm_insert_node(struct drm_mm *mm, |
| 163 | struct drm_mm_node *node, | ||
| 164 | unsigned long size, | ||
| 165 | unsigned alignment); | ||
| 163 | extern int drm_mm_insert_node_in_range(struct drm_mm *mm, | 166 | extern int drm_mm_insert_node_in_range(struct drm_mm *mm, |
| 164 | struct drm_mm_node *node, | 167 | struct drm_mm_node *node, |
| 165 | unsigned long size, unsigned alignment, | 168 | unsigned long size, |
| 166 | unsigned long start, unsigned long end); | 169 | unsigned alignment, |
| 170 | unsigned long start, | ||
| 171 | unsigned long end); | ||
| 172 | extern int drm_mm_insert_node_generic(struct drm_mm *mm, | ||
| 173 | struct drm_mm_node *node, | ||
| 174 | unsigned long size, | ||
| 175 | unsigned alignment, | ||
| 176 | unsigned long color); | ||
| 177 | extern int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, | ||
| 178 | struct drm_mm_node *node, | ||
| 179 | unsigned long size, | ||
| 180 | unsigned alignment, | ||
| 181 | unsigned long color, | ||
| 182 | unsigned long start, | ||
| 183 | unsigned long end); | ||
| 167 | extern void drm_mm_put_block(struct drm_mm_node *cur); | 184 | extern void drm_mm_put_block(struct drm_mm_node *cur); |
| 168 | extern void drm_mm_remove_node(struct drm_mm_node *node); | 185 | extern void drm_mm_remove_node(struct drm_mm_node *node); |
| 169 | extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); | 186 | extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); |
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index b746a3cf5fa9..c4d2e9c74002 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h | |||
| @@ -307,6 +307,7 @@ typedef struct drm_i915_irq_wait { | |||
| 307 | #define I915_PARAM_HAS_PRIME_VMAP_FLUSH 21 | 307 | #define I915_PARAM_HAS_PRIME_VMAP_FLUSH 21 |
| 308 | #define I915_PARAM_RSVD_FOR_FUTURE_USE 22 | 308 | #define I915_PARAM_RSVD_FOR_FUTURE_USE 22 |
| 309 | #define I915_PARAM_HAS_SECURE_BATCHES 23 | 309 | #define I915_PARAM_HAS_SECURE_BATCHES 23 |
| 310 | #define I915_PARAM_HAS_PINNED_BATCHES 24 | ||
| 310 | 311 | ||
| 311 | typedef struct drm_i915_getparam { | 312 | typedef struct drm_i915_getparam { |
| 312 | int param; | 313 | int param; |
| @@ -677,6 +678,15 @@ struct drm_i915_gem_execbuffer2 { | |||
| 677 | */ | 678 | */ |
| 678 | #define I915_EXEC_SECURE (1<<9) | 679 | #define I915_EXEC_SECURE (1<<9) |
| 679 | 680 | ||
| 681 | /** Inform the kernel that the batch is and will always be pinned. This | ||
| 682 | * negates the requirement for a workaround to be performed to avoid | ||
| 683 | * an incoherent CS (such as can be found on 830/845). If this flag is | ||
| 684 | * not passed, the kernel will endeavour to make sure the batch is | ||
| 685 | * coherent with the CS before execution. If this flag is passed, | ||
| 686 | * userspace assumes the responsibility for ensuring the same. | ||
| 687 | */ | ||
| 688 | #define I915_EXEC_IS_PINNED (1<<10) | ||
| 689 | |||
| 680 | #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) | 690 | #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) |
| 681 | #define i915_execbuffer2_set_context_id(eb2, context) \ | 691 | #define i915_execbuffer2_set_context_id(eb2, context) \ |
| 682 | (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK | 692 | (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK |
