diff options
| -rw-r--r-- | libdrm/xf86drm.c | 23 | ||||
| -rw-r--r-- | libdrm/xf86drmMode.c | 106 | ||||
| -rw-r--r-- | libdrm/xf86drmMode.h | 3 | ||||
| -rw-r--r-- | linux-core/ati_pcigart.c | 6 | ||||
| -rw-r--r-- | linux-core/drmP.h | 6 | ||||
| -rw-r--r-- | linux-core/drm_agpsupport.c | 2 | ||||
| -rw-r--r-- | linux-core/drm_bo.c | 5 | ||||
| -rw-r--r-- | linux-core/drm_bo_move.c | 33 | ||||
| -rw-r--r-- | linux-core/drm_compat.c | 29 | ||||
| -rw-r--r-- | linux-core/drm_compat.h | 10 | ||||
| -rw-r--r-- | linux-core/drm_crtc.c | 38 | ||||
| -rw-r--r-- | linux-core/drm_drv.c | 18 | ||||
| -rw-r--r-- | linux-core/drm_edid.c | 28 | ||||
| -rw-r--r-- | linux-core/drm_fops.c | 3 | ||||
| -rw-r--r-- | linux-core/drm_irq.c | 4 | ||||
| -rw-r--r-- | linux-core/drm_objects.h | 8 | ||||
| -rw-r--r-- | linux-core/drm_scatter.c | 11 | ||||
| -rw-r--r-- | linux-core/drm_stub.c | 9 | ||||
| -rw-r--r-- | linux-core/drm_ttm.c | 21 | ||||
| -rw-r--r-- | linux-core/drm_vm.c | 19 | ||||
| -rw-r--r-- | linux-core/i915_drv.c | 15 | ||||
| -rw-r--r-- | linux-core/intel_fb.c | 31 | ||||
| -rw-r--r-- | shared-core/drm.h | 21 | ||||
| -rw-r--r-- | shared-core/i915_dma.c | 79 | ||||
| -rw-r--r-- | shared-core/i915_drm.h | 2 | ||||
| -rw-r--r-- | shared-core/i915_init.c | 236 | ||||
| -rw-r--r-- | shared-core/i915_irq.c | 7 | ||||
| -rw-r--r-- | tests/mode/modetest.c | 2 | ||||
| -rw-r--r-- | tests/modedemo/demo.c | 16 | 
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;  | 
