From ca070c3e7f5a89cd271ad4892279aa267227c717 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Tue, 17 Dec 2013 06:12:18 +0000 Subject: [PATCH] i915: update to 3.12.5 git-svn-id: svn://kolibrios.org@4371 a494cfbc-eb01-0410-851d-a64ba20cac60 --- drivers/video/drm/i915/Makefile.lto | 2 + drivers/video/drm/i915/i915_gem.c | 4 +- drivers/video/drm/i915/i915_gem_execbuffer.c | 85 +++++--- drivers/video/drm/i915/i915_trace.h | 3 +- drivers/video/drm/i915/intel_ddi.c | 20 ++ drivers/video/drm/i915/intel_display.c | 4 + drivers/video/drm/i915/intel_ringbuffer.c | 4 +- drivers/video/drm/i915/intel_uncore.c | 26 +-- drivers/video/drm/i915/kms_display.c | 196 ++++++++++--------- drivers/video/drm/i915/kos_gem_fb.c | 22 +++ 10 files changed, 224 insertions(+), 142 deletions(-) diff --git a/drivers/video/drm/i915/Makefile.lto b/drivers/video/drm/i915/Makefile.lto index cf5ecaa238..bbd7f531af 100644 --- a/drivers/video/drm/i915/Makefile.lto +++ b/drivers/video/drm/i915/Makefile.lto @@ -75,10 +75,12 @@ NAME_SRC= main.c \ intel_sprite.c \ intel_uncore.c \ kms_display.c \ + kos_gem_fb.c \ utils.c \ ../hdmi.c \ Gtt/intel-agp.c \ Gtt/intel-gtt.c \ + ../drm_cache.c \ ../drm_global.c \ ../drm_drv.c \ ../drm_vma_manager.c \ diff --git a/drivers/video/drm/i915/i915_gem.c b/drivers/video/drm/i915/i915_gem.c index 3b6d611097..42b314ad98 100644 --- a/drivers/video/drm/i915/i915_gem.c +++ b/drivers/video/drm/i915/i915_gem.c @@ -682,7 +682,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, if ((page_offset + remain) > PAGE_SIZE) page_length = PAGE_SIZE - page_offset; - MapPage(vaddr, page_base, PG_SW|PG_NOCACHE); + MapPage(vaddr, dev_priv->gtt.mappable_base+page_base, PG_SW|PG_NOCACHE); memcpy(vaddr+page_offset, user_data, page_length); @@ -716,7 +716,7 @@ shmem_pwrite_fast(struct page *page, int shmem_page_offset, int page_length, if (unlikely(page_do_bit17_swizzling)) return -EINVAL; - vaddr = (char *)MapIoMem((addr_t)page, 4096, PG_SW); + vaddr = (char *)MapIoMem((addr_t)page, 4096, PG_SW|PG_NOCACHE); if (needs_clflush_before) drm_clflush_virt_range(vaddr + shmem_page_offset, page_length); diff --git a/drivers/video/drm/i915/i915_gem_execbuffer.c b/drivers/video/drm/i915/i915_gem_execbuffer.c index efbd1213ce..3ac857d965 100644 --- a/drivers/video/drm/i915/i915_gem_execbuffer.c +++ b/drivers/video/drm/i915/i915_gem_execbuffer.c @@ -37,7 +37,6 @@ #define I915_EXEC_IS_PINNED (1<<10) #define I915_EXEC_VEBOX (4<<0) -#define wmb() asm volatile ("sfence") struct drm_i915_gem_object *get_fb_obj(); @@ -205,6 +204,56 @@ static inline int use_cpu_reloc(struct drm_i915_gem_object *obj) obj->cache_level != I915_CACHE_NONE); } +static int +relocate_entry_cpu(struct drm_i915_gem_object *obj, + struct drm_i915_gem_relocation_entry *reloc) +{ + uint32_t page_offset = offset_in_page(reloc->offset); + char *vaddr; + int ret = -EINVAL; + + ret = i915_gem_object_set_to_cpu_domain(obj, 1); + if (ret) + return ret; + + vaddr = (char *)MapIoMem((addr_t)i915_gem_object_get_page(obj, + reloc->offset >> PAGE_SHIFT), 4096, 3); + *(uint32_t *)(vaddr + page_offset) = reloc->delta; + FreeKernelSpace(vaddr); + + return 0; +} + +static int +relocate_entry_gtt(struct drm_i915_gem_object *obj, + struct drm_i915_gem_relocation_entry *reloc) +{ + struct drm_device *dev = obj->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t __iomem *reloc_entry; + void __iomem *reloc_page; + int ret = -EINVAL; + + ret = i915_gem_object_set_to_gtt_domain(obj, true); + if (ret) + return ret; + + ret = i915_gem_object_put_fence(obj); + if (ret) + return ret; + + /* Map the page containing the relocation we're going to perform. */ + reloc->offset += i915_gem_obj_ggtt_offset(obj); + reloc_page = (void*)MapIoMem(dev_priv->gtt.mappable_base + + (reloc->offset & PAGE_MASK), 4096, 0x18|3); + reloc_entry = (uint32_t __iomem *) + (reloc_page + offset_in_page(reloc->offset)); + iowrite32(reloc->delta, reloc_entry); + FreeKernelSpace(reloc_page); + + return 0; +} + static int i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, struct eb_objects *eb, @@ -287,40 +336,14 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, /* We can't wait for rendering with pagefaults disabled */ reloc->delta += target_offset; - if (use_cpu_reloc(obj)) { - uint32_t page_offset = reloc->offset & ~PAGE_MASK; - char *vaddr; + if (use_cpu_reloc(obj)) + ret = relocate_entry_cpu(obj, reloc); + else + ret = relocate_entry_gtt(obj, reloc); - ret = i915_gem_object_set_to_cpu_domain(obj, 1); if (ret) return ret; - vaddr = (char *)MapIoMem((addr_t)i915_gem_object_get_page(obj, - reloc->offset >> PAGE_SHIFT), 4096, 3); - *(uint32_t *)(vaddr + page_offset) = reloc->delta; - FreeKernelSpace(vaddr); - } else { - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t __iomem *reloc_entry; - void __iomem *reloc_page; - - ret = i915_gem_object_set_to_gtt_domain(obj, true); - if (ret) - return ret; - - ret = i915_gem_object_put_fence(obj); - if (ret) - return ret; - - /* Map the page containing the relocation we're going to perform. */ - reloc->offset += i915_gem_obj_ggtt_offset(obj); - reloc_page = (void*)MapIoMem(reloc->offset & PAGE_MASK, 4096, 3); - reloc_entry = (uint32_t __iomem *) - (reloc_page + (reloc->offset & ~PAGE_MASK)); - iowrite32(reloc->delta, reloc_entry); - FreeKernelSpace(reloc_page); - } - /* and update the user's relocation entry */ reloc->presumed_offset = target_offset; diff --git a/drivers/video/drm/i915/i915_trace.h b/drivers/video/drm/i915/i915_trace.h index d1da57d93f..c9365fd169 100644 --- a/drivers/video/drm/i915/i915_trace.h +++ b/drivers/video/drm/i915/i915_trace.h @@ -18,7 +18,7 @@ #define trace_i915_gem_request_wait_end(a, b) #define trace_i915_gem_request_complete(a, b) #define trace_intel_gpu_freq_change(a) -#define trace_i915_reg_rw(a, b, c, d) +#define trace_i915_reg_rw(a, b, c, d, e) #define trace_i915_ring_wait_begin(a) #define trace_i915_gem_object_pwrite(a, b, c) #define trace_i915_gem_request_add(a, b) @@ -26,6 +26,5 @@ #define trace_i915_vma_bind(a, b) #define trace_i915_vma_unbind(a) #define trace_i915_gem_object_clflush(a) -#define trace_i915_reg_rw(a, b, c, d, e) #endif diff --git a/drivers/video/drm/i915/intel_ddi.c b/drivers/video/drm/i915/intel_ddi.c index d168cdb77e..3cbb23fdcb 100644 --- a/drivers/video/drm/i915/intel_ddi.c +++ b/drivers/video/drm/i915/intel_ddi.c @@ -1285,6 +1285,26 @@ void intel_ddi_get_config(struct intel_encoder *encoder, default: break; } + + if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp && + pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { + /* + * This is a big fat ugly hack. + * + * Some machines in UEFI boot mode provide us a VBT that has 18 + * bpp and 1.62 GHz link bandwidth for eDP, which for reasons + * unknown we fail to light up. Yet the same BIOS boots up with + * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as + * max, not what it tells us to use. + * + * Note: This will still be broken if the eDP panel is not lit + * up by the BIOS, and thus we can't get the mode at module + * load. + */ + DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", + pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp); + dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; + } } static void intel_ddi_destroy(struct drm_encoder *encoder) diff --git a/drivers/video/drm/i915/intel_display.c b/drivers/video/drm/i915/intel_display.c index 5e8fbddd20..3ada8ab51d 100644 --- a/drivers/video/drm/i915/intel_display.c +++ b/drivers/video/drm/i915/intel_display.c @@ -6783,7 +6783,9 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) intel_crtc->cursor_visible = visible; } /* and commit changes on next vblank */ + POSTING_READ(CURCNTR(pipe)); I915_WRITE(CURBASE(pipe), base); + POSTING_READ(CURBASE(pipe)); } static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) @@ -6812,7 +6814,9 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) intel_crtc->cursor_visible = visible; } /* and commit changes on next vblank */ + POSTING_READ(CURCNTR_IVB(pipe)); I915_WRITE(CURBASE_IVB(pipe), base); + POSTING_READ(CURBASE_IVB(pipe)); } /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ diff --git a/drivers/video/drm/i915/intel_ringbuffer.c b/drivers/video/drm/i915/intel_ringbuffer.c index 461d587c35..83855243b9 100644 --- a/drivers/video/drm/i915/intel_ringbuffer.c +++ b/drivers/video/drm/i915/intel_ringbuffer.c @@ -1247,8 +1247,8 @@ static int intel_init_ring_buffer(struct drm_device *dev, } obj = NULL; -// if (!HAS_LLC(dev)) -// obj = i915_gem_object_create_stolen(dev, ring->size); + if (!HAS_LLC(dev)) + obj = i915_gem_object_create_stolen(dev, ring->size); if (obj == NULL) obj = i915_gem_alloc_object(dev, ring->size); if (obj == NULL) { diff --git a/drivers/video/drm/i915/intel_uncore.c b/drivers/video/drm/i915/intel_uncore.c index 4854808ba8..3e1f16180e 100644 --- a/drivers/video/drm/i915/intel_uncore.c +++ b/drivers/video/drm/i915/intel_uncore.c @@ -204,6 +204,19 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv) gen6_gt_check_fifodbg(dev_priv); } +static void intel_uncore_forcewake_reset(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (IS_VALLEYVIEW(dev)) { + vlv_force_wake_reset(dev_priv); + } else if (INTEL_INFO(dev)->gen >= 6) { + __gen6_gt_force_wake_reset(dev_priv); + if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) + __gen6_gt_force_wake_mt_reset(dev_priv); + } +} + void intel_uncore_early_sanitize(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -259,19 +272,8 @@ void intel_uncore_init(struct drm_device *dev) dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_put; } -} -static void intel_uncore_forcewake_reset(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (IS_VALLEYVIEW(dev)) { - vlv_force_wake_reset(dev_priv); - } else if (INTEL_INFO(dev)->gen >= 6) { - __gen6_gt_force_wake_reset(dev_priv); - if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) - __gen6_gt_force_wake_mt_reset(dev_priv); - } + intel_uncore_forcewake_reset(dev); } void intel_uncore_sanitize(struct drm_device *dev) diff --git a/drivers/video/drm/i915/kms_display.c b/drivers/video/drm/i915/kms_display.c index 8384e228af..4da1115ea2 100644 --- a/drivers/video/drm/i915/kms_display.c +++ b/drivers/video/drm/i915/kms_display.c @@ -108,8 +108,8 @@ bool set_mode(struct drm_device *dev, struct drm_connector *connector, struct drm_encoder *encoder; struct drm_i915_gem_object *fb_obj; struct drm_mode_set set; - char *con_name; - char *enc_name; + const char *con_name; + const char *enc_name; unsigned hdisplay, vdisplay; int ret; @@ -263,13 +263,85 @@ static struct drm_connector* get_def_connector(struct drm_device *dev) return def_connector; }; +struct drm_connector *get_active_connector(struct drm_device *dev) +{ + struct drm_connector *tmp = NULL; + struct drm_connector_helper_funcs *connector_funcs; + struct drm_encoder *encoder; + + list_for_each_entry(tmp, &dev->mode_config.connector_list, head) + { + if( tmp->status != connector_status_connected) + continue; + + connector_funcs = tmp->helper_private; + encoder = connector_funcs->best_encoder(tmp); + if( encoder == NULL) + { + DRM_DEBUG_KMS("CONNECTOR %x ID: %d no active encoders\n", + tmp, tmp->base.id); + continue; + }; + + tmp->encoder = encoder; + + DRM_DEBUG_KMS("CONNECTOR %p ID:%d status:%d ENCODER %x CRTC %p ID:%d\n", + tmp, tmp->base.id, tmp->status, tmp->encoder, + tmp->encoder->crtc, tmp->encoder->crtc->base.id ); + + return tmp; + }; + + return NULL; +} + +struct drm_crtc *get_possible_crtc(struct drm_device *dev, struct drm_encoder *encoder) + { + struct drm_crtc *tmp_crtc; + int crtc_mask = 1; + + list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) + { + if (encoder->possible_crtcs & crtc_mask) + { + encoder->crtc = tmp_crtc; + dbgprintf("CRTC %p\n", tmp_crtc); + return tmp_crtc; + }; + crtc_mask <<= 1; + }; + return NULL; + }; + +int get_boot_mode(struct drm_connector *connector, videomode_t *usermode) +{ + struct drm_display_mode *mode; + + list_for_each_entry(mode, &connector->modes, head) + { + dbgprintf("check mode w:%d h:%d %dHz\n", + drm_mode_width(mode), drm_mode_height(mode), + drm_mode_vrefresh(mode)); + + if( os_display->width == drm_mode_width(mode) && + os_display->height == drm_mode_height(mode) && + drm_mode_vrefresh(mode) == 60) + { + usermode->width = os_display->width; + usermode->height = os_display->height; + usermode->freq = 60; + return 1; + } + } + return 0; +} int init_display_kms(struct drm_device *dev, videomode_t *usermode) { struct drm_connector *connector; struct drm_connector_helper_funcs *connector_funcs; struct drm_encoder *encoder; - struct drm_crtc *crtc = NULL; + struct drm_crtc *crtc; struct drm_framebuffer *fb; cursor_t *cursor; @@ -280,29 +352,7 @@ int init_display_kms(struct drm_device *dev, videomode_t *usermode) mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - { - if( connector->status != connector_status_connected) - continue; - - connector_funcs = connector->helper_private; - encoder = connector_funcs->best_encoder(connector); - if( encoder == NULL) - { - DRM_DEBUG_KMS("CONNECTOR %x ID: %d no active encoders\n", - connector, connector->base.id); - continue; - } - connector->encoder = encoder; - crtc = encoder->crtc; - - DRM_DEBUG_KMS("CONNECTOR %p ID:%d status:%d ENCODER %x CRTC %p ID:%d\n", - connector, connector->base.id, - connector->status, connector->encoder, - crtc, crtc->base.id ); - break; - }; - + connector = get_active_connector(dev) ; if(connector == NULL) { DRM_DEBUG_KMS("No active connectors!\n"); @@ -310,26 +360,11 @@ int init_display_kms(struct drm_device *dev, videomode_t *usermode) return -1; }; - dbgprintf("CRTC %p\n", crtc); + encoder = connector->encoder; + crtc = encoder->crtc; if(crtc == NULL) - { - struct drm_crtc *tmp_crtc; - int crtc_mask = 1; - - list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) - { - dbgprintf("tmp_crtc %p\n", tmp_crtc); - if (encoder->possible_crtcs & crtc_mask) - { - crtc = tmp_crtc; - encoder->crtc = crtc; - dbgprintf("CRTC %p\n", crtc); - break; - }; - crtc_mask <<= 1; - }; - }; + crtc = get_possible_crtc(dev, encoder); dbgprintf("CRTC %p\n", crtc); @@ -377,31 +412,11 @@ int init_display_kms(struct drm_device *dev, videomode_t *usermode) if( (usermode->width == 0) || (usermode->height == 0)) { + if( !get_boot_mode(connector, usermode)) + { struct drm_display_mode *mode; - list_for_each_entry(mode, &connector->modes, head) - { - dbgprintf("check mode w:%d h:%d %dHz\n", - drm_mode_width(mode), drm_mode_height(mode), - drm_mode_vrefresh(mode)); - - if( os_display->width == drm_mode_width(mode) && - os_display->height == drm_mode_height(mode) && - drm_mode_vrefresh(mode) == 60) - { - usermode->width = os_display->width; - usermode->height = os_display->height; - usermode->freq = 60; - break; - - } - } - - if( usermode->width == 0 || - usermode->height == 0) - { mode = list_entry(connector->modes.next, typeof(*mode), head); - usermode->width = drm_mode_width(mode); usermode->height = drm_mode_height(mode); usermode->freq = drm_mode_vrefresh(mode); @@ -483,7 +498,7 @@ int set_user_mode(videomode_t *mode) void i915_dpms(struct drm_device *dev, int mode) { - struct drm_connector_funcs *f = os_display->connector->funcs; + const struct drm_connector_funcs *f = os_display->connector->funcs; f->dpms(os_display->connector, mode); }; @@ -684,23 +699,19 @@ cursor_t* __stdcall select_cursor_kms(cursor_t *cursor) return old; }; -struct sna_fb +int i915_fbinfo(struct drm_i915_fb_info *fb) { - uint32_t width; - uint32_t height; - uint32_t pitch; - uint32_t tiling; -}; + struct drm_i915_gem_object *obj = get_fb_obj(); -int i915_fbinfo(struct sna_fb *fb) -{ + fb->name = obj->base.name; fb->width = os_display->width; fb->height = os_display->height; - fb->pitch = os_display->pitch; - fb->tiling = 0; + fb->pitch = obj->stride; + fb->tiling = obj->tiling_mode; return 0; -}; +} + typedef struct { @@ -710,14 +721,6 @@ typedef struct int bottom; }rect_t; -struct drm_i915_mask { - __u32 handle; - __u32 width; - __u32 height; - __u32 bo_size; - __u32 bo_pitch; - __u32 bo_map; -}; #define CURRENT_TASK (0x80003000) @@ -740,7 +743,7 @@ int i915_mask_update(struct drm_device *dev, void *data, static unsigned int mask_seqno[256]; rect_t winrc; u32 slot; - int ret; + int ret=0; if(mask->handle == -2) { @@ -788,13 +791,13 @@ int i915_mask_update(struct drm_device *dev, void *data, ret = i915_mutex_lock_interruptible(dev); if (ret) - return ret; + goto err1; ret = i915_gem_object_set_to_cpu_domain(to_intel_bo(obj), true); if(ret !=0 ) { - dbgprintf("%s fail\n", __FUNCTION__); - return ret; + dbgprintf("%s: i915_gem_object_set_to_cpu_domain failed\n", __FUNCTION__); + goto err2; }; // printf("width %d height %d\n", winrc.right, winrc.bottom); @@ -886,13 +889,20 @@ int i915_mask_update(struct drm_device *dev, void *data, }; }; safe_sti(ifl); + + ret = i915_gem_object_set_to_gtt_domain(to_intel_bo(obj), false); + if(ret != 0 ) + { + dbgprintf("%s: i915_gem_object_set_to_gtt_domain failed\n", __FUNCTION__); + }; } +err2: + mutex_unlock(&dev->struct_mutex); +err1: drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); - - return 0; + return ret; } diff --git a/drivers/video/drm/i915/kos_gem_fb.c b/drivers/video/drm/i915/kos_gem_fb.c index 01cb7470b0..40232aa80b 100644 --- a/drivers/video/drm/i915/kos_gem_fb.c +++ b/drivers/video/drm/i915/kos_gem_fb.c @@ -187,8 +187,30 @@ kos_gem_fb_object_create(struct drm_device *dev, list_add_tail(&obj->global_list, &dev_priv->mm.bound_list); list_add_tail(&vma->mm_list, &ggtt->inactive_list); + mutex_lock(&dev->object_name_lock); + idr_preload(GFP_KERNEL); + + if (!obj->base.name) { + ret = idr_alloc(&dev->object_name_idr, &obj->base, 1, 0, GFP_NOWAIT); + if (ret < 0) + goto err_gem; + + obj->base.name = ret; + + /* Allocate a reference for the name table. */ + drm_gem_object_reference(&obj->base); + + printf("%s allocate fb name %d\n", __FUNCTION__, obj->base.name ); + } + + idr_preload_end(); + mutex_unlock(&dev->object_name_lock); + drm_gem_object_unreference(&obj->base); return obj; +err_gem: + idr_preload_end(); + mutex_unlock(&dev->object_name_lock); err_vma: i915_gem_vma_destroy(vma); err_out: