From da432de99fedc9c8acef7ab1f4ecaed6f19a7f84 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Mon, 27 Jan 2014 20:10:22 +0000 Subject: [PATCH] i915: 3.12.9 git-svn-id: svn://kolibrios.org@4539 a494cfbc-eb01-0410-851d-a64ba20cac60 --- drivers/video/drm/drm_cache.c | 6 +- drivers/video/drm/drm_edid.c | 26 ++- drivers/video/drm/drm_fb_helper.c | 2 +- drivers/video/drm/drm_gem.c | 17 +- drivers/video/drm/drm_irq.c | 2 +- drivers/video/drm/i915/i915_dma.c | 5 + drivers/video/drm/i915/i915_drv.h | 4 +- drivers/video/drm/i915/i915_gem.c | 50 +++-- drivers/video/drm/i915/i915_gem_context.c | 16 +- drivers/video/drm/i915/i915_gem_execbuffer.c | 22 +- drivers/video/drm/i915/i915_gem_gtt.c | 2 +- drivers/video/drm/i915/i915_irq.c | 14 +- drivers/video/drm/i915/intel_ddi.c | 8 +- drivers/video/drm/i915/intel_display.c | 27 ++- drivers/video/drm/i915/intel_dp.c | 2 +- drivers/video/drm/i915/intel_pm.c | 8 +- drivers/video/drm/i915/intel_ringbuffer.c | 4 +- drivers/video/drm/i915/kms_display.c | 210 ++++++++++++++++++- drivers/video/drm/i915/main.c | 6 +- 19 files changed, 338 insertions(+), 93 deletions(-) diff --git a/drivers/video/drm/drm_cache.c b/drivers/video/drm/drm_cache.c index d3c712189d..1709b83940 100644 --- a/drivers/video/drm/drm_cache.c +++ b/drivers/video/drm/drm_cache.c @@ -103,7 +103,7 @@ EXPORT_SYMBOL(drm_clflush_pages); void drm_clflush_sg(struct sg_table *st) { - struct sg_page_iter sg_iter; + struct sg_page_iter sg_iter; struct page *page; uint8_t *pva; @@ -112,8 +112,8 @@ drm_clflush_sg(struct sg_table *st) pva = AllocKernelSpace(4096); if( pva != NULL) { - mb(); - for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) + mb(); + for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { page = sg_page_iter_page(&sg_iter); diff --git a/drivers/video/drm/drm_edid.c b/drivers/video/drm/drm_edid.c index 193c63cd64..262ae6397c 100644 --- a/drivers/video/drm/drm_edid.c +++ b/drivers/video/drm/drm_edid.c @@ -68,6 +68,8 @@ #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) /* Force reduced-blanking timings for detailed modes */ #define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) +/* Force 8bpc */ +#define EDID_QUIRK_FORCE_8BPC (1 << 8) struct detailed_mode_closure { struct drm_connector *connector; @@ -128,6 +130,9 @@ static struct edid_quirk { /* Medion MD 30217 PG */ { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 }, + + /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */ + { "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC }, }; /* @@ -1009,12 +1014,12 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid) if (block == 0) { int score = drm_edid_header_is_valid(raw_edid); - if (score == 8) ; - else if (score >= edid_fixup) { - DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); - memcpy(raw_edid, edid_header, sizeof(edid_header)); + if (score == 8) ; + else if (score >= edid_fixup) { + DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); + memcpy(raw_edid, edid_header, sizeof(edid_header)); } else { - goto bad; + goto bad; } } @@ -1163,7 +1168,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) /* base block fetch */ for (i = 0; i < 4; i++) { if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH)) - goto out; + goto out; if (drm_edid_block_valid(block, 0, print_bad_edid)) break; if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { @@ -2258,7 +2263,7 @@ do_cvt_mode(struct detailed_timing *timing, void *c) static int add_cvt_modes(struct drm_connector *connector, struct edid *edid) -{ +{ struct detailed_mode_closure closure = { connector, edid, 0, 0, 0 }; @@ -2683,7 +2688,7 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid) dbl = cea_db_payload_len(db); if (cea_db_tag(db) == VIDEO_BLOCK) - modes += do_cea_modes (connector, db+1, dbl); + modes += do_cea_modes(connector, db + 1, dbl); else if (cea_db_is_hdmi_vsdb(db)) modes += do_hdmi_vsdb_modes(connector, db, dbl); } @@ -2795,7 +2800,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) for_each_cea_db(cea, i, start, end) { db = &cea[i]; dbl = cea_db_payload_len(db); - + switch (cea_db_tag(db)) { case AUDIO_BLOCK: /* Audio Data Block, contains SADs */ @@ -3236,6 +3241,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) drm_add_display_info(edid, &connector->display_info); + if (quirks & EDID_QUIRK_FORCE_8BPC) + connector->display_info.bpc = 8; + return num_modes; } EXPORT_SYMBOL(drm_add_edid_modes); diff --git a/drivers/video/drm/drm_fb_helper.c b/drivers/video/drm/drm_fb_helper.c index 8b0d6a1ebc..dd9d7d4543 100644 --- a/drivers/video/drm/drm_fb_helper.c +++ b/drivers/video/drm/drm_fb_helper.c @@ -689,7 +689,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, if (desired_mode->vdisplay > sizes.surface_height) sizes.surface_height = desired_mode->vdisplay; crtc_count++; - } + } } if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) { diff --git a/drivers/video/drm/drm_gem.c b/drivers/video/drm/drm_gem.c index 02c0c9dc1d..dd9332db3a 100644 --- a/drivers/video/drm/drm_gem.c +++ b/drivers/video/drm/drm_gem.c @@ -254,9 +254,6 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle) * we may want to use ida for number allocation and a hash table * for the pointers, anyway. */ - if(handle == -2) - printf("%s handle %d\n", __FUNCTION__, handle); - spin_lock(&filp->table_lock); /* Check if we currently have a reference on the object */ @@ -267,8 +264,6 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle) } dev = obj->dev; - // printf("%s handle %d obj %p\n", __FUNCTION__, handle, obj); - /* Release reference and decrement refcount. */ idr_remove(&filp->object_idr, handle); spin_unlock(&filp->table_lock); @@ -286,6 +281,12 @@ EXPORT_SYMBOL(drm_gem_handle_delete); * Create a handle for this object. This adds a handle reference * to the object, which includes a regular reference count. Callers * will likely want to dereference the object afterwards. +/** + * drm_gem_handle_create_tail - internal functions to create a handle + * + * This expects the dev->object_name_lock to be held already and will drop it + * before returning. Used to avoid races in establishing new handles when + * importing an object from either an flink name or a dma-buf. */ int drm_gem_handle_create_tail(struct drm_file *file_priv, @@ -436,9 +437,6 @@ drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp, { struct drm_gem_object *obj; - if(handle == -2) - printf("%s handle %d\n", __FUNCTION__, handle); - spin_lock(&filp->table_lock); /* Check if we currently have a reference on the object */ @@ -539,9 +537,6 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data, if (!(dev->driver->driver_features & DRIVER_GEM)) return -ENODEV; - if(handle == -2) - printf("%s handle %d\n", __FUNCTION__, handle); - mutex_lock(&dev->object_name_lock); obj = idr_find(&dev->object_name_idr, (int) args->name); if (obj) { diff --git a/drivers/video/drm/drm_irq.c b/drivers/video/drm/drm_irq.c index d5ed897c94..605d0fbffd 100644 --- a/drivers/video/drm/drm_irq.c +++ b/drivers/video/drm/drm_irq.c @@ -119,7 +119,7 @@ int drm_irq_install(struct drm_device *dev) if (ret < 0) { dev->irq_enabled = 0; - DRM_ERROR(__FUNCTION__); + DRM_ERROR(__FUNCTION__); } u16_t cmd = PciRead16(dev->pdev->busnr, dev->pdev->devfn, 4); diff --git a/drivers/video/drm/i915/i915_dma.c b/drivers/video/drm/i915/i915_dma.c index 30c0a16f3e..48ef87e2d9 100644 --- a/drivers/video/drm/i915/i915_dma.c +++ b/drivers/video/drm/i915/i915_dma.c @@ -1360,6 +1360,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) aperture_size = dev_priv->gtt.mappable_end; + dev_priv->gtt.mappable = AllocKernelSpace(8192); + if (dev_priv->gtt.mappable == NULL) { + ret = -EIO; + goto out_rmmap; + } /* The i915 workqueue is primarily used for batched retirement of * requests (and thus managing bo) once the task has been completed diff --git a/drivers/video/drm/i915/i915_drv.h b/drivers/video/drm/i915/i915_drv.h index ed6bdc9562..b1a26a85b3 100644 --- a/drivers/video/drm/i915/i915_drv.h +++ b/drivers/video/drm/i915/i915_drv.h @@ -534,7 +534,7 @@ struct i915_gtt { size_t stolen_size; /* Total size of stolen memory */ unsigned long mappable_end; /* End offset that we can CPU map */ - struct io_mapping *mappable; /* Mapping to our CPU mappable region */ + void *mappable; /* Mapping to our CPU mappable region */ phys_addr_t mappable_base; /* PA of our GMADR */ /** "Graphics Stolen Memory" holds the global PTEs */ @@ -620,7 +620,7 @@ struct i915_fbc { int interval; } *fbc_work; -enum no_fbc_reason { + enum no_fbc_reason { FBC_OK, /* FBC is enabled */ FBC_UNSUPPORTED, /* FBC is not supported by this chipset */ FBC_NO_OUTPUT, /* no outputs enabled to compress */ diff --git a/drivers/video/drm/i915/i915_gem.c b/drivers/video/drm/i915/i915_gem.c index 0c4ff64276..8e265332a9 100644 --- a/drivers/video/drm/i915/i915_gem.c +++ b/drivers/video/drm/i915/i915_gem.c @@ -633,7 +633,6 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, loff_t offset, page_base; char __user *user_data; int page_offset, page_length, ret; - char *vaddr; ret = i915_gem_obj_ggtt_pin(obj, 0, true, true); if (ret) @@ -647,14 +646,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, if (ret) goto out_unpin; - vaddr = AllocKernelSpace(4096); - if(vaddr == NULL) - { - ret = -ENOSPC; - goto out_unpin; - }; - - user_data = (char __user *) (uintptr_t) args->data_ptr; + user_data = to_user_ptr(args->data_ptr); remain = args->size; offset = i915_gem_obj_ggtt_offset(obj) + args->offset; @@ -672,17 +664,15 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, if ((page_offset + remain) > PAGE_SIZE) page_length = PAGE_SIZE - page_offset; - MapPage(vaddr, dev_priv->gtt.mappable_base+page_base, PG_SW|PG_NOCACHE); + MapPage(dev_priv->gtt.mappable, dev_priv->gtt.mappable_base+page_base, PG_SW); - memcpy(vaddr+page_offset, user_data, page_length); + memcpy(dev_priv->gtt.mappable+page_offset, user_data, page_length); remain -= page_length; user_data += page_length; offset += page_length; } - FreeKernelSpace(vaddr); - out_unpin: i915_gem_object_unpin(obj); out: @@ -706,7 +696,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|PG_NOCACHE); + vaddr = (char *)MapIoMem((addr_t)page, 4096, PG_SW); if (needs_clflush_before) drm_clflush_virt_range(vaddr + shmem_page_offset, page_length); @@ -2082,15 +2072,24 @@ static void i915_gem_free_request(struct drm_i915_gem_request *request) kfree(request); } -static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, +static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv, struct intel_ring_buffer *ring) { - u32 completed_seqno; - u32 acthd; + u32 completed_seqno = ring->get_seqno(ring, false); + u32 acthd = intel_ring_get_active_head(ring); + struct drm_i915_gem_request *request; - acthd = intel_ring_get_active_head(ring); - completed_seqno = ring->get_seqno(ring, false); + list_for_each_entry(request, &ring->request_list, list) { + if (i915_seqno_passed(completed_seqno, request->seqno)) + continue; + i915_set_reset_status(ring, request, acthd); + } +} + +static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, + struct intel_ring_buffer *ring) +{ while (!list_empty(&ring->request_list)) { struct drm_i915_gem_request *request; @@ -2098,9 +2097,6 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, struct drm_i915_gem_request, list); - if (request->seqno > completed_seqno) - i915_set_reset_status(ring, request, acthd); - i915_gem_free_request(request); } @@ -2142,8 +2138,16 @@ void i915_gem_reset(struct drm_device *dev) struct intel_ring_buffer *ring; int i; + /* + * Before we free the objects from the requests, we need to inspect + * them for finding the guilty party. As the requests only borrow + * their reference to the objects, the inspection must be done first. + */ for_each_ring(ring, dev_priv, i) - i915_gem_reset_ring_lists(dev_priv, ring); + i915_gem_reset_ring_status(dev_priv, ring); + + for_each_ring(ring, dev_priv, i) + i915_gem_reset_ring_cleanup(dev_priv, ring); i915_gem_restore_fences(dev); } diff --git a/drivers/video/drm/i915/i915_gem_context.c b/drivers/video/drm/i915/i915_gem_context.c index 403309c2a7..bb6eecb355 100644 --- a/drivers/video/drm/i915/i915_gem_context.c +++ b/drivers/video/drm/i915/i915_gem_context.c @@ -328,10 +328,8 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - mutex_lock(&dev->struct_mutex); idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); idr_destroy(&file_priv->context_idr); - mutex_unlock(&dev->struct_mutex); } static struct i915_hw_context * @@ -404,11 +402,21 @@ static int do_switch(struct i915_hw_context *to) if (ret) return ret; - /* Clear this page out of any CPU caches for coherent swap-in/out. Note + /* + * Pin can switch back to the default context if we end up calling into + * evict_everything - as a last ditch gtt defrag effort that also + * switches to the default context. Hence we need to reload from here. + */ + from = ring->last_context; + + /* + * Clear this page out of any CPU caches for coherent swap-in/out. Note * that thanks to write = false in this call and us not setting any gpu * write domains when putting a context object onto the active list * (when switching away from it), this won't block. - * XXX: We need a real interface to do this instead of trickery. */ + * + * XXX: We need a real interface to do this instead of trickery. + */ ret = i915_gem_object_set_to_gtt_domain(to->obj, false); if (ret) { i915_gem_object_unpin(to->obj); diff --git a/drivers/video/drm/i915/i915_gem_execbuffer.c b/drivers/video/drm/i915/i915_gem_execbuffer.c index 574478b3fc..a2319fd491 100644 --- a/drivers/video/drm/i915/i915_gem_execbuffer.c +++ b/drivers/video/drm/i915/i915_gem_execbuffer.c @@ -190,6 +190,8 @@ static int relocate_entry_cpu(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 page_offset = offset_in_page(reloc->offset); char *vaddr; int ret = -EINVAL; @@ -198,10 +200,9 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj, if (ret) return ret; - vaddr = (char *)MapIoMem((addr_t)i915_gem_object_get_page(obj, - reloc->offset >> PAGE_SHIFT), 4096, 3); + vaddr = dev_priv->gtt.mappable+4096; + MapPage(vaddr,(addr_t)i915_gem_object_get_page(obj,reloc->offset >> PAGE_SHIFT), PG_SW); *(uint32_t *)(vaddr + page_offset) = reloc->delta; - FreeKernelSpace(vaddr); return 0; } @@ -226,12 +227,12 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, /* 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); + MapPage(dev_priv->gtt.mappable,dev_priv->gtt.mappable_base + + (reloc->offset & PAGE_MASK), PG_SW); + reloc_page = dev_priv->gtt.mappable; reloc_entry = (uint32_t __iomem *) (reloc_page + offset_in_page(reloc->offset)); iowrite32(reloc->delta, reloc_entry); - FreeKernelSpace(reloc_page); return 0; } @@ -343,7 +344,7 @@ i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; int remain, ret; - user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; + user_relocs = to_user_ptr(entry->relocs_ptr); remain = entry->relocation_count; while (remain) { @@ -667,7 +668,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, u64 invalid_offset = (u64)-1; int j; - user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; + user_relocs = to_user_ptr(exec[i].relocs_ptr); if (copy_from_user(reloc+total, user_relocs, exec[i].relocation_count * sizeof(*reloc))) { @@ -1260,8 +1261,7 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, return -ENOMEM; } ret = copy_from_user(exec2_list, - (struct drm_i915_relocation_entry __user *) - (uintptr_t) args->buffers_ptr, + to_user_ptr(args->buffers_ptr), sizeof(*exec2_list) * args->buffer_count); if (ret != 0) { DRM_DEBUG("copy %d exec entries failed %d\n", @@ -1275,7 +1275,7 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, &dev_priv->gtt.base); if (!ret) { /* Copy the new buffer offsets back to the user's exec list. */ - ret = copy_to_user((void __user *)(uintptr_t)args->buffers_ptr, + ret = copy_to_user(to_user_ptr(args->buffers_ptr), exec2_list, sizeof(*exec2_list) * args->buffer_count); if (ret) { diff --git a/drivers/video/drm/i915/i915_gem_gtt.c b/drivers/video/drm/i915/i915_gem_gtt.c index 9cc75121b7..e79de24b95 100644 --- a/drivers/video/drm/i915/i915_gem_gtt.c +++ b/drivers/video/drm/i915/i915_gem_gtt.c @@ -831,7 +831,7 @@ void i915_gem_init_global_gtt(struct drm_device *dev) DRM_ERROR("Aliased PPGTT setup failed %d\n", ret); drm_mm_takedown(&dev_priv->gtt.base.mm); gtt_size += GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE; -} + } i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size); } diff --git a/drivers/video/drm/i915/i915_irq.c b/drivers/video/drm/i915/i915_irq.c index 571300de29..050c08ad83 100644 --- a/drivers/video/drm/i915/i915_irq.c +++ b/drivers/video/drm/i915/i915_irq.c @@ -279,7 +279,7 @@ static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev, DRM_DEBUG_KMS("uncleared fifo underrun on pipe %c\n", pipe_name(pipe)); } -} + } } /** @@ -1294,7 +1294,7 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) if (pch_iir & SDE_ERROR_CPT) cpt_serr_int_handler(dev); - } +} static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) { @@ -1385,7 +1385,7 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir) /* clear PCH hotplug event before clear CPU irq */ I915_WRITE(SDEIIR, pch_iir); -} + } } static irqreturn_t ironlake_irq_handler(int irq, void *arg) @@ -1427,7 +1427,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) if (err_int_reenable) ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB); spin_unlock(&dev_priv->irq_lock); -} + } gt_iir = I915_READ(GTIIR); if (gt_iir) { @@ -1437,7 +1437,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) ilk_gt_irq_handler(dev, dev_priv, gt_iir); I915_WRITE(GTIIR, gt_iir); ret = IRQ_HANDLED; -} + } de_iir = I915_READ(DEIIR); if (de_iir) { @@ -1456,7 +1456,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) I915_WRITE(GEN6_PMIIR, pm_iir); ret = IRQ_HANDLED; } -} + } if (err_int_reenable) { spin_lock(&dev_priv->irq_lock); @@ -2122,7 +2122,7 @@ static void gen5_gt_irq_preinstall(struct drm_device *dev) I915_WRITE(GEN6_PMIMR, 0xffffffff); I915_WRITE(GEN6_PMIER, 0x0); POSTING_READ(GEN6_PMIER); -} + } } /* drm_dma.h hooks diff --git a/drivers/video/drm/i915/intel_ddi.c b/drivers/video/drm/i915/intel_ddi.c index 3cbb23fdcb..70386687d9 100644 --- a/drivers/video/drm/i915/intel_ddi.c +++ b/drivers/video/drm/i915/intel_ddi.c @@ -961,12 +961,18 @@ void intel_ddi_setup_hw_pll_state(struct drm_device *dev) enum pipe pipe; struct intel_crtc *intel_crtc; + dev_priv->ddi_plls.spll_refcount = 0; + dev_priv->ddi_plls.wrpll1_refcount = 0; + dev_priv->ddi_plls.wrpll2_refcount = 0; + for_each_pipe(pipe) { intel_crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); - if (!intel_crtc->active) + if (!intel_crtc->active) { + intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE; continue; + } intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv, pipe); diff --git a/drivers/video/drm/i915/intel_display.c b/drivers/video/drm/i915/intel_display.c index fc3bbfd7dc..044399befc 100644 --- a/drivers/video/drm/i915/intel_display.c +++ b/drivers/video/drm/i915/intel_display.c @@ -1432,6 +1432,20 @@ static void i9xx_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) POSTING_READ(DPLL(pipe)); } +static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) +{ + u32 val = 0; + + /* Make sure the pipe isn't still relying on us */ + assert_pipe_disabled(dev_priv, pipe); + + /* Leave integrated clock source enabled */ + if (pipe == PIPE_B) + val = DPLL_INTEGRATED_CRI_CLK_VLV; + I915_WRITE(DPLL(pipe), val); + POSTING_READ(DPLL(pipe)); +} + void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port) { u32 port_mask; @@ -5281,7 +5295,7 @@ static void lpt_reset_fdi_mphy(struct drm_i915_private *dev_priv) if (wait_for_atomic_us((I915_READ(SOUTH_CHICKEN2) & FDI_MPHY_IOSFSB_RESET_STATUS) == 0, 100)) DRM_ERROR("FDI mPHY reset de-assert timeout\n"); - } +} /* WaMPhyProgramming:hsw */ static void lpt_program_fdi_mphy(struct drm_i915_private *dev_priv) @@ -5356,7 +5370,7 @@ static void lpt_program_fdi_mphy(struct drm_i915_private *dev_priv) tmp &= ~(0xF << 28); tmp |= (4 << 28); intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY); - } +} /* Implements 3 different sequences from BSpec chapter "Display iCLK * Programming" based on the parameters passed: @@ -5999,7 +6013,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) uint32_t val; list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) - WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n", + WARN(crtc->active, "CRTC for pipe %c enabled\n", pipe_name(crtc->pipe)); WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n"); @@ -10515,7 +10529,9 @@ void intel_modeset_gem_init(struct drm_device *dev) // intel_setup_overlay(dev); + mutex_lock(&dev->mode_config.mutex); intel_modeset_setup_hw_state(dev, false); + mutex_unlock(&dev->mode_config.mutex); } void intel_modeset_cleanup(struct drm_device *dev) @@ -10589,14 +10605,15 @@ void intel_connector_attach_encoder(struct intel_connector *connector, int intel_modeset_vga_set_state(struct drm_device *dev, bool state) { struct drm_i915_private *dev_priv = dev->dev_private; + unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL; u16 gmch_ctrl; - pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl); + pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl); if (state) gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE; else gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; - pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl); + pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl); return 0; } diff --git a/drivers/video/drm/i915/intel_dp.c b/drivers/video/drm/i915/intel_dp.c index 47a5311e84..ecc2d28b9f 100644 --- a/drivers/video/drm/i915/intel_dp.c +++ b/drivers/video/drm/i915/intel_dp.c @@ -1767,7 +1767,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder) intel_enable_dp(encoder); vlv_wait_port_ready(dev_priv, port); - } +} static void intel_dp_pre_pll_enable(struct intel_encoder *encoder) { diff --git a/drivers/video/drm/i915/intel_pm.c b/drivers/video/drm/i915/intel_pm.c index e4d1e5525c..f57a9d86ef 100644 --- a/drivers/video/drm/i915/intel_pm.c +++ b/drivers/video/drm/i915/intel_pm.c @@ -2355,7 +2355,7 @@ static unsigned int ilk_cursor_wm_max(const struct drm_device *dev, return level == 0 ? 63 : 255; else return level == 0 ? 31 : 63; - } +} /* Calculate the maximum FBC watermark */ static unsigned int ilk_fbc_wm_max(void) @@ -2374,7 +2374,7 @@ static void ilk_wm_max(struct drm_device *dev, max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true); max->cur = ilk_cursor_wm_max(dev, level, config); max->fbc = ilk_fbc_wm_max(); - } +} static bool ilk_check_wm(int level, const struct hsw_wm_maximums *max, @@ -4629,8 +4629,6 @@ static void intel_gen6_powersave_work(struct work_struct *work) rps.delayed_resume_work.work); struct drm_device *dev = dev_priv->dev; - ENTER(); - mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev)) { @@ -4640,8 +4638,6 @@ static void intel_gen6_powersave_work(struct work_struct *work) gen6_update_ring_freq(dev); } mutex_unlock(&dev_priv->rps.hw_lock); - - LEAVE(); } void intel_enable_gt_powersave(struct drm_device *dev) diff --git a/drivers/video/drm/i915/intel_ringbuffer.c b/drivers/video/drm/i915/intel_ringbuffer.c index 83855243b9..7d51795a55 100644 --- a/drivers/video/drm/i915/intel_ringbuffer.c +++ b/drivers/video/drm/i915/intel_ringbuffer.c @@ -483,7 +483,7 @@ init_pipe_control(struct intel_ring_buffer *ring) goto err_unref; ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj); - ring->scratch.cpu_page = (void*)MapIoMem((addr_t)sg_page(ring->scratch.obj->pages->sgl),4096, PG_SW); + ring->scratch.cpu_page = (void*)MapIoMem((addr_t)sg_page(ring->scratch.obj->pages->sgl),4096, PG_SW|0x100); if (ring->scratch.cpu_page == NULL) { ret = -ENOMEM; goto err_unpin; @@ -1182,7 +1182,7 @@ static int init_status_page(struct intel_ring_buffer *ring) } ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); - ring->status_page.page_addr = (void*)MapIoMem((addr_t)sg_page(obj->pages->sgl),4096,PG_SW); + ring->status_page.page_addr = (void*)MapIoMem((addr_t)sg_page(obj->pages->sgl),4096,PG_SW|0x100); if (ring->status_page.page_addr == NULL) { ret = -ENOMEM; goto err_unpin; diff --git a/drivers/video/drm/i915/kms_display.c b/drivers/video/drm/i915/kms_display.c index 77281e886f..43dd2f521c 100644 --- a/drivers/video/drm/i915/kms_display.c +++ b/drivers/video/drm/i915/kms_display.c @@ -913,10 +913,6 @@ 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: @@ -927,6 +923,212 @@ err1: return ret; } +int i915_mask_update_ex(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_i915_mask_update *mask = data; + struct drm_gem_object *obj; + static unsigned int mask_seqno[256]; + static warn_count; + + rect_t win; + u32 winw,winh; + u32 ml,mt,mr,mb; + u32 slot; + int ret = 0; + slot = *((u8*)CURRENT_TASK); + + if( mask_seqno[slot] == os_display->mask_seqno) + return 0; + + GetWindowRect(&win); + win.right+= 1; + win.bottom+= 1; + + winw = win.right - win.left; + winh = win.bottom - win.top; + + if(mask->dx >= winw || + mask->dy >= winh) + return 1; + + ml = win.left + mask->dx; + mt = win.top + mask->dy; + mr = ml + mask->width; + mb = mt + mask->height; + + if( ml >= win.right || mt >= win.bottom || + mr < win.left || mb < win.top ) + return 1; + + if( mr > win.right ) + mr = win.right; + + if( mb > win.bottom ) + mb = win.bottom; + + mask->width = mr - ml; + mask->height = mb - mt; + + if( mask->width == 0 || + mask->height== 0 ) + return 1; + + obj = drm_gem_object_lookup(dev, file, mask->handle); + if (obj == NULL) + return -ENOENT; + + if (!obj->filp) { + drm_gem_object_unreference_unlocked(obj); + return -EINVAL; + } + +#if 1 + if(warn_count < 1000) + { + printf("left %d top %d right %d bottom %d\n", + ml, mt, mr, mb); + warn_count++; + }; +#endif + + +#if 1 + + { + u8* src_offset; + u8* dst_offset; + u32 ifl; + + ret = i915_mutex_lock_interruptible(dev); + if (ret) + goto err1; + + i915_gem_object_set_to_cpu_domain(to_intel_bo(obj), true); + + src_offset = (u8*)( mt*os_display->width + ml); + src_offset+= get_display_map(); + dst_offset = (u8*)mask->bo_map; + + u32_t tmp_h = mask->height; + + ifl = safe_cli(); + { + mask_seqno[slot] = os_display->mask_seqno; + + slot|= (slot<<8)|(slot<<16)|(slot<<24); + + __asm__ __volatile__ ( + "movd %[slot], %%xmm6 \n" + "punpckldq %%xmm6, %%xmm6 \n" + "punpcklqdq %%xmm6, %%xmm6 \n" + :: [slot] "m" (slot) + :"xmm6"); + + while( tmp_h--) + { + int tmp_w = mask->width; + + u8* tmp_src = src_offset; + u8* tmp_dst = dst_offset; + + src_offset+= os_display->width; + dst_offset+= mask->bo_pitch; + + while(tmp_w >= 64) + { + __asm__ __volatile__ ( + "movdqu (%0), %%xmm0 \n" + "movdqu 16(%0), %%xmm1 \n" + "movdqu 32(%0), %%xmm2 \n" + "movdqu 48(%0), %%xmm3 \n" + "pcmpeqb %%xmm6, %%xmm0 \n" + "pcmpeqb %%xmm6, %%xmm1 \n" + "pcmpeqb %%xmm6, %%xmm2 \n" + "pcmpeqb %%xmm6, %%xmm3 \n" + "movdqa %%xmm0, (%%edi) \n" + "movdqa %%xmm1, 16(%%edi) \n" + "movdqa %%xmm2, 32(%%edi) \n" + "movdqa %%xmm3, 48(%%edi) \n" + + :: "r" (tmp_src), "D" (tmp_dst) + :"xmm0","xmm1","xmm2","xmm3"); + tmp_w -= 64; + tmp_src += 64; + tmp_dst += 64; + } + + if( tmp_w >= 32 ) + { + __asm__ __volatile__ ( + "movdqu (%0), %%xmm0 \n" + "movdqu 16(%0), %%xmm1 \n" + "pcmpeqb %%xmm6, %%xmm0 \n" + "pcmpeqb %%xmm6, %%xmm1 \n" + "movdqa %%xmm0, (%%edi) \n" + "movdqa %%xmm1, 16(%%edi) \n" + + :: "r" (tmp_src), "D" (tmp_dst) + :"xmm0","xmm1"); + tmp_w -= 32; + tmp_src += 32; + tmp_dst += 32; + } + + if( tmp_w >= 16 ) + { + __asm__ __volatile__ ( + "movdqu (%0), %%xmm0 \n" + "pcmpeqb %%xmm6, %%xmm0 \n" + "movdqa %%xmm0, (%%edi) \n" + :: "r" (tmp_src), "D" (tmp_dst) + :"xmm0"); + tmp_w -= 16; + tmp_src += 16; + tmp_dst += 16; + } + + if( tmp_w >= 8 ) + { + __asm__ __volatile__ ( + "movq (%0), %%xmm0 \n" + "pcmpeqb %%xmm6, %%xmm0 \n" + "movq %%xmm0, (%%edi) \n" + :: "r" (tmp_src), "D" (tmp_dst) + :"xmm0"); + tmp_w -= 8; + tmp_src += 8; + tmp_dst += 8; + } + if( tmp_w >= 4 ) + { + __asm__ __volatile__ ( + "movd (%0), %%xmm0 \n" + "pcmpeqb %%xmm6, %%xmm0 \n" + "movd %%xmm0, (%%edi) \n" + :: "r" (tmp_src), "D" (tmp_dst) + :"xmm0"); + tmp_w -= 4; + tmp_src += 4; + tmp_dst += 4; + } + while(tmp_w--) + *tmp_dst++ = (*tmp_src++ == (u8)slot) ? 0xFF:0x00; + }; + }; + safe_sti(ifl); + + i915_gem_object_set_to_gtt_domain(to_intel_bo(obj), false); + } +#endif + +err2: + mutex_unlock(&dev->struct_mutex); +err1: + drm_gem_object_unreference(obj); + + return ret; +} diff --git a/drivers/video/drm/i915/main.c b/drivers/video/drm/i915/main.c index 90ffca69c1..42c5ee41db 100644 --- a/drivers/video/drm/i915/main.c +++ b/drivers/video/drm/i915/main.c @@ -266,7 +266,7 @@ u32_t __attribute__((externally_visible)) drvEntry(int action, char *cmdline) #define SRV_FBINFO 43 #define SRV_MASK_UPDATE 44 - +#define SRV_MASK_UPDATE_EX 45 #define check_input(size) \ if( unlikely((inp==NULL)||(io->inp_size != (size))) ) \ @@ -443,6 +443,10 @@ int _stdcall display_handler(ioctl_t *io) case SRV_MASK_UPDATE: retval = i915_mask_update(main_device, inp, file); break; + + case SRV_MASK_UPDATE_EX: + retval = i915_mask_update_ex(main_device, inp, file); + break; }; return retval;