Commit 2ec77fc9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (26 commits)
  drm/radeon: update sarea copies of last_ variables on resume.
  drm/i915: Keep refs on the object over the lifetime of vmas for GTT mmap.
  drm/i915: take struct mutex around fb unref
  drm: Use spread spectrum when the bios tells us it's ok.
  drm: Collapse identical i8xx_clock() and i9xx_clock().
  drm: Bring PLL limits in sync with DDX values.
  drm: Add locking around cursor gem operations.
  drm: Propagate failure from setting crtc base.
  drm: Check for a NULL encoder when reverting on error path
  drm/i915: Cleanup the hws on ringbuffer constrution failure.
  drm/i915: Don't add panel_fixed_mode to the probed modes list at LVDS init.
  drm: Release user fbs in drm_release
  drm/i915: Unpin the fb on error during construction.
  drm/i915: Unpin the hws if we fail to kmap.
  drm/i915: Unpin the ringbuffer if we fail to ioremap it.
  drm/i915: unpin for an invalid memory domain.
  drm/i915: Release and unlock on mmap_gtt error path.
  drm/i915: Set framebuffer alignment based upon the fence constraints.
  drm: Do not leak a new reference for flink() on an existing name
  drm/i915: Fix potential AB-BA deadlock in i915_gem_execbuffer()
  ...
parents be71cb5b 3d16118d
...@@ -1741,9 +1741,8 @@ int drm_mode_getfb(struct drm_device *dev, ...@@ -1741,9 +1741,8 @@ int drm_mode_getfb(struct drm_device *dev,
* RETURNS: * RETURNS:
* Zero on success, errno on failure. * Zero on success, errno on failure.
*/ */
void drm_fb_release(struct file *filp) void drm_fb_release(struct drm_file *priv)
{ {
struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->minor->dev; struct drm_device *dev = priv->minor->dev;
struct drm_framebuffer *fb, *tfb; struct drm_framebuffer *fb, *tfb;
......
...@@ -512,7 +512,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, ...@@ -512,7 +512,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
if (drm_mode_equal(&saved_mode, &crtc->mode)) { if (drm_mode_equal(&saved_mode, &crtc->mode)) {
if (saved_x != crtc->x || saved_y != crtc->y || if (saved_x != crtc->x || saved_y != crtc->y ||
depth_changed || bpp_changed) { depth_changed || bpp_changed) {
crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
old_fb); old_fb);
goto done; goto done;
} }
...@@ -552,7 +552,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, ...@@ -552,7 +552,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
/* Set up the DPLL and any encoders state that needs to adjust or depend /* Set up the DPLL and any encoders state that needs to adjust or depend
* on the DPLL. * on the DPLL.
*/ */
crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
if (!ret)
goto done;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
...@@ -752,6 +754,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) ...@@ -752,6 +754,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
if (!drm_crtc_helper_set_mode(set->crtc, set->mode, if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
set->x, set->y, set->x, set->y,
old_fb)) { old_fb)) {
DRM_ERROR("failed to set mode on crtc %p\n",
set->crtc);
ret = -EINVAL; ret = -EINVAL;
goto fail_set_mode; goto fail_set_mode;
} }
...@@ -765,7 +769,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) ...@@ -765,7 +769,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
old_fb = set->crtc->fb; old_fb = set->crtc->fb;
if (set->crtc->fb != set->fb) if (set->crtc->fb != set->fb)
set->crtc->fb = set->fb; set->crtc->fb = set->fb;
crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb); ret = crtc_funcs->mode_set_base(set->crtc,
set->x, set->y, old_fb);
if (ret != 0)
goto fail_set_mode;
} }
kfree(save_encoders); kfree(save_encoders);
...@@ -775,8 +782,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) ...@@ -775,8 +782,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
fail_set_mode: fail_set_mode:
set->crtc->enabled = save_enabled; set->crtc->enabled = save_enabled;
count = 0; count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (!connector->encoder)
continue;
connector->encoder->crtc = save_crtcs[count++]; connector->encoder->crtc = save_crtcs[count++];
}
fail_no_encoder: fail_no_encoder:
kfree(save_crtcs); kfree(save_crtcs);
count = 0; count = 0;
......
...@@ -457,6 +457,9 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -457,6 +457,9 @@ int drm_release(struct inode *inode, struct file *filp)
if (dev->driver->driver_features & DRIVER_GEM) if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_release(dev, file_priv); drm_gem_release(dev, file_priv);
if (dev->driver->driver_features & DRIVER_MODESET)
drm_fb_release(file_priv);
mutex_lock(&dev->ctxlist_mutex); mutex_lock(&dev->ctxlist_mutex);
if (!list_empty(&dev->ctxlist)) { if (!list_empty(&dev->ctxlist)) {
struct drm_ctx_list *pos, *n; struct drm_ctx_list *pos, *n;
......
...@@ -104,8 +104,8 @@ drm_gem_init(struct drm_device *dev) ...@@ -104,8 +104,8 @@ drm_gem_init(struct drm_device *dev)
if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START, if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
DRM_FILE_PAGE_OFFSET_SIZE)) { DRM_FILE_PAGE_OFFSET_SIZE)) {
drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
drm_ht_remove(&mm->offset_hash); drm_ht_remove(&mm->offset_hash);
drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
return -ENOMEM; return -ENOMEM;
} }
...@@ -295,35 +295,37 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, ...@@ -295,35 +295,37 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
return -EBADF; return -EBADF;
again: again:
if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) {
return -ENOMEM; ret = -ENOMEM;
goto err;
}
spin_lock(&dev->object_name_lock); spin_lock(&dev->object_name_lock);
if (obj->name) { if (!obj->name) {
args->name = obj->name;
spin_unlock(&dev->object_name_lock);
return 0;
}
ret = idr_get_new_above(&dev->object_name_idr, obj, 1, ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
&obj->name); &obj->name);
args->name = (uint64_t) obj->name;
spin_unlock(&dev->object_name_lock); spin_unlock(&dev->object_name_lock);
if (ret == -EAGAIN) if (ret == -EAGAIN)
goto again; goto again;
if (ret != 0) { if (ret != 0)
goto err;
/* Allocate a reference for the name table. */
drm_gem_object_reference(obj);
} else {
args->name = (uint64_t) obj->name;
spin_unlock(&dev->object_name_lock);
ret = 0;
}
err:
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return ret; return ret;
}
/*
* Leave the reference from the lookup around as the
* name table now holds one
*/
args->name = (uint64_t) obj->name;
return 0;
} }
/** /**
...@@ -448,6 +450,7 @@ drm_gem_object_handle_free(struct kref *kref) ...@@ -448,6 +450,7 @@ drm_gem_object_handle_free(struct kref *kref)
spin_lock(&dev->object_name_lock); spin_lock(&dev->object_name_lock);
if (obj->name) { if (obj->name) {
idr_remove(&dev->object_name_idr, obj->name); idr_remove(&dev->object_name_idr, obj->name);
obj->name = 0;
spin_unlock(&dev->object_name_lock); spin_unlock(&dev->object_name_lock);
/* /*
* The object name held a reference to this object, drop * The object name held a reference to this object, drop
...@@ -460,6 +463,26 @@ drm_gem_object_handle_free(struct kref *kref) ...@@ -460,6 +463,26 @@ drm_gem_object_handle_free(struct kref *kref)
} }
EXPORT_SYMBOL(drm_gem_object_handle_free); EXPORT_SYMBOL(drm_gem_object_handle_free);
void drm_gem_vm_open(struct vm_area_struct *vma)
{
struct drm_gem_object *obj = vma->vm_private_data;
drm_gem_object_reference(obj);
}
EXPORT_SYMBOL(drm_gem_vm_open);
void drm_gem_vm_close(struct vm_area_struct *vma)
{
struct drm_gem_object *obj = vma->vm_private_data;
struct drm_device *dev = obj->dev;
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
}
EXPORT_SYMBOL(drm_gem_vm_close);
/** /**
* drm_gem_mmap - memory map routine for GEM objects * drm_gem_mmap - memory map routine for GEM objects
* @filp: DRM file pointer * @filp: DRM file pointer
...@@ -521,6 +544,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -521,6 +544,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
#endif #endif
vma->vm_page_prot = __pgprot(prot); vma->vm_page_prot = __pgprot(prot);
/* Take a ref for this mapping of the object, so that the fault
* handler can dereference the mmap offset's pointer to the object.
* This reference is cleaned up by the corresponding vm_close
* (which should happen whether the vma was created by this call, or
* by a vm_open due to mremap or partial unmap or whatever).
*/
drm_gem_object_reference(obj);
vma->vm_file = filp; /* Needed for drm_vm_open() */ vma->vm_file = filp; /* Needed for drm_vm_open() */
drm_vm_open_locked(vma); drm_vm_open_locked(vma);
......
...@@ -94,6 +94,8 @@ static int i915_resume(struct drm_device *dev) ...@@ -94,6 +94,8 @@ static int i915_resume(struct drm_device *dev)
static struct vm_operations_struct i915_gem_vm_ops = { static struct vm_operations_struct i915_gem_vm_ops = {
.fault = i915_gem_fault, .fault = i915_gem_fault,
.open = drm_gem_vm_open,
.close = drm_gem_vm_close,
}; };
static struct drm_driver driver = { static struct drm_driver driver = {
......
...@@ -184,6 +184,8 @@ typedef struct drm_i915_private { ...@@ -184,6 +184,8 @@ typedef struct drm_i915_private {
unsigned int lvds_dither:1; unsigned int lvds_dither:1;
unsigned int lvds_vbt:1; unsigned int lvds_vbt:1;
unsigned int int_crt_support:1; unsigned int int_crt_support:1;
unsigned int lvds_use_ssc:1;
int lvds_ssc_freq;
struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
......
...@@ -607,8 +607,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -607,8 +607,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
case -EAGAIN: case -EAGAIN:
return VM_FAULT_OOM; return VM_FAULT_OOM;
case -EFAULT: case -EFAULT:
case -EBUSY:
DRM_ERROR("can't insert pfn?? fault or busy...\n");
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
default: default:
return VM_FAULT_NOPAGE; return VM_FAULT_NOPAGE;
...@@ -684,6 +682,30 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) ...@@ -684,6 +682,30 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj)
return ret; return ret;
} }
static void
i915_gem_free_mmap_offset(struct drm_gem_object *obj)
{
struct drm_device *dev = obj->dev;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
struct drm_gem_mm *mm = dev->mm_private;
struct drm_map_list *list;
list = &obj->map_list;
drm_ht_remove_item(&mm->offset_hash, &list->hash);
if (list->file_offset_node) {
drm_mm_put_block(list->file_offset_node);
list->file_offset_node = NULL;
}
if (list->map) {
drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER);
list->map = NULL;
}
obj_priv->mmap_offset = 0;
}
/** /**
* i915_gem_get_gtt_alignment - return required GTT alignment for an object * i915_gem_get_gtt_alignment - return required GTT alignment for an object
* @obj: object to check * @obj: object to check
...@@ -758,9 +780,12 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, ...@@ -758,9 +780,12 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
if (!obj_priv->mmap_offset) { if (!obj_priv->mmap_offset) {
ret = i915_gem_create_mmap_offset(obj); ret = i915_gem_create_mmap_offset(obj);
if (ret) if (ret) {
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return ret; return ret;
} }
}
args->offset = obj_priv->mmap_offset; args->offset = obj_priv->mmap_offset;
...@@ -2251,6 +2276,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, ...@@ -2251,6 +2276,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
(int) reloc.offset, (int) reloc.offset,
reloc.read_domains, reloc.read_domains,
reloc.write_domain); reloc.write_domain);
drm_gem_object_unreference(target_obj);
i915_gem_object_unpin(obj);
return -EINVAL; return -EINVAL;
} }
...@@ -2480,13 +2507,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -2480,13 +2507,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
if (dev_priv->mm.wedged) { if (dev_priv->mm.wedged) {
DRM_ERROR("Execbuf while wedged\n"); DRM_ERROR("Execbuf while wedged\n");
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return -EIO; ret = -EIO;
goto pre_mutex_err;
} }
if (dev_priv->mm.suspended) { if (dev_priv->mm.suspended) {
DRM_ERROR("Execbuf while VT-switched.\n"); DRM_ERROR("Execbuf while VT-switched.\n");
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return -EBUSY; ret = -EBUSY;
goto pre_mutex_err;
} }
/* Look up object handles */ /* Look up object handles */
...@@ -2632,6 +2661,16 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -2632,6 +2661,16 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
i915_verify_inactive(dev, __FILE__, __LINE__); i915_verify_inactive(dev, __FILE__, __LINE__);
err:
for (i = 0; i < pinned; i++)
i915_gem_object_unpin(object_list[i]);
for (i = 0; i < args->buffer_count; i++)
drm_gem_object_unreference(object_list[i]);
mutex_unlock(&dev->struct_mutex);
if (!ret) {
/* Copy the new buffer offsets back to the user's exec list. */ /* Copy the new buffer offsets back to the user's exec list. */
ret = copy_to_user((struct drm_i915_relocation_entry __user *) ret = copy_to_user((struct drm_i915_relocation_entry __user *)
(uintptr_t) args->buffers_ptr, (uintptr_t) args->buffers_ptr,
...@@ -2641,14 +2680,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ...@@ -2641,14 +2680,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
DRM_ERROR("failed to copy %d exec entries " DRM_ERROR("failed to copy %d exec entries "
"back to user (%d)\n", "back to user (%d)\n",
args->buffer_count, ret); args->buffer_count, ret);
err: }
for (i = 0; i < pinned; i++)
i915_gem_object_unpin(object_list[i]);
for (i = 0; i < args->buffer_count; i++)
drm_gem_object_unreference(object_list[i]);
mutex_unlock(&dev->struct_mutex);
pre_mutex_err: pre_mutex_err:
drm_free(object_list, sizeof(*object_list) * args->buffer_count, drm_free(object_list, sizeof(*object_list) * args->buffer_count,
...@@ -2753,6 +2785,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, ...@@ -2753,6 +2785,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) {
DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
args->handle); args->handle);
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return -EINVAL; return -EINVAL;
} }
...@@ -2885,9 +2918,6 @@ int i915_gem_init_object(struct drm_gem_object *obj) ...@@ -2885,9 +2918,6 @@ int i915_gem_init_object(struct drm_gem_object *obj)
void i915_gem_free_object(struct drm_gem_object *obj) void i915_gem_free_object(struct drm_gem_object *obj)
{ {
struct drm_device *dev = obj->dev; struct drm_device *dev = obj->dev;
struct drm_gem_mm *mm = dev->mm_private;
struct drm_map_list *list;
struct drm_map *map;
struct drm_i915_gem_object *obj_priv = obj->driver_private; struct drm_i915_gem_object *obj_priv = obj->driver_private;
while (obj_priv->pin_count > 0) while (obj_priv->pin_count > 0)
...@@ -2898,19 +2928,7 @@ void i915_gem_free_object(struct drm_gem_object *obj) ...@@ -2898,19 +2928,7 @@ void i915_gem_free_object(struct drm_gem_object *obj)
i915_gem_object_unbind(obj); i915_gem_object_unbind(obj);
list = &obj->map_list; i915_gem_free_mmap_offset(obj);
drm_ht_remove_item(&mm->offset_hash, &list->hash);
if (list->file_offset_node) {
drm_mm_put_block(list->file_offset_node);
list->file_offset_node = NULL;
}
map = list->map;
if (map) {
drm_free(map, sizeof(*map), DRM_MEM_DRIVER);
list->map = NULL;
}
drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
...@@ -3095,6 +3113,7 @@ i915_gem_init_hws(struct drm_device *dev) ...@@ -3095,6 +3113,7 @@ i915_gem_init_hws(struct drm_device *dev)
if (dev_priv->hw_status_page == NULL) { if (dev_priv->hw_status_page == NULL) {
DRM_ERROR("Failed to map status page.\n"); DRM_ERROR("Failed to map status page.\n");
memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
return -EINVAL; return -EINVAL;
} }
...@@ -3107,6 +3126,27 @@ i915_gem_init_hws(struct drm_device *dev) ...@@ -3107,6 +3126,27 @@ i915_gem_init_hws(struct drm_device *dev)
return 0; return 0;
} }
static void
i915_gem_cleanup_hws(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_gem_object *obj = dev_priv->hws_obj;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
if (dev_priv->hws_obj == NULL)
return;
kunmap(obj_priv->page_list[0]);
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj);
dev_priv->hws_obj = NULL;
memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
dev_priv->hw_status_page = NULL;
/* Write high address into HWS_PGA when disabling. */
I915_WRITE(HWS_PGA, 0x1ffff000);
}
int int
i915_gem_init_ringbuffer(struct drm_device *dev) i915_gem_init_ringbuffer(struct drm_device *dev)
{ {
...@@ -3124,6 +3164,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev) ...@@ -3124,6 +3164,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
obj = drm_gem_object_alloc(dev, 128 * 1024); obj = drm_gem_object_alloc(dev, 128 * 1024);
if (obj == NULL) { if (obj == NULL) {
DRM_ERROR("Failed to allocate ringbuffer\n"); DRM_ERROR("Failed to allocate ringbuffer\n");
i915_gem_cleanup_hws(dev);
return -ENOMEM; return -ENOMEM;
} }
obj_priv = obj->driver_private; obj_priv = obj->driver_private;
...@@ -3131,6 +3172,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev) ...@@ -3131,6 +3172,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
ret = i915_gem_object_pin(obj, 4096); ret = i915_gem_object_pin(obj, 4096);
if (ret != 0) { if (ret != 0) {
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
i915_gem_cleanup_hws(dev);
return ret; return ret;
} }
...@@ -3148,7 +3190,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev) ...@@ -3148,7 +3190,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
if (ring->map.handle == NULL) { if (ring->map.handle == NULL) {
DRM_ERROR("Failed to map ringbuffer.\n"); DRM_ERROR("Failed to map ringbuffer.\n");
memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
i915_gem_cleanup_hws(dev);
return -EINVAL; return -EINVAL;
} }
ring->ring_obj = obj; ring->ring_obj = obj;
...@@ -3228,20 +3272,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) ...@@ -3228,20 +3272,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)
dev_priv->ring.ring_obj = NULL; dev_priv->ring.ring_obj = NULL;
memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
if (dev_priv->hws_obj != NULL) { i915_gem_cleanup_hws(dev);
struct drm_gem_object *obj = dev_priv->hws_obj;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
kunmap(obj_priv->page_list[0]);
i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj);
dev_priv->hws_obj = NULL;
memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
dev_priv->hw_status_page = NULL;
/* Write high address into HWS_PGA when disabling. */
I915_WRITE(HWS_PGA, 0x1ffff000);
}
} }
int int
......
...@@ -299,9 +299,8 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, ...@@ -299,9 +299,8 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
} }
obj_priv->stride = args->stride; obj_priv->stride = args->stride;
mutex_unlock(&dev->struct_mutex);
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return 0; return 0;
} }
...@@ -340,9 +339,8 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, ...@@ -340,9 +339,8 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
DRM_ERROR("unknown tiling mode\n"); DRM_ERROR("unknown tiling mode\n");
} }
mutex_unlock(&dev->struct_mutex);
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return 0; return 0;
} }
...@@ -135,6 +135,14 @@ parse_general_features(struct drm_i915_private *dev_priv, ...@@ -135,6 +135,14 @@ parse_general_features(struct drm_i915_private *dev_priv,
if (general) { if (general) {
dev_priv->int_tv_support = general->int_tv_support; dev_priv->int_tv_support = general->int_tv_support;
dev_priv->int_crt_support = general->int_crt_support; dev_priv->int_crt_support = general->int_crt_support;
dev_priv->lvds_use_ssc = general->enable_ssc;
if (dev_priv->lvds_use_ssc) {
if (IS_I855(dev_priv->dev))
dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
else
dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
}
} }
} }
......
...@@ -90,12 +90,12 @@ typedef struct { ...@@ -90,12 +90,12 @@ typedef struct {
#define I9XX_DOT_MAX 400000 #define I9XX_DOT_MAX 400000
#define I9XX_VCO_MIN 1400000 #define I9XX_VCO_MIN 1400000
#define I9XX_VCO_MAX 2800000 #define I9XX_VCO_MAX 2800000
#define I9XX_N_MIN 3 #define I9XX_N_MIN 1
#define I9XX_N_MAX 8 #define I9XX_N_MAX 6
#define I9XX_M_MIN 70 #define I9XX_M_MIN 70
#define I9XX_M_MAX 120 #define I9XX_M_MAX 120
#define I9XX_M1_MIN 10 #define I9XX_M1_MIN 10
#define I9XX_M1_MAX 20 #define I9XX_M1_MAX 22
#define I9XX_M2_MIN 5 #define I9XX_M2_MIN 5
#define I9XX_M2_MAX 9 #define I9XX_M2_MAX 9
#define I9XX_P_SDVO_DAC_MIN 5 #define I9XX_P_SDVO_DAC_MIN 5
...@@ -189,19 +189,7 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) ...@@ -189,19 +189,7 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
return limit; return limit;
} }
/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ static void intel_clock(int refclk, intel_clock_t *clock)
static void i8xx_clock(int refclk, intel_clock_t *clock)
{
clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
clock->p = clock->p1 * clock->p2;
clock->vco = refclk * clock->m / (clock->n + 2);
clock->dot = clock->vco / clock->p;
}
/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
static void i9xx_clock(int refclk, intel_clock_t *clock)
{ {
clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
clock->p = clock->p1 * clock->p2; clock->p = clock->p1 * clock->p2;
...@@ -209,15 +197,6 @@ static void i9xx_clock(int refclk, intel_clock_t *clock) ...@@ -209,15 +197,6 @@ static void i9xx_clock(int refclk, intel_clock_t *clock)
clock->dot = clock->vco / clock->p; clock->dot = clock->vco / clock->p;
} }
static void intel_clock(struct drm_device *dev, int refclk,
intel_clock_t *clock)
{
if (IS_I9XX(dev))
i9xx_clock (refclk, clock);
else
i8xx_clock (refclk, clock);
}
/** /**
* Returns whether any output on the specified pipe is of the specified type * Returns whether any output on the specified pipe is of the specified type
*/ */
...@@ -238,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type) ...@@ -238,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
return false; return false;
} }
#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } #define INTELPllInvalid(s) do { DRM_DEBUG(s); return false; } while (0)
/** /**
* Returns whether the given set of divisors are valid for a given refclk with * Returns whether the given set of divisors are valid for a given refclk with
* the given connectors. * the given connectors.
...@@ -318,7 +297,7 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target, ...@@ -318,7 +297,7 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target,
clock.p1 <= limit->p1.max; clock.p1++) { clock.p1 <= limit->p1.max; clock.p1++) {
int this_err; int this_err;
intel_clock(dev, refclk, &clock); intel_clock(refclk, &clock);
if (!intel_PLL_is_valid(crtc, &clock)) if (!intel_PLL_is_valid(crtc, &clock))
continue; continue;
...@@ -343,7 +322,7 @@ intel_wait_for_vblank(struct drm_device *dev) ...@@ -343,7 +322,7 @@ intel_wait_for_vblank(struct drm_device *dev)
udelay(20000); udelay(20000);
} }
static void static int
intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb) struct drm_framebuffer *old_fb)
{ {
...@@ -361,11 +340,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -361,11 +340,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
u32 dspcntr, alignment; u32 dspcntr, alignment;
int ret;
/* no fb bound */ /* no fb bound */
if (!crtc->fb) { if (!crtc->fb) {
DRM_DEBUG("No FB bound\n"); DRM_DEBUG("No FB bound\n");
return; return 0;
}
switch (pipe) {
case 0:
case 1:
break;
default:
DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
return -EINVAL;
} }
intel_fb = to_intel_framebuffer(crtc->fb); intel_fb = to_intel_framebuffer(crtc->fb);
...@@ -377,28 +366,30 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -377,28 +366,30 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
alignment = 64 * 1024; alignment = 64 * 1024;
break; break;
case I915_TILING_X: case I915_TILING_X:
if (IS_I9XX(dev)) /* pin() will align the object as required by fence */
alignment = 1024 * 1024; alignment = 0;
else
alignment = 512 * 1024;
break; break;
case I915_TILING_Y: case I915_TILING_Y:
/* FIXME: Is this true? */ /* FIXME: Is this true? */
DRM_ERROR("Y tiled not allowed for scan out buffers\n"); DRM_ERROR("Y tiled not allowed for scan out buffers\n");
return; return -EINVAL;
default: default:
BUG(); BUG();
} }
if (i915_gem_object_pin(intel_fb->obj, alignment)) mutex_lock(&dev->struct_mutex);
return; ret = i915_gem_object_pin(intel_fb->obj, alignment);
if (ret != 0) {
i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1); mutex_unlock(&dev->struct_mutex);
return ret;
Start = obj_priv->gtt_offset; }
Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
I915_WRITE(dspstride, crtc->fb->pitch); ret = i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
if (ret != 0) {
i915_gem_object_unpin(intel_fb->obj);
mutex_unlock(&dev->struct_mutex);
return ret;
}
dspcntr = I915_READ(dspcntr_reg); dspcntr = I915_READ(dspcntr_reg);
/* Mask out pixel format bits in case we change it */ /* Mask out pixel format bits in case we change it */
...@@ -419,11 +410,17 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -419,11 +410,17 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
break; break;
default: default:
DRM_ERROR("Unknown color depth\n"); DRM_ERROR("Unknown color depth\n");
return; i915_gem_object_unpin(intel_fb->obj);
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
} }
I915_WRITE(dspcntr_reg, dspcntr); I915_WRITE(dspcntr_reg, dspcntr);
Start = obj_priv->gtt_offset;
Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
I915_WRITE(dspstride, crtc->fb->pitch);
if (IS_I965G(dev)) { if (IS_I965G(dev)) {
I915_WRITE(dspbase, Offset); I915_WRITE(dspbase, Offset);
I915_READ(dspbase); I915_READ(dspbase);
...@@ -440,27 +437,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -440,27 +437,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
intel_fb = to_intel_framebuffer(old_fb); intel_fb = to_intel_framebuffer(old_fb);
i915_gem_object_unpin(intel_fb->obj); i915_gem_object_unpin(intel_fb->obj);
} }
mutex_unlock(&dev->struct_mutex);
if (!dev->primary->master) if (!dev->primary->master)
return; return 0;
master_priv = dev->primary->master->driver_priv; master_priv = dev->primary->master->driver_priv;
if (!master_priv->sarea_priv) if (!master_priv->sarea_priv)
return; return 0;
switch (pipe) { if (pipe) {
case 0:
master_priv->sarea_priv->pipeA_x = x;
master_priv->sarea_priv->pipeA_y = y;
break;
case 1:
master_priv->sarea_priv->pipeB_x = x; master_priv->sarea_priv->pipeB_x = x;
master_priv->sarea_priv->pipeB_y = y; master_priv->sarea_priv->pipeB_y = y;
break; } else {
default: master_priv->sarea_priv->pipeA_x = x;
DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); master_priv->sarea_priv->pipeA_y = y;
break;
} }
return 0;
} }
...@@ -708,7 +702,7 @@ static int intel_panel_fitter_pipe (struct drm_device *dev) ...@@ -708,7 +702,7 @@ static int intel_panel_fitter_pipe (struct drm_device *dev)
return 1; return 1;
} }
static void intel_crtc_mode_set(struct drm_crtc *crtc, static int intel_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, struct drm_display_mode *adjusted_mode,
int x, int y, int x, int y,
...@@ -732,13 +726,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -732,13 +726,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
int refclk; int refclk, num_outputs = 0;
intel_clock_t clock; intel_clock_t clock;
u32 dpll = 0, fp = 0, dspcntr, pipeconf; u32 dpll = 0, fp = 0, dspcntr, pipeconf;
bool ok, is_sdvo = false, is_dvo = false; bool ok, is_sdvo = false, is_dvo = false;
bool is_crt = false, is_lvds = false, is_tv = false; bool is_crt = false, is_lvds = false, is_tv = false;
struct drm_mode_config *mode_config = &dev->mode_config; struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_connector *connector; struct drm_connector *connector;
int ret;
drm_vblank_pre_modeset(dev, pipe); drm_vblank_pre_modeset(dev, pipe);
...@@ -768,9 +763,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -768,9 +763,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
is_crt = true; is_crt = true;
break; break;
} }
num_outputs++;
} }
if (IS_I9XX(dev)) { if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2) {
refclk = dev_priv->lvds_ssc_freq * 1000;
DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000);
} else if (IS_I9XX(dev)) {
refclk = 96000; refclk = 96000;
} else { } else {
refclk = 48000; refclk = 48000;
...@@ -779,7 +779,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -779,7 +779,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock); ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock);
if (!ok) { if (!ok) {
DRM_ERROR("Couldn't find PLL settings for mode!\n"); DRM_ERROR("Couldn't find PLL settings for mode!\n");
return; return -EINVAL;
} }
fp = clock.n << 16 | clock.m1 << 8 | clock.m2; fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
...@@ -829,11 +829,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -829,11 +829,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
} }
} }
if (is_tv) { if (is_sdvo && is_tv)
dpll |= PLL_REF_INPUT_TVCLKINBC;
else if (is_tv)
/* XXX: just matching BIOS for now */ /* XXX: just matching BIOS for now */
/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ /* dpll |= PLL_REF_INPUT_TVCLKINBC; */
dpll |= 3; dpll |= 3;
} else if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2)
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
else else
dpll |= PLL_REF_INPUT_DREFCLK; dpll |= PLL_REF_INPUT_DREFCLK;
...@@ -950,9 +953,13 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, ...@@ -950,9 +953,13 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(dspcntr_reg, dspcntr); I915_WRITE(dspcntr_reg, dspcntr);
/* Flush the plane changes */ /* Flush the plane changes */
intel_pipe_set_base(crtc, x, y, old_fb); ret = intel_pipe_set_base(crtc, x, y, old_fb);
if (ret != 0)
return ret;
drm_vblank_post_modeset(dev, pipe); drm_vblank_post_modeset(dev, pipe);
return 0;
} }
/** Loads the palette/gamma unit for the CRTC with the prepared values */ /** Loads the palette/gamma unit for the CRTC with the prepared values */
...@@ -1023,18 +1030,19 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -1023,18 +1030,19 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
} }
/* we only need to pin inside GTT if cursor is non-phy */ /* we only need to pin inside GTT if cursor is non-phy */
mutex_lock(&dev->struct_mutex);
if (!dev_priv->cursor_needs_physical) { if (!dev_priv->cursor_needs_physical) {
ret = i915_gem_object_pin(bo, PAGE_SIZE); ret = i915_gem_object_pin(bo, PAGE_SIZE);
if (ret) { if (ret) {
DRM_ERROR("failed to pin cursor bo\n"); DRM_ERROR("failed to pin cursor bo\n");
goto fail; goto fail_locked;
} }
addr = obj_priv->gtt_offset; addr = obj_priv->gtt_offset;
} else { } else {
ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1); ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
if (ret) { if (ret) {
DRM_ERROR("failed to attach phys object\n"); DRM_ERROR("failed to attach phys object\n");
goto fail; goto fail_locked;
} }
addr = obj_priv->phys_obj->handle->busaddr; addr = obj_priv->phys_obj->handle->busaddr;
} }
...@@ -1054,10 +1062,9 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -1054,10 +1062,9 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
} else } else
i915_gem_object_unpin(intel_crtc->cursor_bo); i915_gem_object_unpin(intel_crtc->cursor_bo);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(intel_crtc->cursor_bo); drm_gem_object_unreference(intel_crtc->cursor_bo);
mutex_unlock(&dev->struct_mutex);
} }
mutex_unlock(&dev->struct_mutex);
intel_crtc->cursor_addr = addr; intel_crtc->cursor_addr = addr;
intel_crtc->cursor_bo = bo; intel_crtc->cursor_bo = bo;
...@@ -1065,6 +1072,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -1065,6 +1072,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
return 0; return 0;
fail: fail:
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
fail_locked:
drm_gem_object_unreference(bo); drm_gem_object_unreference(bo);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return ret; return ret;
...@@ -1292,7 +1300,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) ...@@ -1292,7 +1300,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
} }
/* XXX: Handle the 100Mhz refclk */ /* XXX: Handle the 100Mhz refclk */
i9xx_clock(96000, &clock); intel_clock(96000, &clock);
} else { } else {
bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN); bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
...@@ -1304,9 +1312,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) ...@@ -1304,9 +1312,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
if ((dpll & PLL_REF_INPUT_MASK) == if ((dpll & PLL_REF_INPUT_MASK) ==
PLLB_REF_INPUT_SPREADSPECTRUMIN) { PLLB_REF_INPUT_SPREADSPECTRUMIN) {
/* XXX: might not be 66MHz */ /* XXX: might not be 66MHz */
i8xx_clock(66000, &clock); intel_clock(66000, &clock);
} else } else
i8xx_clock(48000, &clock); intel_clock(48000, &clock);
} else { } else {
if (dpll & PLL_P1_DIVIDE_BY_TWO) if (dpll & PLL_P1_DIVIDE_BY_TWO)
clock.p1 = 2; clock.p1 = 2;
...@@ -1319,7 +1327,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) ...@@ -1319,7 +1327,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
else else
clock.p2 = 2; clock.p2 = 2;
i8xx_clock(48000, &clock); intel_clock(48000, &clock);
} }
} }
...@@ -1598,7 +1606,9 @@ intel_user_framebuffer_create(struct drm_device *dev, ...@@ -1598,7 +1606,9 @@ intel_user_framebuffer_create(struct drm_device *dev,
ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj); ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj);
if (ret) { if (ret) {
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj); drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return NULL; return NULL;
} }
......
...@@ -473,7 +473,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, ...@@ -473,7 +473,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo); ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo);
if (ret) { if (ret) {
DRM_ERROR("failed to allocate fb.\n"); DRM_ERROR("failed to allocate fb.\n");
goto out_unref; goto out_unpin;
} }
list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list); list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list);
...@@ -484,7 +484,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, ...@@ -484,7 +484,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
info = framebuffer_alloc(sizeof(struct intelfb_par), device); info = framebuffer_alloc(sizeof(struct intelfb_par), device);
if (!info) { if (!info) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_unref; goto out_unpin;
} }
par = info->par; par = info->par;
...@@ -513,7 +513,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, ...@@ -513,7 +513,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
size); size);
if (!info->screen_base) { if (!info->screen_base) {
ret = -ENOSPC; ret = -ENOSPC;
goto out_unref; goto out_unpin;
} }
info->screen_size = size; info->screen_size = size;
...@@ -608,6 +608,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, ...@@ -608,6 +608,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return 0; return 0;
out_unpin:
i915_gem_object_unpin(fbo);
out_unref: out_unref:
drm_gem_object_unreference(fbo); drm_gem_object_unreference(fbo);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
......
...@@ -481,8 +481,6 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -481,8 +481,6 @@ void intel_lvds_init(struct drm_device *dev)
if (dev_priv->panel_fixed_mode) { if (dev_priv->panel_fixed_mode) {
dev_priv->panel_fixed_mode->type |= dev_priv->panel_fixed_mode->type |=
DRM_MODE_TYPE_PREFERRED; DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector,
dev_priv->panel_fixed_mode);
goto out; goto out;
} }
} }
......
...@@ -193,7 +193,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, ...@@ -193,7 +193,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
/** Mapping of command numbers to names, for debug output */ /** Mapping of command numbers to names, for debug output */
const static struct _sdvo_cmd_name { static const struct _sdvo_cmd_name {
u8 cmd; u8 cmd;
char *name; char *name;
} sdvo_cmd_names[] = { } sdvo_cmd_names[] = {
......
...@@ -411,7 +411,7 @@ struct tv_mode { ...@@ -411,7 +411,7 @@ struct tv_mode {
* These values account for -1s required. * These values account for -1s required.
*/ */
const static struct tv_mode tv_modes[] = { static const struct tv_mode tv_modes[] = {
{ {
.name = "NTSC-M", .name = "NTSC-M",
.clock = 107520, .clock = 107520,
......
...@@ -557,8 +557,10 @@ static int radeon_do_engine_reset(struct drm_device * dev) ...@@ -557,8 +557,10 @@ static int radeon_do_engine_reset(struct drm_device * dev)
} }
static void radeon_cp_init_ring_buffer(struct drm_device * dev, static void radeon_cp_init_ring_buffer(struct drm_device * dev,
drm_radeon_private_t * dev_priv) drm_radeon_private_t *dev_priv,
struct drm_file *file_priv)
{ {
struct drm_radeon_master_private *master_priv;
u32 ring_start, cur_read_ptr; u32 ring_start, cur_read_ptr;
u32 tmp; u32 tmp;
...@@ -677,6 +679,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, ...@@ -677,6 +679,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
dev_priv->scratch[2] = 0; dev_priv->scratch[2] = 0;
RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0); RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);
/* reset sarea copies of these */
master_priv = file_priv->master->driver_priv;
if (master_priv->sarea_priv) {
master_priv->sarea_priv->last_frame = 0;
master_priv->sarea_priv->last_dispatch = 0;
master_priv->sarea_priv->last_clear = 0;
}
radeon_do_wait_for_idle(dev_priv); radeon_do_wait_for_idle(dev_priv);
/* Sync everything up */ /* Sync everything up */
...@@ -1215,7 +1225,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, ...@@ -1215,7 +1225,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
} }
radeon_cp_load_microcode(dev_priv); radeon_cp_load_microcode(dev_priv);
radeon_cp_init_ring_buffer(dev, dev_priv); radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
dev_priv->last_buf = 0; dev_priv->last_buf = 0;
...@@ -1281,7 +1291,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev) ...@@ -1281,7 +1291,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev)
* *
* Charl P. Botha <http://cpbotha.net> * Charl P. Botha <http://cpbotha.net>
*/ */
static int radeon_do_resume_cp(struct drm_device * dev) static int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
...@@ -1304,7 +1314,7 @@ static int radeon_do_resume_cp(struct drm_device * dev) ...@@ -1304,7 +1314,7 @@ static int radeon_do_resume_cp(struct drm_device * dev)
} }
radeon_cp_load_microcode(dev_priv); radeon_cp_load_microcode(dev_priv);
radeon_cp_init_ring_buffer(dev, dev_priv); radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
radeon_do_engine_reset(dev); radeon_do_engine_reset(dev);
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
...@@ -1479,8 +1489,7 @@ int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_pri ...@@ -1479,8 +1489,7 @@ int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_pri
*/ */
int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv) int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
{ {
return radeon_do_resume_cp(dev, file_priv);
return radeon_do_resume_cp(dev);
} }
int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
......
...@@ -1321,6 +1321,8 @@ void drm_gem_object_free(struct kref *kref); ...@@ -1321,6 +1321,8 @@ void drm_gem_object_free(struct kref *kref);
struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
size_t size); size_t size);
void drm_gem_object_handle_free(struct kref *kref); void drm_gem_object_handle_free(struct kref *kref);
void drm_gem_vm_open(struct vm_area_struct *vma);
void drm_gem_vm_close(struct vm_area_struct *vma);
int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
static inline void static inline void
......
...@@ -609,7 +609,7 @@ extern char *drm_get_dvi_i_subconnector_name(int val); ...@@ -609,7 +609,7 @@ extern char *drm_get_dvi_i_subconnector_name(int val);
extern char *drm_get_dvi_i_select_name(int val); extern char *drm_get_dvi_i_select_name(int val);
extern char *drm_get_tv_subconnector_name(int val); extern char *drm_get_tv_subconnector_name(int val);
extern char *drm_get_tv_select_name(int val); extern char *drm_get_tv_select_name(int val);
extern void drm_fb_release(struct file *filp); extern void drm_fb_release(struct drm_file *file_priv);
extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group);
extern struct edid *drm_get_edid(struct drm_connector *connector, extern struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter); struct i2c_adapter *adapter);
......
...@@ -54,12 +54,12 @@ struct drm_crtc_helper_funcs { ...@@ -54,12 +54,12 @@ struct drm_crtc_helper_funcs {
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode); struct drm_display_mode *adjusted_mode);
/* Actually set the mode */ /* Actually set the mode */
void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, int x, int y, struct drm_display_mode *adjusted_mode, int x, int y,
struct drm_framebuffer *old_fb); struct drm_framebuffer *old_fb);
/* Move the crtc on the current fb to the given position *optional* */ /* Move the crtc on the current fb to the given position *optional* */
void (*mode_set_base)(struct drm_crtc *crtc, int x, int y, int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb); struct drm_framebuffer *old_fb);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment