Skip to content

Commit

Permalink
Merge tag 'drm-intel-next-2015-02-27' of git://anongit.freedesktop.or…
Browse files Browse the repository at this point in the history
…g/drm-intel into drm-next

- Y tiling support for scanout from Tvrtko&Damien
- Remove more UMS support
- some small prep patches for OLR removal from John Harrison
- first few patches for dynamic pagetable allocation from Ben Widawsky, rebased
  by tons of other people
- DRRS support patches (Sonika&Vandana)
- fbc patches from Paulo
- make sure our vblank callbacks aren't called when the pipes are off
- various patches all over

* tag 'drm-intel-next-2015-02-27' of git://anongit.freedesktop.org/drm-intel: (61 commits)
  drm/i915: Update DRIVER_DATE to 20150227
  drm/i915: Clarify obj->map_and_fenceable
  drm/i915/skl: Allow Y (and Yf) frame buffer creation
  drm/i915/skl: Update watermarks for Y tiling
  drm/i915/skl: Updated watermark programming
  drm/i915/skl: Adjust get_plane_config() to support Yb/Yf tiling
  drm/i915/skl: Teach pin_and_fence_fb_obj() about Y tiling constraints
  drm/i915/skl: Adjust intel_fb_align_height() for Yb/Yf tiling
  drm/i915/skl: Allow scanning out Y and Yf fbs
  drm/i915/skl: Add new displayable tiling formats
  drm/i915: Remove DRIVER_MODESET checks from modeset code
  drm/i915: Remove regfile code&data for UMS suspend/resume
  drm/i915: Remove DRIVER_MODESET checks from gem code
  drm/i915: Remove DRIVER_MODESET checks in the gpu reset code
  drm/i915: Remove DRIVER_MODESET checks from suspend/resume code
  drm/i915: Remove DRIVER_MODESET checks in load/unload/close code
  drm/i915: fix a printk format
  drm/i915: Add media rc6 residency file to sysfs
  drm/i915: Add missing description to parameter in alloc_pt_range
  drm/i915: Removed the read of RP_STATE_CAP from sysfs/debugfs functions
  ...
  • Loading branch information
Dave Airlie committed Mar 9, 2015
2 parents d136dfe + f89fe1f commit 8dd0eb3
Show file tree
Hide file tree
Showing 38 changed files with 1,604 additions and 1,706 deletions.
11 changes: 11 additions & 0 deletions Documentation/DocBook/drm.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -4051,6 +4051,17 @@ int num_ioctls;</synopsis>
<title>Frame Buffer Compression (FBC)</title>
!Pdrivers/gpu/drm/i915/intel_fbc.c Frame Buffer Compression (FBC)
!Idrivers/gpu/drm/i915/intel_fbc.c
</sect2>
<sect2>
<title>Display Refresh Rate Switching (DRRS)</title>
!Pdrivers/gpu/drm/i915/intel_dp.c Display Refresh Rate Switching (DRRS)
!Fdrivers/gpu/drm/i915/intel_dp.c intel_dp_set_drrs_state
!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_enable
!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_disable
!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_invalidate
!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_flush
!Fdrivers/gpu/drm/i915/intel_dp.c intel_dp_drrs_init

</sect2>
<sect2>
<title>DPIO</title>
Expand Down
56 changes: 46 additions & 10 deletions drivers/gpu/drm/drm_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,6 @@ static void vblank_disable_fn(unsigned long arg)
void drm_vblank_cleanup(struct drm_device *dev)
{
int crtc;
unsigned long irqflags;

/* Bail if the driver didn't call drm_vblank_init() */
if (dev->num_crtcs == 0)
Expand All @@ -285,11 +284,10 @@ void drm_vblank_cleanup(struct drm_device *dev)
for (crtc = 0; crtc < dev->num_crtcs; crtc++) {
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];

del_timer_sync(&vblank->disable_timer);
WARN_ON(vblank->enabled &&
drm_core_check_feature(dev, DRIVER_MODESET));

spin_lock_irqsave(&dev->vbl_lock, irqflags);
vblank_disable_and_save(dev, crtc);
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
del_timer_sync(&vblank->disable_timer);
}

kfree(dev->vblank);
Expand Down Expand Up @@ -475,17 +473,23 @@ int drm_irq_uninstall(struct drm_device *dev)
dev->irq_enabled = false;

/*
* Wake up any waiters so they don't hang.
* Wake up any waiters so they don't hang. This is just to paper over
* isssues for UMS drivers which aren't in full control of their
* vblank/irq handling. KMS drivers must ensure that vblanks are all
* disabled when uninstalling the irq handler.
*/
if (dev->num_crtcs) {
spin_lock_irqsave(&dev->vbl_lock, irqflags);
for (i = 0; i < dev->num_crtcs; i++) {
struct drm_vblank_crtc *vblank = &dev->vblank[i];

if (!vblank->enabled)
continue;

WARN_ON(drm_core_check_feature(dev, DRIVER_MODESET));

vblank_disable_and_save(dev, i);
wake_up(&vblank->queue);
vblank->enabled = false;
vblank->last =
dev->driver->get_vblank_counter(dev, i);
}
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
}
Expand Down Expand Up @@ -1232,6 +1236,38 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc)
}
EXPORT_SYMBOL(drm_crtc_vblank_off);

/**
* drm_crtc_vblank_reset - reset vblank state to off on a CRTC
* @crtc: CRTC in question
*
* Drivers can use this function to reset the vblank state to off at load time.
* Drivers should use this together with the drm_crtc_vblank_off() and
* drm_crtc_vblank_on() functions. The difference compared to
* drm_crtc_vblank_off() is that this function doesn't save the vblank counter
* and hence doesn't need to call any driver hooks.
*/
void drm_crtc_vblank_reset(struct drm_crtc *drm_crtc)
{
struct drm_device *dev = drm_crtc->dev;
unsigned long irqflags;
int crtc = drm_crtc_index(drm_crtc);
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];

spin_lock_irqsave(&dev->vbl_lock, irqflags);
/*
* Prevent subsequent drm_vblank_get() from enabling the vblank
* interrupt by bumping the refcount.
*/
if (!vblank->inmodeset) {
atomic_inc(&vblank->refcount);
vblank->inmodeset = 1;
}
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);

WARN_ON(!list_empty(&dev->vblank_event_list));
}
EXPORT_SYMBOL(drm_crtc_vblank_reset);

/**
* drm_vblank_on - enable vblank events on a CRTC
* @dev: DRM device
Expand Down Expand Up @@ -1653,7 +1689,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
struct timeval tvblank;
unsigned long irqflags;

if (!dev->num_crtcs)
if (WARN_ON_ONCE(!dev->num_crtcs))
return false;

if (WARN_ON(crtc >= dev->num_crtcs))
Expand Down
3 changes: 1 addition & 2 deletions drivers/gpu/drm/i915/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ i915-y += dvo_ch7017.o \
i915-y += i915_vgpu.o

# legacy horrors
i915-y += i915_dma.o \
i915_ums.o
i915-y += i915_dma.o

obj-$(CONFIG_DRM_I915) += i915.o

Expand Down
74 changes: 34 additions & 40 deletions drivers/gpu/drm/i915/i915_cmd_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,24 +818,26 @@ static bool valid_reg(const u32 *table, int count, u32 addr)
return false;
}

static u32 *vmap_batch(struct drm_i915_gem_object *obj)
static u32 *vmap_batch(struct drm_i915_gem_object *obj,
unsigned start, unsigned len)
{
int i;
void *addr = NULL;
struct sg_page_iter sg_iter;
int first_page = start >> PAGE_SHIFT;
int last_page = (len + start + 4095) >> PAGE_SHIFT;
int npages = last_page - first_page;
struct page **pages;

pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
pages = drm_malloc_ab(npages, sizeof(*pages));
if (pages == NULL) {
DRM_DEBUG_DRIVER("Failed to get space for pages\n");
goto finish;
}

i = 0;
for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
pages[i] = sg_page_iter_page(&sg_iter);
i++;
}
for_each_sg_page(obj->pages->sgl, &sg_iter, npages, first_page)
pages[i++] = sg_page_iter_page(&sg_iter);

addr = vmap(pages, i, 0, PAGE_KERNEL);
if (addr == NULL) {
Expand All @@ -855,61 +857,61 @@ static u32 *copy_batch(struct drm_i915_gem_object *dest_obj,
u32 batch_start_offset,
u32 batch_len)
{
int ret = 0;
int needs_clflush = 0;
u32 *src_base, *dest_base = NULL;
u32 *src_addr, *dest_addr;
u32 offset = batch_start_offset / sizeof(*dest_addr);
u32 end = batch_start_offset + batch_len;
void *src_base, *src;
void *dst = NULL;
int ret;

if (end > dest_obj->base.size || end > src_obj->base.size)
if (batch_len > dest_obj->base.size ||
batch_len + batch_start_offset > src_obj->base.size)
return ERR_PTR(-E2BIG);

ret = i915_gem_obj_prepare_shmem_read(src_obj, &needs_clflush);
if (ret) {
DRM_DEBUG_DRIVER("CMD: failed to prep read\n");
DRM_DEBUG_DRIVER("CMD: failed to prepare shadow batch\n");
return ERR_PTR(ret);
}

src_base = vmap_batch(src_obj);
src_base = vmap_batch(src_obj, batch_start_offset, batch_len);
if (!src_base) {
DRM_DEBUG_DRIVER("CMD: Failed to vmap batch\n");
ret = -ENOMEM;
goto unpin_src;
}

src_addr = src_base + offset;

if (needs_clflush)
drm_clflush_virt_range((char *)src_addr, batch_len);
ret = i915_gem_object_get_pages(dest_obj);
if (ret) {
DRM_DEBUG_DRIVER("CMD: Failed to get pages for shadow batch\n");
goto unmap_src;
}
i915_gem_object_pin_pages(dest_obj);

ret = i915_gem_object_set_to_cpu_domain(dest_obj, true);
if (ret) {
DRM_DEBUG_DRIVER("CMD: Failed to set batch CPU domain\n");
DRM_DEBUG_DRIVER("CMD: Failed to set shadow batch to CPU\n");
goto unmap_src;
}

dest_base = vmap_batch(dest_obj);
if (!dest_base) {
dst = vmap_batch(dest_obj, 0, batch_len);
if (!dst) {
DRM_DEBUG_DRIVER("CMD: Failed to vmap shadow batch\n");
i915_gem_object_unpin_pages(dest_obj);
ret = -ENOMEM;
goto unmap_src;
}

dest_addr = dest_base + offset;

if (batch_start_offset != 0)
memset((u8 *)dest_base, 0, batch_start_offset);
src = src_base + offset_in_page(batch_start_offset);
if (needs_clflush)
drm_clflush_virt_range(src, batch_len);

memcpy(dest_addr, src_addr, batch_len);
memset((u8 *)dest_addr + batch_len, 0, dest_obj->base.size - end);
memcpy(dst, src, batch_len);

unmap_src:
vunmap(src_base);
unpin_src:
i915_gem_object_unpin_pages(src_obj);

return ret ? ERR_PTR(ret) : dest_base;
return ret ? ERR_PTR(ret) : dst;
}

/**
Expand Down Expand Up @@ -1046,34 +1048,26 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
u32 batch_len,
bool is_master)
{
int ret = 0;
u32 *cmd, *batch_base, *batch_end;
struct drm_i915_cmd_descriptor default_desc = { 0 };
bool oacontrol_set = false; /* OACONTROL tracking. See check_cmd() */

ret = i915_gem_obj_ggtt_pin(shadow_batch_obj, 4096, 0);
if (ret) {
DRM_DEBUG_DRIVER("CMD: Failed to pin shadow batch\n");
return -1;
}
int ret = 0;

batch_base = copy_batch(shadow_batch_obj, batch_obj,
batch_start_offset, batch_len);
if (IS_ERR(batch_base)) {
DRM_DEBUG_DRIVER("CMD: Failed to copy batch\n");
i915_gem_object_ggtt_unpin(shadow_batch_obj);
return PTR_ERR(batch_base);
}

cmd = batch_base + (batch_start_offset / sizeof(*cmd));

/*
* We use the batch length as size because the shadow object is as
* large or larger and copy_batch() will write MI_NOPs to the extra
* space. Parsing should be faster in some cases this way.
*/
batch_end = cmd + (batch_len / sizeof(*batch_end));
batch_end = batch_base + (batch_len / sizeof(*batch_end));

cmd = batch_base;
while (cmd < batch_end) {
const struct drm_i915_cmd_descriptor *desc;
u32 length;
Expand Down Expand Up @@ -1132,7 +1126,7 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
}

vunmap(batch_base);
i915_gem_object_ggtt_unpin(shadow_batch_obj);
i915_gem_object_unpin_pages(shadow_batch_obj);

return ret;
}
Expand Down
Loading

0 comments on commit 8dd0eb3

Please sign in to comment.