Merge branches 'x86/acpi', 'x86/apic', 'x86/asm', 'x86/cleanups', 'x86/mm', 'x86/signal' and 'x86/urgent'; commit 'v2.6.29-rc6' into x86/core
This commit is contained in:
@@ -70,7 +70,7 @@ config DRM_I915
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
depends on FB
|
||||
select FB
|
||||
tristate "i915 driver"
|
||||
help
|
||||
Choose this option if you have a system that has Intel 830M, 845G,
|
||||
@@ -80,18 +80,17 @@ config DRM_I915
|
||||
XFree86 4.4 and above. If unsure, build this and i830 as modules and
|
||||
the X server will load the correct one.
|
||||
|
||||
endchoice
|
||||
|
||||
config DRM_I915_KMS
|
||||
bool "Enable modesetting on intel by default"
|
||||
depends on DRM_I915
|
||||
help
|
||||
Choose this option if you want kernel modesetting enabled by default,
|
||||
and you have a new enough userspace to support this. Running old
|
||||
userspaces with this enabled will cause pain. Note that this causes
|
||||
the driver to bind to PCI devices, which precludes loading things
|
||||
like intelfb.
|
||||
Choose this option if you want kernel modesetting enabled by default,
|
||||
and you have a new enough userspace to support this. Running old
|
||||
userspaces with this enabled will cause pain. Note that this causes
|
||||
the driver to bind to PCI devices, which precludes loading things
|
||||
like intelfb.
|
||||
|
||||
endchoice
|
||||
|
||||
config DRM_MGA
|
||||
tristate "Matrox g200/g400"
|
||||
|
@@ -1741,9 +1741,8 @@ out:
|
||||
* RETURNS:
|
||||
* 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_framebuffer *fb, *tfb;
|
||||
|
||||
|
@@ -512,8 +512,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
|
||||
if (drm_mode_equal(&saved_mode, &crtc->mode)) {
|
||||
if (saved_x != crtc->x || saved_y != crtc->y ||
|
||||
depth_changed || bpp_changed) {
|
||||
crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
|
||||
old_fb);
|
||||
ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
|
||||
old_fb);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
* 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) {
|
||||
|
||||
@@ -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,
|
||||
set->x, set->y,
|
||||
old_fb)) {
|
||||
DRM_ERROR("failed to set mode on crtc %p\n",
|
||||
set->crtc);
|
||||
ret = -EINVAL;
|
||||
goto fail_set_mode;
|
||||
}
|
||||
@@ -765,7 +769,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
old_fb = set->crtc->fb;
|
||||
if (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);
|
||||
@@ -775,8 +782,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
fail_set_mode:
|
||||
set->crtc->enabled = save_enabled;
|
||||
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++];
|
||||
}
|
||||
fail_no_encoder:
|
||||
kfree(save_crtcs);
|
||||
count = 0;
|
||||
|
@@ -457,6 +457,9 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||
if (dev->driver->driver_features & DRIVER_GEM)
|
||||
drm_gem_release(dev, file_priv);
|
||||
|
||||
if (dev->driver->driver_features & DRIVER_MODESET)
|
||||
drm_fb_release(file_priv);
|
||||
|
||||
mutex_lock(&dev->ctxlist_mutex);
|
||||
if (!list_empty(&dev->ctxlist)) {
|
||||
struct drm_ctx_list *pos, *n;
|
||||
|
@@ -104,8 +104,8 @@ drm_gem_init(struct drm_device *dev)
|
||||
|
||||
if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
|
||||
DRM_FILE_PAGE_OFFSET_SIZE)) {
|
||||
drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
|
||||
drm_ht_remove(&mm->offset_hash);
|
||||
drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -295,35 +295,37 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
|
||||
return -EBADF;
|
||||
|
||||
again:
|
||||
if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
|
||||
return -ENOMEM;
|
||||
if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_lock(&dev->object_name_lock);
|
||||
if (obj->name) {
|
||||
args->name = obj->name;
|
||||
if (!obj->name) {
|
||||
ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
|
||||
&obj->name);
|
||||
args->name = (uint64_t) obj->name;
|
||||
spin_unlock(&dev->object_name_lock);
|
||||
return 0;
|
||||
}
|
||||
ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
|
||||
&obj->name);
|
||||
spin_unlock(&dev->object_name_lock);
|
||||
if (ret == -EAGAIN)
|
||||
goto again;
|
||||
|
||||
if (ret != 0) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
if (ret == -EAGAIN)
|
||||
goto again;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Leave the reference from the lookup around as the
|
||||
* name table now holds one
|
||||
*/
|
||||
args->name = (uint64_t) obj->name;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -448,6 +450,7 @@ drm_gem_object_handle_free(struct kref *kref)
|
||||
spin_lock(&dev->object_name_lock);
|
||||
if (obj->name) {
|
||||
idr_remove(&dev->object_name_idr, obj->name);
|
||||
obj->name = 0;
|
||||
spin_unlock(&dev->object_name_lock);
|
||||
/*
|
||||
* The object name held a reference to this object, drop
|
||||
@@ -460,6 +463,26 @@ drm_gem_object_handle_free(struct kref *kref)
|
||||
}
|
||||
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
|
||||
* @filp: DRM file pointer
|
||||
@@ -521,6 +544,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
#endif
|
||||
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() */
|
||||
drm_vm_open_locked(vma);
|
||||
|
||||
|
@@ -276,6 +276,7 @@ int drm_irq_uninstall(struct drm_device * dev)
|
||||
for (i = 0; i < dev->num_crtcs; i++) {
|
||||
DRM_WAKEUP(&dev->vbl_queue[i]);
|
||||
dev->vblank_enabled[i] = 0;
|
||||
dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
|
||||
|
@@ -171,9 +171,14 @@ EXPORT_SYMBOL(drm_core_ioremap);
|
||||
|
||||
void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev)
|
||||
{
|
||||
map->handle = ioremap_wc(map->offset, map->size);
|
||||
if (drm_core_has_AGP(dev) &&
|
||||
dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
|
||||
map->handle = agp_remap(map->offset, map->size, dev);
|
||||
else
|
||||
map->handle = ioremap_wc(map->offset, map->size);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_core_ioremap_wc);
|
||||
|
||||
void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
|
||||
{
|
||||
if (!map->handle || !map->size)
|
||||
|
@@ -678,9 +678,9 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
|
||||
*start = &buf[offset];
|
||||
*eof = 0;
|
||||
|
||||
DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
|
||||
DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%llx\n",
|
||||
atomic_read(&dev->vma_count),
|
||||
high_memory, virt_to_phys(high_memory));
|
||||
high_memory, (u64)virt_to_phys(high_memory));
|
||||
list_for_each_entry(pt, &dev->vmalist, head) {
|
||||
if (!(vma = pt->vma))
|
||||
continue;
|
||||
|
@@ -202,7 +202,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
|
||||
dev_priv->ring.map.flags = 0;
|
||||
dev_priv->ring.map.mtrr = 0;
|
||||
|
||||
drm_core_ioremap(&dev_priv->ring.map, dev);
|
||||
drm_core_ioremap_wc(&dev_priv->ring.map, dev);
|
||||
|
||||
if (dev_priv->ring.map.handle == NULL) {
|
||||
i915_dma_cleanup(dev);
|
||||
@@ -731,8 +731,11 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||
case I915_PARAM_HAS_GEM:
|
||||
value = dev_priv->has_gem;
|
||||
break;
|
||||
case I915_PARAM_NUM_FENCES_AVAIL:
|
||||
value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown parameter %d\n", param->param);
|
||||
DRM_DEBUG("Unknown parameter %d\n", param->param);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -764,8 +767,15 @@ static int i915_setparam(struct drm_device *dev, void *data,
|
||||
case I915_SETPARAM_ALLOW_BATCHBUFFER:
|
||||
dev_priv->allow_batchbuffer = param->value;
|
||||
break;
|
||||
case I915_SETPARAM_NUM_USED_FENCES:
|
||||
if (param->value > dev_priv->num_fence_regs ||
|
||||
param->value < 0)
|
||||
return -EINVAL;
|
||||
/* Userspace can use first N regs */
|
||||
dev_priv->fence_reg_start = param->value;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unknown parameter %d\n", param->param);
|
||||
DRM_DEBUG("unknown parameter %d\n", param->param);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -966,10 +976,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
||||
if (ret)
|
||||
goto kfree_devname;
|
||||
|
||||
dev_priv->mm.gtt_mapping =
|
||||
io_mapping_create_wc(dev->agp->base,
|
||||
dev->agp->agp_info.aper_size * 1024*1024);
|
||||
|
||||
/* Allow hardware batchbuffers unless told otherwise.
|
||||
*/
|
||||
dev_priv->allow_batchbuffer = 1;
|
||||
@@ -1081,6 +1087,23 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
goto free_priv;
|
||||
}
|
||||
|
||||
dev_priv->mm.gtt_mapping =
|
||||
io_mapping_create_wc(dev->agp->base,
|
||||
dev->agp->agp_info.aper_size * 1024*1024);
|
||||
/* Set up a WC MTRR for non-PAT systems. This is more common than
|
||||
* one would think, because the kernel disables PAT on first
|
||||
* generation Core chips because WC PAT gets overridden by a UC
|
||||
* MTRR if present. Even if a UC MTRR isn't present.
|
||||
*/
|
||||
dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base,
|
||||
dev->agp->agp_info.aper_size *
|
||||
1024 * 1024,
|
||||
MTRR_TYPE_WRCOMB, 1);
|
||||
if (dev_priv->mm.gtt_mtrr < 0) {
|
||||
DRM_INFO("MTRR allocation failed\n. Graphics "
|
||||
"performance may suffer.\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HIGHMEM64G
|
||||
/* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */
|
||||
dev_priv->has_gem = 0;
|
||||
@@ -1089,6 +1112,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
dev_priv->has_gem = 1;
|
||||
#endif
|
||||
|
||||
dev->driver->get_vblank_counter = i915_get_vblank_counter;
|
||||
if (IS_GM45(dev))
|
||||
dev->driver->get_vblank_counter = gm45_get_vblank_counter;
|
||||
|
||||
i915_gem_load(dev);
|
||||
|
||||
/* Init HWS */
|
||||
@@ -1145,8 +1172,14 @@ int i915_driver_unload(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
io_mapping_free(dev_priv->mm.gtt_mapping);
|
||||
if (dev_priv->mm.gtt_mtrr >= 0) {
|
||||
mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
|
||||
dev->agp->agp_info.aper_size * 1024 * 1024);
|
||||
dev_priv->mm.gtt_mtrr = -1;
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
io_mapping_free(dev_priv->mm.gtt_mapping);
|
||||
drm_irq_uninstall(dev);
|
||||
}
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "i915_drm.h"
|
||||
@@ -66,6 +67,12 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
|
||||
|
||||
i915_save_state(dev);
|
||||
|
||||
/* If KMS is active, we do the leavevt stuff here */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET) && i915_gem_idle(dev)) {
|
||||
dev_err(&dev->pdev->dev, "GEM idle failed, aborting suspend\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
intel_opregion_free(dev);
|
||||
|
||||
if (state.event == PM_EVENT_SUSPEND) {
|
||||
@@ -79,6 +86,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
|
||||
|
||||
static int i915_resume(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret = 0;
|
||||
|
||||
pci_set_power_state(dev->pdev, PCI_D0);
|
||||
pci_restore_state(dev->pdev);
|
||||
if (pci_enable_device(dev->pdev))
|
||||
@@ -89,11 +99,24 @@ static int i915_resume(struct drm_device *dev)
|
||||
|
||||
intel_opregion_init(dev);
|
||||
|
||||
return 0;
|
||||
/* KMS EnterVT equivalent */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
dev_priv->mm.suspended = 0;
|
||||
|
||||
ret = i915_gem_init_ringbuffer(dev);
|
||||
if (ret != 0)
|
||||
ret = -1;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct vm_operations_struct i915_gem_vm_ops = {
|
||||
.fault = i915_gem_fault,
|
||||
.open = drm_gem_vm_open,
|
||||
.close = drm_gem_vm_close,
|
||||
};
|
||||
|
||||
static struct drm_driver driver = {
|
||||
@@ -112,7 +135,6 @@ static struct drm_driver driver = {
|
||||
.suspend = i915_suspend,
|
||||
.resume = i915_resume,
|
||||
.device_is_agp = i915_driver_device_is_agp,
|
||||
.get_vblank_counter = i915_get_vblank_counter,
|
||||
.enable_vblank = i915_enable_vblank,
|
||||
.disable_vblank = i915_disable_vblank,
|
||||
.irq_preinstall = i915_driver_irq_preinstall,
|
||||
|
@@ -184,6 +184,8 @@ typedef struct drm_i915_private {
|
||||
unsigned int lvds_dither:1;
|
||||
unsigned int lvds_vbt: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 */
|
||||
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
|
||||
@@ -284,6 +286,7 @@ typedef struct drm_i915_private {
|
||||
struct drm_mm gtt_space;
|
||||
|
||||
struct io_mapping *gtt_mapping;
|
||||
int gtt_mtrr;
|
||||
|
||||
/**
|
||||
* List of objects currently involved in rendering from the
|
||||
@@ -534,6 +537,7 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
|
||||
extern int i915_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void i915_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern int i915_vblank_swap(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
|
||||
@@ -601,6 +605,7 @@ int i915_gem_init_object(struct drm_gem_object *obj);
|
||||
void i915_gem_free_object(struct drm_gem_object *obj);
|
||||
int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
|
||||
void i915_gem_object_unpin(struct drm_gem_object *obj);
|
||||
int i915_gem_object_unbind(struct drm_gem_object *obj);
|
||||
void i915_gem_lastclose(struct drm_device *dev);
|
||||
uint32_t i915_get_gem_seqno(struct drm_device *dev);
|
||||
void i915_gem_retire_requests(struct drm_device *dev);
|
||||
@@ -613,6 +618,7 @@ int i915_gem_init_ringbuffer(struct drm_device *dev);
|
||||
void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
|
||||
int i915_gem_do_init(struct drm_device *dev, unsigned long start,
|
||||
unsigned long end);
|
||||
int i915_gem_idle(struct drm_device *dev);
|
||||
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
|
||||
int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
|
||||
int write);
|
||||
@@ -784,6 +790,11 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
||||
IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev))
|
||||
|
||||
#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev))
|
||||
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
|
||||
* rows, which changed the alignment requirements and fence programming.
|
||||
*/
|
||||
#define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
|
||||
IS_I915GM(dev)))
|
||||
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev))
|
||||
|
||||
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
|
||||
|
@@ -34,10 +34,6 @@
|
||||
|
||||
#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
|
||||
|
||||
static void
|
||||
i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
|
||||
uint32_t read_domains,
|
||||
uint32_t write_domain);
|
||||
static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
|
||||
static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
|
||||
static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
|
||||
@@ -52,7 +48,7 @@ static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
|
||||
static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
|
||||
static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
|
||||
unsigned alignment);
|
||||
static void i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
|
||||
static int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write);
|
||||
static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
|
||||
static int i915_gem_evict_something(struct drm_device *dev);
|
||||
static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
|
||||
@@ -567,6 +563,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
pgoff_t page_offset;
|
||||
unsigned long pfn;
|
||||
int ret = 0;
|
||||
bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
|
||||
|
||||
/* We don't use vmf->pgoff since that has the fake offset */
|
||||
page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
|
||||
@@ -585,8 +582,13 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
|
||||
/* Need a new fence register? */
|
||||
if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
|
||||
obj_priv->tiling_mode != I915_TILING_NONE)
|
||||
i915_gem_object_get_fence_reg(obj);
|
||||
obj_priv->tiling_mode != I915_TILING_NONE) {
|
||||
ret = i915_gem_object_get_fence_reg(obj, write);
|
||||
if (ret) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
}
|
||||
|
||||
pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
|
||||
page_offset;
|
||||
@@ -601,8 +603,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
case -EAGAIN:
|
||||
return VM_FAULT_OOM;
|
||||
case -EFAULT:
|
||||
case -EBUSY:
|
||||
DRM_ERROR("can't insert pfn?? fault or busy...\n");
|
||||
return VM_FAULT_SIGBUS;
|
||||
default:
|
||||
return VM_FAULT_NOPAGE;
|
||||
@@ -678,6 +678,30 @@ out_free_list:
|
||||
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
|
||||
* @obj: object to check
|
||||
@@ -752,8 +776,11 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
if (!obj_priv->mmap_offset) {
|
||||
ret = i915_gem_create_mmap_offset(obj);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
args->offset = obj_priv->mmap_offset;
|
||||
@@ -1211,7 +1238,7 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj)
|
||||
/**
|
||||
* Unbinds an object from the GTT aperture.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
i915_gem_object_unbind(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
@@ -1445,21 +1472,26 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
int regnum = obj_priv->fence_reg;
|
||||
int tile_width;
|
||||
uint32_t val;
|
||||
uint32_t pitch_val;
|
||||
|
||||
if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
|
||||
(obj_priv->gtt_offset & (obj->size - 1))) {
|
||||
WARN(1, "%s: object not 1M or size aligned\n", __func__);
|
||||
WARN(1, "%s: object 0x%08x not 1M or size (0x%zx) aligned\n",
|
||||
__func__, obj_priv->gtt_offset, obj->size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj_priv->tiling_mode == I915_TILING_Y && (IS_I945G(dev) ||
|
||||
IS_I945GM(dev) ||
|
||||
IS_G33(dev)))
|
||||
pitch_val = (obj_priv->stride / 128) - 1;
|
||||
if (obj_priv->tiling_mode == I915_TILING_Y &&
|
||||
HAS_128_BYTE_Y_TILING(dev))
|
||||
tile_width = 128;
|
||||
else
|
||||
pitch_val = (obj_priv->stride / 512) - 1;
|
||||
tile_width = 512;
|
||||
|
||||
/* Note: pitch better be a power of two tile widths */
|
||||
pitch_val = obj_priv->stride / tile_width;
|
||||
pitch_val = ffs(pitch_val) - 1;
|
||||
|
||||
val = obj_priv->gtt_offset;
|
||||
if (obj_priv->tiling_mode == I915_TILING_Y)
|
||||
@@ -1483,7 +1515,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
|
||||
|
||||
if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
|
||||
(obj_priv->gtt_offset & (obj->size - 1))) {
|
||||
WARN(1, "%s: object not 1M or size aligned\n", __func__);
|
||||
WARN(1, "%s: object 0x%08x not 1M or size aligned\n",
|
||||
__func__, obj_priv->gtt_offset);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1503,6 +1536,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
|
||||
/**
|
||||
* i915_gem_object_get_fence_reg - set up a fence reg for an object
|
||||
* @obj: object to map through a fence reg
|
||||
* @write: object is about to be written
|
||||
*
|
||||
* When mapping objects through the GTT, userspace wants to be able to write
|
||||
* to them without having to worry about swizzling if the object is tiled.
|
||||
@@ -1513,8 +1547,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
|
||||
* It then sets up the reg based on the object's properties: address, pitch
|
||||
* and tiling format.
|
||||
*/
|
||||
static void
|
||||
i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
|
||||
static int
|
||||
i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
@@ -1527,12 +1561,18 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
|
||||
WARN(1, "allocating a fence for non-tiled object?\n");
|
||||
break;
|
||||
case I915_TILING_X:
|
||||
WARN(obj_priv->stride & (512 - 1),
|
||||
"object is X tiled but has non-512B pitch\n");
|
||||
if (!obj_priv->stride)
|
||||
return -EINVAL;
|
||||
WARN((obj_priv->stride & (512 - 1)),
|
||||
"object 0x%08x is X tiled but has non-512B pitch\n",
|
||||
obj_priv->gtt_offset);
|
||||
break;
|
||||
case I915_TILING_Y:
|
||||
WARN(obj_priv->stride & (128 - 1),
|
||||
"object is Y tiled but has non-128B pitch\n");
|
||||
if (!obj_priv->stride)
|
||||
return -EINVAL;
|
||||
WARN((obj_priv->stride & (128 - 1)),
|
||||
"object 0x%08x is Y tiled but has non-128B pitch\n",
|
||||
obj_priv->gtt_offset);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1563,10 +1603,11 @@ try_again:
|
||||
* objects to finish before trying again.
|
||||
*/
|
||||
if (i == dev_priv->num_fence_regs) {
|
||||
ret = i915_gem_object_wait_rendering(reg->obj);
|
||||
ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0);
|
||||
if (ret) {
|
||||
WARN(ret, "wait_rendering failed: %d\n", ret);
|
||||
return;
|
||||
WARN(ret != -ERESTARTSYS,
|
||||
"switch to GTT domain failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
goto try_again;
|
||||
}
|
||||
@@ -1591,6 +1632,8 @@ try_again:
|
||||
i915_write_fence_reg(reg);
|
||||
else
|
||||
i830_write_fence_reg(reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1631,7 +1674,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
|
||||
if (dev_priv->mm.suspended)
|
||||
return -EBUSY;
|
||||
if (alignment == 0)
|
||||
alignment = PAGE_SIZE;
|
||||
alignment = i915_gem_get_gtt_alignment(obj);
|
||||
if (alignment & (PAGE_SIZE - 1)) {
|
||||
DRM_ERROR("Invalid object alignment requested %u\n", alignment);
|
||||
return -EINVAL;
|
||||
@@ -1974,30 +2017,28 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write)
|
||||
* drm_agp_chipset_flush
|
||||
*/
|
||||
static void
|
||||
i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
|
||||
uint32_t read_domains,
|
||||
uint32_t write_domain)
|
||||
i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
uint32_t invalidate_domains = 0;
|
||||
uint32_t flush_domains = 0;
|
||||
|
||||
BUG_ON(read_domains & I915_GEM_DOMAIN_CPU);
|
||||
BUG_ON(write_domain == I915_GEM_DOMAIN_CPU);
|
||||
BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU);
|
||||
BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU);
|
||||
|
||||
#if WATCH_BUF
|
||||
DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
|
||||
__func__, obj,
|
||||
obj->read_domains, read_domains,
|
||||
obj->write_domain, write_domain);
|
||||
obj->read_domains, obj->pending_read_domains,
|
||||
obj->write_domain, obj->pending_write_domain);
|
||||
#endif
|
||||
/*
|
||||
* If the object isn't moving to a new write domain,
|
||||
* let the object stay in multiple read domains
|
||||
*/
|
||||
if (write_domain == 0)
|
||||
read_domains |= obj->read_domains;
|
||||
if (obj->pending_write_domain == 0)
|
||||
obj->pending_read_domains |= obj->read_domains;
|
||||
else
|
||||
obj_priv->dirty = 1;
|
||||
|
||||
@@ -2007,15 +2048,17 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
|
||||
* any read domains which differ from the old
|
||||
* write domain
|
||||
*/
|
||||
if (obj->write_domain && obj->write_domain != read_domains) {
|
||||
if (obj->write_domain &&
|
||||
obj->write_domain != obj->pending_read_domains) {
|
||||
flush_domains |= obj->write_domain;
|
||||
invalidate_domains |= read_domains & ~obj->write_domain;
|
||||
invalidate_domains |=
|
||||
obj->pending_read_domains & ~obj->write_domain;
|
||||
}
|
||||
/*
|
||||
* Invalidate any read caches which may have
|
||||
* stale data. That is, any new read domains.
|
||||
*/
|
||||
invalidate_domains |= read_domains & ~obj->read_domains;
|
||||
invalidate_domains |= obj->pending_read_domains & ~obj->read_domains;
|
||||
if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) {
|
||||
#if WATCH_BUF
|
||||
DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n",
|
||||
@@ -2024,9 +2067,15 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
|
||||
i915_gem_clflush_object(obj);
|
||||
}
|
||||
|
||||
if ((write_domain | flush_domains) != 0)
|
||||
obj->write_domain = write_domain;
|
||||
obj->read_domains = read_domains;
|
||||
/* The actual obj->write_domain will be updated with
|
||||
* pending_write_domain after we emit the accumulated flush for all
|
||||
* of our domain changes in execbuffers (which clears objects'
|
||||
* write_domains). So if we have a current write domain that we
|
||||
* aren't changing, set pending_write_domain to that.
|
||||
*/
|
||||
if (flush_domains == 0 && obj->pending_write_domain == 0)
|
||||
obj->pending_write_domain = obj->write_domain;
|
||||
obj->read_domains = obj->pending_read_domains;
|
||||
|
||||
dev->invalidate_domains |= invalidate_domains;
|
||||
dev->flush_domains |= flush_domains;
|
||||
@@ -2229,6 +2278,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
|
||||
(int) reloc.offset,
|
||||
reloc.read_domains,
|
||||
reloc.write_domain);
|
||||
drm_gem_object_unreference(target_obj);
|
||||
i915_gem_object_unpin(obj);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -2458,13 +2509,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||
if (dev_priv->mm.wedged) {
|
||||
DRM_ERROR("Execbuf while wedged\n");
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
goto pre_mutex_err;
|
||||
}
|
||||
|
||||
if (dev_priv->mm.suspended) {
|
||||
DRM_ERROR("Execbuf while VT-switched.\n");
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -EBUSY;
|
||||
ret = -EBUSY;
|
||||
goto pre_mutex_err;
|
||||
}
|
||||
|
||||
/* Look up object handles */
|
||||
@@ -2532,9 +2585,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||
struct drm_gem_object *obj = object_list[i];
|
||||
|
||||
/* Compute new gpu domains and update invalidate/flush */
|
||||
i915_gem_object_set_to_gpu_domain(obj,
|
||||
obj->pending_read_domains,
|
||||
obj->pending_write_domain);
|
||||
i915_gem_object_set_to_gpu_domain(obj);
|
||||
}
|
||||
|
||||
i915_verify_inactive(dev, __FILE__, __LINE__);
|
||||
@@ -2553,6 +2604,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||
(void)i915_add_request(dev, dev->flush_domains);
|
||||
}
|
||||
|
||||
for (i = 0; i < args->buffer_count; i++) {
|
||||
struct drm_gem_object *obj = object_list[i];
|
||||
|
||||
obj->write_domain = obj->pending_write_domain;
|
||||
}
|
||||
|
||||
i915_verify_inactive(dev, __FILE__, __LINE__);
|
||||
|
||||
#if WATCH_COHERENCY
|
||||
@@ -2610,15 +2667,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||
|
||||
i915_verify_inactive(dev, __FILE__, __LINE__);
|
||||
|
||||
/* Copy the new buffer offsets back to the user's exec list. */
|
||||
ret = copy_to_user((struct drm_i915_relocation_entry __user *)
|
||||
(uintptr_t) args->buffers_ptr,
|
||||
exec_list,
|
||||
sizeof(*exec_list) * args->buffer_count);
|
||||
if (ret)
|
||||
DRM_ERROR("failed to copy %d exec entries "
|
||||
"back to user (%d)\n",
|
||||
args->buffer_count, ret);
|
||||
err:
|
||||
for (i = 0; i < pinned; i++)
|
||||
i915_gem_object_unpin(object_list[i]);
|
||||
@@ -2628,6 +2676,18 @@ err:
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
if (!ret) {
|
||||
/* Copy the new buffer offsets back to the user's exec list. */
|
||||
ret = copy_to_user((struct drm_i915_relocation_entry __user *)
|
||||
(uintptr_t) args->buffers_ptr,
|
||||
exec_list,
|
||||
sizeof(*exec_list) * args->buffer_count);
|
||||
if (ret)
|
||||
DRM_ERROR("failed to copy %d exec entries "
|
||||
"back to user (%d)\n",
|
||||
args->buffer_count, ret);
|
||||
}
|
||||
|
||||
pre_mutex_err:
|
||||
drm_free(object_list, sizeof(*object_list) * args->buffer_count,
|
||||
DRM_MEM_DRIVER);
|
||||
@@ -2652,6 +2712,14 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
|
||||
DRM_ERROR("Failure to bind: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* Pre-965 chips need a fence register set up in order to
|
||||
* properly handle tiled surfaces.
|
||||
*/
|
||||
if (!IS_I965G(dev) &&
|
||||
obj_priv->fence_reg == I915_FENCE_REG_NONE &&
|
||||
obj_priv->tiling_mode != I915_TILING_NONE)
|
||||
i915_gem_object_get_fence_reg(obj, true);
|
||||
}
|
||||
obj_priv->pin_count++;
|
||||
|
||||
@@ -2723,6 +2791,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
|
||||
if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) {
|
||||
DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
|
||||
args->handle);
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -2803,6 +2872,13 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
/* Update the active list for the hardware's current position.
|
||||
* Otherwise this only updates on a delayed timer or when irqs are
|
||||
* actually unmasked, and our working set ends up being larger than
|
||||
* required.
|
||||
*/
|
||||
i915_gem_retire_requests(dev);
|
||||
|
||||
obj_priv = obj->driver_private;
|
||||
/* Don't count being on the flushing list against the object being
|
||||
* done. Otherwise, a buffer left on the flushing list but not getting
|
||||
@@ -2855,9 +2931,6 @@ int i915_gem_init_object(struct drm_gem_object *obj)
|
||||
void i915_gem_free_object(struct drm_gem_object *obj)
|
||||
{
|
||||
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;
|
||||
|
||||
while (obj_priv->pin_count > 0)
|
||||
@@ -2868,19 +2941,7 @@ void i915_gem_free_object(struct drm_gem_object *obj)
|
||||
|
||||
i915_gem_object_unbind(obj);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
map = list->map;
|
||||
if (map) {
|
||||
drm_free(map, sizeof(*map), DRM_MEM_DRIVER);
|
||||
list->map = NULL;
|
||||
}
|
||||
i915_gem_free_mmap_offset(obj);
|
||||
|
||||
drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
|
||||
drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
|
||||
@@ -2919,7 +2980,7 @@ i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
i915_gem_idle(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
@@ -3065,6 +3126,7 @@ i915_gem_init_hws(struct drm_device *dev)
|
||||
if (dev_priv->hw_status_page == NULL) {
|
||||
DRM_ERROR("Failed to map status page.\n");
|
||||
memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
|
||||
i915_gem_object_unpin(obj);
|
||||
drm_gem_object_unreference(obj);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -3077,6 +3139,31 @@ i915_gem_init_hws(struct drm_device *dev)
|
||||
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;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
|
||||
if (dev_priv->hws_obj == NULL)
|
||||
return;
|
||||
|
||||
obj = dev_priv->hws_obj;
|
||||
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
|
||||
i915_gem_init_ringbuffer(struct drm_device *dev)
|
||||
{
|
||||
@@ -3094,6 +3181,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
|
||||
obj = drm_gem_object_alloc(dev, 128 * 1024);
|
||||
if (obj == NULL) {
|
||||
DRM_ERROR("Failed to allocate ringbuffer\n");
|
||||
i915_gem_cleanup_hws(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
obj_priv = obj->driver_private;
|
||||
@@ -3101,6 +3189,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
|
||||
ret = i915_gem_object_pin(obj, 4096);
|
||||
if (ret != 0) {
|
||||
drm_gem_object_unreference(obj);
|
||||
i915_gem_cleanup_hws(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3118,7 +3207,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
|
||||
if (ring->map.handle == NULL) {
|
||||
DRM_ERROR("Failed to map ringbuffer.\n");
|
||||
memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
|
||||
i915_gem_object_unpin(obj);
|
||||
drm_gem_object_unreference(obj);
|
||||
i915_gem_cleanup_hws(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
ring->ring_obj = obj;
|
||||
@@ -3198,20 +3289,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)
|
||||
dev_priv->ring.ring_obj = NULL;
|
||||
memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
|
||||
|
||||
if (dev_priv->hws_obj != NULL) {
|
||||
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);
|
||||
}
|
||||
i915_gem_cleanup_hws(dev);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -3229,10 +3307,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
|
||||
dev_priv->mm.wedged = 0;
|
||||
}
|
||||
|
||||
dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base,
|
||||
dev->agp->agp_info.aper_size
|
||||
* 1024 * 1024);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
dev_priv->mm.suspended = 0;
|
||||
|
||||
@@ -3255,7 +3329,6 @@ int
|
||||
i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
@@ -3264,7 +3337,6 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
|
||||
ret = i915_gem_idle(dev);
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
io_mapping_free(dev_priv->mm.gtt_mapping);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3273,6 +3345,9 @@ i915_gem_lastclose(struct drm_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return;
|
||||
|
||||
ret = i915_gem_idle(dev);
|
||||
if (ret)
|
||||
DRM_ERROR("failed to idle hardware: %d\n", ret);
|
||||
@@ -3294,7 +3369,7 @@ i915_gem_load(struct drm_device *dev)
|
||||
/* Old X drivers will take 0-2 for front, back, depth buffers */
|
||||
dev_priv->fence_reg_start = 3;
|
||||
|
||||
if (IS_I965G(dev))
|
||||
if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
|
||||
dev_priv->num_fence_regs = 16;
|
||||
else
|
||||
dev_priv->num_fence_regs = 8;
|
||||
|
@@ -173,6 +173,73 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
||||
dev_priv->mm.bit_6_swizzle_y = swizzle_y;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the size of the fence for a tiled object of the given size.
|
||||
*/
|
||||
static int
|
||||
i915_get_fence_size(struct drm_device *dev, int size)
|
||||
{
|
||||
int i;
|
||||
int start;
|
||||
|
||||
if (IS_I965G(dev)) {
|
||||
/* The 965 can have fences at any page boundary. */
|
||||
return ALIGN(size, 4096);
|
||||
} else {
|
||||
/* Align the size to a power of two greater than the smallest
|
||||
* fence size.
|
||||
*/
|
||||
if (IS_I9XX(dev))
|
||||
start = 1024 * 1024;
|
||||
else
|
||||
start = 512 * 1024;
|
||||
|
||||
for (i = start; i < size; i <<= 1)
|
||||
;
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check pitch constriants for all chips & tiling formats */
|
||||
static bool
|
||||
i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
||||
{
|
||||
int tile_width;
|
||||
|
||||
/* Linear is always fine */
|
||||
if (tiling_mode == I915_TILING_NONE)
|
||||
return true;
|
||||
|
||||
if (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))
|
||||
tile_width = 128;
|
||||
else
|
||||
tile_width = 512;
|
||||
|
||||
/* 965+ just needs multiples of tile width */
|
||||
if (IS_I965G(dev)) {
|
||||
if (stride & (tile_width - 1))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Pre-965 needs power of two tile widths */
|
||||
if (stride < tile_width)
|
||||
return false;
|
||||
|
||||
if (stride & (stride - 1))
|
||||
return false;
|
||||
|
||||
/* We don't handle the aperture area covered by the fence being bigger
|
||||
* than the object size.
|
||||
*/
|
||||
if (i915_get_fence_size(dev, size) != size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tiling mode of an object, returning the required swizzling of
|
||||
* bit 6 of addresses in the object.
|
||||
@@ -191,6 +258,11 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
||||
return -EINVAL;
|
||||
obj_priv = obj->driver_private;
|
||||
|
||||
if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) {
|
||||
drm_gem_object_unreference(obj);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
if (args->tiling_mode == I915_TILING_NONE) {
|
||||
@@ -207,12 +279,28 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
||||
args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
|
||||
}
|
||||
}
|
||||
obj_priv->tiling_mode = args->tiling_mode;
|
||||
if (args->tiling_mode != obj_priv->tiling_mode) {
|
||||
int ret;
|
||||
|
||||
/* Unbind the object, as switching tiling means we're
|
||||
* switching the cache organization due to fencing, probably.
|
||||
*/
|
||||
ret = i915_gem_object_unbind(obj);
|
||||
if (ret != 0) {
|
||||
WARN(ret != -ERESTARTSYS,
|
||||
"failed to unbind object for tiling switch");
|
||||
args->tiling_mode = obj_priv->tiling_mode;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
drm_gem_object_unreference(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
obj_priv->tiling_mode = args->tiling_mode;
|
||||
}
|
||||
obj_priv->stride = args->stride;
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -251,9 +339,8 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
|
||||
DRM_ERROR("unknown tiling mode\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -174,6 +174,19 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
|
||||
return count;
|
||||
}
|
||||
|
||||
u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
|
||||
|
||||
if (!i915_pipe_enabled(dev, pipe)) {
|
||||
DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return I915_READ(reg);
|
||||
}
|
||||
|
||||
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
|
@@ -186,12 +186,12 @@
|
||||
#define FENCE_REG_830_0 0x2000
|
||||
#define I830_FENCE_START_MASK 0x07f80000
|
||||
#define I830_FENCE_TILING_Y_SHIFT 12
|
||||
#define I830_FENCE_SIZE_BITS(size) ((get_order(size >> 19) - 1) << 8)
|
||||
#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8)
|
||||
#define I830_FENCE_PITCH_SHIFT 4
|
||||
#define I830_FENCE_REG_VALID (1<<0)
|
||||
|
||||
#define I915_FENCE_START_MASK 0x0ff00000
|
||||
#define I915_FENCE_SIZE_BITS(size) ((get_order(size >> 20) - 1) << 8)
|
||||
#define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8)
|
||||
|
||||
#define FENCE_REG_965_0 0x03000
|
||||
#define I965_FENCE_PITCH_SHIFT 2
|
||||
@@ -1371,6 +1371,9 @@
|
||||
#define PIPE_FRAME_LOW_SHIFT 24
|
||||
#define PIPE_PIXEL_MASK 0x00ffffff
|
||||
#define PIPE_PIXEL_SHIFT 0
|
||||
/* GM45+ just has to be different */
|
||||
#define PIPEA_FRMCOUNT_GM45 0x70040
|
||||
#define PIPEA_FLIPCOUNT_GM45 0x70044
|
||||
|
||||
/* Cursor A & B regs */
|
||||
#define CURACNTR 0x70080
|
||||
@@ -1439,6 +1442,9 @@
|
||||
#define PIPEBSTAT 0x71024
|
||||
#define PIPEBFRAMEHIGH 0x71040
|
||||
#define PIPEBFRAMEPIXEL 0x71044
|
||||
#define PIPEB_FRMCOUNT_GM45 0x71040
|
||||
#define PIPEB_FLIPCOUNT_GM45 0x71044
|
||||
|
||||
|
||||
/* Display B control */
|
||||
#define DSPBCNTR 0x71180
|
||||
|
@@ -135,6 +135,14 @@ parse_general_features(struct drm_i915_private *dev_priv,
|
||||
if (general) {
|
||||
dev_priv->int_tv_support = general->int_tv_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 {
|
||||
#define I9XX_DOT_MAX 400000
|
||||
#define I9XX_VCO_MIN 1400000
|
||||
#define I9XX_VCO_MAX 2800000
|
||||
#define I9XX_N_MIN 3
|
||||
#define I9XX_N_MAX 8
|
||||
#define I9XX_N_MIN 1
|
||||
#define I9XX_N_MAX 6
|
||||
#define I9XX_M_MIN 70
|
||||
#define I9XX_M_MAX 120
|
||||
#define I9XX_M1_MIN 10
|
||||
#define I9XX_M1_MAX 20
|
||||
#define I9XX_M1_MAX 22
|
||||
#define I9XX_M2_MIN 5
|
||||
#define I9XX_M2_MAX 9
|
||||
#define I9XX_P_SDVO_DAC_MIN 5
|
||||
@@ -189,9 +189,7 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
|
||||
return limit;
|
||||
}
|
||||
|
||||
/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
|
||||
|
||||
static void i8xx_clock(int refclk, intel_clock_t *clock)
|
||||
static void intel_clock(int refclk, intel_clock_t *clock)
|
||||
{
|
||||
clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
|
||||
clock->p = clock->p1 * clock->p2;
|
||||
@@ -199,25 +197,6 @@ static void i8xx_clock(int refclk, intel_clock_t *clock)
|
||||
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->p = clock->p1 * clock->p2;
|
||||
clock->vco = refclk * clock->m / (clock->n + 2);
|
||||
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
|
||||
*/
|
||||
@@ -238,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
|
||||
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
|
||||
* the given connectors.
|
||||
@@ -318,7 +297,7 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target,
|
||||
clock.p1 <= limit->p1.max; clock.p1++) {
|
||||
int this_err;
|
||||
|
||||
intel_clock(dev, refclk, &clock);
|
||||
intel_clock(refclk, &clock);
|
||||
|
||||
if (!intel_PLL_is_valid(crtc, &clock))
|
||||
continue;
|
||||
@@ -343,7 +322,7 @@ intel_wait_for_vblank(struct drm_device *dev)
|
||||
udelay(20000);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
@@ -361,11 +340,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
|
||||
int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
|
||||
u32 dspcntr, alignment;
|
||||
int ret;
|
||||
|
||||
/* no fb bound */
|
||||
if (!crtc->fb) {
|
||||
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);
|
||||
@@ -377,28 +366,30 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
alignment = 64 * 1024;
|
||||
break;
|
||||
case I915_TILING_X:
|
||||
if (IS_I9XX(dev))
|
||||
alignment = 1024 * 1024;
|
||||
else
|
||||
alignment = 512 * 1024;
|
||||
/* pin() will align the object as required by fence */
|
||||
alignment = 0;
|
||||
break;
|
||||
case I915_TILING_Y:
|
||||
/* FIXME: Is this true? */
|
||||
DRM_ERROR("Y tiled not allowed for scan out buffers\n");
|
||||
return;
|
||||
return -EINVAL;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (i915_gem_object_pin(intel_fb->obj, alignment))
|
||||
return;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ret = i915_gem_object_pin(intel_fb->obj, alignment);
|
||||
if (ret != 0) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
|
||||
|
||||
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);
|
||||
/* 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,
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
|
||||
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);
|
||||
I915_WRITE(dspstride, crtc->fb->pitch);
|
||||
if (IS_I965G(dev)) {
|
||||
I915_WRITE(dspbase, Offset);
|
||||
I915_READ(dspbase);
|
||||
@@ -440,27 +437,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
intel_fb = to_intel_framebuffer(old_fb);
|
||||
i915_gem_object_unpin(intel_fb->obj);
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
if (!dev->primary->master)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
master_priv = dev->primary->master->driver_priv;
|
||||
if (!master_priv->sarea_priv)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
master_priv->sarea_priv->pipeA_x = x;
|
||||
master_priv->sarea_priv->pipeA_y = y;
|
||||
break;
|
||||
case 1:
|
||||
if (pipe) {
|
||||
master_priv->sarea_priv->pipeB_x = x;
|
||||
master_priv->sarea_priv->pipeB_y = y;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
|
||||
break;
|
||||
} else {
|
||||
master_priv->sarea_priv->pipeA_x = x;
|
||||
master_priv->sarea_priv->pipeA_y = y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -708,11 +702,11 @@ static int intel_panel_fitter_pipe (struct drm_device *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode,
|
||||
int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode,
|
||||
int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
@@ -732,13 +726,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
|
||||
int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
|
||||
int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
|
||||
int refclk;
|
||||
int refclk, num_outputs = 0;
|
||||
intel_clock_t clock;
|
||||
u32 dpll = 0, fp = 0, dspcntr, pipeconf;
|
||||
bool ok, is_sdvo = false, is_dvo = false;
|
||||
bool is_crt = false, is_lvds = false, is_tv = false;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_connector *connector;
|
||||
int ret;
|
||||
|
||||
drm_vblank_pre_modeset(dev, pipe);
|
||||
|
||||
@@ -755,6 +750,8 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
case INTEL_OUTPUT_SDVO:
|
||||
case INTEL_OUTPUT_HDMI:
|
||||
is_sdvo = true;
|
||||
if (intel_output->needs_tv_clock)
|
||||
is_tv = true;
|
||||
break;
|
||||
case INTEL_OUTPUT_DVO:
|
||||
is_dvo = true;
|
||||
@@ -766,9 +763,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
is_crt = true;
|
||||
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;
|
||||
} else {
|
||||
refclk = 48000;
|
||||
@@ -777,7 +779,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock);
|
||||
if (!ok) {
|
||||
DRM_ERROR("Couldn't find PLL settings for mode!\n");
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
|
||||
@@ -827,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 */
|
||||
/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
|
||||
/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
|
||||
dpll |= 3;
|
||||
}
|
||||
else if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2)
|
||||
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
|
||||
else
|
||||
dpll |= PLL_REF_INPUT_DREFCLK;
|
||||
|
||||
@@ -948,9 +953,13 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
I915_WRITE(dspcntr_reg, dspcntr);
|
||||
|
||||
/* 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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Loads the palette/gamma unit for the CRTC with the prepared values */
|
||||
@@ -999,6 +1008,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
temp = CURSOR_MODE_DISABLE;
|
||||
addr = 0;
|
||||
bo = NULL;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
@@ -1021,18 +1031,19 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
}
|
||||
|
||||
/* we only need to pin inside GTT if cursor is non-phy */
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (!dev_priv->cursor_needs_physical) {
|
||||
ret = i915_gem_object_pin(bo, PAGE_SIZE);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to pin cursor bo\n");
|
||||
goto fail;
|
||||
goto fail_locked;
|
||||
}
|
||||
addr = obj_priv->gtt_offset;
|
||||
} else {
|
||||
ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to attach phys object\n");
|
||||
goto fail;
|
||||
goto fail_locked;
|
||||
}
|
||||
addr = obj_priv->phys_obj->handle->busaddr;
|
||||
}
|
||||
@@ -1052,10 +1063,9 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
|
||||
} else
|
||||
i915_gem_object_unpin(intel_crtc->cursor_bo);
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
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_bo = bo;
|
||||
@@ -1063,6 +1073,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
return 0;
|
||||
fail:
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
fail_locked:
|
||||
drm_gem_object_unreference(bo);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
@@ -1290,7 +1301,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
}
|
||||
|
||||
/* XXX: Handle the 100Mhz refclk */
|
||||
i9xx_clock(96000, &clock);
|
||||
intel_clock(96000, &clock);
|
||||
} else {
|
||||
bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
|
||||
|
||||
@@ -1302,9 +1313,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
if ((dpll & PLL_REF_INPUT_MASK) ==
|
||||
PLLB_REF_INPUT_SPREADSPECTRUMIN) {
|
||||
/* XXX: might not be 66MHz */
|
||||
i8xx_clock(66000, &clock);
|
||||
intel_clock(66000, &clock);
|
||||
} else
|
||||
i8xx_clock(48000, &clock);
|
||||
intel_clock(48000, &clock);
|
||||
} else {
|
||||
if (dpll & PLL_P1_DIVIDE_BY_TWO)
|
||||
clock.p1 = 2;
|
||||
@@ -1317,7 +1328,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
else
|
||||
clock.p2 = 2;
|
||||
|
||||
i8xx_clock(48000, &clock);
|
||||
intel_clock(48000, &clock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1452,6 +1463,7 @@ static int intel_connector_clones(struct drm_device *dev, int type_mask)
|
||||
|
||||
static void intel_setup_outputs(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
|
||||
intel_crt_init(dev);
|
||||
@@ -1463,13 +1475,16 @@ static void intel_setup_outputs(struct drm_device *dev)
|
||||
if (IS_I9XX(dev)) {
|
||||
int found;
|
||||
|
||||
found = intel_sdvo_init(dev, SDVOB);
|
||||
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
|
||||
intel_hdmi_init(dev, SDVOB);
|
||||
|
||||
found = intel_sdvo_init(dev, SDVOC);
|
||||
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
|
||||
intel_hdmi_init(dev, SDVOC);
|
||||
if (I915_READ(SDVOB) & SDVO_DETECTED) {
|
||||
found = intel_sdvo_init(dev, SDVOB);
|
||||
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
|
||||
intel_hdmi_init(dev, SDVOB);
|
||||
}
|
||||
if (!IS_G4X(dev) || (I915_READ(SDVOB) & SDVO_DETECTED)) {
|
||||
found = intel_sdvo_init(dev, SDVOC);
|
||||
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
|
||||
intel_hdmi_init(dev, SDVOC);
|
||||
}
|
||||
} else
|
||||
intel_dvo_init(dev);
|
||||
|
||||
@@ -1592,7 +1607,9 @@ intel_user_framebuffer_create(struct drm_device *dev,
|
||||
|
||||
ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj);
|
||||
if (ret) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@@ -82,6 +82,7 @@ struct intel_output {
|
||||
struct intel_i2c_chan *i2c_bus; /* for control functions */
|
||||
struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */
|
||||
bool load_detect_temp;
|
||||
bool needs_tv_clock;
|
||||
void *dev_priv;
|
||||
};
|
||||
|
||||
|
@@ -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);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to allocate fb.\n");
|
||||
goto out_unref;
|
||||
goto out_unpin;
|
||||
}
|
||||
|
||||
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,
|
||||
info = framebuffer_alloc(sizeof(struct intelfb_par), device);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unref;
|
||||
goto out_unpin;
|
||||
}
|
||||
|
||||
par = info->par;
|
||||
@@ -513,7 +513,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
|
||||
size);
|
||||
if (!info->screen_base) {
|
||||
ret = -ENOSPC;
|
||||
goto out_unref;
|
||||
goto out_unpin;
|
||||
}
|
||||
info->screen_size = size;
|
||||
|
||||
@@ -608,6 +608,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return 0;
|
||||
|
||||
out_unpin:
|
||||
i915_gem_object_unpin(fbo);
|
||||
out_unref:
|
||||
drm_gem_object_unreference(fbo);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
@@ -27,6 +27,7 @@
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/i2c.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
@@ -311,10 +312,8 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
|
||||
if (dev_priv->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -405,6 +404,16 @@ void intel_lvds_init(struct drm_device *dev)
|
||||
u32 lvds;
|
||||
int pipe;
|
||||
|
||||
/* Blacklist machines that we know falsely report LVDS. */
|
||||
/* FIXME: add a check for the Aopen Mini PC */
|
||||
|
||||
/* Apple Mac Mini Core Duo and Mac Mini Core 2 Duo */
|
||||
if(dmi_match(DMI_PRODUCT_NAME, "Macmini1,1") ||
|
||||
dmi_match(DMI_PRODUCT_NAME, "Macmini2,1")) {
|
||||
DRM_DEBUG("Skipping LVDS initialization for Apple Mac Mini\n");
|
||||
return;
|
||||
}
|
||||
|
||||
intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
|
||||
if (!intel_output) {
|
||||
return;
|
||||
@@ -458,7 +467,7 @@ void intel_lvds_init(struct drm_device *dev)
|
||||
dev_priv->panel_fixed_mode =
|
||||
drm_mode_duplicate(dev, scan);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
goto out; /* FIXME: check for quirks */
|
||||
goto out;
|
||||
}
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
}
|
||||
@@ -472,8 +481,6 @@ void intel_lvds_init(struct drm_device *dev)
|
||||
if (dev_priv->panel_fixed_mode) {
|
||||
dev_priv->panel_fixed_mode->type |=
|
||||
DRM_MODE_TYPE_PREFERRED;
|
||||
drm_mode_probed_add(connector,
|
||||
dev_priv->panel_fixed_mode);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -492,7 +499,7 @@ void intel_lvds_init(struct drm_device *dev)
|
||||
if (dev_priv->panel_fixed_mode) {
|
||||
dev_priv->panel_fixed_mode->type |=
|
||||
DRM_MODE_TYPE_PREFERRED;
|
||||
goto out; /* FIXME: check for quirks */
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,38 +507,6 @@ void intel_lvds_init(struct drm_device *dev)
|
||||
if (!dev_priv->panel_fixed_mode)
|
||||
goto failed;
|
||||
|
||||
/* FIXME: detect aopen & mac mini type stuff automatically? */
|
||||
/*
|
||||
* Blacklist machines with BIOSes that list an LVDS panel without
|
||||
* actually having one.
|
||||
*/
|
||||
if (IS_I945GM(dev)) {
|
||||
/* aopen mini pc */
|
||||
if (dev->pdev->subsystem_vendor == 0xa0a0)
|
||||
goto failed;
|
||||
|
||||
if ((dev->pdev->subsystem_vendor == 0x8086) &&
|
||||
(dev->pdev->subsystem_device == 0x7270)) {
|
||||
/* It's a Mac Mini or Macbook Pro.
|
||||
*
|
||||
* Apple hardware is out to get us. The macbook pro
|
||||
* has a real LVDS panel, but the mac mini does not,
|
||||
* and they have the same device IDs. We'll
|
||||
* distinguish by panel size, on the assumption
|
||||
* that Apple isn't about to make any machines with an
|
||||
* 800x600 display.
|
||||
*/
|
||||
|
||||
if (dev_priv->panel_fixed_mode != NULL &&
|
||||
dev_priv->panel_fixed_mode->hdisplay == 800 &&
|
||||
dev_priv->panel_fixed_mode->vdisplay == 600) {
|
||||
DRM_DEBUG("Suspected Mac Mini, ignoring the LVDS\n");
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
out:
|
||||
drm_sysfs_connector_add(connector);
|
||||
return;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -173,6 +173,9 @@ struct intel_sdvo_get_trained_inputs_response {
|
||||
* Returns two struct intel_sdvo_output_flags structures.
|
||||
*/
|
||||
#define SDVO_CMD_GET_IN_OUT_MAP 0x06
|
||||
struct intel_sdvo_in_out_map {
|
||||
u16 in0, in1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the current mapping of SDVO inputs to outputs on the device.
|
||||
@@ -206,7 +209,8 @@ struct intel_sdvo_get_trained_inputs_response {
|
||||
struct intel_sdvo_get_interrupt_event_source_response {
|
||||
u16 interrupt_status;
|
||||
unsigned int ambient_light_interrupt:1;
|
||||
unsigned int pad:7;
|
||||
unsigned int hdmi_audio_encrypt_change:1;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
@@ -305,23 +309,411 @@ struct intel_sdvo_set_target_input_args {
|
||||
# define SDVO_CLOCK_RATE_MULT_4X (1 << 3)
|
||||
|
||||
#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27
|
||||
/** 5 bytes of bit flags for TV formats shared by all TV format functions */
|
||||
struct intel_sdvo_tv_format {
|
||||
unsigned int ntsc_m:1;
|
||||
unsigned int ntsc_j:1;
|
||||
unsigned int ntsc_443:1;
|
||||
unsigned int pal_b:1;
|
||||
unsigned int pal_d:1;
|
||||
unsigned int pal_g:1;
|
||||
unsigned int pal_h:1;
|
||||
unsigned int pal_i:1;
|
||||
|
||||
unsigned int pal_m:1;
|
||||
unsigned int pal_n:1;
|
||||
unsigned int pal_nc:1;
|
||||
unsigned int pal_60:1;
|
||||
unsigned int secam_b:1;
|
||||
unsigned int secam_d:1;
|
||||
unsigned int secam_g:1;
|
||||
unsigned int secam_k:1;
|
||||
|
||||
unsigned int secam_k1:1;
|
||||
unsigned int secam_l:1;
|
||||
unsigned int secam_60:1;
|
||||
unsigned int hdtv_std_smpte_240m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_240m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_260m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_260m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080i_50:1;
|
||||
|
||||
unsigned int hdtv_std_smpte_274m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_23:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_24:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_25:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_29:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_30:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_50:1;
|
||||
|
||||
unsigned int hdtv_std_smpte_274m_1080p_59:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_60:1;
|
||||
unsigned int hdtv_std_smpte_295m_1080i_50:1;
|
||||
unsigned int hdtv_std_smpte_295m_1080p_50:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_59:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_60:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_50:1;
|
||||
unsigned int hdtv_std_smpte_293m_480p_59:1;
|
||||
|
||||
unsigned int hdtv_std_smpte_170m_480i_59:1;
|
||||
unsigned int hdtv_std_iturbt601_576i_50:1;
|
||||
unsigned int hdtv_std_iturbt601_576p_50:1;
|
||||
unsigned int hdtv_std_eia_7702a_480i_60:1;
|
||||
unsigned int hdtv_std_eia_7702a_480p_60:1;
|
||||
unsigned int pad:3;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define SDVO_CMD_GET_TV_FORMAT 0x28
|
||||
|
||||
#define SDVO_CMD_SET_TV_FORMAT 0x29
|
||||
|
||||
/** Returns the resolutiosn that can be used with the given TV format */
|
||||
#define SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT 0x83
|
||||
struct intel_sdvo_sdtv_resolution_request {
|
||||
unsigned int ntsc_m:1;
|
||||
unsigned int ntsc_j:1;
|
||||
unsigned int ntsc_443:1;
|
||||
unsigned int pal_b:1;
|
||||
unsigned int pal_d:1;
|
||||
unsigned int pal_g:1;
|
||||
unsigned int pal_h:1;
|
||||
unsigned int pal_i:1;
|
||||
|
||||
unsigned int pal_m:1;
|
||||
unsigned int pal_n:1;
|
||||
unsigned int pal_nc:1;
|
||||
unsigned int pal_60:1;
|
||||
unsigned int secam_b:1;
|
||||
unsigned int secam_d:1;
|
||||
unsigned int secam_g:1;
|
||||
unsigned int secam_k:1;
|
||||
|
||||
unsigned int secam_k1:1;
|
||||
unsigned int secam_l:1;
|
||||
unsigned int secam_60:1;
|
||||
unsigned int pad:5;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct intel_sdvo_sdtv_resolution_reply {
|
||||
unsigned int res_320x200:1;
|
||||
unsigned int res_320x240:1;
|
||||
unsigned int res_400x300:1;
|
||||
unsigned int res_640x350:1;
|
||||
unsigned int res_640x400:1;
|
||||
unsigned int res_640x480:1;
|
||||
unsigned int res_704x480:1;
|
||||
unsigned int res_704x576:1;
|
||||
|
||||
unsigned int res_720x350:1;
|
||||
unsigned int res_720x400:1;
|
||||
unsigned int res_720x480:1;
|
||||
unsigned int res_720x540:1;
|
||||
unsigned int res_720x576:1;
|
||||
unsigned int res_768x576:1;
|
||||
unsigned int res_800x600:1;
|
||||
unsigned int res_832x624:1;
|
||||
|
||||
unsigned int res_920x766:1;
|
||||
unsigned int res_1024x768:1;
|
||||
unsigned int res_1280x1024:1;
|
||||
unsigned int pad:5;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Get supported resolution with squire pixel aspect ratio that can be
|
||||
scaled for the requested HDTV format */
|
||||
#define SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT 0x85
|
||||
|
||||
struct intel_sdvo_hdtv_resolution_request {
|
||||
unsigned int hdtv_std_smpte_240m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_240m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_260m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_260m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080i_50:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_23:1;
|
||||
|
||||
unsigned int hdtv_std_smpte_274m_1080p_24:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_25:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_29:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_30:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_50:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_59:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_60:1;
|
||||
unsigned int hdtv_std_smpte_295m_1080i_50:1;
|
||||
|
||||
unsigned int hdtv_std_smpte_295m_1080p_50:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_59:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_60:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_50:1;
|
||||
unsigned int hdtv_std_smpte_293m_480p_59:1;
|
||||
unsigned int hdtv_std_smpte_170m_480i_59:1;
|
||||
unsigned int hdtv_std_iturbt601_576i_50:1;
|
||||
unsigned int hdtv_std_iturbt601_576p_50:1;
|
||||
|
||||
unsigned int hdtv_std_eia_7702a_480i_60:1;
|
||||
unsigned int hdtv_std_eia_7702a_480p_60:1;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct intel_sdvo_hdtv_resolution_reply {
|
||||
unsigned int res_640x480:1;
|
||||
unsigned int res_800x600:1;
|
||||
unsigned int res_1024x768:1;
|
||||
unsigned int res_1280x960:1;
|
||||
unsigned int res_1400x1050:1;
|
||||
unsigned int res_1600x1200:1;
|
||||
unsigned int res_1920x1440:1;
|
||||
unsigned int res_2048x1536:1;
|
||||
|
||||
unsigned int res_2560x1920:1;
|
||||
unsigned int res_3200x2400:1;
|
||||
unsigned int res_3840x2880:1;
|
||||
unsigned int pad1:5;
|
||||
|
||||
unsigned int res_848x480:1;
|
||||
unsigned int res_1064x600:1;
|
||||
unsigned int res_1280x720:1;
|
||||
unsigned int res_1360x768:1;
|
||||
unsigned int res_1704x960:1;
|
||||
unsigned int res_1864x1050:1;
|
||||
unsigned int res_1920x1080:1;
|
||||
unsigned int res_2128x1200:1;
|
||||
|
||||
unsigned int res_2560x1400:1;
|
||||
unsigned int res_2728x1536:1;
|
||||
unsigned int res_3408x1920:1;
|
||||
unsigned int res_4264x2400:1;
|
||||
unsigned int res_5120x2880:1;
|
||||
unsigned int pad2:3;
|
||||
|
||||
unsigned int res_768x480:1;
|
||||
unsigned int res_960x600:1;
|
||||
unsigned int res_1152x720:1;
|
||||
unsigned int res_1124x768:1;
|
||||
unsigned int res_1536x960:1;
|
||||
unsigned int res_1680x1050:1;
|
||||
unsigned int res_1728x1080:1;
|
||||
unsigned int res_1920x1200:1;
|
||||
|
||||
unsigned int res_2304x1440:1;
|
||||
unsigned int res_2456x1536:1;
|
||||
unsigned int res_3072x1920:1;
|
||||
unsigned int res_3840x2400:1;
|
||||
unsigned int res_4608x2880:1;
|
||||
unsigned int pad3:3;
|
||||
|
||||
unsigned int res_1280x1024:1;
|
||||
unsigned int pad4:7;
|
||||
|
||||
unsigned int res_1280x768:1;
|
||||
unsigned int pad5:7;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Get supported power state returns info for encoder and monitor, rely on
|
||||
last SetTargetInput and SetTargetOutput calls */
|
||||
#define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a
|
||||
/* Get power state returns info for encoder and monitor, rely on last
|
||||
SetTargetInput and SetTargetOutput calls */
|
||||
#define SDVO_CMD_GET_POWER_STATE 0x2b
|
||||
#define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b
|
||||
#define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c
|
||||
# define SDVO_ENCODER_STATE_ON (1 << 0)
|
||||
# define SDVO_ENCODER_STATE_STANDBY (1 << 1)
|
||||
# define SDVO_ENCODER_STATE_SUSPEND (1 << 2)
|
||||
# define SDVO_ENCODER_STATE_OFF (1 << 3)
|
||||
# define SDVO_MONITOR_STATE_ON (1 << 4)
|
||||
# define SDVO_MONITOR_STATE_STANDBY (1 << 5)
|
||||
# define SDVO_MONITOR_STATE_SUSPEND (1 << 6)
|
||||
# define SDVO_MONITOR_STATE_OFF (1 << 7)
|
||||
|
||||
#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93
|
||||
#define SDVO_CMD_GET_MAX_PANEL_POWER_SEQUENCING 0x2d
|
||||
#define SDVO_CMD_GET_PANEL_POWER_SEQUENCING 0x2e
|
||||
#define SDVO_CMD_SET_PANEL_POWER_SEQUENCING 0x2f
|
||||
/**
|
||||
* The panel power sequencing parameters are in units of milliseconds.
|
||||
* The high fields are bits 8:9 of the 10-bit values.
|
||||
*/
|
||||
struct sdvo_panel_power_sequencing {
|
||||
u8 t0;
|
||||
u8 t1;
|
||||
u8 t2;
|
||||
u8 t3;
|
||||
u8 t4;
|
||||
|
||||
unsigned int t0_high:2;
|
||||
unsigned int t1_high:2;
|
||||
unsigned int t2_high:2;
|
||||
unsigned int t3_high:2;
|
||||
|
||||
unsigned int t4_high:2;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL 0x30
|
||||
struct sdvo_max_backlight_reply {
|
||||
u8 max_value;
|
||||
u8 default_value;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define SDVO_CMD_GET_BACKLIGHT_LEVEL 0x31
|
||||
#define SDVO_CMD_SET_BACKLIGHT_LEVEL 0x32
|
||||
|
||||
#define SDVO_CMD_GET_AMBIENT_LIGHT 0x33
|
||||
struct sdvo_get_ambient_light_reply {
|
||||
u16 trip_low;
|
||||
u16 trip_high;
|
||||
u16 value;
|
||||
} __attribute__((packed));
|
||||
#define SDVO_CMD_SET_AMBIENT_LIGHT 0x34
|
||||
struct sdvo_set_ambient_light_reply {
|
||||
u16 trip_low;
|
||||
u16 trip_high;
|
||||
unsigned int enable:1;
|
||||
unsigned int pad:7;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Set display power state */
|
||||
#define SDVO_CMD_SET_DISPLAY_POWER_STATE 0x7d
|
||||
# define SDVO_DISPLAY_STATE_ON (1 << 0)
|
||||
# define SDVO_DISPLAY_STATE_STANDBY (1 << 1)
|
||||
# define SDVO_DISPLAY_STATE_SUSPEND (1 << 2)
|
||||
# define SDVO_DISPLAY_STATE_OFF (1 << 3)
|
||||
|
||||
#define SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS 0x84
|
||||
struct intel_sdvo_enhancements_reply {
|
||||
unsigned int flicker_filter:1;
|
||||
unsigned int flicker_filter_adaptive:1;
|
||||
unsigned int flicker_filter_2d:1;
|
||||
unsigned int saturation:1;
|
||||
unsigned int hue:1;
|
||||
unsigned int brightness:1;
|
||||
unsigned int contrast:1;
|
||||
unsigned int overscan_h:1;
|
||||
|
||||
unsigned int overscan_v:1;
|
||||
unsigned int position_h:1;
|
||||
unsigned int position_v:1;
|
||||
unsigned int sharpness:1;
|
||||
unsigned int dot_crawl:1;
|
||||
unsigned int dither:1;
|
||||
unsigned int max_tv_chroma_filter:1;
|
||||
unsigned int max_tv_luma_filter:1;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Picture enhancement limits below are dependent on the current TV format,
|
||||
* and thus need to be queried and set after it.
|
||||
*/
|
||||
#define SDVO_CMD_GET_MAX_FLICKER_FITER 0x4d
|
||||
#define SDVO_CMD_GET_MAX_ADAPTIVE_FLICKER_FITER 0x7b
|
||||
#define SDVO_CMD_GET_MAX_2D_FLICKER_FITER 0x52
|
||||
#define SDVO_CMD_GET_MAX_SATURATION 0x55
|
||||
#define SDVO_CMD_GET_MAX_HUE 0x58
|
||||
#define SDVO_CMD_GET_MAX_BRIGHTNESS 0x5b
|
||||
#define SDVO_CMD_GET_MAX_CONTRAST 0x5e
|
||||
#define SDVO_CMD_GET_MAX_OVERSCAN_H 0x61
|
||||
#define SDVO_CMD_GET_MAX_OVERSCAN_V 0x64
|
||||
#define SDVO_CMD_GET_MAX_POSITION_H 0x67
|
||||
#define SDVO_CMD_GET_MAX_POSITION_V 0x6a
|
||||
#define SDVO_CMD_GET_MAX_SHARPNESS_V 0x6d
|
||||
#define SDVO_CMD_GET_MAX_TV_CHROMA 0x74
|
||||
#define SDVO_CMD_GET_MAX_TV_LUMA 0x77
|
||||
struct intel_sdvo_enhancement_limits_reply {
|
||||
u16 max_value;
|
||||
u16 default_value;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define SDVO_CMD_GET_LVDS_PANEL_INFORMATION 0x7f
|
||||
#define SDVO_CMD_SET_LVDS_PANEL_INFORMATION 0x80
|
||||
# define SDVO_LVDS_COLOR_DEPTH_18 (0 << 0)
|
||||
# define SDVO_LVDS_COLOR_DEPTH_24 (1 << 0)
|
||||
# define SDVO_LVDS_CONNECTOR_SPWG (0 << 2)
|
||||
# define SDVO_LVDS_CONNECTOR_OPENLDI (1 << 2)
|
||||
# define SDVO_LVDS_SINGLE_CHANNEL (0 << 4)
|
||||
# define SDVO_LVDS_DUAL_CHANNEL (1 << 4)
|
||||
|
||||
#define SDVO_CMD_GET_FLICKER_FILTER 0x4e
|
||||
#define SDVO_CMD_SET_FLICKER_FILTER 0x4f
|
||||
#define SDVO_CMD_GET_ADAPTIVE_FLICKER_FITER 0x50
|
||||
#define SDVO_CMD_SET_ADAPTIVE_FLICKER_FITER 0x51
|
||||
#define SDVO_CMD_GET_2D_FLICKER_FITER 0x53
|
||||
#define SDVO_CMD_SET_2D_FLICKER_FITER 0x54
|
||||
#define SDVO_CMD_GET_SATURATION 0x56
|
||||
#define SDVO_CMD_SET_SATURATION 0x57
|
||||
#define SDVO_CMD_GET_HUE 0x59
|
||||
#define SDVO_CMD_SET_HUE 0x5a
|
||||
#define SDVO_CMD_GET_BRIGHTNESS 0x5c
|
||||
#define SDVO_CMD_SET_BRIGHTNESS 0x5d
|
||||
#define SDVO_CMD_GET_CONTRAST 0x5f
|
||||
#define SDVO_CMD_SET_CONTRAST 0x60
|
||||
#define SDVO_CMD_GET_OVERSCAN_H 0x62
|
||||
#define SDVO_CMD_SET_OVERSCAN_H 0x63
|
||||
#define SDVO_CMD_GET_OVERSCAN_V 0x65
|
||||
#define SDVO_CMD_SET_OVERSCAN_V 0x66
|
||||
#define SDVO_CMD_GET_POSITION_H 0x68
|
||||
#define SDVO_CMD_SET_POSITION_H 0x69
|
||||
#define SDVO_CMD_GET_POSITION_V 0x6b
|
||||
#define SDVO_CMD_SET_POSITION_V 0x6c
|
||||
#define SDVO_CMD_GET_SHARPNESS 0x6e
|
||||
#define SDVO_CMD_SET_SHARPNESS 0x6f
|
||||
#define SDVO_CMD_GET_TV_CHROMA 0x75
|
||||
#define SDVO_CMD_SET_TV_CHROMA 0x76
|
||||
#define SDVO_CMD_GET_TV_LUMA 0x78
|
||||
#define SDVO_CMD_SET_TV_LUMA 0x79
|
||||
struct intel_sdvo_enhancements_arg {
|
||||
u16 value;
|
||||
}__attribute__((packed));
|
||||
|
||||
#define SDVO_CMD_GET_DOT_CRAWL 0x70
|
||||
#define SDVO_CMD_SET_DOT_CRAWL 0x71
|
||||
# define SDVO_DOT_CRAWL_ON (1 << 0)
|
||||
# define SDVO_DOT_CRAWL_DEFAULT_ON (1 << 1)
|
||||
|
||||
#define SDVO_CMD_GET_DITHER 0x72
|
||||
#define SDVO_CMD_SET_DITHER 0x73
|
||||
# define SDVO_DITHER_ON (1 << 0)
|
||||
# define SDVO_DITHER_DEFAULT_ON (1 << 1)
|
||||
|
||||
#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a
|
||||
# define SDVO_CONTROL_BUS_PROM 0x0
|
||||
# define SDVO_CONTROL_BUS_DDC1 0x1
|
||||
# define SDVO_CONTROL_BUS_DDC2 0x2
|
||||
# define SDVO_CONTROL_BUS_DDC3 0x3
|
||||
# define SDVO_CONTROL_BUS_PROM (1 << 0)
|
||||
# define SDVO_CONTROL_BUS_DDC1 (1 << 1)
|
||||
# define SDVO_CONTROL_BUS_DDC2 (1 << 2)
|
||||
# define SDVO_CONTROL_BUS_DDC3 (1 << 3)
|
||||
|
||||
/* HDMI op codes */
|
||||
#define SDVO_CMD_GET_SUPP_ENCODE 0x9d
|
||||
#define SDVO_CMD_GET_ENCODE 0x9e
|
||||
#define SDVO_CMD_SET_ENCODE 0x9f
|
||||
#define SDVO_ENCODE_DVI 0x0
|
||||
#define SDVO_ENCODE_HDMI 0x1
|
||||
#define SDVO_CMD_SET_PIXEL_REPLI 0x8b
|
||||
#define SDVO_CMD_GET_PIXEL_REPLI 0x8c
|
||||
#define SDVO_CMD_GET_COLORIMETRY_CAP 0x8d
|
||||
#define SDVO_CMD_SET_COLORIMETRY 0x8e
|
||||
#define SDVO_COLORIMETRY_RGB256 0x0
|
||||
#define SDVO_COLORIMETRY_RGB220 0x1
|
||||
#define SDVO_COLORIMETRY_YCrCb422 0x3
|
||||
#define SDVO_COLORIMETRY_YCrCb444 0x4
|
||||
#define SDVO_CMD_GET_COLORIMETRY 0x8f
|
||||
#define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90
|
||||
#define SDVO_CMD_SET_AUDIO_STAT 0x91
|
||||
#define SDVO_CMD_GET_AUDIO_STAT 0x92
|
||||
#define SDVO_CMD_SET_HBUF_INDEX 0x93
|
||||
#define SDVO_CMD_GET_HBUF_INDEX 0x94
|
||||
#define SDVO_CMD_GET_HBUF_INFO 0x95
|
||||
#define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96
|
||||
#define SDVO_CMD_GET_HBUF_AV_SPLIT 0x97
|
||||
#define SDVO_CMD_SET_HBUF_DATA 0x98
|
||||
#define SDVO_CMD_GET_HBUF_DATA 0x99
|
||||
#define SDVO_CMD_SET_HBUF_TXRATE 0x9a
|
||||
#define SDVO_CMD_GET_HBUF_TXRATE 0x9b
|
||||
#define SDVO_HBUF_TX_DISABLED (0 << 6)
|
||||
#define SDVO_HBUF_TX_ONCE (2 << 6)
|
||||
#define SDVO_HBUF_TX_VSYNC (3 << 6)
|
||||
#define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c
|
||||
|
||||
struct intel_sdvo_encode{
|
||||
u8 dvi_rev;
|
||||
u8 hdmi_rev;
|
||||
} __attribute__ ((packed));
|
||||
|
@@ -411,7 +411,7 @@ struct tv_mode {
|
||||
* These values account for -1s required.
|
||||
*/
|
||||
|
||||
const static struct tv_mode tv_modes[] = {
|
||||
static const struct tv_mode tv_modes[] = {
|
||||
{
|
||||
.name = "NTSC-M",
|
||||
.clock = 107520,
|
||||
|
@@ -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,
|
||||
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 tmp;
|
||||
|
||||
@@ -677,6 +679,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
|
||||
dev_priv->scratch[2] = 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);
|
||||
|
||||
/* Sync everything up */
|
||||
@@ -1039,9 +1049,9 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
|
||||
|
||||
#if __OS_HAS_AGP
|
||||
if (dev_priv->flags & RADEON_IS_AGP) {
|
||||
drm_core_ioremap(dev_priv->cp_ring, dev);
|
||||
drm_core_ioremap(dev_priv->ring_rptr, dev);
|
||||
drm_core_ioremap(dev->agp_buffer_map, dev);
|
||||
drm_core_ioremap_wc(dev_priv->cp_ring, dev);
|
||||
drm_core_ioremap_wc(dev_priv->ring_rptr, dev);
|
||||
drm_core_ioremap_wc(dev->agp_buffer_map, dev);
|
||||
if (!dev_priv->cp_ring->handle ||
|
||||
!dev_priv->ring_rptr->handle ||
|
||||
!dev->agp_buffer_map->handle) {
|
||||
@@ -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_init_ring_buffer(dev, dev_priv);
|
||||
radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
|
||||
|
||||
dev_priv->last_buf = 0;
|
||||
|
||||
@@ -1281,7 +1291,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev)
|
||||
*
|
||||
* 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;
|
||||
|
||||
@@ -1304,7 +1314,7 @@ static int radeon_do_resume_cp(struct drm_device * dev)
|
||||
}
|
||||
|
||||
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_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
|
||||
*/
|
||||
int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
|
||||
return radeon_do_resume_cp(dev);
|
||||
return radeon_do_resume_cp(dev, file_priv);
|
||||
}
|
||||
|
||||
int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
|
Reference in New Issue
Block a user