diff options
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 513 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_suspend.c | 40 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 146 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 19 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 84 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/atom.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r600_cs.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r600_reg.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_bios.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_combios.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_connectors.c | 34 |
15 files changed, 510 insertions, 384 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index f7af91cb273d..7ca59359fee2 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -471,6 +471,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 471 | int count = 0, ro, fail = 0; | 471 | int count = 0, ro, fail = 0; |
| 472 | struct drm_crtc_helper_funcs *crtc_funcs; | 472 | struct drm_crtc_helper_funcs *crtc_funcs; |
| 473 | int ret = 0; | 473 | int ret = 0; |
| 474 | int i; | ||
| 474 | 475 | ||
| 475 | DRM_DEBUG_KMS("\n"); | 476 | DRM_DEBUG_KMS("\n"); |
| 476 | 477 | ||
| @@ -666,6 +667,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 666 | if (ret != 0) | 667 | if (ret != 0) |
| 667 | goto fail; | 668 | goto fail; |
| 668 | } | 669 | } |
| 670 | DRM_DEBUG_KMS("Setting connector DPMS state to on\n"); | ||
| 671 | for (i = 0; i < set->num_connectors; i++) { | ||
| 672 | DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, | ||
| 673 | drm_get_connector_name(set->connectors[i])); | ||
| 674 | set->connectors[i]->dpms = DRM_MODE_DPMS_ON; | ||
| 675 | } | ||
| 669 | 676 | ||
| 670 | kfree(save_connectors); | 677 | kfree(save_connectors); |
| 671 | kfree(save_encoders); | 678 | kfree(save_encoders); |
| @@ -841,7 +848,7 @@ static void output_poll_execute(struct work_struct *work) | |||
| 841 | struct delayed_work *delayed_work = to_delayed_work(work); | 848 | struct delayed_work *delayed_work = to_delayed_work(work); |
| 842 | struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); | 849 | struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); |
| 843 | struct drm_connector *connector; | 850 | struct drm_connector *connector; |
| 844 | enum drm_connector_status old_status, status; | 851 | enum drm_connector_status old_status; |
| 845 | bool repoll = false, changed = false; | 852 | bool repoll = false, changed = false; |
| 846 | 853 | ||
| 847 | if (!drm_kms_helper_poll) | 854 | if (!drm_kms_helper_poll) |
| @@ -866,8 +873,9 @@ static void output_poll_execute(struct work_struct *work) | |||
| 866 | !(connector->polled & DRM_CONNECTOR_POLL_HPD)) | 873 | !(connector->polled & DRM_CONNECTOR_POLL_HPD)) |
| 867 | continue; | 874 | continue; |
| 868 | 875 | ||
| 869 | status = connector->funcs->detect(connector, false); | 876 | connector->status = connector->funcs->detect(connector, false); |
| 870 | if (old_status != status) | 877 | DRM_DEBUG_KMS("connector status updated to %d\n", connector->status); |
| 878 | if (old_status != connector->status) | ||
| 871 | changed = true; | 879 | changed = true; |
| 872 | } | 880 | } |
| 873 | 881 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 17b1cba3b5f1..5e54821af996 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -38,8 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); | 39 | static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); |
| 40 | 40 | ||
| 41 | static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, | 41 | static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); |
| 42 | bool pipelined); | ||
| 43 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); | 42 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); |
| 44 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); | 43 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); |
| 45 | static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, | 44 | static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, |
| @@ -2594,7 +2593,7 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj, | |||
| 2594 | if (reg->gpu) { | 2593 | if (reg->gpu) { |
| 2595 | int ret; | 2594 | int ret; |
| 2596 | 2595 | ||
| 2597 | ret = i915_gem_object_flush_gpu_write_domain(obj, true); | 2596 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 2598 | if (ret) | 2597 | if (ret) |
| 2599 | return ret; | 2598 | return ret; |
| 2600 | 2599 | ||
| @@ -2742,8 +2741,7 @@ i915_gem_clflush_object(struct drm_gem_object *obj) | |||
| 2742 | 2741 | ||
| 2743 | /** Flushes any GPU write domain for the object if it's dirty. */ | 2742 | /** Flushes any GPU write domain for the object if it's dirty. */ |
| 2744 | static int | 2743 | static int |
| 2745 | i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, | 2744 | i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj) |
| 2746 | bool pipelined) | ||
| 2747 | { | 2745 | { |
| 2748 | struct drm_device *dev = obj->dev; | 2746 | struct drm_device *dev = obj->dev; |
| 2749 | uint32_t old_write_domain; | 2747 | uint32_t old_write_domain; |
| @@ -2762,10 +2760,7 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, | |||
| 2762 | obj->read_domains, | 2760 | obj->read_domains, |
| 2763 | old_write_domain); | 2761 | old_write_domain); |
| 2764 | 2762 | ||
| 2765 | if (pipelined) | 2763 | return 0; |
| 2766 | return 0; | ||
| 2767 | |||
| 2768 | return i915_gem_object_wait_rendering(obj, true); | ||
| 2769 | } | 2764 | } |
| 2770 | 2765 | ||
| 2771 | /** Flushes the GTT write domain for the object if it's dirty. */ | 2766 | /** Flushes the GTT write domain for the object if it's dirty. */ |
| @@ -2826,18 +2821,15 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) | |||
| 2826 | if (obj_priv->gtt_space == NULL) | 2821 | if (obj_priv->gtt_space == NULL) |
| 2827 | return -EINVAL; | 2822 | return -EINVAL; |
| 2828 | 2823 | ||
| 2829 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); | 2824 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 2830 | if (ret != 0) | 2825 | if (ret != 0) |
| 2831 | return ret; | 2826 | return ret; |
| 2827 | ret = i915_gem_object_wait_rendering(obj, true); | ||
| 2828 | if (ret) | ||
| 2829 | return ret; | ||
| 2832 | 2830 | ||
| 2833 | i915_gem_object_flush_cpu_write_domain(obj); | 2831 | i915_gem_object_flush_cpu_write_domain(obj); |
| 2834 | 2832 | ||
| 2835 | if (write) { | ||
| 2836 | ret = i915_gem_object_wait_rendering(obj, true); | ||
| 2837 | if (ret) | ||
| 2838 | return ret; | ||
| 2839 | } | ||
| 2840 | |||
| 2841 | old_write_domain = obj->write_domain; | 2833 | old_write_domain = obj->write_domain; |
| 2842 | old_read_domains = obj->read_domains; | 2834 | old_read_domains = obj->read_domains; |
| 2843 | 2835 | ||
| @@ -2875,7 +2867,7 @@ i915_gem_object_set_to_display_plane(struct drm_gem_object *obj, | |||
| 2875 | if (obj_priv->gtt_space == NULL) | 2867 | if (obj_priv->gtt_space == NULL) |
| 2876 | return -EINVAL; | 2868 | return -EINVAL; |
| 2877 | 2869 | ||
| 2878 | ret = i915_gem_object_flush_gpu_write_domain(obj, true); | 2870 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 2879 | if (ret) | 2871 | if (ret) |
| 2880 | return ret; | 2872 | return ret; |
| 2881 | 2873 | ||
| @@ -2924,9 +2916,12 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
| 2924 | uint32_t old_write_domain, old_read_domains; | 2916 | uint32_t old_write_domain, old_read_domains; |
| 2925 | int ret; | 2917 | int ret; |
| 2926 | 2918 | ||
| 2927 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); | 2919 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 2928 | if (ret != 0) | 2920 | if (ret != 0) |
| 2929 | return ret; | 2921 | return ret; |
| 2922 | ret = i915_gem_object_wait_rendering(obj, true); | ||
| 2923 | if (ret) | ||
| 2924 | return ret; | ||
| 2930 | 2925 | ||
| 2931 | i915_gem_object_flush_gtt_write_domain(obj); | 2926 | i915_gem_object_flush_gtt_write_domain(obj); |
| 2932 | 2927 | ||
| @@ -2935,12 +2930,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
| 2935 | */ | 2930 | */ |
| 2936 | i915_gem_object_set_to_full_cpu_read_domain(obj); | 2931 | i915_gem_object_set_to_full_cpu_read_domain(obj); |
| 2937 | 2932 | ||
| 2938 | if (write) { | ||
| 2939 | ret = i915_gem_object_wait_rendering(obj, true); | ||
| 2940 | if (ret) | ||
| 2941 | return ret; | ||
| 2942 | } | ||
| 2943 | |||
| 2944 | old_write_domain = obj->write_domain; | 2933 | old_write_domain = obj->write_domain; |
| 2945 | old_read_domains = obj->read_domains; | 2934 | old_read_domains = obj->read_domains; |
| 2946 | 2935 | ||
| @@ -3205,9 +3194,13 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
| 3205 | if (offset == 0 && size == obj->size) | 3194 | if (offset == 0 && size == obj->size) |
| 3206 | return i915_gem_object_set_to_cpu_domain(obj, 0); | 3195 | return i915_gem_object_set_to_cpu_domain(obj, 0); |
| 3207 | 3196 | ||
| 3208 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); | 3197 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
| 3209 | if (ret != 0) | 3198 | if (ret != 0) |
| 3210 | return ret; | 3199 | return ret; |
| 3200 | ret = i915_gem_object_wait_rendering(obj, true); | ||
| 3201 | if (ret) | ||
| 3202 | return ret; | ||
| 3203 | |||
| 3211 | i915_gem_object_flush_gtt_write_domain(obj); | 3204 | i915_gem_object_flush_gtt_write_domain(obj); |
| 3212 | 3205 | ||
| 3213 | /* If we're already fully in the CPU read domain, we're done. */ | 3206 | /* If we're already fully in the CPU read domain, we're done. */ |
| @@ -3254,192 +3247,230 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
| 3254 | return 0; | 3247 | return 0; |
| 3255 | } | 3248 | } |
| 3256 | 3249 | ||
| 3257 | /** | ||
| 3258 | * Pin an object to the GTT and evaluate the relocations landing in it. | ||
| 3259 | */ | ||
| 3260 | static int | 3250 | static int |
| 3261 | i915_gem_execbuffer_relocate(struct drm_i915_gem_object *obj, | 3251 | i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, |
| 3262 | struct drm_file *file_priv, | 3252 | struct drm_file *file_priv, |
| 3263 | struct drm_i915_gem_exec_object2 *entry) | 3253 | struct drm_i915_gem_exec_object2 *entry, |
| 3254 | struct drm_i915_gem_relocation_entry *reloc) | ||
| 3264 | { | 3255 | { |
| 3265 | struct drm_device *dev = obj->base.dev; | 3256 | struct drm_device *dev = obj->base.dev; |
| 3266 | drm_i915_private_t *dev_priv = dev->dev_private; | 3257 | struct drm_gem_object *target_obj; |
| 3267 | struct drm_i915_gem_relocation_entry __user *user_relocs; | 3258 | uint32_t target_offset; |
| 3268 | struct drm_gem_object *target_obj = NULL; | 3259 | int ret = -EINVAL; |
| 3269 | uint32_t target_handle = 0; | ||
| 3270 | int i, ret = 0; | ||
| 3271 | 3260 | ||
| 3272 | user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; | 3261 | target_obj = drm_gem_object_lookup(dev, file_priv, |
| 3273 | for (i = 0; i < entry->relocation_count; i++) { | 3262 | reloc->target_handle); |
| 3274 | struct drm_i915_gem_relocation_entry reloc; | 3263 | if (target_obj == NULL) |
| 3275 | uint32_t target_offset; | 3264 | return -ENOENT; |
| 3276 | 3265 | ||
| 3277 | if (__copy_from_user_inatomic(&reloc, | 3266 | target_offset = to_intel_bo(target_obj)->gtt_offset; |
| 3278 | user_relocs+i, | ||
| 3279 | sizeof(reloc))) { | ||
| 3280 | ret = -EFAULT; | ||
| 3281 | break; | ||
| 3282 | } | ||
| 3283 | 3267 | ||
| 3284 | if (reloc.target_handle != target_handle) { | 3268 | #if WATCH_RELOC |
| 3285 | drm_gem_object_unreference(target_obj); | 3269 | DRM_INFO("%s: obj %p offset %08x target %d " |
| 3270 | "read %08x write %08x gtt %08x " | ||
| 3271 | "presumed %08x delta %08x\n", | ||
| 3272 | __func__, | ||
| 3273 | obj, | ||
| 3274 | (int) reloc->offset, | ||
| 3275 | (int) reloc->target_handle, | ||
| 3276 | (int) reloc->read_domains, | ||
| 3277 | (int) reloc->write_domain, | ||
| 3278 | (int) target_offset, | ||
| 3279 | (int) reloc->presumed_offset, | ||
| 3280 | reloc->delta); | ||
| 3281 | #endif | ||
| 3286 | 3282 | ||
| 3287 | target_obj = drm_gem_object_lookup(dev, file_priv, | 3283 | /* The target buffer should have appeared before us in the |
| 3288 | reloc.target_handle); | 3284 | * exec_object list, so it should have a GTT space bound by now. |
| 3289 | if (target_obj == NULL) { | 3285 | */ |
| 3290 | ret = -ENOENT; | 3286 | if (target_offset == 0) { |
| 3291 | break; | 3287 | DRM_ERROR("No GTT space found for object %d\n", |
| 3292 | } | 3288 | reloc->target_handle); |
| 3289 | goto err; | ||
| 3290 | } | ||
| 3293 | 3291 | ||
| 3294 | target_handle = reloc.target_handle; | 3292 | /* Validate that the target is in a valid r/w GPU domain */ |
| 3295 | } | 3293 | if (reloc->write_domain & (reloc->write_domain - 1)) { |
| 3296 | target_offset = to_intel_bo(target_obj)->gtt_offset; | 3294 | DRM_ERROR("reloc with multiple write domains: " |
| 3295 | "obj %p target %d offset %d " | ||
| 3296 | "read %08x write %08x", | ||
| 3297 | obj, reloc->target_handle, | ||
| 3298 | (int) reloc->offset, | ||
| 3299 | reloc->read_domains, | ||
| 3300 | reloc->write_domain); | ||
| 3301 | goto err; | ||
| 3302 | } | ||
| 3303 | if (reloc->write_domain & I915_GEM_DOMAIN_CPU || | ||
| 3304 | reloc->read_domains & I915_GEM_DOMAIN_CPU) { | ||
| 3305 | DRM_ERROR("reloc with read/write CPU domains: " | ||
| 3306 | "obj %p target %d offset %d " | ||
| 3307 | "read %08x write %08x", | ||
| 3308 | obj, reloc->target_handle, | ||
| 3309 | (int) reloc->offset, | ||
| 3310 | reloc->read_domains, | ||
| 3311 | reloc->write_domain); | ||
| 3312 | goto err; | ||
| 3313 | } | ||
| 3314 | if (reloc->write_domain && target_obj->pending_write_domain && | ||
| 3315 | reloc->write_domain != target_obj->pending_write_domain) { | ||
| 3316 | DRM_ERROR("Write domain conflict: " | ||
| 3317 | "obj %p target %d offset %d " | ||
| 3318 | "new %08x old %08x\n", | ||
| 3319 | obj, reloc->target_handle, | ||
| 3320 | (int) reloc->offset, | ||
| 3321 | reloc->write_domain, | ||
| 3322 | target_obj->pending_write_domain); | ||
| 3323 | goto err; | ||
| 3324 | } | ||
| 3297 | 3325 | ||
| 3298 | #if WATCH_RELOC | 3326 | target_obj->pending_read_domains |= reloc->read_domains; |
| 3299 | DRM_INFO("%s: obj %p offset %08x target %d " | 3327 | target_obj->pending_write_domain |= reloc->write_domain; |
| 3300 | "read %08x write %08x gtt %08x " | ||
| 3301 | "presumed %08x delta %08x\n", | ||
| 3302 | __func__, | ||
| 3303 | obj, | ||
| 3304 | (int) reloc.offset, | ||
| 3305 | (int) reloc.target_handle, | ||
| 3306 | (int) reloc.read_domains, | ||
| 3307 | (int) reloc.write_domain, | ||
| 3308 | (int) target_offset, | ||
| 3309 | (int) reloc.presumed_offset, | ||
| 3310 | reloc.delta); | ||
| 3311 | #endif | ||
| 3312 | 3328 | ||
| 3313 | /* The target buffer should have appeared before us in the | 3329 | /* If the relocation already has the right value in it, no |
| 3314 | * exec_object list, so it should have a GTT space bound by now. | 3330 | * more work needs to be done. |
| 3315 | */ | 3331 | */ |
| 3316 | if (target_offset == 0) { | 3332 | if (target_offset == reloc->presumed_offset) |
| 3317 | DRM_ERROR("No GTT space found for object %d\n", | 3333 | goto out; |
| 3318 | reloc.target_handle); | ||
| 3319 | ret = -EINVAL; | ||
| 3320 | break; | ||
| 3321 | } | ||
| 3322 | 3334 | ||
| 3323 | /* Validate that the target is in a valid r/w GPU domain */ | 3335 | /* Check that the relocation address is valid... */ |
| 3324 | if (reloc.write_domain & (reloc.write_domain - 1)) { | 3336 | if (reloc->offset > obj->base.size - 4) { |
| 3325 | DRM_ERROR("reloc with multiple write domains: " | 3337 | DRM_ERROR("Relocation beyond object bounds: " |
| 3326 | "obj %p target %d offset %d " | 3338 | "obj %p target %d offset %d size %d.\n", |
| 3327 | "read %08x write %08x", | 3339 | obj, reloc->target_handle, |
| 3328 | obj, reloc.target_handle, | 3340 | (int) reloc->offset, |
| 3329 | (int) reloc.offset, | 3341 | (int) obj->base.size); |
| 3330 | reloc.read_domains, | 3342 | goto err; |
| 3331 | reloc.write_domain); | 3343 | } |
| 3332 | ret = -EINVAL; | 3344 | if (reloc->offset & 3) { |
| 3333 | break; | 3345 | DRM_ERROR("Relocation not 4-byte aligned: " |
| 3334 | } | 3346 | "obj %p target %d offset %d.\n", |
| 3335 | if (reloc.write_domain & I915_GEM_DOMAIN_CPU || | 3347 | obj, reloc->target_handle, |
| 3336 | reloc.read_domains & I915_GEM_DOMAIN_CPU) { | 3348 | (int) reloc->offset); |
| 3337 | DRM_ERROR("reloc with read/write CPU domains: " | 3349 | goto err; |
| 3338 | "obj %p target %d offset %d " | 3350 | } |
| 3339 | "read %08x write %08x", | ||
| 3340 | obj, reloc.target_handle, | ||
| 3341 | (int) reloc.offset, | ||
| 3342 | reloc.read_domains, | ||
| 3343 | reloc.write_domain); | ||
| 3344 | ret = -EINVAL; | ||
| 3345 | break; | ||
| 3346 | } | ||
| 3347 | if (reloc.write_domain && target_obj->pending_write_domain && | ||
| 3348 | reloc.write_domain != target_obj->pending_write_domain) { | ||
| 3349 | DRM_ERROR("Write domain conflict: " | ||
| 3350 | "obj %p target %d offset %d " | ||
| 3351 | "new %08x old %08x\n", | ||
| 3352 | obj, reloc.target_handle, | ||
| 3353 | (int) reloc.offset, | ||
| 3354 | reloc.write_domain, | ||
| 3355 | target_obj->pending_write_domain); | ||
| 3356 | ret = -EINVAL; | ||
| 3357 | break; | ||
| 3358 | } | ||
| 3359 | 3351 | ||
| 3360 | target_obj->pending_read_domains |= reloc.read_domains; | 3352 | /* and points to somewhere within the target object. */ |
| 3361 | target_obj->pending_write_domain |= reloc.write_domain; | 3353 | if (reloc->delta >= target_obj->size) { |
| 3354 | DRM_ERROR("Relocation beyond target object bounds: " | ||
| 3355 | "obj %p target %d delta %d size %d.\n", | ||
| 3356 | obj, reloc->target_handle, | ||
| 3357 | (int) reloc->delta, | ||
| 3358 | (int) target_obj->size); | ||
| 3359 | goto err; | ||
| 3360 | } | ||
| 3362 | 3361 | ||
| 3363 | /* If the relocation already has the right value in it, no | 3362 | reloc->delta += target_offset; |
| 3364 | * more work needs to be done. | 3363 | if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { |
| 3365 | */ | 3364 | uint32_t page_offset = reloc->offset & ~PAGE_MASK; |
| 3366 | if (target_offset == reloc.presumed_offset) | 3365 | char *vaddr; |
| 3367 | continue; | ||
| 3368 | 3366 | ||
| 3369 | /* Check that the relocation address is valid... */ | 3367 | vaddr = kmap_atomic(obj->pages[reloc->offset >> PAGE_SHIFT]); |
| 3370 | if (reloc.offset > obj->base.size - 4) { | 3368 | *(uint32_t *)(vaddr + page_offset) = reloc->delta; |
| 3371 | DRM_ERROR("Relocation beyond object bounds: " | 3369 | kunmap_atomic(vaddr); |
| 3372 | "obj %p target %d offset %d size %d.\n", | 3370 | } else { |
| 3373 | obj, reloc.target_handle, | 3371 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3374 | (int) reloc.offset, (int) obj->base.size); | 3372 | uint32_t __iomem *reloc_entry; |
| 3375 | ret = -EINVAL; | 3373 | void __iomem *reloc_page; |
| 3376 | break; | ||
| 3377 | } | ||
| 3378 | if (reloc.offset & 3) { | ||
| 3379 | DRM_ERROR("Relocation not 4-byte aligned: " | ||
| 3380 | "obj %p target %d offset %d.\n", | ||
| 3381 | obj, reloc.target_handle, | ||
| 3382 | (int) reloc.offset); | ||
| 3383 | ret = -EINVAL; | ||
| 3384 | break; | ||
| 3385 | } | ||
| 3386 | 3374 | ||
| 3387 | /* and points to somewhere within the target object. */ | 3375 | ret = i915_gem_object_set_to_gtt_domain(&obj->base, 1); |
| 3388 | if (reloc.delta >= target_obj->size) { | 3376 | if (ret) |
| 3389 | DRM_ERROR("Relocation beyond target object bounds: " | 3377 | goto err; |
| 3390 | "obj %p target %d delta %d size %d.\n", | ||
| 3391 | obj, reloc.target_handle, | ||
| 3392 | (int) reloc.delta, (int) target_obj->size); | ||
| 3393 | ret = -EINVAL; | ||
| 3394 | break; | ||
| 3395 | } | ||
| 3396 | 3378 | ||
| 3397 | reloc.delta += target_offset; | 3379 | /* Map the page containing the relocation we're going to perform. */ |
| 3398 | if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { | 3380 | reloc->offset += obj->gtt_offset; |
| 3399 | uint32_t page_offset = reloc.offset & ~PAGE_MASK; | 3381 | reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, |
| 3400 | char *vaddr; | 3382 | reloc->offset & PAGE_MASK); |
| 3383 | reloc_entry = (uint32_t __iomem *) | ||
| 3384 | (reloc_page + (reloc->offset & ~PAGE_MASK)); | ||
| 3385 | iowrite32(reloc->delta, reloc_entry); | ||
| 3386 | io_mapping_unmap_atomic(reloc_page); | ||
| 3387 | } | ||
| 3401 | 3388 | ||
| 3402 | vaddr = kmap_atomic(obj->pages[reloc.offset >> PAGE_SHIFT]); | 3389 | /* and update the user's relocation entry */ |
| 3403 | *(uint32_t *)(vaddr + page_offset) = reloc.delta; | 3390 | reloc->presumed_offset = target_offset; |
| 3404 | kunmap_atomic(vaddr); | ||
| 3405 | } else { | ||
| 3406 | uint32_t __iomem *reloc_entry; | ||
| 3407 | void __iomem *reloc_page; | ||
| 3408 | 3391 | ||
| 3409 | ret = i915_gem_object_set_to_gtt_domain(&obj->base, 1); | 3392 | out: |
| 3410 | if (ret) | 3393 | ret = 0; |
| 3411 | break; | 3394 | err: |
| 3395 | drm_gem_object_unreference(target_obj); | ||
| 3396 | return ret; | ||
| 3397 | } | ||
| 3412 | 3398 | ||
| 3413 | /* Map the page containing the relocation we're going to perform. */ | 3399 | static int |
| 3414 | reloc.offset += obj->gtt_offset; | 3400 | i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, |
| 3415 | reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | 3401 | struct drm_file *file_priv, |
| 3416 | reloc.offset & PAGE_MASK); | 3402 | struct drm_i915_gem_exec_object2 *entry) |
| 3417 | reloc_entry = (uint32_t __iomem *) | 3403 | { |
| 3418 | (reloc_page + (reloc.offset & ~PAGE_MASK)); | 3404 | struct drm_i915_gem_relocation_entry __user *user_relocs; |
| 3419 | iowrite32(reloc.delta, reloc_entry); | 3405 | int i, ret; |
| 3420 | io_mapping_unmap_atomic(reloc_page); | 3406 | |
| 3421 | } | 3407 | user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; |
| 3408 | for (i = 0; i < entry->relocation_count; i++) { | ||
| 3409 | struct drm_i915_gem_relocation_entry reloc; | ||
| 3410 | |||
| 3411 | if (__copy_from_user_inatomic(&reloc, | ||
| 3412 | user_relocs+i, | ||
| 3413 | sizeof(reloc))) | ||
| 3414 | return -EFAULT; | ||
| 3415 | |||
| 3416 | ret = i915_gem_execbuffer_relocate_entry(obj, file_priv, entry, &reloc); | ||
| 3417 | if (ret) | ||
| 3418 | return ret; | ||
| 3422 | 3419 | ||
| 3423 | /* and update the user's relocation entry */ | ||
| 3424 | reloc.presumed_offset = target_offset; | ||
| 3425 | if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset, | 3420 | if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset, |
| 3426 | &reloc.presumed_offset, | 3421 | &reloc.presumed_offset, |
| 3427 | sizeof(reloc.presumed_offset))) { | 3422 | sizeof(reloc.presumed_offset))) |
| 3428 | ret = -EFAULT; | 3423 | return -EFAULT; |
| 3429 | break; | ||
| 3430 | } | ||
| 3431 | } | 3424 | } |
| 3432 | 3425 | ||
| 3433 | drm_gem_object_unreference(target_obj); | 3426 | return 0; |
| 3434 | return ret; | 3427 | } |
| 3428 | |||
| 3429 | static int | ||
| 3430 | i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj, | ||
| 3431 | struct drm_file *file_priv, | ||
| 3432 | struct drm_i915_gem_exec_object2 *entry, | ||
| 3433 | struct drm_i915_gem_relocation_entry *relocs) | ||
| 3434 | { | ||
| 3435 | int i, ret; | ||
| 3436 | |||
| 3437 | for (i = 0; i < entry->relocation_count; i++) { | ||
| 3438 | ret = i915_gem_execbuffer_relocate_entry(obj, file_priv, entry, &relocs[i]); | ||
| 3439 | if (ret) | ||
| 3440 | return ret; | ||
| 3441 | } | ||
| 3442 | |||
| 3443 | return 0; | ||
| 3435 | } | 3444 | } |
| 3436 | 3445 | ||
| 3437 | static int | 3446 | static int |
| 3438 | i915_gem_execbuffer_pin(struct drm_device *dev, | 3447 | i915_gem_execbuffer_relocate(struct drm_device *dev, |
| 3439 | struct drm_file *file, | 3448 | struct drm_file *file, |
| 3440 | struct drm_gem_object **object_list, | 3449 | struct drm_gem_object **object_list, |
| 3441 | struct drm_i915_gem_exec_object2 *exec_list, | 3450 | struct drm_i915_gem_exec_object2 *exec_list, |
| 3442 | int count) | 3451 | int count) |
| 3452 | { | ||
| 3453 | int i, ret; | ||
| 3454 | |||
| 3455 | for (i = 0; i < count; i++) { | ||
| 3456 | struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); | ||
| 3457 | obj->base.pending_read_domains = 0; | ||
| 3458 | obj->base.pending_write_domain = 0; | ||
| 3459 | ret = i915_gem_execbuffer_relocate_object(obj, file, | ||
| 3460 | &exec_list[i]); | ||
| 3461 | if (ret) | ||
| 3462 | return ret; | ||
| 3463 | } | ||
| 3464 | |||
| 3465 | return 0; | ||
| 3466 | } | ||
| 3467 | |||
| 3468 | static int | ||
| 3469 | i915_gem_execbuffer_reserve(struct drm_device *dev, | ||
| 3470 | struct drm_file *file, | ||
| 3471 | struct drm_gem_object **object_list, | ||
| 3472 | struct drm_i915_gem_exec_object2 *exec_list, | ||
| 3473 | int count) | ||
| 3443 | { | 3474 | { |
| 3444 | struct drm_i915_private *dev_priv = dev->dev_private; | 3475 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3445 | int ret, i, retry; | 3476 | int ret, i, retry; |
| @@ -3502,6 +3533,87 @@ i915_gem_execbuffer_pin(struct drm_device *dev, | |||
| 3502 | } | 3533 | } |
| 3503 | 3534 | ||
| 3504 | static int | 3535 | static int |
| 3536 | i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | ||
| 3537 | struct drm_file *file, | ||
| 3538 | struct drm_gem_object **object_list, | ||
| 3539 | struct drm_i915_gem_exec_object2 *exec_list, | ||
| 3540 | int count) | ||
| 3541 | { | ||
| 3542 | struct drm_i915_gem_relocation_entry *reloc; | ||
| 3543 | int i, total, ret; | ||
| 3544 | |||
| 3545 | for (i = 0; i < count; i++) { | ||
| 3546 | struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); | ||
| 3547 | obj->in_execbuffer = false; | ||
| 3548 | } | ||
| 3549 | |||
| 3550 | mutex_unlock(&dev->struct_mutex); | ||
| 3551 | |||
| 3552 | total = 0; | ||
| 3553 | for (i = 0; i < count; i++) | ||
| 3554 | total += exec_list[i].relocation_count; | ||
| 3555 | |||
| 3556 | reloc = drm_malloc_ab(total, sizeof(*reloc)); | ||
| 3557 | if (reloc == NULL) { | ||
| 3558 | mutex_lock(&dev->struct_mutex); | ||
| 3559 | return -ENOMEM; | ||
| 3560 | } | ||
| 3561 | |||
| 3562 | total = 0; | ||
| 3563 | for (i = 0; i < count; i++) { | ||
| 3564 | struct drm_i915_gem_relocation_entry __user *user_relocs; | ||
| 3565 | |||
| 3566 | user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; | ||
| 3567 | |||
| 3568 | if (copy_from_user(reloc+total, user_relocs, | ||
| 3569 | exec_list[i].relocation_count * | ||
| 3570 | sizeof(*reloc))) { | ||
| 3571 | ret = -EFAULT; | ||
| 3572 | mutex_lock(&dev->struct_mutex); | ||
| 3573 | goto err; | ||
| 3574 | } | ||
| 3575 | |||
| 3576 | total += exec_list[i].relocation_count; | ||
| 3577 | } | ||
| 3578 | |||
| 3579 | ret = i915_mutex_lock_interruptible(dev); | ||
| 3580 | if (ret) { | ||
| 3581 | mutex_lock(&dev->struct_mutex); | ||
| 3582 | goto err; | ||
| 3583 | } | ||
| 3584 | |||
| 3585 | ret = i915_gem_execbuffer_reserve(dev, file, | ||
| 3586 | object_list, exec_list, | ||
| 3587 | count); | ||
| 3588 | if (ret) | ||
| 3589 | goto err; | ||
| 3590 | |||
| 3591 | total = 0; | ||
| 3592 | for (i = 0; i < count; i++) { | ||
| 3593 | struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); | ||
| 3594 | obj->base.pending_read_domains = 0; | ||
| 3595 | obj->base.pending_write_domain = 0; | ||
| 3596 | ret = i915_gem_execbuffer_relocate_object_slow(obj, file, | ||
| 3597 | &exec_list[i], | ||
| 3598 | reloc + total); | ||
| 3599 | if (ret) | ||
| 3600 | goto err; | ||
| 3601 | |||
| 3602 | total += exec_list[i].relocation_count; | ||
| 3603 | } | ||
| 3604 | |||
| 3605 | /* Leave the user relocations as are, this is the painfully slow path, | ||
| 3606 | * and we want to avoid the complication of dropping the lock whilst | ||
| 3607 | * having buffers reserved in the aperture and so causing spurious | ||
| 3608 | * ENOSPC for random operations. | ||
| 3609 | */ | ||
| 3610 | |||
| 3611 | err: | ||
| 3612 | drm_free_large(reloc); | ||
| 3613 | return ret; | ||
| 3614 | } | ||
| 3615 | |||
| 3616 | static int | ||
| 3505 | i915_gem_execbuffer_move_to_gpu(struct drm_device *dev, | 3617 | i915_gem_execbuffer_move_to_gpu(struct drm_device *dev, |
| 3506 | struct drm_file *file, | 3618 | struct drm_file *file, |
| 3507 | struct intel_ring_buffer *ring, | 3619 | struct intel_ring_buffer *ring, |
| @@ -3630,8 +3742,15 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, | |||
| 3630 | 3742 | ||
| 3631 | for (i = 0; i < count; i++) { | 3743 | for (i = 0; i < count; i++) { |
| 3632 | char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; | 3744 | char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; |
| 3633 | size_t length = exec[i].relocation_count * sizeof(struct drm_i915_gem_relocation_entry); | 3745 | int length; /* limited by fault_in_pages_readable() */ |
| 3746 | |||
| 3747 | /* First check for malicious input causing overflow */ | ||
| 3748 | if (exec[i].relocation_count > | ||
| 3749 | INT_MAX / sizeof(struct drm_i915_gem_relocation_entry)) | ||
| 3750 | return -EINVAL; | ||
| 3634 | 3751 | ||
| 3752 | length = exec[i].relocation_count * | ||
| 3753 | sizeof(struct drm_i915_gem_relocation_entry); | ||
| 3635 | if (!access_ok(VERIFY_READ, ptr, length)) | 3754 | if (!access_ok(VERIFY_READ, ptr, length)) |
| 3636 | return -EFAULT; | 3755 | return -EFAULT; |
| 3637 | 3756 | ||
| @@ -3774,18 +3893,24 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 3774 | } | 3893 | } |
| 3775 | 3894 | ||
| 3776 | /* Move the objects en-masse into the GTT, evicting if necessary. */ | 3895 | /* Move the objects en-masse into the GTT, evicting if necessary. */ |
| 3777 | ret = i915_gem_execbuffer_pin(dev, file, | 3896 | ret = i915_gem_execbuffer_reserve(dev, file, |
| 3778 | object_list, exec_list, | 3897 | object_list, exec_list, |
| 3779 | args->buffer_count); | 3898 | args->buffer_count); |
| 3780 | if (ret) | 3899 | if (ret) |
| 3781 | goto err; | 3900 | goto err; |
| 3782 | 3901 | ||
| 3783 | /* The objects are in their final locations, apply the relocations. */ | 3902 | /* The objects are in their final locations, apply the relocations. */ |
| 3784 | for (i = 0; i < args->buffer_count; i++) { | 3903 | ret = i915_gem_execbuffer_relocate(dev, file, |
| 3785 | struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); | 3904 | object_list, exec_list, |
| 3786 | obj->base.pending_read_domains = 0; | 3905 | args->buffer_count); |
| 3787 | obj->base.pending_write_domain = 0; | 3906 | if (ret) { |
| 3788 | ret = i915_gem_execbuffer_relocate(obj, file, &exec_list[i]); | 3907 | if (ret == -EFAULT) { |
| 3908 | ret = i915_gem_execbuffer_relocate_slow(dev, file, | ||
| 3909 | object_list, | ||
| 3910 | exec_list, | ||
| 3911 | args->buffer_count); | ||
| 3912 | BUG_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
| 3913 | } | ||
| 3789 | if (ret) | 3914 | if (ret) |
| 3790 | goto err; | 3915 | goto err; |
| 3791 | } | 3916 | } |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 454c064f8ef7..42729d25da58 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
| @@ -239,6 +239,16 @@ static void i915_save_modeset_reg(struct drm_device *dev) | |||
| 239 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | 239 | if (drm_core_check_feature(dev, DRIVER_MODESET)) |
| 240 | return; | 240 | return; |
| 241 | 241 | ||
| 242 | /* Cursor state */ | ||
| 243 | dev_priv->saveCURACNTR = I915_READ(CURACNTR); | ||
| 244 | dev_priv->saveCURAPOS = I915_READ(CURAPOS); | ||
| 245 | dev_priv->saveCURABASE = I915_READ(CURABASE); | ||
| 246 | dev_priv->saveCURBCNTR = I915_READ(CURBCNTR); | ||
| 247 | dev_priv->saveCURBPOS = I915_READ(CURBPOS); | ||
| 248 | dev_priv->saveCURBBASE = I915_READ(CURBBASE); | ||
| 249 | if (IS_GEN2(dev)) | ||
| 250 | dev_priv->saveCURSIZE = I915_READ(CURSIZE); | ||
| 251 | |||
| 242 | if (HAS_PCH_SPLIT(dev)) { | 252 | if (HAS_PCH_SPLIT(dev)) { |
| 243 | dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL); | 253 | dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL); |
| 244 | dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL); | 254 | dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL); |
| @@ -529,6 +539,16 @@ static void i915_restore_modeset_reg(struct drm_device *dev) | |||
| 529 | I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); | 539 | I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); |
| 530 | I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); | 540 | I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); |
| 531 | 541 | ||
| 542 | /* Cursor state */ | ||
| 543 | I915_WRITE(CURAPOS, dev_priv->saveCURAPOS); | ||
| 544 | I915_WRITE(CURACNTR, dev_priv->saveCURACNTR); | ||
| 545 | I915_WRITE(CURABASE, dev_priv->saveCURABASE); | ||
| 546 | I915_WRITE(CURBPOS, dev_priv->saveCURBPOS); | ||
| 547 | I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR); | ||
| 548 | I915_WRITE(CURBBASE, dev_priv->saveCURBBASE); | ||
| 549 | if (IS_GEN2(dev)) | ||
| 550 | I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); | ||
| 551 | |||
| 532 | return; | 552 | return; |
| 533 | } | 553 | } |
| 534 | 554 | ||
| @@ -543,16 +563,6 @@ void i915_save_display(struct drm_device *dev) | |||
| 543 | /* Don't save them in KMS mode */ | 563 | /* Don't save them in KMS mode */ |
| 544 | i915_save_modeset_reg(dev); | 564 | i915_save_modeset_reg(dev); |
| 545 | 565 | ||
| 546 | /* Cursor state */ | ||
| 547 | dev_priv->saveCURACNTR = I915_READ(CURACNTR); | ||
| 548 | dev_priv->saveCURAPOS = I915_READ(CURAPOS); | ||
| 549 | dev_priv->saveCURABASE = I915_READ(CURABASE); | ||
| 550 | dev_priv->saveCURBCNTR = I915_READ(CURBCNTR); | ||
| 551 | dev_priv->saveCURBPOS = I915_READ(CURBPOS); | ||
| 552 | dev_priv->saveCURBBASE = I915_READ(CURBBASE); | ||
| 553 | if (IS_GEN2(dev)) | ||
| 554 | dev_priv->saveCURSIZE = I915_READ(CURSIZE); | ||
| 555 | |||
| 556 | /* CRT state */ | 566 | /* CRT state */ |
| 557 | if (HAS_PCH_SPLIT(dev)) { | 567 | if (HAS_PCH_SPLIT(dev)) { |
| 558 | dev_priv->saveADPA = I915_READ(PCH_ADPA); | 568 | dev_priv->saveADPA = I915_READ(PCH_ADPA); |
| @@ -657,16 +667,6 @@ void i915_restore_display(struct drm_device *dev) | |||
| 657 | /* Don't restore them in KMS mode */ | 667 | /* Don't restore them in KMS mode */ |
| 658 | i915_restore_modeset_reg(dev); | 668 | i915_restore_modeset_reg(dev); |
| 659 | 669 | ||
| 660 | /* Cursor state */ | ||
| 661 | I915_WRITE(CURAPOS, dev_priv->saveCURAPOS); | ||
| 662 | I915_WRITE(CURACNTR, dev_priv->saveCURACNTR); | ||
| 663 | I915_WRITE(CURABASE, dev_priv->saveCURABASE); | ||
| 664 | I915_WRITE(CURBPOS, dev_priv->saveCURBPOS); | ||
| 665 | I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR); | ||
| 666 | I915_WRITE(CURBBASE, dev_priv->saveCURBBASE); | ||
| 667 | if (IS_GEN2(dev)) | ||
| 668 | I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); | ||
| 669 | |||
| 670 | /* CRT state */ | 670 | /* CRT state */ |
| 671 | if (HAS_PCH_SPLIT(dev)) | 671 | if (HAS_PCH_SPLIT(dev)) |
| 672 | I915_WRITE(PCH_ADPA, dev_priv->saveADPA); | 672 | I915_WRITE(PCH_ADPA, dev_priv->saveADPA); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bee24b1a58e8..255b52ee0091 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -5336,9 +5336,14 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 5336 | struct drm_i915_private *dev_priv = dev->dev_private; | 5336 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 5337 | struct intel_encoder *encoder; | 5337 | struct intel_encoder *encoder; |
| 5338 | bool dpd_is_edp = false; | 5338 | bool dpd_is_edp = false; |
| 5339 | bool has_lvds = false; | ||
| 5339 | 5340 | ||
| 5340 | if (IS_MOBILE(dev) && !IS_I830(dev)) | 5341 | if (IS_MOBILE(dev) && !IS_I830(dev)) |
| 5341 | intel_lvds_init(dev); | 5342 | has_lvds = intel_lvds_init(dev); |
| 5343 | if (!has_lvds && !HAS_PCH_SPLIT(dev)) { | ||
| 5344 | /* disable the panel fitter on everything but LVDS */ | ||
| 5345 | I915_WRITE(PFIT_CONTROL, 0); | ||
| 5346 | } | ||
| 5342 | 5347 | ||
| 5343 | if (HAS_PCH_SPLIT(dev)) { | 5348 | if (HAS_PCH_SPLIT(dev)) { |
| 5344 | dpd_is_edp = intel_dpd_is_edp(dev); | 5349 | dpd_is_edp = intel_dpd_is_edp(dev); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c8e005553310..300f64b4238b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -584,17 +584,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 584 | mode->clock = dev_priv->panel_fixed_mode->clock; | 584 | mode->clock = dev_priv->panel_fixed_mode->clock; |
| 585 | } | 585 | } |
| 586 | 586 | ||
| 587 | /* Just use VBT values for eDP */ | ||
| 588 | if (is_edp(intel_dp)) { | ||
| 589 | intel_dp->lane_count = dev_priv->edp.lanes; | ||
| 590 | intel_dp->link_bw = dev_priv->edp.rate; | ||
| 591 | adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw); | ||
| 592 | DRM_DEBUG_KMS("eDP link bw %02x lane count %d clock %d\n", | ||
| 593 | intel_dp->link_bw, intel_dp->lane_count, | ||
| 594 | adjusted_mode->clock); | ||
| 595 | return true; | ||
| 596 | } | ||
| 597 | |||
| 598 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { | 587 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { |
| 599 | for (clock = 0; clock <= max_clock; clock++) { | 588 | for (clock = 0; clock <= max_clock; clock++) { |
| 600 | int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); | 589 | int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); |
| @@ -613,6 +602,19 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 613 | } | 602 | } |
| 614 | } | 603 | } |
| 615 | 604 | ||
| 605 | if (is_edp(intel_dp)) { | ||
| 606 | /* okay we failed just pick the highest */ | ||
| 607 | intel_dp->lane_count = max_lane_count; | ||
| 608 | intel_dp->link_bw = bws[max_clock]; | ||
| 609 | adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw); | ||
| 610 | DRM_DEBUG_KMS("Force picking display port link bw %02x lane " | ||
| 611 | "count %d clock %d\n", | ||
| 612 | intel_dp->link_bw, intel_dp->lane_count, | ||
| 613 | adjusted_mode->clock); | ||
| 614 | |||
| 615 | return true; | ||
| 616 | } | ||
| 617 | |||
| 616 | return false; | 618 | return false; |
| 617 | } | 619 | } |
| 618 | 620 | ||
| @@ -1087,21 +1089,11 @@ intel_get_adjust_train(struct intel_dp *intel_dp) | |||
| 1087 | } | 1089 | } |
| 1088 | 1090 | ||
| 1089 | static uint32_t | 1091 | static uint32_t |
| 1090 | intel_dp_signal_levels(struct intel_dp *intel_dp) | 1092 | intel_dp_signal_levels(uint8_t train_set, int lane_count) |
| 1091 | { | 1093 | { |
| 1092 | struct drm_device *dev = intel_dp->base.base.dev; | 1094 | uint32_t signal_levels = 0; |
| 1093 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1094 | uint32_t signal_levels = 0; | ||
| 1095 | u8 train_set = intel_dp->train_set[0]; | ||
| 1096 | u32 vswing = train_set & DP_TRAIN_VOLTAGE_SWING_MASK; | ||
| 1097 | u32 preemphasis = train_set & DP_TRAIN_PRE_EMPHASIS_MASK; | ||
| 1098 | 1095 | ||
| 1099 | if (is_edp(intel_dp)) { | 1096 | switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { |
| 1100 | vswing = dev_priv->edp.vswing; | ||
| 1101 | preemphasis = dev_priv->edp.preemphasis; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | switch (vswing) { | ||
| 1105 | case DP_TRAIN_VOLTAGE_SWING_400: | 1097 | case DP_TRAIN_VOLTAGE_SWING_400: |
| 1106 | default: | 1098 | default: |
| 1107 | signal_levels |= DP_VOLTAGE_0_4; | 1099 | signal_levels |= DP_VOLTAGE_0_4; |
| @@ -1116,7 +1108,7 @@ intel_dp_signal_levels(struct intel_dp *intel_dp) | |||
| 1116 | signal_levels |= DP_VOLTAGE_1_2; | 1108 | signal_levels |= DP_VOLTAGE_1_2; |
| 1117 | break; | 1109 | break; |
| 1118 | } | 1110 | } |
| 1119 | switch (preemphasis) { | 1111 | switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { |
| 1120 | case DP_TRAIN_PRE_EMPHASIS_0: | 1112 | case DP_TRAIN_PRE_EMPHASIS_0: |
| 1121 | default: | 1113 | default: |
| 1122 | signal_levels |= DP_PRE_EMPHASIS_0; | 1114 | signal_levels |= DP_PRE_EMPHASIS_0; |
| @@ -1203,18 +1195,6 @@ intel_channel_eq_ok(struct intel_dp *intel_dp) | |||
| 1203 | } | 1195 | } |
| 1204 | 1196 | ||
| 1205 | static bool | 1197 | static bool |
| 1206 | intel_dp_aux_handshake_required(struct intel_dp *intel_dp) | ||
| 1207 | { | ||
| 1208 | struct drm_device *dev = intel_dp->base.base.dev; | ||
| 1209 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1210 | |||
| 1211 | if (is_edp(intel_dp) && dev_priv->no_aux_handshake) | ||
| 1212 | return false; | ||
| 1213 | |||
| 1214 | return true; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | static bool | ||
| 1218 | intel_dp_set_link_train(struct intel_dp *intel_dp, | 1198 | intel_dp_set_link_train(struct intel_dp *intel_dp, |
| 1219 | uint32_t dp_reg_value, | 1199 | uint32_t dp_reg_value, |
| 1220 | uint8_t dp_train_pat) | 1200 | uint8_t dp_train_pat) |
| @@ -1226,9 +1206,6 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
| 1226 | I915_WRITE(intel_dp->output_reg, dp_reg_value); | 1206 | I915_WRITE(intel_dp->output_reg, dp_reg_value); |
| 1227 | POSTING_READ(intel_dp->output_reg); | 1207 | POSTING_READ(intel_dp->output_reg); |
| 1228 | 1208 | ||
| 1229 | if (!intel_dp_aux_handshake_required(intel_dp)) | ||
| 1230 | return true; | ||
| 1231 | |||
| 1232 | intel_dp_aux_native_write_1(intel_dp, | 1209 | intel_dp_aux_native_write_1(intel_dp, |
| 1233 | DP_TRAINING_PATTERN_SET, | 1210 | DP_TRAINING_PATTERN_SET, |
| 1234 | dp_train_pat); | 1211 | dp_train_pat); |
| @@ -1261,11 +1238,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
| 1261 | POSTING_READ(intel_dp->output_reg); | 1238 | POSTING_READ(intel_dp->output_reg); |
| 1262 | intel_wait_for_vblank(dev, intel_crtc->pipe); | 1239 | intel_wait_for_vblank(dev, intel_crtc->pipe); |
| 1263 | 1240 | ||
| 1264 | if (intel_dp_aux_handshake_required(intel_dp)) | 1241 | /* Write the link configuration data */ |
| 1265 | /* Write the link configuration data */ | 1242 | intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, |
| 1266 | intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, | 1243 | intel_dp->link_configuration, |
| 1267 | intel_dp->link_configuration, | 1244 | DP_LINK_CONFIGURATION_SIZE); |
| 1268 | DP_LINK_CONFIGURATION_SIZE); | ||
| 1269 | 1245 | ||
| 1270 | DP |= DP_PORT_EN; | 1246 | DP |= DP_PORT_EN; |
| 1271 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) | 1247 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) |
| @@ -1283,7 +1259,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
| 1283 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); | 1259 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); |
| 1284 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | 1260 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; |
| 1285 | } else { | 1261 | } else { |
| 1286 | signal_levels = intel_dp_signal_levels(intel_dp); | 1262 | signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); |
| 1287 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | 1263 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; |
| 1288 | } | 1264 | } |
| 1289 | 1265 | ||
| @@ -1297,37 +1273,33 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
| 1297 | break; | 1273 | break; |
| 1298 | /* Set training pattern 1 */ | 1274 | /* Set training pattern 1 */ |
| 1299 | 1275 | ||
| 1300 | udelay(500); | 1276 | udelay(100); |
| 1301 | if (intel_dp_aux_handshake_required(intel_dp)) { | 1277 | if (!intel_dp_get_link_status(intel_dp)) |
| 1302 | break; | 1278 | break; |
| 1303 | } else { | ||
| 1304 | if (!intel_dp_get_link_status(intel_dp)) | ||
| 1305 | break; | ||
| 1306 | 1279 | ||
| 1307 | if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { | 1280 | if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { |
| 1308 | clock_recovery = true; | 1281 | clock_recovery = true; |
| 1309 | break; | 1282 | break; |
| 1310 | } | 1283 | } |
| 1311 | 1284 | ||
| 1312 | /* Check to see if we've tried the max voltage */ | 1285 | /* Check to see if we've tried the max voltage */ |
| 1313 | for (i = 0; i < intel_dp->lane_count; i++) | 1286 | for (i = 0; i < intel_dp->lane_count; i++) |
| 1314 | if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) | 1287 | if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) |
| 1315 | break; | ||
| 1316 | if (i == intel_dp->lane_count) | ||
| 1317 | break; | 1288 | break; |
| 1289 | if (i == intel_dp->lane_count) | ||
| 1290 | break; | ||
| 1318 | 1291 | ||
| 1319 | /* Check to see if we've tried the same voltage 5 times */ | 1292 | /* Check to see if we've tried the same voltage 5 times */ |
| 1320 | if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { | 1293 | if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { |
| 1321 | ++tries; | 1294 | ++tries; |
| 1322 | if (tries == 5) | 1295 | if (tries == 5) |
| 1323 | break; | 1296 | break; |
| 1324 | } else | 1297 | } else |
| 1325 | tries = 0; | 1298 | tries = 0; |
| 1326 | voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; | 1299 | voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; |
| 1327 | 1300 | ||
| 1328 | /* Compute new intel_dp->train_set as requested by target */ | 1301 | /* Compute new intel_dp->train_set as requested by target */ |
| 1329 | intel_get_adjust_train(intel_dp); | 1302 | intel_get_adjust_train(intel_dp); |
| 1330 | } | ||
| 1331 | } | 1303 | } |
| 1332 | 1304 | ||
| 1333 | intel_dp->DP = DP; | 1305 | intel_dp->DP = DP; |
| @@ -1354,7 +1326,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
| 1354 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); | 1326 | signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); |
| 1355 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; | 1327 | DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; |
| 1356 | } else { | 1328 | } else { |
| 1357 | signal_levels = intel_dp_signal_levels(intel_dp); | 1329 | signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); |
| 1358 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | 1330 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; |
| 1359 | } | 1331 | } |
| 1360 | 1332 | ||
| @@ -1368,28 +1340,24 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
| 1368 | DP_TRAINING_PATTERN_2)) | 1340 | DP_TRAINING_PATTERN_2)) |
| 1369 | break; | 1341 | break; |
| 1370 | 1342 | ||
| 1371 | udelay(500); | 1343 | udelay(400); |
| 1372 | 1344 | if (!intel_dp_get_link_status(intel_dp)) | |
| 1373 | if (!intel_dp_aux_handshake_required(intel_dp)) { | ||
| 1374 | break; | 1345 | break; |
| 1375 | } else { | ||
| 1376 | if (!intel_dp_get_link_status(intel_dp)) | ||
| 1377 | break; | ||
| 1378 | 1346 | ||
| 1379 | if (intel_channel_eq_ok(intel_dp)) { | 1347 | if (intel_channel_eq_ok(intel_dp)) { |
| 1380 | channel_eq = true; | 1348 | channel_eq = true; |
| 1381 | break; | 1349 | break; |
| 1382 | } | 1350 | } |
| 1383 | 1351 | ||
| 1384 | /* Try 5 times */ | 1352 | /* Try 5 times */ |
| 1385 | if (tries > 5) | 1353 | if (tries > 5) |
| 1386 | break; | 1354 | break; |
| 1387 | 1355 | ||
| 1388 | /* Compute new intel_dp->train_set as requested by target */ | 1356 | /* Compute new intel_dp->train_set as requested by target */ |
| 1389 | intel_get_adjust_train(intel_dp); | 1357 | intel_get_adjust_train(intel_dp); |
| 1390 | ++tries; | 1358 | ++tries; |
| 1391 | } | ||
| 1392 | } | 1359 | } |
| 1360 | |||
| 1393 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) | 1361 | if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) |
| 1394 | reg = DP | DP_LINK_TRAIN_OFF_CPT; | 1362 | reg = DP | DP_LINK_TRAIN_OFF_CPT; |
| 1395 | else | 1363 | else |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 21551fe74541..e52c6125bb1f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -237,7 +237,7 @@ extern bool intel_sdvo_init(struct drm_device *dev, int output_device); | |||
| 237 | extern void intel_dvo_init(struct drm_device *dev); | 237 | extern void intel_dvo_init(struct drm_device *dev); |
| 238 | extern void intel_tv_init(struct drm_device *dev); | 238 | extern void intel_tv_init(struct drm_device *dev); |
| 239 | extern void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj); | 239 | extern void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj); |
| 240 | extern void intel_lvds_init(struct drm_device *dev); | 240 | extern bool intel_lvds_init(struct drm_device *dev); |
| 241 | extern void intel_dp_init(struct drm_device *dev, int dp_reg); | 241 | extern void intel_dp_init(struct drm_device *dev, int dp_reg); |
| 242 | void | 242 | void |
| 243 | intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | 243 | intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 4324a326f98e..f79327fc6653 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -837,7 +837,7 @@ static bool intel_lvds_ddc_probe(struct drm_device *dev, u8 pin) | |||
| 837 | * Create the connector, register the LVDS DDC bus, and try to figure out what | 837 | * Create the connector, register the LVDS DDC bus, and try to figure out what |
| 838 | * modes we can display on the LVDS panel (if present). | 838 | * modes we can display on the LVDS panel (if present). |
| 839 | */ | 839 | */ |
| 840 | void intel_lvds_init(struct drm_device *dev) | 840 | bool intel_lvds_init(struct drm_device *dev) |
| 841 | { | 841 | { |
| 842 | struct drm_i915_private *dev_priv = dev->dev_private; | 842 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 843 | struct intel_lvds *intel_lvds; | 843 | struct intel_lvds *intel_lvds; |
| @@ -853,37 +853,37 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 853 | 853 | ||
| 854 | /* Skip init on machines we know falsely report LVDS */ | 854 | /* Skip init on machines we know falsely report LVDS */ |
| 855 | if (dmi_check_system(intel_no_lvds)) | 855 | if (dmi_check_system(intel_no_lvds)) |
| 856 | return; | 856 | return false; |
| 857 | 857 | ||
| 858 | pin = GMBUS_PORT_PANEL; | 858 | pin = GMBUS_PORT_PANEL; |
| 859 | if (!lvds_is_present_in_vbt(dev, &pin)) { | 859 | if (!lvds_is_present_in_vbt(dev, &pin)) { |
| 860 | DRM_DEBUG_KMS("LVDS is not present in VBT\n"); | 860 | DRM_DEBUG_KMS("LVDS is not present in VBT\n"); |
| 861 | return; | 861 | return false; |
| 862 | } | 862 | } |
| 863 | 863 | ||
| 864 | if (HAS_PCH_SPLIT(dev)) { | 864 | if (HAS_PCH_SPLIT(dev)) { |
| 865 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) | 865 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) |
| 866 | return; | 866 | return false; |
| 867 | if (dev_priv->edp.support) { | 867 | if (dev_priv->edp.support) { |
| 868 | DRM_DEBUG_KMS("disable LVDS for eDP support\n"); | 868 | DRM_DEBUG_KMS("disable LVDS for eDP support\n"); |
| 869 | return; | 869 | return false; |
| 870 | } | 870 | } |
| 871 | } | 871 | } |
| 872 | 872 | ||
| 873 | if (!intel_lvds_ddc_probe(dev, pin)) { | 873 | if (!intel_lvds_ddc_probe(dev, pin)) { |
| 874 | DRM_DEBUG_KMS("LVDS did not respond to DDC probe\n"); | 874 | DRM_DEBUG_KMS("LVDS did not respond to DDC probe\n"); |
| 875 | return; | 875 | return false; |
| 876 | } | 876 | } |
| 877 | 877 | ||
| 878 | intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL); | 878 | intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL); |
| 879 | if (!intel_lvds) { | 879 | if (!intel_lvds) { |
| 880 | return; | 880 | return false; |
| 881 | } | 881 | } |
| 882 | 882 | ||
| 883 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); | 883 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); |
| 884 | if (!intel_connector) { | 884 | if (!intel_connector) { |
| 885 | kfree(intel_lvds); | 885 | kfree(intel_lvds); |
| 886 | return; | 886 | return false; |
| 887 | } | 887 | } |
| 888 | 888 | ||
| 889 | if (!HAS_PCH_SPLIT(dev)) { | 889 | if (!HAS_PCH_SPLIT(dev)) { |
| @@ -1026,7 +1026,7 @@ out: | |||
| 1026 | /* keep the LVDS connector */ | 1026 | /* keep the LVDS connector */ |
| 1027 | dev_priv->int_lvds_connector = connector; | 1027 | dev_priv->int_lvds_connector = connector; |
| 1028 | drm_sysfs_connector_add(connector); | 1028 | drm_sysfs_connector_add(connector); |
| 1029 | return; | 1029 | return true; |
| 1030 | 1030 | ||
| 1031 | failed: | 1031 | failed: |
| 1032 | DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); | 1032 | DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); |
| @@ -1034,4 +1034,5 @@ failed: | |||
| 1034 | drm_encoder_cleanup(encoder); | 1034 | drm_encoder_cleanup(encoder); |
| 1035 | kfree(intel_lvds); | 1035 | kfree(intel_lvds); |
| 1036 | kfree(intel_connector); | 1036 | kfree(intel_connector); |
| 1037 | return false; | ||
| 1037 | } | 1038 | } |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index de158b76bcd5..d97e6cb52d34 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -107,7 +107,8 @@ struct intel_sdvo { | |||
| 107 | * This is set if we treat the device as HDMI, instead of DVI. | 107 | * This is set if we treat the device as HDMI, instead of DVI. |
| 108 | */ | 108 | */ |
| 109 | bool is_hdmi; | 109 | bool is_hdmi; |
| 110 | bool has_audio; | 110 | bool has_hdmi_monitor; |
| 111 | bool has_hdmi_audio; | ||
| 111 | 112 | ||
| 112 | /** | 113 | /** |
| 113 | * This is set if we detect output of sdvo device as LVDS and | 114 | * This is set if we detect output of sdvo device as LVDS and |
| @@ -1023,7 +1024,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1023 | if (!intel_sdvo_set_target_input(intel_sdvo)) | 1024 | if (!intel_sdvo_set_target_input(intel_sdvo)) |
| 1024 | return; | 1025 | return; |
| 1025 | 1026 | ||
| 1026 | if (intel_sdvo->is_hdmi && | 1027 | if (intel_sdvo->has_hdmi_monitor && |
| 1027 | !intel_sdvo_set_avi_infoframe(intel_sdvo)) | 1028 | !intel_sdvo_set_avi_infoframe(intel_sdvo)) |
| 1028 | return; | 1029 | return; |
| 1029 | 1030 | ||
| @@ -1063,7 +1064,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1063 | } | 1064 | } |
| 1064 | if (intel_crtc->pipe == 1) | 1065 | if (intel_crtc->pipe == 1) |
| 1065 | sdvox |= SDVO_PIPE_B_SELECT; | 1066 | sdvox |= SDVO_PIPE_B_SELECT; |
| 1066 | if (intel_sdvo->has_audio) | 1067 | if (intel_sdvo->has_hdmi_audio) |
| 1067 | sdvox |= SDVO_AUDIO_ENABLE; | 1068 | sdvox |= SDVO_AUDIO_ENABLE; |
| 1068 | 1069 | ||
| 1069 | if (INTEL_INFO(dev)->gen >= 4) { | 1070 | if (INTEL_INFO(dev)->gen >= 4) { |
| @@ -1295,55 +1296,14 @@ intel_sdvo_get_edid(struct drm_connector *connector) | |||
| 1295 | return drm_get_edid(connector, &sdvo->ddc); | 1296 | return drm_get_edid(connector, &sdvo->ddc); |
| 1296 | } | 1297 | } |
| 1297 | 1298 | ||
| 1298 | static struct drm_connector * | ||
| 1299 | intel_find_analog_connector(struct drm_device *dev) | ||
| 1300 | { | ||
| 1301 | struct drm_connector *connector; | ||
| 1302 | struct intel_sdvo *encoder; | ||
| 1303 | |||
| 1304 | list_for_each_entry(encoder, | ||
| 1305 | &dev->mode_config.encoder_list, | ||
| 1306 | base.base.head) { | ||
| 1307 | if (encoder->base.type == INTEL_OUTPUT_ANALOG) { | ||
| 1308 | list_for_each_entry(connector, | ||
| 1309 | &dev->mode_config.connector_list, | ||
| 1310 | head) { | ||
| 1311 | if (&encoder->base == | ||
| 1312 | intel_attached_encoder(connector)) | ||
| 1313 | return connector; | ||
| 1314 | } | ||
| 1315 | } | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | return NULL; | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | static int | ||
| 1322 | intel_analog_is_connected(struct drm_device *dev) | ||
| 1323 | { | ||
| 1324 | struct drm_connector *analog_connector; | ||
| 1325 | |||
| 1326 | analog_connector = intel_find_analog_connector(dev); | ||
| 1327 | if (!analog_connector) | ||
| 1328 | return false; | ||
| 1329 | |||
| 1330 | if (analog_connector->funcs->detect(analog_connector, false) == | ||
| 1331 | connector_status_disconnected) | ||
| 1332 | return false; | ||
| 1333 | |||
| 1334 | return true; | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | /* Mac mini hack -- use the same DDC as the analog connector */ | 1299 | /* Mac mini hack -- use the same DDC as the analog connector */ |
| 1338 | static struct edid * | 1300 | static struct edid * |
| 1339 | intel_sdvo_get_analog_edid(struct drm_connector *connector) | 1301 | intel_sdvo_get_analog_edid(struct drm_connector *connector) |
| 1340 | { | 1302 | { |
| 1341 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | 1303 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
| 1342 | 1304 | ||
| 1343 | if (!intel_analog_is_connected(connector->dev)) | 1305 | return drm_get_edid(connector, |
| 1344 | return NULL; | 1306 | &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); |
| 1345 | |||
| 1346 | return drm_get_edid(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); | ||
| 1347 | } | 1307 | } |
| 1348 | 1308 | ||
| 1349 | enum drm_connector_status | 1309 | enum drm_connector_status |
| @@ -1388,8 +1348,10 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
| 1388 | /* DDC bus is shared, match EDID to connector type */ | 1348 | /* DDC bus is shared, match EDID to connector type */ |
| 1389 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { | 1349 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
| 1390 | status = connector_status_connected; | 1350 | status = connector_status_connected; |
| 1391 | intel_sdvo->is_hdmi = drm_detect_hdmi_monitor(edid); | 1351 | if (intel_sdvo->is_hdmi) { |
| 1392 | intel_sdvo->has_audio = drm_detect_monitor_audio(edid); | 1352 | intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid); |
| 1353 | intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid); | ||
| 1354 | } | ||
| 1393 | } | 1355 | } |
| 1394 | connector->display_info.raw_edid = NULL; | 1356 | connector->display_info.raw_edid = NULL; |
| 1395 | kfree(edid); | 1357 | kfree(edid); |
| @@ -1398,7 +1360,7 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
| 1398 | if (status == connector_status_connected) { | 1360 | if (status == connector_status_connected) { |
| 1399 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); | 1361 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); |
| 1400 | if (intel_sdvo_connector->force_audio) | 1362 | if (intel_sdvo_connector->force_audio) |
| 1401 | intel_sdvo->has_audio = intel_sdvo_connector->force_audio > 0; | 1363 | intel_sdvo->has_hdmi_audio = intel_sdvo_connector->force_audio > 0; |
| 1402 | } | 1364 | } |
| 1403 | 1365 | ||
| 1404 | return status; | 1366 | return status; |
| @@ -1415,10 +1377,12 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) | |||
| 1415 | if (!intel_sdvo_write_cmd(intel_sdvo, | 1377 | if (!intel_sdvo_write_cmd(intel_sdvo, |
| 1416 | SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0)) | 1378 | SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0)) |
| 1417 | return connector_status_unknown; | 1379 | return connector_status_unknown; |
| 1418 | if (intel_sdvo->is_tv) { | 1380 | |
| 1419 | /* add 30ms delay when the output type is SDVO-TV */ | 1381 | /* add 30ms delay when the output type might be TV */ |
| 1382 | if (intel_sdvo->caps.output_flags & | ||
| 1383 | (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_CVBS0)) | ||
| 1420 | mdelay(30); | 1384 | mdelay(30); |
| 1421 | } | 1385 | |
| 1422 | if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) | 1386 | if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) |
| 1423 | return connector_status_unknown; | 1387 | return connector_status_unknown; |
| 1424 | 1388 | ||
| @@ -1472,8 +1436,10 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) | |||
| 1472 | edid = intel_sdvo_get_analog_edid(connector); | 1436 | edid = intel_sdvo_get_analog_edid(connector); |
| 1473 | 1437 | ||
| 1474 | if (edid != NULL) { | 1438 | if (edid != NULL) { |
| 1475 | drm_mode_connector_update_edid_property(connector, edid); | 1439 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
| 1476 | drm_add_edid_modes(connector, edid); | 1440 | drm_mode_connector_update_edid_property(connector, edid); |
| 1441 | drm_add_edid_modes(connector, edid); | ||
| 1442 | } | ||
| 1477 | connector->display_info.raw_edid = NULL; | 1443 | connector->display_info.raw_edid = NULL; |
| 1478 | kfree(edid); | 1444 | kfree(edid); |
| 1479 | } | 1445 | } |
| @@ -1713,12 +1679,12 @@ intel_sdvo_set_property(struct drm_connector *connector, | |||
| 1713 | 1679 | ||
| 1714 | intel_sdvo_connector->force_audio = val; | 1680 | intel_sdvo_connector->force_audio = val; |
| 1715 | 1681 | ||
| 1716 | if (val > 0 && intel_sdvo->has_audio) | 1682 | if (val > 0 && intel_sdvo->has_hdmi_audio) |
| 1717 | return 0; | 1683 | return 0; |
| 1718 | if (val < 0 && !intel_sdvo->has_audio) | 1684 | if (val < 0 && !intel_sdvo->has_hdmi_audio) |
| 1719 | return 0; | 1685 | return 0; |
| 1720 | 1686 | ||
| 1721 | intel_sdvo->has_audio = val > 0; | 1687 | intel_sdvo->has_hdmi_audio = val > 0; |
| 1722 | goto done; | 1688 | goto done; |
| 1723 | } | 1689 | } |
| 1724 | 1690 | ||
| @@ -2070,6 +2036,8 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | |||
| 2070 | intel_sdvo_set_colorimetry(intel_sdvo, | 2036 | intel_sdvo_set_colorimetry(intel_sdvo, |
| 2071 | SDVO_COLORIMETRY_RGB256); | 2037 | SDVO_COLORIMETRY_RGB256); |
| 2072 | connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; | 2038 | connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; |
| 2039 | |||
| 2040 | intel_sdvo_add_hdmi_properties(intel_sdvo_connector); | ||
| 2073 | intel_sdvo->is_hdmi = true; | 2041 | intel_sdvo->is_hdmi = true; |
| 2074 | } | 2042 | } |
| 2075 | intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | | 2043 | intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | |
| @@ -2077,8 +2045,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | |||
| 2077 | 2045 | ||
| 2078 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); | 2046 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); |
| 2079 | 2047 | ||
| 2080 | intel_sdvo_add_hdmi_properties(intel_sdvo_connector); | ||
| 2081 | |||
| 2082 | return true; | 2048 | return true; |
| 2083 | } | 2049 | } |
| 2084 | 2050 | ||
diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 8e421f644a54..05efb5b9f13e 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c | |||
| @@ -112,6 +112,7 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base, | |||
| 112 | base += 3; | 112 | base += 3; |
| 113 | break; | 113 | break; |
| 114 | case ATOM_IIO_WRITE: | 114 | case ATOM_IIO_WRITE: |
| 115 | (void)ctx->card->ioreg_read(ctx->card, CU16(base + 1)); | ||
| 115 | ctx->card->ioreg_write(ctx->card, CU16(base + 1), temp); | 116 | ctx->card->ioreg_write(ctx->card, CU16(base + 1), temp); |
| 116 | base += 3; | 117 | base += 3; |
| 117 | break; | 118 | break; |
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 9bebac1ec006..0f90fc3482ce 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
| @@ -315,7 +315,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) | |||
| 315 | if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { | 315 | if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { |
| 316 | /* the initial DDX does bad things with the CB size occasionally */ | 316 | /* the initial DDX does bad things with the CB size occasionally */ |
| 317 | /* it rounds up height too far for slice tile max but the BO is smaller */ | 317 | /* it rounds up height too far for slice tile max but the BO is smaller */ |
| 318 | tmp = (height - 7) * pitch * bpe; | 318 | tmp = (height - 7) * 8 * bpe; |
| 319 | if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { | 319 | if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { |
| 320 | dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i])); | 320 | dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i])); |
| 321 | return -EINVAL; | 321 | return -EINVAL; |
diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h index d84612ae47e0..33cda016b083 100644 --- a/drivers/gpu/drm/radeon/r600_reg.h +++ b/drivers/gpu/drm/radeon/r600_reg.h | |||
| @@ -86,6 +86,7 @@ | |||
| 86 | #define R600_HDP_NONSURFACE_BASE 0x2c04 | 86 | #define R600_HDP_NONSURFACE_BASE 0x2c04 |
| 87 | 87 | ||
| 88 | #define R600_BUS_CNTL 0x5420 | 88 | #define R600_BUS_CNTL 0x5420 |
| 89 | # define R600_BIOS_ROM_DIS (1 << 1) | ||
| 89 | #define R600_CONFIG_CNTL 0x5424 | 90 | #define R600_CONFIG_CNTL 0x5424 |
| 90 | #define R600_CONFIG_MEMSIZE 0x5428 | 91 | #define R600_CONFIG_MEMSIZE 0x5428 |
| 91 | #define R600_CONFIG_F0_BASE 0x542C | 92 | #define R600_CONFIG_F0_BASE 0x542C |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 87ead090c7d5..bc5a2c3382d9 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
| @@ -98,6 +98,14 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev | |||
| 98 | } | 98 | } |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | /* some DCE3 boards have bad data for this entry */ | ||
| 102 | if (ASIC_IS_DCE3(rdev)) { | ||
| 103 | if ((i == 4) && | ||
| 104 | (gpio->usClkMaskRegisterIndex == 0x1fda) && | ||
| 105 | (gpio->sucI2cId.ucAccess == 0x94)) | ||
| 106 | gpio->sucI2cId.ucAccess = 0x14; | ||
| 107 | } | ||
| 108 | |||
| 101 | if (gpio->sucI2cId.ucAccess == id) { | 109 | if (gpio->sucI2cId.ucAccess == id) { |
| 102 | i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; | 110 | i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; |
| 103 | i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; | 111 | i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; |
| @@ -174,6 +182,14 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev) | |||
| 174 | } | 182 | } |
| 175 | } | 183 | } |
| 176 | 184 | ||
| 185 | /* some DCE3 boards have bad data for this entry */ | ||
| 186 | if (ASIC_IS_DCE3(rdev)) { | ||
| 187 | if ((i == 4) && | ||
| 188 | (gpio->usClkMaskRegisterIndex == 0x1fda) && | ||
| 189 | (gpio->sucI2cId.ucAccess == 0x94)) | ||
| 190 | gpio->sucI2cId.ucAccess = 0x14; | ||
| 191 | } | ||
| 192 | |||
| 177 | i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; | 193 | i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; |
| 178 | i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; | 194 | i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; |
| 179 | i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; | 195 | i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; |
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 654787ec43f4..8f2c7b50dcf5 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c | |||
| @@ -130,6 +130,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) | |||
| 130 | } | 130 | } |
| 131 | return true; | 131 | return true; |
| 132 | } | 132 | } |
| 133 | |||
| 133 | static bool r700_read_disabled_bios(struct radeon_device *rdev) | 134 | static bool r700_read_disabled_bios(struct radeon_device *rdev) |
| 134 | { | 135 | { |
| 135 | uint32_t viph_control; | 136 | uint32_t viph_control; |
| @@ -143,7 +144,7 @@ static bool r700_read_disabled_bios(struct radeon_device *rdev) | |||
| 143 | bool r; | 144 | bool r; |
| 144 | 145 | ||
| 145 | viph_control = RREG32(RADEON_VIPH_CONTROL); | 146 | viph_control = RREG32(RADEON_VIPH_CONTROL); |
| 146 | bus_cntl = RREG32(RADEON_BUS_CNTL); | 147 | bus_cntl = RREG32(R600_BUS_CNTL); |
| 147 | d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); | 148 | d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); |
| 148 | d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); | 149 | d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); |
| 149 | vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); | 150 | vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); |
| @@ -152,7 +153,7 @@ static bool r700_read_disabled_bios(struct radeon_device *rdev) | |||
| 152 | /* disable VIP */ | 153 | /* disable VIP */ |
| 153 | WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); | 154 | WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); |
| 154 | /* enable the rom */ | 155 | /* enable the rom */ |
| 155 | WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); | 156 | WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); |
| 156 | /* Disable VGA mode */ | 157 | /* Disable VGA mode */ |
| 157 | WREG32(AVIVO_D1VGA_CONTROL, | 158 | WREG32(AVIVO_D1VGA_CONTROL, |
| 158 | (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | | 159 | (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | |
| @@ -191,7 +192,7 @@ static bool r700_read_disabled_bios(struct radeon_device *rdev) | |||
| 191 | cg_spll_status = RREG32(R600_CG_SPLL_STATUS); | 192 | cg_spll_status = RREG32(R600_CG_SPLL_STATUS); |
| 192 | } | 193 | } |
| 193 | WREG32(RADEON_VIPH_CONTROL, viph_control); | 194 | WREG32(RADEON_VIPH_CONTROL, viph_control); |
| 194 | WREG32(RADEON_BUS_CNTL, bus_cntl); | 195 | WREG32(R600_BUS_CNTL, bus_cntl); |
| 195 | WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); | 196 | WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); |
| 196 | WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); | 197 | WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); |
| 197 | WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); | 198 | WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); |
| @@ -216,7 +217,7 @@ static bool r600_read_disabled_bios(struct radeon_device *rdev) | |||
| 216 | bool r; | 217 | bool r; |
| 217 | 218 | ||
| 218 | viph_control = RREG32(RADEON_VIPH_CONTROL); | 219 | viph_control = RREG32(RADEON_VIPH_CONTROL); |
| 219 | bus_cntl = RREG32(RADEON_BUS_CNTL); | 220 | bus_cntl = RREG32(R600_BUS_CNTL); |
| 220 | d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); | 221 | d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); |
| 221 | d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); | 222 | d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); |
| 222 | vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); | 223 | vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); |
| @@ -231,7 +232,7 @@ static bool r600_read_disabled_bios(struct radeon_device *rdev) | |||
| 231 | /* disable VIP */ | 232 | /* disable VIP */ |
| 232 | WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); | 233 | WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); |
| 233 | /* enable the rom */ | 234 | /* enable the rom */ |
| 234 | WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); | 235 | WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); |
| 235 | /* Disable VGA mode */ | 236 | /* Disable VGA mode */ |
| 236 | WREG32(AVIVO_D1VGA_CONTROL, | 237 | WREG32(AVIVO_D1VGA_CONTROL, |
| 237 | (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | | 238 | (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | |
| @@ -262,7 +263,7 @@ static bool r600_read_disabled_bios(struct radeon_device *rdev) | |||
| 262 | 263 | ||
| 263 | /* restore regs */ | 264 | /* restore regs */ |
| 264 | WREG32(RADEON_VIPH_CONTROL, viph_control); | 265 | WREG32(RADEON_VIPH_CONTROL, viph_control); |
| 265 | WREG32(RADEON_BUS_CNTL, bus_cntl); | 266 | WREG32(R600_BUS_CNTL, bus_cntl); |
| 266 | WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); | 267 | WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); |
| 267 | WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); | 268 | WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); |
| 268 | WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); | 269 | WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 3bddea5b5295..137b8075f6e7 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
| @@ -729,7 +729,7 @@ void radeon_combios_i2c_init(struct radeon_device *rdev) | |||
| 729 | clk = RBIOS8(offset + 3 + (i * 5) + 3); | 729 | clk = RBIOS8(offset + 3 + (i * 5) + 3); |
| 730 | data = RBIOS8(offset + 3 + (i * 5) + 4); | 730 | data = RBIOS8(offset + 3 + (i * 5) + 4); |
| 731 | i2c = combios_setup_i2c_bus(rdev, DDC_MONID, | 731 | i2c = combios_setup_i2c_bus(rdev, DDC_MONID, |
| 732 | clk, data); | 732 | (1 << clk), (1 << data)); |
| 733 | rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); | 733 | rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); |
| 734 | break; | 734 | break; |
| 735 | } | 735 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 3bef9f6d66fd..8afaf7a7459e 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -1175,6 +1175,8 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1175 | /* no HPD on analog connectors */ | 1175 | /* no HPD on analog connectors */ |
| 1176 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; | 1176 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
| 1177 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | 1177 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; |
| 1178 | connector->interlace_allowed = true; | ||
| 1179 | connector->doublescan_allowed = true; | ||
| 1178 | break; | 1180 | break; |
| 1179 | case DRM_MODE_CONNECTOR_DVIA: | 1181 | case DRM_MODE_CONNECTOR_DVIA: |
| 1180 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1182 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
| @@ -1190,6 +1192,8 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1190 | 1); | 1192 | 1); |
| 1191 | /* no HPD on analog connectors */ | 1193 | /* no HPD on analog connectors */ |
| 1192 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; | 1194 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
| 1195 | connector->interlace_allowed = true; | ||
| 1196 | connector->doublescan_allowed = true; | ||
| 1193 | break; | 1197 | break; |
| 1194 | case DRM_MODE_CONNECTOR_DVII: | 1198 | case DRM_MODE_CONNECTOR_DVII: |
| 1195 | case DRM_MODE_CONNECTOR_DVID: | 1199 | case DRM_MODE_CONNECTOR_DVID: |
| @@ -1226,6 +1230,11 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1226 | rdev->mode_info.load_detect_property, | 1230 | rdev->mode_info.load_detect_property, |
| 1227 | 1); | 1231 | 1); |
| 1228 | } | 1232 | } |
| 1233 | connector->interlace_allowed = true; | ||
| 1234 | if (connector_type == DRM_MODE_CONNECTOR_DVII) | ||
| 1235 | connector->doublescan_allowed = true; | ||
| 1236 | else | ||
| 1237 | connector->doublescan_allowed = false; | ||
| 1229 | break; | 1238 | break; |
| 1230 | case DRM_MODE_CONNECTOR_HDMIA: | 1239 | case DRM_MODE_CONNECTOR_HDMIA: |
| 1231 | case DRM_MODE_CONNECTOR_HDMIB: | 1240 | case DRM_MODE_CONNECTOR_HDMIB: |
| @@ -1256,6 +1265,11 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1256 | 0); | 1265 | 0); |
| 1257 | } | 1266 | } |
| 1258 | subpixel_order = SubPixelHorizontalRGB; | 1267 | subpixel_order = SubPixelHorizontalRGB; |
| 1268 | connector->interlace_allowed = true; | ||
| 1269 | if (connector_type == DRM_MODE_CONNECTOR_HDMIB) | ||
| 1270 | connector->doublescan_allowed = true; | ||
| 1271 | else | ||
| 1272 | connector->doublescan_allowed = false; | ||
| 1259 | break; | 1273 | break; |
| 1260 | case DRM_MODE_CONNECTOR_DisplayPort: | 1274 | case DRM_MODE_CONNECTOR_DisplayPort: |
| 1261 | case DRM_MODE_CONNECTOR_eDP: | 1275 | case DRM_MODE_CONNECTOR_eDP: |
| @@ -1293,6 +1307,9 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1293 | rdev->mode_info.underscan_vborder_property, | 1307 | rdev->mode_info.underscan_vborder_property, |
| 1294 | 0); | 1308 | 0); |
| 1295 | } | 1309 | } |
| 1310 | connector->interlace_allowed = true; | ||
| 1311 | /* in theory with a DP to VGA converter... */ | ||
| 1312 | connector->doublescan_allowed = false; | ||
| 1296 | break; | 1313 | break; |
| 1297 | case DRM_MODE_CONNECTOR_SVIDEO: | 1314 | case DRM_MODE_CONNECTOR_SVIDEO: |
| 1298 | case DRM_MODE_CONNECTOR_Composite: | 1315 | case DRM_MODE_CONNECTOR_Composite: |
| @@ -1308,6 +1325,8 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1308 | radeon_atombios_get_tv_info(rdev)); | 1325 | radeon_atombios_get_tv_info(rdev)); |
| 1309 | /* no HPD on analog connectors */ | 1326 | /* no HPD on analog connectors */ |
| 1310 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; | 1327 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
| 1328 | connector->interlace_allowed = false; | ||
| 1329 | connector->doublescan_allowed = false; | ||
| 1311 | break; | 1330 | break; |
| 1312 | case DRM_MODE_CONNECTOR_LVDS: | 1331 | case DRM_MODE_CONNECTOR_LVDS: |
| 1313 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); | 1332 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
| @@ -1326,6 +1345,8 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1326 | dev->mode_config.scaling_mode_property, | 1345 | dev->mode_config.scaling_mode_property, |
| 1327 | DRM_MODE_SCALE_FULLSCREEN); | 1346 | DRM_MODE_SCALE_FULLSCREEN); |
| 1328 | subpixel_order = SubPixelHorizontalRGB; | 1347 | subpixel_order = SubPixelHorizontalRGB; |
| 1348 | connector->interlace_allowed = false; | ||
| 1349 | connector->doublescan_allowed = false; | ||
| 1329 | break; | 1350 | break; |
| 1330 | } | 1351 | } |
| 1331 | 1352 | ||
| @@ -1403,6 +1424,8 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
| 1403 | /* no HPD on analog connectors */ | 1424 | /* no HPD on analog connectors */ |
| 1404 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; | 1425 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
| 1405 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | 1426 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; |
| 1427 | connector->interlace_allowed = true; | ||
| 1428 | connector->doublescan_allowed = true; | ||
| 1406 | break; | 1429 | break; |
| 1407 | case DRM_MODE_CONNECTOR_DVIA: | 1430 | case DRM_MODE_CONNECTOR_DVIA: |
| 1408 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1431 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
| @@ -1418,6 +1441,8 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
| 1418 | 1); | 1441 | 1); |
| 1419 | /* no HPD on analog connectors */ | 1442 | /* no HPD on analog connectors */ |
| 1420 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; | 1443 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
| 1444 | connector->interlace_allowed = true; | ||
| 1445 | connector->doublescan_allowed = true; | ||
| 1421 | break; | 1446 | break; |
| 1422 | case DRM_MODE_CONNECTOR_DVII: | 1447 | case DRM_MODE_CONNECTOR_DVII: |
| 1423 | case DRM_MODE_CONNECTOR_DVID: | 1448 | case DRM_MODE_CONNECTOR_DVID: |
| @@ -1435,6 +1460,11 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
| 1435 | 1); | 1460 | 1); |
| 1436 | } | 1461 | } |
| 1437 | subpixel_order = SubPixelHorizontalRGB; | 1462 | subpixel_order = SubPixelHorizontalRGB; |
| 1463 | connector->interlace_allowed = true; | ||
| 1464 | if (connector_type == DRM_MODE_CONNECTOR_DVII) | ||
| 1465 | connector->doublescan_allowed = true; | ||
| 1466 | else | ||
| 1467 | connector->doublescan_allowed = false; | ||
| 1438 | break; | 1468 | break; |
| 1439 | case DRM_MODE_CONNECTOR_SVIDEO: | 1469 | case DRM_MODE_CONNECTOR_SVIDEO: |
| 1440 | case DRM_MODE_CONNECTOR_Composite: | 1470 | case DRM_MODE_CONNECTOR_Composite: |
| @@ -1457,6 +1487,8 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
| 1457 | radeon_combios_get_tv_info(rdev)); | 1487 | radeon_combios_get_tv_info(rdev)); |
| 1458 | /* no HPD on analog connectors */ | 1488 | /* no HPD on analog connectors */ |
| 1459 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; | 1489 | radeon_connector->hpd.hpd = RADEON_HPD_NONE; |
| 1490 | connector->interlace_allowed = false; | ||
| 1491 | connector->doublescan_allowed = false; | ||
| 1460 | break; | 1492 | break; |
| 1461 | case DRM_MODE_CONNECTOR_LVDS: | 1493 | case DRM_MODE_CONNECTOR_LVDS: |
| 1462 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); | 1494 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
| @@ -1470,6 +1502,8 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
| 1470 | dev->mode_config.scaling_mode_property, | 1502 | dev->mode_config.scaling_mode_property, |
| 1471 | DRM_MODE_SCALE_FULLSCREEN); | 1503 | DRM_MODE_SCALE_FULLSCREEN); |
| 1472 | subpixel_order = SubPixelHorizontalRGB; | 1504 | subpixel_order = SubPixelHorizontalRGB; |
| 1505 | connector->interlace_allowed = false; | ||
| 1506 | connector->doublescan_allowed = false; | ||
| 1473 | break; | 1507 | break; |
| 1474 | } | 1508 | } |
| 1475 | 1509 | ||
