summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdrm/xf86drm.c23
-rw-r--r--libdrm/xf86drmMode.c106
-rw-r--r--libdrm/xf86drmMode.h3
-rw-r--r--linux-core/ati_pcigart.c6
-rw-r--r--linux-core/drmP.h6
-rw-r--r--linux-core/drm_agpsupport.c2
-rw-r--r--linux-core/drm_bo.c5
-rw-r--r--linux-core/drm_bo_move.c33
-rw-r--r--linux-core/drm_compat.c29
-rw-r--r--linux-core/drm_compat.h10
-rw-r--r--linux-core/drm_crtc.c38
-rw-r--r--linux-core/drm_drv.c18
-rw-r--r--linux-core/drm_edid.c28
-rw-r--r--linux-core/drm_fops.c3
-rw-r--r--linux-core/drm_irq.c4
-rw-r--r--linux-core/drm_objects.h8
-rw-r--r--linux-core/drm_scatter.c11
-rw-r--r--linux-core/drm_stub.c9
-rw-r--r--linux-core/drm_ttm.c21
-rw-r--r--linux-core/drm_vm.c19
-rw-r--r--linux-core/i915_drv.c15
-rw-r--r--linux-core/intel_fb.c31
-rw-r--r--shared-core/drm.h21
-rw-r--r--shared-core/i915_dma.c79
-rw-r--r--shared-core/i915_drm.h2
-rw-r--r--shared-core/i915_init.c236
-rw-r--r--shared-core/i915_irq.c7
-rw-r--r--tests/mode/modetest.c2
-rw-r--r--tests/modedemo/demo.c16
29 files changed, 563 insertions, 228 deletions
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c
index 13e99555..bcf562d5 100644
--- a/libdrm/xf86drm.c
+++ b/libdrm/xf86drm.c
@@ -2806,23 +2806,18 @@ int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint)
}
return 0;
}
-
+
int drmBOBusy(int fd, drmBO *buf, int *busy)
{
- if (!(buf->flags & DRM_BO_FLAG_SHAREABLE) &&
- !(buf->replyFlags & DRM_BO_REP_BUSY)) {
- *busy = 0;
- return 0;
- }
- else {
- int ret = drmBOInfo(fd, buf);
- if (ret)
- return ret;
- *busy = (buf->replyFlags & DRM_BO_REP_BUSY);
- return 0;
- }
+ int ret = drmBOInfo(fd, buf);
+
+ if (ret)
+ return ret;
+
+ *busy = (buf->replyFlags & DRM_BO_REP_BUSY);
+ return 0;
}
-
+
int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
unsigned memType)
{
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c
index 52fef81b..f86cc48f 100644
--- a/libdrm/xf86drmMode.c
+++ b/libdrm/xf86drmMode.c
@@ -36,11 +36,15 @@
* platforms find which headers to include to get uint32_t
*/
#include <stdint.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
#include "xf86drmMode.h"
#include "xf86drm.h"
#include <drm.h>
#include <string.h>
+#include <dirent.h>
+#include <errno.h>
#define U642VOID(x) ((void *)(unsigned long)(x))
#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
@@ -66,27 +70,6 @@ void* drmAllocCpy(void *array, int count, int entry_size)
return r;
}
-/**
- * Generate crtc and output ids.
- *
- * Will generate ids starting from 1 up to count if count is greater then 0.
- */
-static uint32_t* drmAllocGenerate(int count)
-{
- uint32_t *r;
- int i;
-
- if(0 <= count)
- return 0;
-
- if (!(r = drmMalloc(count*sizeof(*r))))
- return 0;
-
- for (i = 0; i < count; r[i] = ++i);
-
- return 0;
-}
-
/*
* A couple of free functions.
*/
@@ -143,7 +126,6 @@ void drmModeFreeOutput(drmModeOutputPtr ptr)
drmModeResPtr drmModeGetResources(int fd)
{
struct drm_mode_card_res res;
- int i;
drmModeResPtr r = 0;
memset(&res, 0, sizeof(struct drm_mode_card_res));
@@ -201,7 +183,8 @@ uint32_t drmModeGetHotplug(int fd)
}
int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
- uint8_t bpp, uint32_t pitch, drmBO *bo, uint32_t *buf_id)
+ uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
+ uint32_t *buf_id)
{
struct drm_mode_fb_cmd f;
int ret;
@@ -211,9 +194,9 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
f.pitch = pitch;
f.bpp = bpp;
f.depth = depth;
- f.handle = bo->handle;
+ f.handle = bo_handle;
- if (ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f))
+ if ((ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f)))
return ret;
*buf_id = f.buffer_id;
@@ -260,7 +243,6 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
{
struct drm_mode_crtc crtc;
drmModeCrtcPtr r;
- int i = 0;
crtc.count_outputs = 0;
crtc.outputs = 0;
@@ -293,10 +275,6 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
r->possibles = crtc.possibles;
return r;
-
-err_allocs:
-
- return 0;
}
@@ -450,8 +428,7 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
{
struct drm_mode_get_property prop;
drmModePropertyPtr r;
- struct drm_mode_property_blob *blob_tmp;
- int i;
+
prop.prop_id = property_id;
prop.count_enum_blobs = 0;
prop.count_values = 0;
@@ -566,8 +543,71 @@ int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id,
osp.prop_id = property_id;
osp.value = value;
- if (ret = ioctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp))
+ if ((ret = ioctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)))
return ret;
return 0;
}
+
+/*
+ * checks if a modesetting capable driver has attached to the pci id
+ * returns 0 if modesetting supported.
+ * -EINVAL or invalid bus id
+ * -ENOSYS if no modesetting support
+*/
+int drmCheckModesettingSupported(const char *busid)
+{
+#ifdef __linux__
+ char pci_dev_dir[1024];
+ int domain, bus, dev, func;
+ DIR *sysdir;
+ struct dirent *dent;
+ int found = 0, ret;
+
+ ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func);
+ if (ret != 4)
+ return -EINVAL;
+
+ sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm",
+ domain, bus, dev, func);
+
+ sysdir = opendir(pci_dev_dir);
+ if (sysdir) {
+ dent = readdir(sysdir);
+ while (dent) {
+ if (!strncmp(dent->d_name, "controlD", 8)) {
+ found = 1;
+ break;
+ }
+
+ dent = readdir(sysdir);
+ }
+ closedir(sysdir);
+ if (found)
+ return 0;
+ }
+
+ sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
+ domain, bus, dev, func);
+
+ sysdir = opendir(pci_dev_dir);
+ if (!sysdir)
+ return -EINVAL;
+
+ dent = readdir(sysdir);
+ while (dent) {
+ if (!strncmp(dent->d_name, "drm:controlD", 12)) {
+ found = 1;
+ break;
+ }
+
+ dent = readdir(sysdir);
+ }
+
+ closedir(sysdir);
+ if (found)
+ return 0;
+#endif
+ return -ENOSYS;
+
+}
diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h
index 7cc3ceca..edf9efee 100644
--- a/libdrm/xf86drmMode.h
+++ b/libdrm/xf86drmMode.h
@@ -177,7 +177,7 @@ extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
* Creates a new framebuffer with an buffer object as its scanout buffer.
*/
extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
- uint8_t bpp, uint32_t pitch, drmBO *bo,
+ uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
uint32_t *buf_id);
/**
* Destroies the given framebuffer.
@@ -243,3 +243,4 @@ extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id);
extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr);
extern int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id,
uint64_t value);
+extern int drmCheckModesettingSupported(const char *busid);
diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c
index 68029635..93519e5f 100644
--- a/linux-core/ati_pcigart.c
+++ b/linux-core/ati_pcigart.c
@@ -224,6 +224,12 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
}
}
+ if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
+ dma_sync_single_for_device(&dev->pdev->dev,
+ bus_address,
+ max_pages * sizeof(u32),
+ PCI_DMA_TODEVICE);
+
ret = 1;
#if defined(__i386__) || defined(__x86_64__)
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 51b02dc8..47974856 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -106,6 +106,7 @@ struct drm_file;
#define DRIVER_IRQ_SHARED 0x80
#define DRIVER_DMA_QUEUE 0x100
#define DRIVER_FB_DMA 0x200
+#define DRIVER_MODESET 0x400
/*@}*/
@@ -760,9 +761,10 @@ struct drm_driver {
};
#define DRM_MINOR_UNASSIGNED 0
-#define DRM_MINOR_CONTROL 1
-#define DRM_MINOR_LEGACY 2
+#define DRM_MINOR_LEGACY 1
+#define DRM_MINOR_CONTROL 2
#define DRM_MINOR_RENDER 3
+
/**
* DRM minor structure. This structure represents a drm minor number.
*/
diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c
index adcb93a5..0aa94a75 100644
--- a/linux-core/drm_agpsupport.c
+++ b/linux-core/drm_agpsupport.c
@@ -666,7 +666,7 @@ void drm_agp_chipset_flush(struct drm_device *dev)
{
agp_flush_chipset(dev->agp->bridge);
}
-EXPORT_SYMBOL(drm_agp_flush_chipset);
+EXPORT_SYMBOL(drm_agp_chipset_flush);
#endif
#endif /* __OS_HAS_AGP */
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index b6115e8d..1d3f87e5 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -969,7 +969,7 @@ static int drm_bo_modify_proposed_flags (struct drm_buffer_object *bo,
return -EINVAL;
}
- if ((new_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) {
+ if (bo->type != drm_bo_type_kernel && (new_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) {
DRM_ERROR("DRM_BO_FLAG_NO_EVICT is only available to priviliged processes.\n");
return -EPERM;
}
@@ -1065,7 +1065,7 @@ static int drm_bo_busy(struct drm_buffer_object *bo)
return 0;
}
-static int drm_bo_evict_cached(struct drm_buffer_object *bo)
+int drm_bo_evict_cached(struct drm_buffer_object *bo)
{
int ret = 0;
@@ -1075,6 +1075,7 @@ static int drm_bo_evict_cached(struct drm_buffer_object *bo)
return ret;
}
+EXPORT_SYMBOL(drm_bo_evict_cached);
/*
* Wait until a buffer is unmapped.
*/
diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c
index db433d63..536ff5d3 100644
--- a/linux-core/drm_bo_move.c
+++ b/linux-core/drm_bo_move.c
@@ -596,3 +596,36 @@ void drm_bo_kunmap(struct drm_bo_kmap_obj *map)
map->page = NULL;
}
EXPORT_SYMBOL(drm_bo_kunmap);
+
+int drm_bo_pfn_prot(struct drm_buffer_object *bo,
+ unsigned long dst_offset,
+ unsigned long *pfn,
+ pgprot_t *prot)
+{
+ struct drm_bo_mem_reg *mem = &bo->mem;
+ struct drm_device *dev = bo->dev;
+ unsigned long bus_offset;
+ unsigned long bus_size;
+ unsigned long bus_base;
+ struct drm_mem_type_manager *man = &dev->bm.man[mem->mem_type];
+ int ret;
+
+ ret = drm_bo_pci_offset(dev, mem, &bus_base, &bus_offset,
+ &bus_size);
+ if (ret)
+ return -EINVAL;
+
+ if (bus_size != 0)
+ *pfn = (bus_base + bus_offset + dst_offset) >> PAGE_SHIFT;
+ else if (!bo->ttm)
+ return -EINVAL;
+ else
+ *pfn = page_to_pfn(drm_ttm_get_page(bo->ttm, dst_offset >> PAGE_SHIFT));
+
+ *prot = (mem->flags & DRM_BO_FLAG_CACHED) ?
+ PAGE_KERNEL : drm_kernel_io_prot(man->drm_bus_maptype);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_bo_pfn_prot);
+
diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c
index e95269ec..9b982662 100644
--- a/linux-core/drm_compat.c
+++ b/linux-core/drm_compat.c
@@ -779,3 +779,32 @@ struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
}
EXPORT_SYMBOL(pci_get_bus_and_slot);
#endif
+
+#if defined(DRM_KMAP_ATOMIC_PROT_PFN) && defined(CONFIG_HIMEM)
+#define drm_kmap_get_fixmap_pte(vaddr) \
+ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr))
+
+void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type,
+ pgprot_t protection)
+{
+ enum fixed_addresses idx;
+ unsigned long vaddr;
+ static pte_t *km_pte;
+ static int initialized = 0;
+
+ if (unlikely(!initialized)) {
+ km_pte = drm_kmap_get_fixmap_pte(__fix_to_virt(FIX_KMAP_BEGIN));
+ initialized = 1;
+ }
+
+ pagefault_disable();
+ idx = type + KM_TYPE_NR*smp_processor_id();
+ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ set_pte(km_pte-idx, pfn_pte(pfn, protection));
+
+ return (void*) vaddr;
+}
+
+EXPORT_SYMBOL(kmap_atomic_prot_pfn);
+#endif
+
diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h
index f5f06017..03838a18 100644
--- a/linux-core/drm_compat.h
+++ b/linux-core/drm_compat.h
@@ -343,4 +343,14 @@ extern struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devf
#define PM_EVENT_PRETHAW 3
#endif
+#if (defined(CONFIG_X86) && defined(CONFIG_X86_32) && defined(CONFIG_HIMEM))
+#define DRM_KMAP_ATOMIC_PROT_PFN
+extern void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type,
+ pgprot_t protection);
+#endif
+
+#if !defined(flush_agp_mappings)
+#define flush_agp_mappings() do {} while(0)
+#endif
+
#endif
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c
index 1a4624c8..e0c85cef 100644
--- a/linux-core/drm_crtc.c
+++ b/linux-core/drm_crtc.c
@@ -48,7 +48,8 @@ static struct drm_prop_enum_list drm_dpms_enum_list[] =
{ DPMSModeOff, "Off" }
};
static struct drm_prop_enum_list drm_conn_enum_list[] =
-{ { ConnectorVGA, "VGA" },
+{ { ConnectorUnknown, "Unknown" },
+ { ConnectorVGA, "VGA" },
{ ConnectorDVII, "DVI-I" },
{ ConnectorDVID, "DVI-D" },
{ ConnectorDVIA, "DVI-A" },
@@ -419,14 +420,14 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
int saved_x, saved_y;
bool didLock = false;
struct drm_output *output;
+ bool ret = true;
adjusted_mode = drm_mode_duplicate(dev, mode);
crtc->enabled = drm_crtc_in_use(crtc);
- if (!crtc->enabled) {
+ if (!crtc->enabled)
return true;
- }
didLock = crtc->funcs->lock(crtc);
@@ -457,12 +458,12 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
if (output->crtc != crtc)
continue;
- if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
+ if (!(ret = output->funcs->mode_fixup(output, mode, adjusted_mode))) {
goto done;
}
}
- if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
+ if (!(ret = crtc->funcs->mode_fixup(crtc, mode, adjusted_mode))) {
goto done;
}
@@ -516,10 +517,16 @@ bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
// drm_crtc_set_screen_sub_pixel_order(dev);
done:
+ if (!ret) {
+ crtc->mode = saved_mode;
+ crtc->x = saved_x;
+ crtc->y = saved_y;
+ }
+
if (didLock)
crtc->funcs->unlock (crtc);
- return true;
+ return ret;
}
EXPORT_SYMBOL(drm_crtc_set_mode);
@@ -728,20 +735,20 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev)
"EDID", 0);
dev->mode_config.dpms_property =
- drm_property_create(dev, DRM_MODE_PROP_ENUM, "DPMS", 4);
-
+ drm_property_create(dev, DRM_MODE_PROP_ENUM,
+ "DPMS", ARRAY_SIZE(drm_dpms_enum_list));
for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++)
drm_property_add_enum(dev->mode_config.dpms_property, i, drm_dpms_enum_list[i].type, drm_dpms_enum_list[i].name);
dev->mode_config.connector_type_property =
drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE,
- "Connector Type", 10);
+ "Connector Type", ARRAY_SIZE(drm_conn_enum_list));
for (i = 0; i < ARRAY_SIZE(drm_conn_enum_list); i++)
drm_property_add_enum(dev->mode_config.connector_type_property, i, drm_conn_enum_list[i].type, drm_conn_enum_list[i].name);
dev->mode_config.connector_num_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE,
- "Connector ID", 2);
+ "Connector ID", 2);
dev->mode_config.connector_num_property->values[0] = 0;
dev->mode_config.connector_num_property->values[1] = 20;
@@ -776,7 +783,6 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev)
dev->mode_config.tv_bottom_margin_property->values[0] = 0;
dev->mode_config.tv_bottom_margin_property->values[1] = 100;
-
return 0;
}
@@ -1104,13 +1110,17 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info,
/* We should be able to check here if the fb has the same properties
* and then just flip_or_move it */
if (crtc->fb != fb)
- changed = true;
+ flip_or_move = true;
if (crtc_info->x != crtc->x || crtc_info->y != crtc->y)
flip_or_move = true;
- if (new_mode && !drm_mode_equal(new_mode, &crtc->mode))
+ if (new_mode && !drm_mode_equal(new_mode, &crtc->mode)) {
+ DRM_DEBUG("modes are different\n");
+ drm_mode_debug_printmodeline(dev, &crtc->mode);
+ drm_mode_debug_printmodeline(dev, new_mode);
changed = true;
+ }
list_for_each_entry(output, &dev->mode_config.output_list, head) {
save_crtcs[count++] = output->crtc;
@@ -1155,6 +1165,8 @@ int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info,
}
drm_disable_unused_functions(dev);
} else if (flip_or_move) {
+ if (crtc->fb != fb)
+ crtc->fb = fb;
crtc->funcs->mode_set_base(crtc, crtc_info->x, crtc_info->y);
}
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index 4932ea59..434789dd 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -187,7 +187,9 @@ int drm_lastclose(struct drm_device * dev)
DRM_DEBUG("\n");
-/* return 0; */
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_bo_driver_finish(dev);
+
/*
* We can't do much about this function failing.
*/
@@ -414,7 +416,8 @@ static void drm_cleanup(struct drm_device * dev)
drm_ht_remove(&dev->object_hash);
drm_put_minor(&dev->primary);
- drm_put_minor(&dev->control);
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_put_minor(&dev->control);
if (drm_put_dev(dev))
DRM_ERROR("Cannot unload module\n");
}
@@ -424,13 +427,20 @@ int drm_minors_cleanup(int id, void *ptr, void *data)
struct drm_minor *minor = ptr;
struct drm_device *dev;
struct drm_driver *driver = data;
- if (id < 127 || id > 192)
- return 0;
dev = minor->dev;
if (minor->dev->driver != driver)
return 0;
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ if (minor->type != DRM_MINOR_CONTROL)
+ return 0;
+ } else {
+ if (minor->type != DRM_MINOR_LEGACY)
+ return 0;
+ }
+
+
if (dev)
pci_dev_put(dev->pdev);
drm_cleanup(dev);
diff --git a/linux-core/drm_edid.c b/linux-core/drm_edid.c
index 41aa8f5e..9762567b 100644
--- a/linux-core/drm_edid.c
+++ b/linux-core/drm_edid.c
@@ -223,8 +223,10 @@ static int add_established_modes(struct drm_output *output, struct edid *edid)
if (est_bits & (1<<i)) {
struct drm_display_mode *newmode;
newmode = drm_mode_duplicate(dev, &edid_est_modes[i]);
- drm_mode_probed_add(output, newmode);
- modes++;
+ if (newmode) {
+ drm_mode_probed_add(output, newmode);
+ modes++;
+ }
}
return modes;
@@ -251,8 +253,10 @@ static int add_standard_modes(struct drm_output *output, struct edid *edid)
continue;
newmode = drm_mode_std(dev, &edid->standard_timings[i]);
- drm_mode_probed_add(output, newmode);
- modes++;
+ if (newmode) {
+ drm_mode_probed_add(output, newmode);
+ modes++;
+ }
}
return modes;
@@ -283,11 +287,13 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
if (timing->pixel_clock) {
newmode = drm_mode_detailed(dev, timing);
/* First detailed mode is preferred */
- if (i == 0 && edid->preferred_timing)
- newmode->type |= DRM_MODE_TYPE_PREFERRED;
- drm_mode_probed_add(output, newmode);
+ if (newmode) {
+ if (i == 0 && edid->preferred_timing)
+ newmode->type |= DRM_MODE_TYPE_PREFERRED;
+ drm_mode_probed_add(output, newmode);
- modes++;
+ modes++;
+ }
continue;
}
@@ -312,8 +318,10 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
std = &data->data.timings[j];
newmode = drm_mode_std(dev, std);
- drm_mode_probed_add(output, newmode);
- modes++;
+ if (newmode) {
+ drm_mode_probed_add(output, newmode);
+ modes++;
+ }
}
break;
default:
diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c
index 5a74f424..fcadc544 100644
--- a/linux-core/drm_fops.c
+++ b/linux-core/drm_fops.c
@@ -481,7 +481,8 @@ int drm_release(struct inode *inode, struct file *filp)
}
mutex_unlock(&dev->ctxlist_mutex);
- drm_fb_release(filp);
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_fb_release(filp);
file_priv->master = NULL;
diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c
index 637f5e1d..6b740b18 100644
--- a/linux-core/drm_irq.c
+++ b/linux-core/drm_irq.c
@@ -306,6 +306,8 @@ int drm_control(struct drm_device *dev, void *data,
case DRM_INST_HANDLER:
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return 0;
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
ctl->irq != dev->irq)
return -EINVAL;
@@ -313,6 +315,8 @@ int drm_control(struct drm_device *dev, void *data,
case DRM_UNINST_HANDLER:
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return 0;
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
return drm_irq_uninstall(dev);
default:
return -EINVAL;
diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h
index cce58178..8f81b665 100644
--- a/linux-core/drm_objects.h
+++ b/linux-core/drm_objects.h
@@ -383,7 +383,7 @@ extern int drm_ttm_destroy(struct drm_ttm *ttm);
* The array of page pointers was allocated with vmalloc
* instead of drm_calloc.
*/
-#define DRM_TTM_PAGE_VMALLOC (1 << 4)
+#define DRM_TTM_PAGEDIR_VMALLOC (1 << 4)
/*
* This ttm is mapped from user space
*/
@@ -700,7 +700,7 @@ extern int drm_bo_do_validate(struct drm_buffer_object *bo,
uint64_t flags, uint64_t mask, uint32_t hint,
uint32_t fence_class,
struct drm_bo_info_rep *rep);
-
+extern int drm_bo_evict_cached(struct drm_buffer_object *bo);
/*
* Buffer object memory move- and map helpers.
* drm_bo_move.c
@@ -741,6 +741,10 @@ static inline void *drm_bmo_virtual(struct drm_bo_kmap_obj *map, int *is_iomem)
extern void drm_bo_kunmap(struct drm_bo_kmap_obj *map);
extern int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page,
unsigned long num_pages, struct drm_bo_kmap_obj *map);
+extern int drm_bo_pfn_prot(struct drm_buffer_object *bo,
+ unsigned long dst_offset,
+ unsigned long *pfn,
+ pgprot_t *prot);
/*
diff --git a/linux-core/drm_scatter.c b/linux-core/drm_scatter.c
index 77b9f95d..dfae4b84 100644
--- a/linux-core/drm_scatter.c
+++ b/linux-core/drm_scatter.c
@@ -36,6 +36,15 @@
#define DEBUG_SCATTER 0
+static inline void *drm_vmalloc_dma(unsigned long size)
+{
+#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE)
+ return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL | _PAGE_NO_CACHE);
+#else
+ return vmalloc_32(size);
+#endif
+}
+
void drm_sg_cleanup(struct drm_sg_mem *entry)
{
struct page *page;
@@ -105,7 +114,7 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
}
memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
- entry->virtual = vmalloc_32(pages << PAGE_SHIFT);
+ entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT);
if (!entry->virtual) {
drm_free(entry->busaddr,
entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c
index 334c8f03..6856075b 100644
--- a/linux-core/drm_stub.c
+++ b/linux-core/drm_stub.c
@@ -343,8 +343,10 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
goto err_g3;
}
- if ((ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL)))
- goto err_g3;
+ /* only add the control node on a modesetting platform */
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ if ((ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL)))
+ goto err_g3;
if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
goto err_g4;
@@ -361,7 +363,8 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
err_g5:
drm_put_minor(&dev->primary);
err_g4:
- drm_put_minor(&dev->control);
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_put_minor(&dev->control);
err_g3:
if (!drm_fb_loaded)
pci_disable_device(pdev);
diff --git a/linux-core/drm_ttm.c b/linux-core/drm_ttm.c
index a9d87338..cc80b132 100644
--- a/linux-core/drm_ttm.c
+++ b/linux-core/drm_ttm.c
@@ -42,11 +42,12 @@ void drm_ttm_cache_flush(void)
}
EXPORT_SYMBOL(drm_ttm_cache_flush);
-/*
- * Use kmalloc if possible. Otherwise fall back to vmalloc.
+/**
+ * Allocates storage for pointers to the pages that back the ttm.
+ *
+ * Uses kmalloc if possible. Otherwise falls back to vmalloc.
*/
-
-static void drm_ttm_alloc_pages(struct drm_ttm *ttm)
+static void drm_ttm_alloc_page_directory(struct drm_ttm *ttm)
{
unsigned long size = ttm->num_pages * sizeof(*ttm->pages);
ttm->pages = NULL;
@@ -60,19 +61,19 @@ static void drm_ttm_alloc_pages(struct drm_ttm *ttm)
if (!ttm->pages) {
ttm->pages = vmalloc_user(size);
if (ttm->pages)
- ttm->page_flags |= DRM_TTM_PAGE_VMALLOC;
+ ttm->page_flags |= DRM_TTM_PAGEDIR_VMALLOC;
}
if (!ttm->pages)
drm_free_memctl(size);
}
-static void drm_ttm_free_pages(struct drm_ttm *ttm)
+static void drm_ttm_free_page_directory(struct drm_ttm *ttm)
{
unsigned long size = ttm->num_pages * sizeof(*ttm->pages);
- if (ttm->page_flags & DRM_TTM_PAGE_VMALLOC) {
+ if (ttm->page_flags & DRM_TTM_PAGEDIR_VMALLOC) {
vfree(ttm->pages);
- ttm->page_flags &= ~DRM_TTM_PAGE_VMALLOC;
+ ttm->page_flags &= ~DRM_TTM_PAGEDIR_VMALLOC;
} else {
drm_free(ttm->pages, size, DRM_MEM_TTM);
}
@@ -215,7 +216,7 @@ int drm_ttm_destroy(struct drm_ttm *ttm)
else
drm_ttm_free_alloced_pages(ttm);
- drm_ttm_free_pages(ttm);
+ drm_ttm_free_page_directory(ttm);
}
drm_ctl_free(ttm, sizeof(*ttm), DRM_MEM_TTM);
@@ -349,7 +350,7 @@ struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size,
* Account also for AGP module memory usage.
*/
- drm_ttm_alloc_pages(ttm);
+ drm_ttm_alloc_page_directory(ttm);
if (!ttm->pages) {
drm_ttm_destroy(ttm);
DRM_ERROR("Failed allocating page table\n");
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c
index 15e1c0f5..ffda8284 100644
--- a/linux-core/drm_vm.c
+++ b/linux-core/drm_vm.c
@@ -59,17 +59,27 @@ pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
pgprot_val(tmp) |= _PAGE_NO_CACHE;
if (map_type == _DRM_REGISTERS)
pgprot_val(tmp) |= _PAGE_GUARDED;
-#endif
-#if defined(__ia64__)
+#elif defined(__ia64__)
if (efi_range_is_wc(vma->vm_start, vma->vm_end -
vma->vm_start))
tmp = pgprot_writecombine(tmp);
else
tmp = pgprot_noncached(tmp);
+#elif defined(__sparc__)
+ tmp = pgprot_noncached(tmp);
#endif
return tmp;
}
+static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
+{
+ pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
+
+#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE)
+ tmp |= _PAGE_NO_CACHE;
+#endif
+ return tmp;
+}
/**
* \c nopage method for AGP virtual memory.
@@ -628,9 +638,6 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
offset = dev->driver->get_reg_ofs(dev);
vma->vm_flags |= VM_IO; /* not in core dump */
vma->vm_page_prot = drm_io_prot(map->type, vma);
-#ifdef __sparc__
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#endif
if (io_remap_pfn_range(vma, vma->vm_start,
(map->offset + offset) >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
@@ -649,6 +656,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
page_to_pfn(virt_to_page(map->handle)),
vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
+ vma->vm_page_prot = drm_dma_prot(map->type, vma);
/* fall through to _DRM_SHM */
case _DRM_SHM:
vma->vm_ops = &drm_vm_shm_ops;
@@ -661,6 +669,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
vma->vm_ops = &drm_vm_sg_ops;
vma->vm_private_data = (void *)map;
vma->vm_flags |= VM_RESERVED;
+ vma->vm_page_prot = drm_dma_prot(map->type, vma);
break;
case _DRM_TTM:
return drm_bo_mmap_locked(vma, filp, map);
diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c
index 6c12f1a1..0e65c0cd 100644
--- a/linux-core/i915_drv.c
+++ b/linux-core/i915_drv.c
@@ -39,14 +39,17 @@ static struct pci_device_id pciidlist[] = {
i915_PCI_IDS
};
+unsigned int i915_modeset = 0;
+module_param_named(modeset, i915_modeset, int, 0400);
+
#ifdef I915_HAVE_FENCE
extern struct drm_fence_driver i915_fence_driver;
#endif
#ifdef I915_HAVE_BUFFER
-static uint32_t i915_mem_prios[] = {DRM_BO_MEM_VRAM, DRM_BO_MEM_PRIV0, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL};
-static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_PRIV0, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL};
+static uint32_t i915_mem_prios[] = {DRM_BO_MEM_VRAM, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL};
+static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL};
static struct drm_bo_driver i915_bo_driver = {
.mem_type_prio = i915_mem_prios,
@@ -563,8 +566,9 @@ static struct drm_driver driver = {
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
.load = i915_driver_load,
.unload = i915_driver_unload,
-/* .lastclose = i915_driver_lastclose,
- .preclose = i915_driver_preclose, */
+ .firstopen = i915_driver_firstopen,
+ .lastclose = i915_driver_lastclose,
+ .preclose = i915_driver_preclose,
.suspend = i915_suspend,
.resume = i915_resume,
.device_is_agp = i915_driver_device_is_agp,
@@ -624,6 +628,9 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *ent)
static int __init i915_init(void)
{
driver.num_ioctls = i915_max_ioctl;
+ if (i915_modeset == 1)
+ driver.driver_features |= DRIVER_MODESET;
+
return drm_init(&driver, pciidlist);
}
diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c
index e33494c6..52ff3a67 100644
--- a/linux-core/intel_fb.c
+++ b/linux-core/intel_fb.c
@@ -228,6 +228,7 @@ static int intelfb_set_par(struct fb_info *info)
struct drm_output *output = NULL;
struct fb_var_screeninfo *var = &info->var;
int found = 0;
+ int changed = 0;
DRM_DEBUG("\n");
@@ -310,11 +311,22 @@ static int intelfb_set_par(struct fb_info *info)
}
/* re-attach fb */
- if (!par->crtc->fb)
+ if (!par->crtc->fb) {
par->crtc->fb = par->fb;
+ changed = 1;
+ }
- if (!drm_crtc_set_mode(par->crtc, drm_mode, var->xoffset, var->yoffset))
- return -EINVAL;
+ if (par->crtc->x != var->xoffset || par->crtc->y != var->yoffset)
+ changed = 1;
+
+ drm_mode_debug_printmodeline(dev, drm_mode);
+ drm_mode_debug_printmodeline(dev, &par->crtc->mode);
+ if (!drm_mode_equal(drm_mode, &par->crtc->mode))
+ changed = 1;
+
+ if (changed)
+ if (!drm_crtc_set_mode(par->crtc, drm_mode, var->xoffset, var->yoffset))
+ return -EINVAL;
return 0;
}
@@ -469,16 +481,21 @@ static int intelfb_pan_display(struct fb_var_screeninfo *var,
{
struct intelfb_par *par = info->par;
struct drm_crtc *crtc = par->crtc;
-
+ int changed = 0;
DRM_DEBUG("\n");
/* TODO add check size and pos*/
+ if (par->crtc->x != var->xoffset || par->crtc->y != var->yoffset)
+ changed = 1;
/* re-attach fb */
- if (!crtc->fb)
+ if (!crtc->fb) {
crtc->fb = par->fb;
+ changed = 1;
+ }
- drm_crtc_set_mode(crtc, &crtc->mode, var->xoffset, var->yoffset);
+ if (changed)
+ drm_crtc_set_mode(crtc, &crtc->mode, var->xoffset, var->yoffset);
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
@@ -572,7 +589,7 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc)
fb->bits_per_pixel = 32;
fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8);
fb->depth = 24;
- ret = drm_buffer_object_create(dev, fb->pitch * fb->height * 4,
+ ret = drm_buffer_object_create(dev, fb->pitch * fb->height,
drm_bo_type_kernel,
DRM_BO_FLAG_READ |
DRM_BO_FLAG_WRITE |
diff --git a/shared-core/drm.h b/shared-core/drm.h
index cbe83fd1..303a84b6 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -645,8 +645,14 @@ struct drm_set_version {
#define DRM_FENCE_FLAG_EMIT 0x00000001
#define DRM_FENCE_FLAG_SHAREABLE 0x00000002
+/**
+ * On hardware with no interrupt events for operation completion,
+ * indicates that the kernel should sleep while waiting for any blocking
+ * operation to complete rather than spinning.
+ *
+ * Has no effect otherwise.
+ */
#define DRM_FENCE_FLAG_WAIT_LAZY 0x00000004
-#define DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS 0x00000008
#define DRM_FENCE_FLAG_NO_USER 0x00000010
/* Reserved for driver use */
@@ -795,13 +801,12 @@ struct drm_fence_arg {
* with it as a result of this operation
*/
#define DRM_BO_HINT_DONT_FENCE 0x00000004
-/*
- * Sleep while waiting for the operation to complete.
- * Without this flag, the kernel will, instead, spin
- * until this operation has completed. I'm not sure
- * why you would ever want this, so please always
- * provide DRM_BO_HINT_WAIT_LAZY to any operation
- * which may block
+/**
+ * On hardware with no interrupt events for operation completion,
+ * indicates that the kernel should sleep while waiting for any blocking
+ * operation to complete rather than spinning.
+ *
+ * Has no effect otherwise.
*/
#define DRM_BO_HINT_WAIT_LAZY 0x00000008
/*
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index eee24dd1..8237e145 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -66,6 +66,11 @@ void i915_kernel_lost_context(struct drm_device * dev)
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_ring_buffer *ring = &(dev_priv->ring);
+ /* we should never lose context on the ring with modesetting
+ * as we don't expose it to userspace */
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return;
+
ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
ring->space = ring->head - (ring->tail + 8);
@@ -75,6 +80,11 @@ void i915_kernel_lost_context(struct drm_device * dev)
int i915_dma_cleanup(struct drm_device * dev)
{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
+
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
@@ -82,6 +92,28 @@ int i915_dma_cleanup(struct drm_device * dev)
if (dev->irq)
drm_irq_uninstall(dev);
+ if (dev_priv->ring.virtual_start) {
+ drm_core_ioremapfree(&dev_priv->ring.map, dev);
+ dev_priv->ring.virtual_start = 0;
+ dev_priv->ring.map.handle = 0;
+ dev_priv->ring.map.size = 0;
+ dev_priv->ring.Size = 0;
+ }
+
+ if (dev_priv->status_page_dmah) {
+ drm_pci_free(dev, dev_priv->status_page_dmah);
+ dev_priv->status_page_dmah = NULL;
+ /* Need to rewrite hardware status page */
+ I915_WRITE(0x02080, 0x1ffff000);
+ }
+
+ if (dev_priv->status_gfx_addr) {
+ dev_priv->status_gfx_addr = 0;
+ drm_core_ioremapfree(&dev_priv->hws_map, dev);
+ I915_WRITE(0x02080, 0x1ffff000);
+ }
+
+
return 0;
}
@@ -153,13 +185,17 @@ static int i915_initialize(struct drm_device * dev,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
- dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
- if (!dev_priv->mmio_map) {
- i915_dma_cleanup(dev);
- DRM_ERROR("can not find mmio map!\n");
- return -EINVAL;
+ if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
+ if (init->mmio_offset != 0)
+ dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
+ if (!dev_priv->mmio_map) {
+ i915_dma_cleanup(dev);
+ DRM_ERROR("can not find mmio map!\n");
+ return -EINVAL;
+ }
}
+
#ifdef I915_HAVE_BUFFER
dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS;
#endif
@@ -246,6 +282,9 @@ static int i915_dma_resume(struct drm_device * dev)
DRM_DEBUG("\n");
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
+
if (!dev_priv->mmio_map) {
DRM_ERROR("can not find mmio map!\n");
return -EINVAL;
@@ -765,6 +804,8 @@ struct i915_relocatee_info {
unsigned page_offset;
struct drm_bo_kmap_obj kmap;
int is_iomem;
+ int idle;
+ int evicted;
};
struct drm_i915_validate_buffer {
@@ -820,6 +861,14 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers,
drm_bo_kunmap(&relocatee->kmap);
relocatee->data_page = NULL;
relocatee->offset = new_cmd_offset;
+
+ if (unlikely(!relocatee->idle)) {
+ ret = drm_bo_wait(relocatee->buf, 0, 0, 0);
+ if (ret)
+ return ret;
+ relocatee->idle = 1;
+ }
+
ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT,
1, &relocatee->kmap);
if (ret) {
@@ -829,6 +878,12 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers,
relocatee->data_page = drm_bmo_virtual(&relocatee->kmap,
&relocatee->is_iomem);
relocatee->page_offset = (relocatee->offset & PAGE_MASK);
+
+ if (!relocatee->evicted &&
+ relocatee->buf->mem.flags & DRM_BO_FLAG_CACHED_MAPPED) {
+ drm_bo_evict_cached(relocatee->buf);
+ relocatee->evicted = 1;
+ }
}
val = buffers[buf_index].buffer->offset;
@@ -963,10 +1018,6 @@ static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle,
}
mutex_lock (&relocatee.buf->mutex);
- ret = drm_bo_wait (relocatee.buf, 0, 0, FALSE);
- if (ret)
- goto out_err1;
-
while (reloc_user_ptr) {
ret = i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, &relocatee, buffers, buf_count);
if (ret) {
@@ -1430,6 +1481,16 @@ drm_i915_mmio_entry_t mmio_table[] = {
I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE,
0x30010,
6
+ },
+ [MMIO_REGS_FENCE] = {
+ I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE,
+ 0x2000,
+ 8
+ },
+ [MMIO_REGS_FENCE_NEW] = {
+ I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE,
+ 0x3000,
+ 16
}
};
diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h
index a40cabdc..824aee27 100644
--- a/shared-core/i915_drm.h
+++ b/shared-core/i915_drm.h
@@ -328,6 +328,8 @@ typedef struct drm_i915_vblank_swap {
#define MMIO_REGS_PS_DEPTH_COUNT 8
#define MMIO_REGS_DOVSTA 9
#define MMIO_REGS_GAMMA 10
+#define MMIO_REGS_FENCE 11
+#define MMIO_REGS_FENCE_NEW 12
typedef struct drm_i915_mmio_entry {
unsigned int flag;
diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c
index b2d3f0d0..3d8a1dca 100644
--- a/shared-core/i915_init.c
+++ b/shared-core/i915_init.c
@@ -153,106 +153,113 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
DRM_DEBUG("fb_base: 0x%08lx\n", dev->mode_config.fb_base);
ret = drm_addmap(dev, dev_priv->mmiobase, dev_priv->mmiolen,
- _DRM_REGISTERS, _DRM_READ_ONLY|_DRM_DRIVER, &dev_priv->mmio_map);
+ _DRM_REGISTERS, _DRM_KERNEL|_DRM_READ_ONLY|_DRM_DRIVER, &dev_priv->mmio_map);
if (ret != 0) {
DRM_ERROR("Cannot add mapping for MMIO registers\n");
return ret;
}
+#ifdef __linux__
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+ intel_init_chipset_flush_compat(dev);
+#endif
+#endif
+
/*
* Initialize the memory manager for local and AGP space
*/
drm_bo_driver_init(dev);
- i915_probe_agp(dev->pdev, &agp_size, &prealloc_size);
- printk("setting up %ld bytes of VRAM space\n", prealloc_size);
- printk("setting up %ld bytes of TT space\n", (agp_size - prealloc_size));
- drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, prealloc_size >> PAGE_SHIFT, 1);
- drm_bo_init_mm(dev, DRM_BO_MEM_TT, prealloc_size >> PAGE_SHIFT, (agp_size - prealloc_size) >> PAGE_SHIFT, 1);
-
- I915_WRITE(LP_RING + RING_LEN, 0);
- I915_WRITE(LP_RING + RING_HEAD, 0);
- I915_WRITE(LP_RING + RING_TAIL, 0);
-
- size = PRIMARY_RINGBUFFER_SIZE;
- ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel,
- DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE |
- DRM_BO_FLAG_MEM_VRAM |
- DRM_BO_FLAG_NO_EVICT,
- DRM_BO_HINT_DONT_FENCE, 0x1, 0,
- &dev_priv->ring_buffer);
- if (ret < 0) {
- DRM_ERROR("Unable to allocate or pin ring buffer\n");
- return -EINVAL;
- }
-
- /* remap the buffer object properly */
- dev_priv->ring.Start = dev_priv->ring_buffer->offset;
- dev_priv->ring.End = dev_priv->ring.Start + size;
- dev_priv->ring.Size = size;
- dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-
- /* FIXME: need wrapper with PCI mem checks */
- ret = drm_mem_reg_ioremap(dev, &dev_priv->ring_buffer->mem,
- (void **) &dev_priv->ring.virtual_start);
- if (ret)
- DRM_ERROR("error mapping ring buffer: %d\n", ret);
-
- DRM_DEBUG("ring start %08lX, %p, %08lX\n", dev_priv->ring.Start,
- dev_priv->ring.virtual_start, dev_priv->ring.Size);
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ i915_probe_agp(dev->pdev, &agp_size, &prealloc_size);
+ printk("setting up %ld bytes of VRAM space\n", prealloc_size);
+ printk("setting up %ld bytes of TT space\n", (agp_size - prealloc_size));
+ drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, prealloc_size >> PAGE_SHIFT, 1);
+ drm_bo_init_mm(dev, DRM_BO_MEM_TT, prealloc_size >> PAGE_SHIFT, (agp_size - prealloc_size) >> PAGE_SHIFT, 1);
+
+ I915_WRITE(LP_RING + RING_LEN, 0);
+ I915_WRITE(LP_RING + RING_HEAD, 0);
+ I915_WRITE(LP_RING + RING_TAIL, 0);
+
+ size = PRIMARY_RINGBUFFER_SIZE;
+ ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel,
+ DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE |
+ DRM_BO_FLAG_MEM_VRAM |
+ DRM_BO_FLAG_NO_EVICT,
+ DRM_BO_HINT_DONT_FENCE, 0x1, 0,
+ &dev_priv->ring_buffer);
+ if (ret < 0) {
+ DRM_ERROR("Unable to allocate or pin ring buffer\n");
+ return -EINVAL;
+ }
+
+ /* remap the buffer object properly */
+ dev_priv->ring.Start = dev_priv->ring_buffer->offset;
+ dev_priv->ring.End = dev_priv->ring.Start + size;
+ dev_priv->ring.Size = size;
+ dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
+ /* FIXME: need wrapper with PCI mem checks */
+ ret = drm_mem_reg_ioremap(dev, &dev_priv->ring_buffer->mem,
+ (void **) &dev_priv->ring.virtual_start);
+ if (ret)
+ DRM_ERROR("error mapping ring buffer: %d\n", ret);
+
+ DRM_DEBUG("ring start %08lX, %p, %08lX\n", dev_priv->ring.Start,
+ dev_priv->ring.virtual_start, dev_priv->ring.Size);
//
- memset((void *)(dev_priv->ring.virtual_start), 0, dev_priv->ring.Size);
-
- I915_WRITE(LP_RING + RING_START, dev_priv->ring.Start);
- I915_WRITE(LP_RING + RING_LEN,
- ((dev_priv->ring.Size - 4096) & RING_NR_PAGES) |
- (RING_NO_REPORT | RING_VALID));
-
- /* We are using separate values as placeholders for mechanisms for
- * private backbuffer/depthbuffer usage.
- */
- dev_priv->use_mi_batchbuffer_start = 0;
+ memset((void *)(dev_priv->ring.virtual_start), 0, dev_priv->ring.Size);
+
+ I915_WRITE(LP_RING + RING_START, dev_priv->ring.Start);
+ I915_WRITE(LP_RING + RING_LEN,
+ ((dev_priv->ring.Size - 4096) & RING_NR_PAGES) |
+ (RING_NO_REPORT | RING_VALID));
+
+ /* We are using separate values as placeholders for mechanisms for
+ * private backbuffer/depthbuffer usage.
+ */
+ dev_priv->use_mi_batchbuffer_start = 0;
+
+ /* Allow hardware batchbuffers unless told otherwise.
+ */
+ dev_priv->allow_batchbuffer = 1;
+
+ /* Program Hardware Status Page */
+ if (!IS_G33(dev)) {
+ dev_priv->status_page_dmah =
+ drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+
+ if (!dev_priv->status_page_dmah) {
+ dev->dev_private = (void *)dev_priv;
+ i915_dma_cleanup(dev);
+ DRM_ERROR("Can not allocate hardware status page\n");
+ return -ENOMEM;
+ }
+ dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+ dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+
+ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+
+ I915_WRITE(I915REG_HWS_PGA, dev_priv->dma_status_page);
+ }
+ DRM_DEBUG("Enabled hardware status page\n");
- /* Allow hardware batchbuffers unless told otherwise.
- */
- dev_priv->allow_batchbuffer = 1;
-
- /* Program Hardware Status Page */
- if (!IS_G33(dev)) {
- dev_priv->status_page_dmah =
- drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
-
- if (!dev_priv->status_page_dmah) {
- dev->dev_private = (void *)dev_priv;
- i915_dma_cleanup(dev);
- DRM_ERROR("Can not allocate hardware status page\n");
- return -ENOMEM;
+ dev_priv->wq = create_singlethread_workqueue("i915");
+ if (dev_priv == 0) {
+ DRM_DEBUG("Error\n");
}
- dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
- dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+ intel_modeset_init(dev);
+ drm_initial_config(dev, false);
- I915_WRITE(I915REG_HWS_PGA, dev_priv->dma_status_page);
- }
- DRM_DEBUG("Enabled hardware status page\n");
+ drm_mm_print(&dev->bm.man[DRM_BO_MEM_VRAM].manager, "VRAM");
+ drm_mm_print(&dev->bm.man[DRM_BO_MEM_TT].manager, "TT");
- dev_priv->wq = create_singlethread_workqueue("i915");
- if (dev_priv == 0) {
- DRM_DEBUG("Error\n");
+ drm_irq_install(dev);
}
-
- intel_modeset_init(dev);
- drm_initial_config(dev, false);
-
- drm_mm_print(&dev->bm.man[DRM_BO_MEM_VRAM].manager, "VRAM");
- drm_mm_print(&dev->bm.man[DRM_BO_MEM_TT].manager, "TT");
-
- drm_irq_install(dev);
-
return 0;
}
@@ -262,7 +269,11 @@ int i915_driver_unload(struct drm_device *dev)
I915_WRITE(LP_RING + RING_LEN, 0);
- intel_modeset_cleanup(dev);
+
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ drm_irq_uninstall(dev);
+ intel_modeset_cleanup(dev);
+ }
#if 0
if (dev_priv->ring.virtual_start) {
@@ -298,25 +309,33 @@ int i915_driver_unload(struct drm_device *dev)
I915_WRITE(I915REG_HWS_PGA, 0x1ffff000);
}
- drm_mem_reg_iounmap(dev, &dev_priv->ring_buffer->mem,
- dev_priv->ring.virtual_start);
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ drm_mem_reg_iounmap(dev, &dev_priv->ring_buffer->mem,
+ dev_priv->ring.virtual_start);
- DRM_DEBUG("usage is %d\n", atomic_read(&dev_priv->ring_buffer->usage));
- mutex_lock(&dev->struct_mutex);
- drm_bo_usage_deref_locked(&dev_priv->ring_buffer);
+ DRM_DEBUG("usage is %d\n", atomic_read(&dev_priv->ring_buffer->usage));
+ mutex_lock(&dev->struct_mutex);
+ drm_bo_usage_deref_locked(&dev_priv->ring_buffer);
- if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) {
- DRM_ERROR("Memory manager type 3 not clean. "
- "Delaying takedown\n");
- }
- if (drm_bo_clean_mm(dev, DRM_BO_MEM_VRAM, 1)) {
- DRM_ERROR("Memory manager type 3 not clean. "
- "Delaying takedown\n");
+ if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) {
+ DRM_ERROR("Memory manager type 3 not clean. "
+ "Delaying takedown\n");
+ }
+ if (drm_bo_clean_mm(dev, DRM_BO_MEM_VRAM, 1)) {
+ DRM_ERROR("Memory manager type 3 not clean. "
+ "Delaying takedown\n");
+ }
+ mutex_unlock(&dev->struct_mutex);
}
- mutex_unlock(&dev->struct_mutex);
drm_bo_driver_finish(dev);
+#ifdef __linux__
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+ intel_init_chipset_flush_compat(dev);
+#endif
+#endif
+
DRM_DEBUG("%p\n", dev_priv->mmio_map);
drm_rmmap(dev, dev_priv->mmio_map);
@@ -363,3 +382,32 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
master->driver_priv = NULL;
}
+
+void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ i915_mem_release(dev, file_priv, dev_priv->agp_heap);
+}
+
+void i915_driver_lastclose(struct drm_device * dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return;
+
+ if (dev_priv->agp_heap)
+ i915_mem_takedown(&(dev_priv->agp_heap));
+
+ i915_dma_cleanup(dev);
+}
+
+int i915_driver_firstopen(struct drm_device *dev)
+{
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
+
+ drm_bo_driver_init(dev);
+ return 0;
+}
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index dad6ef86..b9d137f4 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -415,6 +415,13 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
if (i915_in_vblank(dev, pipe))
count++;
#endif
+ /* count may be reset by other driver(e.g. 2D driver),
+ we have no way to know if it is wrapped or resetted
+ when count is zero. do a rough guess.
+ */
+ if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2)
+ dev->last_vblank[pipe] = 0;
+
return count;
}
diff --git a/tests/mode/modetest.c b/tests/mode/modetest.c
index ab0cdc9c..a50b0cc5 100644
--- a/tests/mode/modetest.c
+++ b/tests/mode/modetest.c
@@ -291,7 +291,7 @@ int testFrameBufferAdd(int fd, drmModeResPtr res)
goto err;
printf("\tAdding FB\n");
- ret = drmModeAddFB(fd, 800, 600, 32, 8, 0, &bo, &fb);
+ ret = drmModeAddFB(fd, 800, 600, 32, 8, 0, bo->handle, &fb);
if (ret)
goto err_bo;
diff --git a/tests/modedemo/demo.c b/tests/modedemo/demo.c
index db51cd66..83a33aa6 100644
--- a/tests/modedemo/demo.c
+++ b/tests/modedemo/demo.c
@@ -429,7 +429,7 @@ void demoUpdateRes(struct demo_driver *driver)
int demoFindConnectedOutputs(struct demo_driver *driver, drmModeOutputPtr *out, size_t max_out)
{
int count = 0;
- int i;
+ int i,j;
int fd = driver->fd;
drmModeResPtr res = driver->res;
@@ -441,10 +441,20 @@ int demoFindConnectedOutputs(struct demo_driver *driver, drmModeOutputPtr *out,
if (!output)
continue;
- if (output->connection != DRM_MODE_CONNECTED) {
+ if (output->connection == DRM_MODE_DISCONNECTED) {
drmModeFreeOutput(output);
continue;
}
+
+ for (j = 0; j < output->count_props; j++) {
+ drmModePropertyPtr prop;
+
+ prop = drmModeGetProperty(fd, output->props[j]);
+
+ printf("Property: %s\n",prop->name);
+ if (prop->count_enums)
+ printf("%s\n",prop->enums[output->prop_values[j]].name);
+ }
out[count++] = output;
}
@@ -483,7 +493,7 @@ drmModeFBPtr createFB(int fd, drmModeResPtr res)
goto err;
}
- ret = drmModeAddFB(fd, SIZE_X, SIZE_Y, 32, 32, PITCH * 4, &bo, &fb);
+ ret = drmModeAddFB(fd, SIZE_X, SIZE_Y, 32, 32, PITCH * 4, bo.handle, &fb);
if (ret)
goto err_bo;