Merge branch 'modesetting-101' of ssh://git.freedesktop.org/git/mesa/drm into modesetting-101

main
Jerome Glisse 2008-03-10 23:36:27 +01:00 committed by John Doe
commit a7e6ca62ad
29 changed files with 561 additions and 226 deletions

View File

@ -2809,18 +2809,13 @@ int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint)
int drmBOBusy(int fd, drmBO *buf, int *busy) int drmBOBusy(int fd, drmBO *buf, int *busy)
{ {
if (!(buf->flags & DRM_BO_FLAG_SHAREABLE) && int ret = drmBOInfo(fd, buf);
!(buf->replyFlags & DRM_BO_REP_BUSY)) {
*busy = 0; if (ret)
return 0; return ret;
}
else { *busy = (buf->replyFlags & DRM_BO_REP_BUSY);
int ret = drmBOInfo(fd, buf); return 0;
if (ret)
return ret;
*busy = (buf->replyFlags & DRM_BO_REP_BUSY);
return 0;
}
} }
int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize, int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,

View File

@ -36,11 +36,15 @@
* platforms find which headers to include to get uint32_t * platforms find which headers to include to get uint32_t
*/ */
#include <stdint.h> #include <stdint.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include "xf86drmMode.h" #include "xf86drmMode.h"
#include "xf86drm.h" #include "xf86drm.h"
#include <drm.h> #include <drm.h>
#include <string.h> #include <string.h>
#include <dirent.h>
#include <errno.h>
#define U642VOID(x) ((void *)(unsigned long)(x)) #define U642VOID(x) ((void *)(unsigned long)(x))
#define VOID2U64(x) ((uint64_t)(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; 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. * A couple of free functions.
*/ */
@ -143,7 +126,6 @@ void drmModeFreeOutput(drmModeOutputPtr ptr)
drmModeResPtr drmModeGetResources(int fd) drmModeResPtr drmModeGetResources(int fd)
{ {
struct drm_mode_card_res res; struct drm_mode_card_res res;
int i;
drmModeResPtr r = 0; drmModeResPtr r = 0;
memset(&res, 0, sizeof(struct drm_mode_card_res)); 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, 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; struct drm_mode_fb_cmd f;
int ret; int ret;
@ -211,9 +194,9 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
f.pitch = pitch; f.pitch = pitch;
f.bpp = bpp; f.bpp = bpp;
f.depth = depth; 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; return ret;
*buf_id = f.buffer_id; *buf_id = f.buffer_id;
@ -260,7 +243,6 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
{ {
struct drm_mode_crtc crtc; struct drm_mode_crtc crtc;
drmModeCrtcPtr r; drmModeCrtcPtr r;
int i = 0;
crtc.count_outputs = 0; crtc.count_outputs = 0;
crtc.outputs = 0; crtc.outputs = 0;
@ -293,10 +275,6 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
r->possibles = crtc.possibles; r->possibles = crtc.possibles;
return r; return r;
err_allocs:
return 0;
} }
@ -450,8 +428,7 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
{ {
struct drm_mode_get_property prop; struct drm_mode_get_property prop;
drmModePropertyPtr r; drmModePropertyPtr r;
struct drm_mode_property_blob *blob_tmp;
int i;
prop.prop_id = property_id; prop.prop_id = property_id;
prop.count_enum_blobs = 0; prop.count_enum_blobs = 0;
prop.count_values = 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.prop_id = property_id;
osp.value = value; osp.value = value;
if (ret = ioctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)) if ((ret = ioctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)))
return ret; return ret;
return 0; 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;
}

View File

@ -177,7 +177,7 @@ extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
* Creates a new framebuffer with an buffer object as its scanout buffer. * 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, 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); uint32_t *buf_id);
/** /**
* Destroies the given framebuffer. * Destroies the given framebuffer.
@ -243,3 +243,4 @@ extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id);
extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr); extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr);
extern int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id, extern int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id,
uint64_t value); uint64_t value);
extern int drmCheckModesettingSupported(const char *busid);

View File

@ -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; ret = 1;
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)

View File

@ -106,6 +106,7 @@ struct drm_file;
#define DRIVER_IRQ_SHARED 0x80 #define DRIVER_IRQ_SHARED 0x80
#define DRIVER_DMA_QUEUE 0x100 #define DRIVER_DMA_QUEUE 0x100
#define DRIVER_FB_DMA 0x200 #define DRIVER_FB_DMA 0x200
#define DRIVER_MODESET 0x400
/*@}*/ /*@}*/
@ -760,9 +761,10 @@ struct drm_driver {
}; };
#define DRM_MINOR_UNASSIGNED 0 #define DRM_MINOR_UNASSIGNED 0
#define DRM_MINOR_CONTROL 1 #define DRM_MINOR_LEGACY 1
#define DRM_MINOR_LEGACY 2 #define DRM_MINOR_CONTROL 2
#define DRM_MINOR_RENDER 3 #define DRM_MINOR_RENDER 3
/** /**
* DRM minor structure. This structure represents a drm minor number. * DRM minor structure. This structure represents a drm minor number.
*/ */

View File

@ -666,7 +666,7 @@ void drm_agp_chipset_flush(struct drm_device *dev)
{ {
agp_flush_chipset(dev->agp->bridge); agp_flush_chipset(dev->agp->bridge);
} }
EXPORT_SYMBOL(drm_agp_flush_chipset); EXPORT_SYMBOL(drm_agp_chipset_flush);
#endif #endif
#endif /* __OS_HAS_AGP */ #endif /* __OS_HAS_AGP */

View File

@ -969,7 +969,7 @@ static int drm_bo_modify_proposed_flags (struct drm_buffer_object *bo,
return -EINVAL; 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"); DRM_ERROR("DRM_BO_FLAG_NO_EVICT is only available to priviliged processes.\n");
return -EPERM; return -EPERM;
} }
@ -1065,7 +1065,7 @@ static int drm_bo_busy(struct drm_buffer_object *bo)
return 0; 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; int ret = 0;
@ -1075,6 +1075,7 @@ static int drm_bo_evict_cached(struct drm_buffer_object *bo)
return ret; return ret;
} }
EXPORT_SYMBOL(drm_bo_evict_cached);
/* /*
* Wait until a buffer is unmapped. * Wait until a buffer is unmapped.
*/ */

View File

@ -596,3 +596,36 @@ void drm_bo_kunmap(struct drm_bo_kmap_obj *map)
map->page = NULL; map->page = NULL;
} }
EXPORT_SYMBOL(drm_bo_kunmap); 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);

View File

@ -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); EXPORT_SYMBOL(pci_get_bus_and_slot);
#endif #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

View File

@ -343,4 +343,14 @@ extern struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devf
#define PM_EVENT_PRETHAW 3 #define PM_EVENT_PRETHAW 3
#endif #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 #endif

View File

@ -48,7 +48,8 @@ static struct drm_prop_enum_list drm_dpms_enum_list[] =
{ DPMSModeOff, "Off" } { DPMSModeOff, "Off" }
}; };
static struct drm_prop_enum_list drm_conn_enum_list[] = static struct drm_prop_enum_list drm_conn_enum_list[] =
{ { ConnectorVGA, "VGA" }, { { ConnectorUnknown, "Unknown" },
{ ConnectorVGA, "VGA" },
{ ConnectorDVII, "DVI-I" }, { ConnectorDVII, "DVI-I" },
{ ConnectorDVID, "DVI-D" }, { ConnectorDVID, "DVI-D" },
{ ConnectorDVIA, "DVI-A" }, { 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; int saved_x, saved_y;
bool didLock = false; bool didLock = false;
struct drm_output *output; struct drm_output *output;
bool ret = true;
adjusted_mode = drm_mode_duplicate(dev, mode); adjusted_mode = drm_mode_duplicate(dev, mode);
crtc->enabled = drm_crtc_in_use(crtc); crtc->enabled = drm_crtc_in_use(crtc);
if (!crtc->enabled) { if (!crtc->enabled)
return true; return true;
}
didLock = crtc->funcs->lock(crtc); 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) if (output->crtc != crtc)
continue; continue;
if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { if (!(ret = output->funcs->mode_fixup(output, mode, adjusted_mode))) {
goto done; goto done;
} }
} }
if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { if (!(ret = crtc->funcs->mode_fixup(crtc, mode, adjusted_mode))) {
goto done; 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); // drm_crtc_set_screen_sub_pixel_order(dev);
done: done:
if (!ret) {
crtc->mode = saved_mode;
crtc->x = saved_x;
crtc->y = saved_y;
}
if (didLock) if (didLock)
crtc->funcs->unlock (crtc); crtc->funcs->unlock (crtc);
return true; return ret;
} }
EXPORT_SYMBOL(drm_crtc_set_mode); EXPORT_SYMBOL(drm_crtc_set_mode);
@ -728,20 +735,20 @@ static int drm_mode_create_standard_output_properties(struct drm_device *dev)
"EDID", 0); "EDID", 0);
dev->mode_config.dpms_property = 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++) 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); 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 = dev->mode_config.connector_type_property =
drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE, 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++) 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); 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 = dev->mode_config.connector_num_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE, 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[0] = 0;
dev->mode_config.connector_num_property->values[1] = 20; 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[0] = 0;
dev->mode_config.tv_bottom_margin_property->values[1] = 100; dev->mode_config.tv_bottom_margin_property->values[1] = 100;
return 0; 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 /* We should be able to check here if the fb has the same properties
* and then just flip_or_move it */ * and then just flip_or_move it */
if (crtc->fb != fb) if (crtc->fb != fb)
changed = true; flip_or_move = true;
if (crtc_info->x != crtc->x || crtc_info->y != crtc->y) if (crtc_info->x != crtc->x || crtc_info->y != crtc->y)
flip_or_move = true; 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; changed = true;
}
list_for_each_entry(output, &dev->mode_config.output_list, head) { list_for_each_entry(output, &dev->mode_config.output_list, head) {
save_crtcs[count++] = output->crtc; 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); drm_disable_unused_functions(dev);
} else if (flip_or_move) { } else if (flip_or_move) {
if (crtc->fb != fb)
crtc->fb = fb;
crtc->funcs->mode_set_base(crtc, crtc_info->x, crtc_info->y); crtc->funcs->mode_set_base(crtc, crtc_info->x, crtc_info->y);
} }

View File

@ -187,7 +187,9 @@ int drm_lastclose(struct drm_device * dev)
DRM_DEBUG("\n"); 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. * 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_ht_remove(&dev->object_hash);
drm_put_minor(&dev->primary); 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)) if (drm_put_dev(dev))
DRM_ERROR("Cannot unload module\n"); 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_minor *minor = ptr;
struct drm_device *dev; struct drm_device *dev;
struct drm_driver *driver = data; struct drm_driver *driver = data;
if (id < 127 || id > 192)
return 0;
dev = minor->dev; dev = minor->dev;
if (minor->dev->driver != driver) if (minor->dev->driver != driver)
return 0; 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) if (dev)
pci_dev_put(dev->pdev); pci_dev_put(dev->pdev);
drm_cleanup(dev); drm_cleanup(dev);

View File

@ -223,8 +223,10 @@ static int add_established_modes(struct drm_output *output, struct edid *edid)
if (est_bits & (1<<i)) { if (est_bits & (1<<i)) {
struct drm_display_mode *newmode; struct drm_display_mode *newmode;
newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); newmode = drm_mode_duplicate(dev, &edid_est_modes[i]);
drm_mode_probed_add(output, newmode); if (newmode) {
modes++; drm_mode_probed_add(output, newmode);
modes++;
}
} }
return modes; return modes;
@ -251,8 +253,10 @@ static int add_standard_modes(struct drm_output *output, struct edid *edid)
continue; continue;
newmode = drm_mode_std(dev, &edid->standard_timings[i]); newmode = drm_mode_std(dev, &edid->standard_timings[i]);
drm_mode_probed_add(output, newmode); if (newmode) {
modes++; drm_mode_probed_add(output, newmode);
modes++;
}
} }
return modes; return modes;
@ -283,11 +287,13 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
if (timing->pixel_clock) { if (timing->pixel_clock) {
newmode = drm_mode_detailed(dev, timing); newmode = drm_mode_detailed(dev, timing);
/* First detailed mode is preferred */ /* First detailed mode is preferred */
if (i == 0 && edid->preferred_timing) if (newmode) {
newmode->type |= DRM_MODE_TYPE_PREFERRED; if (i == 0 && edid->preferred_timing)
drm_mode_probed_add(output, newmode); newmode->type |= DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(output, newmode);
modes++; modes++;
}
continue; continue;
} }
@ -312,8 +318,10 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
std = &data->data.timings[j]; std = &data->data.timings[j];
newmode = drm_mode_std(dev, std); newmode = drm_mode_std(dev, std);
drm_mode_probed_add(output, newmode); if (newmode) {
modes++; drm_mode_probed_add(output, newmode);
modes++;
}
} }
break; break;
default: default:

View File

@ -481,7 +481,8 @@ int drm_release(struct inode *inode, struct file *filp)
} }
mutex_unlock(&dev->ctxlist_mutex); 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; file_priv->master = NULL;

View File

@ -306,6 +306,8 @@ int drm_control(struct drm_device *dev, void *data,
case DRM_INST_HANDLER: case DRM_INST_HANDLER:
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return 0; return 0;
if (drm_core_check_feature(dev, DRIVER_MODESET))
return 0;
if (dev->if_version < DRM_IF_VERSION(1, 2) && if (dev->if_version < DRM_IF_VERSION(1, 2) &&
ctl->irq != dev->irq) ctl->irq != dev->irq)
return -EINVAL; return -EINVAL;
@ -313,6 +315,8 @@ int drm_control(struct drm_device *dev, void *data,
case DRM_UNINST_HANDLER: case DRM_UNINST_HANDLER:
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return 0; return 0;
if (drm_core_check_feature(dev, DRIVER_MODESET))
return 0;
return drm_irq_uninstall(dev); return drm_irq_uninstall(dev);
default: default:
return -EINVAL; return -EINVAL;

View File

@ -383,7 +383,7 @@ extern int drm_ttm_destroy(struct drm_ttm *ttm);
* The array of page pointers was allocated with vmalloc * The array of page pointers was allocated with vmalloc
* instead of drm_calloc. * 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 * 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, uint64_t flags, uint64_t mask, uint32_t hint,
uint32_t fence_class, uint32_t fence_class,
struct drm_bo_info_rep *rep); struct drm_bo_info_rep *rep);
extern int drm_bo_evict_cached(struct drm_buffer_object *bo);
/* /*
* Buffer object memory move- and map helpers. * Buffer object memory move- and map helpers.
* drm_bo_move.c * 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 void drm_bo_kunmap(struct drm_bo_kmap_obj *map);
extern int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page, extern int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page,
unsigned long num_pages, struct drm_bo_kmap_obj *map); 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);
/* /*

View File

@ -36,6 +36,15 @@
#define DEBUG_SCATTER 0 #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) void drm_sg_cleanup(struct drm_sg_mem *entry)
{ {
struct page *page; 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)); 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) { if (!entry->virtual) {
drm_free(entry->busaddr, drm_free(entry->busaddr,
entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES); entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);

View File

@ -343,8 +343,10 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
goto err_g3; goto err_g3;
} }
if ((ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL))) /* only add the control node on a modesetting platform */
goto err_g3; 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))) if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
goto err_g4; goto err_g4;
@ -361,7 +363,8 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
err_g5: err_g5:
drm_put_minor(&dev->primary); drm_put_minor(&dev->primary);
err_g4: err_g4:
drm_put_minor(&dev->control); if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_put_minor(&dev->control);
err_g3: err_g3:
if (!drm_fb_loaded) if (!drm_fb_loaded)
pci_disable_device(pdev); pci_disable_device(pdev);

View File

@ -42,11 +42,12 @@ void drm_ttm_cache_flush(void)
} }
EXPORT_SYMBOL(drm_ttm_cache_flush); 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_page_directory(struct drm_ttm *ttm)
static void drm_ttm_alloc_pages(struct drm_ttm *ttm)
{ {
unsigned long size = ttm->num_pages * sizeof(*ttm->pages); unsigned long size = ttm->num_pages * sizeof(*ttm->pages);
ttm->pages = NULL; ttm->pages = NULL;
@ -60,19 +61,19 @@ static void drm_ttm_alloc_pages(struct drm_ttm *ttm)
if (!ttm->pages) { if (!ttm->pages) {
ttm->pages = vmalloc_user(size); ttm->pages = vmalloc_user(size);
if (ttm->pages) if (ttm->pages)
ttm->page_flags |= DRM_TTM_PAGE_VMALLOC; ttm->page_flags |= DRM_TTM_PAGEDIR_VMALLOC;
} }
if (!ttm->pages) if (!ttm->pages)
drm_free_memctl(size); 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); 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); vfree(ttm->pages);
ttm->page_flags &= ~DRM_TTM_PAGE_VMALLOC; ttm->page_flags &= ~DRM_TTM_PAGEDIR_VMALLOC;
} else { } else {
drm_free(ttm->pages, size, DRM_MEM_TTM); drm_free(ttm->pages, size, DRM_MEM_TTM);
} }
@ -215,7 +216,7 @@ int drm_ttm_destroy(struct drm_ttm *ttm)
else else
drm_ttm_free_alloced_pages(ttm); 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); 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. * Account also for AGP module memory usage.
*/ */
drm_ttm_alloc_pages(ttm); drm_ttm_alloc_page_directory(ttm);
if (!ttm->pages) { if (!ttm->pages) {
drm_ttm_destroy(ttm); drm_ttm_destroy(ttm);
DRM_ERROR("Failed allocating page table\n"); DRM_ERROR("Failed allocating page table\n");

View File

@ -59,17 +59,27 @@ pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
pgprot_val(tmp) |= _PAGE_NO_CACHE; pgprot_val(tmp) |= _PAGE_NO_CACHE;
if (map_type == _DRM_REGISTERS) if (map_type == _DRM_REGISTERS)
pgprot_val(tmp) |= _PAGE_GUARDED; pgprot_val(tmp) |= _PAGE_GUARDED;
#endif #elif defined(__ia64__)
#if defined(__ia64__)
if (efi_range_is_wc(vma->vm_start, vma->vm_end - if (efi_range_is_wc(vma->vm_start, vma->vm_end -
vma->vm_start)) vma->vm_start))
tmp = pgprot_writecombine(tmp); tmp = pgprot_writecombine(tmp);
else else
tmp = pgprot_noncached(tmp); tmp = pgprot_noncached(tmp);
#elif defined(__sparc__)
tmp = pgprot_noncached(tmp);
#endif #endif
return tmp; 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. * \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); offset = dev->driver->get_reg_ofs(dev);
vma->vm_flags |= VM_IO; /* not in core dump */ vma->vm_flags |= VM_IO; /* not in core dump */
vma->vm_page_prot = drm_io_prot(map->type, vma); 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, if (io_remap_pfn_range(vma, vma->vm_start,
(map->offset + offset) >> PAGE_SHIFT, (map->offset + offset) >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, 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)), page_to_pfn(virt_to_page(map->handle)),
vma->vm_end - vma->vm_start, vma->vm_page_prot)) vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN; return -EAGAIN;
vma->vm_page_prot = drm_dma_prot(map->type, vma);
/* fall through to _DRM_SHM */ /* fall through to _DRM_SHM */
case _DRM_SHM: case _DRM_SHM:
vma->vm_ops = &drm_vm_shm_ops; 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_ops = &drm_vm_sg_ops;
vma->vm_private_data = (void *)map; vma->vm_private_data = (void *)map;
vma->vm_flags |= VM_RESERVED; vma->vm_flags |= VM_RESERVED;
vma->vm_page_prot = drm_dma_prot(map->type, vma);
break; break;
case _DRM_TTM: case _DRM_TTM:
return drm_bo_mmap_locked(vma, filp, map); return drm_bo_mmap_locked(vma, filp, map);

View File

@ -39,14 +39,17 @@ static struct pci_device_id pciidlist[] = {
i915_PCI_IDS i915_PCI_IDS
}; };
unsigned int i915_modeset = 0;
module_param_named(modeset, i915_modeset, int, 0400);
#ifdef I915_HAVE_FENCE #ifdef I915_HAVE_FENCE
extern struct drm_fence_driver i915_fence_driver; extern struct drm_fence_driver i915_fence_driver;
#endif #endif
#ifdef I915_HAVE_BUFFER #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_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_PRIV0, DRM_BO_MEM_VRAM, 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 = { static struct drm_bo_driver i915_bo_driver = {
.mem_type_prio = i915_mem_prios, .mem_type_prio = i915_mem_prios,
@ -563,8 +566,9 @@ static struct drm_driver driver = {
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
.load = i915_driver_load, .load = i915_driver_load,
.unload = i915_driver_unload, .unload = i915_driver_unload,
/* .lastclose = i915_driver_lastclose, .firstopen = i915_driver_firstopen,
.preclose = i915_driver_preclose, */ .lastclose = i915_driver_lastclose,
.preclose = i915_driver_preclose,
.suspend = i915_suspend, .suspend = i915_suspend,
.resume = i915_resume, .resume = i915_resume,
.device_is_agp = i915_driver_device_is_agp, .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) static int __init i915_init(void)
{ {
driver.num_ioctls = i915_max_ioctl; driver.num_ioctls = i915_max_ioctl;
if (i915_modeset == 1)
driver.driver_features |= DRIVER_MODESET;
return drm_init(&driver, pciidlist); return drm_init(&driver, pciidlist);
} }

View File

@ -228,6 +228,7 @@ static int intelfb_set_par(struct fb_info *info)
struct drm_output *output = NULL; struct drm_output *output = NULL;
struct fb_var_screeninfo *var = &info->var; struct fb_var_screeninfo *var = &info->var;
int found = 0; int found = 0;
int changed = 0;
DRM_DEBUG("\n"); DRM_DEBUG("\n");
@ -310,11 +311,22 @@ static int intelfb_set_par(struct fb_info *info)
} }
/* re-attach fb */ /* re-attach fb */
if (!par->crtc->fb) if (!par->crtc->fb) {
par->crtc->fb = par->fb; par->crtc->fb = par->fb;
changed = 1;
}
if (!drm_crtc_set_mode(par->crtc, drm_mode, var->xoffset, var->yoffset)) if (par->crtc->x != var->xoffset || par->crtc->y != var->yoffset)
return -EINVAL; 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; return 0;
} }
@ -469,16 +481,21 @@ static int intelfb_pan_display(struct fb_var_screeninfo *var,
{ {
struct intelfb_par *par = info->par; struct intelfb_par *par = info->par;
struct drm_crtc *crtc = par->crtc; struct drm_crtc *crtc = par->crtc;
int changed = 0;
DRM_DEBUG("\n"); DRM_DEBUG("\n");
/* TODO add check size and pos*/ /* TODO add check size and pos*/
if (par->crtc->x != var->xoffset || par->crtc->y != var->yoffset)
changed = 1;
/* re-attach fb */ /* re-attach fb */
if (!crtc->fb) if (!crtc->fb) {
crtc->fb = par->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.xoffset = var->xoffset;
info->var.yoffset = var->yoffset; 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->bits_per_pixel = 32;
fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8); fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8);
fb->depth = 24; 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_type_kernel,
DRM_BO_FLAG_READ | DRM_BO_FLAG_READ |
DRM_BO_FLAG_WRITE | DRM_BO_FLAG_WRITE |

View File

@ -645,8 +645,14 @@ struct drm_set_version {
#define DRM_FENCE_FLAG_EMIT 0x00000001 #define DRM_FENCE_FLAG_EMIT 0x00000001
#define DRM_FENCE_FLAG_SHAREABLE 0x00000002 #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_LAZY 0x00000004
#define DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS 0x00000008
#define DRM_FENCE_FLAG_NO_USER 0x00000010 #define DRM_FENCE_FLAG_NO_USER 0x00000010
/* Reserved for driver use */ /* Reserved for driver use */
@ -795,13 +801,12 @@ struct drm_fence_arg {
* with it as a result of this operation * with it as a result of this operation
*/ */
#define DRM_BO_HINT_DONT_FENCE 0x00000004 #define DRM_BO_HINT_DONT_FENCE 0x00000004
/* /**
* Sleep while waiting for the operation to complete. * On hardware with no interrupt events for operation completion,
* Without this flag, the kernel will, instead, spin * indicates that the kernel should sleep while waiting for any blocking
* until this operation has completed. I'm not sure * operation to complete rather than spinning.
* why you would ever want this, so please always *
* provide DRM_BO_HINT_WAIT_LAZY to any operation * Has no effect otherwise.
* which may block
*/ */
#define DRM_BO_HINT_WAIT_LAZY 0x00000008 #define DRM_BO_HINT_WAIT_LAZY 0x00000008
/* /*

View File

@ -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_private *dev_priv = dev->dev_private;
struct drm_i915_ring_buffer *ring = &(dev_priv->ring); 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->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR; ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
ring->space = ring->head - (ring->tail + 8); 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) 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 /* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private * may not have been called from userspace and after dev_private
* is freed, it's too late. * is freed, it's too late.
@ -82,6 +92,28 @@ int i915_dma_cleanup(struct drm_device * dev)
if (dev->irq) if (dev->irq)
drm_irq_uninstall(dev); 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; 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_private *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
if (!dev_priv->mmio_map) { if (init->mmio_offset != 0)
i915_dma_cleanup(dev); dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
DRM_ERROR("can not find mmio map!\n"); if (!dev_priv->mmio_map) {
return -EINVAL; i915_dma_cleanup(dev);
DRM_ERROR("can not find mmio map!\n");
return -EINVAL;
}
} }
#ifdef I915_HAVE_BUFFER #ifdef I915_HAVE_BUFFER
dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS; dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS;
#endif #endif
@ -246,6 +282,9 @@ static int i915_dma_resume(struct drm_device * dev)
DRM_DEBUG("\n"); DRM_DEBUG("\n");
if (drm_core_check_feature(dev, DRIVER_MODESET))
return 0;
if (!dev_priv->mmio_map) { if (!dev_priv->mmio_map) {
DRM_ERROR("can not find mmio map!\n"); DRM_ERROR("can not find mmio map!\n");
return -EINVAL; return -EINVAL;
@ -765,6 +804,8 @@ struct i915_relocatee_info {
unsigned page_offset; unsigned page_offset;
struct drm_bo_kmap_obj kmap; struct drm_bo_kmap_obj kmap;
int is_iomem; int is_iomem;
int idle;
int evicted;
}; };
struct drm_i915_validate_buffer { 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); drm_bo_kunmap(&relocatee->kmap);
relocatee->data_page = NULL; relocatee->data_page = NULL;
relocatee->offset = new_cmd_offset; 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, ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT,
1, &relocatee->kmap); 1, &relocatee->kmap);
if (ret) { 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->data_page = drm_bmo_virtual(&relocatee->kmap,
&relocatee->is_iomem); &relocatee->is_iomem);
relocatee->page_offset = (relocatee->offset & PAGE_MASK); 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; 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); mutex_lock (&relocatee.buf->mutex);
ret = drm_bo_wait (relocatee.buf, 0, 0, FALSE);
if (ret)
goto out_err1;
while (reloc_user_ptr) { while (reloc_user_ptr) {
ret = i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, &relocatee, buffers, buf_count); ret = i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, &relocatee, buffers, buf_count);
if (ret) { if (ret) {
@ -1430,6 +1481,16 @@ drm_i915_mmio_entry_t mmio_table[] = {
I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE, I915_MMIO_MAY_READ|I915_MMIO_MAY_WRITE,
0x30010, 0x30010,
6 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
} }
}; };

View File

@ -328,6 +328,8 @@ typedef struct drm_i915_vblank_swap {
#define MMIO_REGS_PS_DEPTH_COUNT 8 #define MMIO_REGS_PS_DEPTH_COUNT 8
#define MMIO_REGS_DOVSTA 9 #define MMIO_REGS_DOVSTA 9
#define MMIO_REGS_GAMMA 10 #define MMIO_REGS_GAMMA 10
#define MMIO_REGS_FENCE 11
#define MMIO_REGS_FENCE_NEW 12
typedef struct drm_i915_mmio_entry { typedef struct drm_i915_mmio_entry {
unsigned int flag; unsigned int flag;

View File

@ -153,105 +153,112 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
DRM_DEBUG("fb_base: 0x%08lx\n", dev->mode_config.fb_base); DRM_DEBUG("fb_base: 0x%08lx\n", dev->mode_config.fb_base);
ret = drm_addmap(dev, dev_priv->mmiobase, dev_priv->mmiolen, 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) { if (ret != 0) {
DRM_ERROR("Cannot add mapping for MMIO registers\n"); DRM_ERROR("Cannot add mapping for MMIO registers\n");
return ret; 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 * Initialize the memory manager for local and AGP space
*/ */
drm_bo_driver_init(dev); drm_bo_driver_init(dev);
i915_probe_agp(dev->pdev, &agp_size, &prealloc_size); if (drm_core_check_feature(dev, DRIVER_MODESET)) {
printk("setting up %ld bytes of VRAM space\n", prealloc_size); i915_probe_agp(dev->pdev, &agp_size, &prealloc_size);
printk("setting up %ld bytes of TT space\n", (agp_size - prealloc_size)); printk("setting up %ld bytes of VRAM space\n", prealloc_size);
drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, prealloc_size >> PAGE_SHIFT, 1); printk("setting up %ld bytes of TT space\n", (agp_size - prealloc_size));
drm_bo_init_mm(dev, DRM_BO_MEM_TT, prealloc_size >> PAGE_SHIFT, (agp_size - prealloc_size) >> PAGE_SHIFT, 1); 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_LEN, 0);
I915_WRITE(LP_RING + RING_HEAD, 0); I915_WRITE(LP_RING + RING_HEAD, 0);
I915_WRITE(LP_RING + RING_TAIL, 0); I915_WRITE(LP_RING + RING_TAIL, 0);
size = PRIMARY_RINGBUFFER_SIZE; size = PRIMARY_RINGBUFFER_SIZE;
ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel, ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel,
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE |
DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_VRAM |
DRM_BO_FLAG_NO_EVICT, DRM_BO_FLAG_NO_EVICT,
DRM_BO_HINT_DONT_FENCE, 0x1, 0, DRM_BO_HINT_DONT_FENCE, 0x1, 0,
&dev_priv->ring_buffer); &dev_priv->ring_buffer);
if (ret < 0) { if (ret < 0) {
DRM_ERROR("Unable to allocate or pin ring buffer\n"); DRM_ERROR("Unable to allocate or pin ring buffer\n");
return -EINVAL; return -EINVAL;
} }
/* remap the buffer object properly */ /* remap the buffer object properly */
dev_priv->ring.Start = dev_priv->ring_buffer->offset; dev_priv->ring.Start = dev_priv->ring_buffer->offset;
dev_priv->ring.End = dev_priv->ring.Start + size; dev_priv->ring.End = dev_priv->ring.Start + size;
dev_priv->ring.Size = size; dev_priv->ring.Size = size;
dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
/* FIXME: need wrapper with PCI mem checks */ /* FIXME: need wrapper with PCI mem checks */
ret = drm_mem_reg_ioremap(dev, &dev_priv->ring_buffer->mem, ret = drm_mem_reg_ioremap(dev, &dev_priv->ring_buffer->mem,
(void **) &dev_priv->ring.virtual_start); (void **) &dev_priv->ring.virtual_start);
if (ret) if (ret)
DRM_ERROR("error mapping ring buffer: %d\n", ret); DRM_ERROR("error mapping ring buffer: %d\n", ret);
DRM_DEBUG("ring start %08lX, %p, %08lX\n", dev_priv->ring.Start, DRM_DEBUG("ring start %08lX, %p, %08lX\n", dev_priv->ring.Start,
dev_priv->ring.virtual_start, dev_priv->ring.Size); dev_priv->ring.virtual_start, dev_priv->ring.Size);
// //
memset((void *)(dev_priv->ring.virtual_start), 0, 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_START, dev_priv->ring.Start);
I915_WRITE(LP_RING + RING_LEN, I915_WRITE(LP_RING + RING_LEN,
((dev_priv->ring.Size - 4096) & RING_NR_PAGES) | ((dev_priv->ring.Size - 4096) & RING_NR_PAGES) |
(RING_NO_REPORT | RING_VALID)); (RING_NO_REPORT | RING_VALID));
/* We are using separate values as placeholders for mechanisms for /* We are using separate values as placeholders for mechanisms for
* private backbuffer/depthbuffer usage. * private backbuffer/depthbuffer usage.
*/ */
dev_priv->use_mi_batchbuffer_start = 0; dev_priv->use_mi_batchbuffer_start = 0;
/* Allow hardware batchbuffers unless told otherwise. /* Allow hardware batchbuffers unless told otherwise.
*/ */
dev_priv->allow_batchbuffer = 1; dev_priv->allow_batchbuffer = 1;
/* Program Hardware Status Page */ /* Program Hardware Status Page */
if (!IS_G33(dev)) { if (!IS_G33(dev)) {
dev_priv->status_page_dmah = dev_priv->status_page_dmah =
drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
if (!dev_priv->status_page_dmah) { if (!dev_priv->status_page_dmah) {
dev->dev_private = (void *)dev_priv; dev->dev_private = (void *)dev_priv;
i915_dma_cleanup(dev); i915_dma_cleanup(dev);
DRM_ERROR("Can not allocate hardware status page\n"); DRM_ERROR("Can not allocate hardware status page\n");
return -ENOMEM; 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);
} }
dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; DRM_DEBUG("Enabled hardware status page\n");
dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
memset(dev_priv->hw_status_page, 0, PAGE_SIZE); dev_priv->wq = create_singlethread_workqueue("i915");
if (dev_priv == 0) {
DRM_DEBUG("Error\n");
}
I915_WRITE(I915REG_HWS_PGA, dev_priv->dma_status_page); 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);
} }
DRM_DEBUG("Enabled hardware status page\n");
dev_priv->wq = create_singlethread_workqueue("i915");
if (dev_priv == 0) {
DRM_DEBUG("Error\n");
}
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; return 0;
} }
@ -262,7 +269,11 @@ int i915_driver_unload(struct drm_device *dev)
I915_WRITE(LP_RING + RING_LEN, 0); 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 0
if (dev_priv->ring.virtual_start) { if (dev_priv->ring.virtual_start) {
@ -298,25 +309,33 @@ int i915_driver_unload(struct drm_device *dev)
I915_WRITE(I915REG_HWS_PGA, 0x1ffff000); I915_WRITE(I915REG_HWS_PGA, 0x1ffff000);
} }
drm_mem_reg_iounmap(dev, &dev_priv->ring_buffer->mem, if (drm_core_check_feature(dev, DRIVER_MODESET)) {
dev_priv->ring.virtual_start); 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)); DRM_DEBUG("usage is %d\n", atomic_read(&dev_priv->ring_buffer->usage));
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
drm_bo_usage_deref_locked(&dev_priv->ring_buffer); drm_bo_usage_deref_locked(&dev_priv->ring_buffer);
if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) { if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) {
DRM_ERROR("Memory manager type 3 not clean. " DRM_ERROR("Memory manager type 3 not clean. "
"Delaying takedown\n"); "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);
} }
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);
drm_bo_driver_finish(dev); 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_DEBUG("%p\n", dev_priv->mmio_map);
drm_rmmap(dev, 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; 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;
}

View File

@ -415,6 +415,13 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
if (i915_in_vblank(dev, pipe)) if (i915_in_vblank(dev, pipe))
count++; count++;
#endif #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; return count;
} }

View File

@ -291,7 +291,7 @@ int testFrameBufferAdd(int fd, drmModeResPtr res)
goto err; goto err;
printf("\tAdding FB\n"); 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) if (ret)
goto err_bo; goto err_bo;

View File

@ -429,7 +429,7 @@ void demoUpdateRes(struct demo_driver *driver)
int demoFindConnectedOutputs(struct demo_driver *driver, drmModeOutputPtr *out, size_t max_out) int demoFindConnectedOutputs(struct demo_driver *driver, drmModeOutputPtr *out, size_t max_out)
{ {
int count = 0; int count = 0;
int i; int i,j;
int fd = driver->fd; int fd = driver->fd;
drmModeResPtr res = driver->res; drmModeResPtr res = driver->res;
@ -441,11 +441,21 @@ int demoFindConnectedOutputs(struct demo_driver *driver, drmModeOutputPtr *out,
if (!output) if (!output)
continue; continue;
if (output->connection != DRM_MODE_CONNECTED) { if (output->connection == DRM_MODE_DISCONNECTED) {
drmModeFreeOutput(output); drmModeFreeOutput(output);
continue; 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; out[count++] = output;
} }
@ -483,7 +493,7 @@ drmModeFBPtr createFB(int fd, drmModeResPtr res)
goto err; 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) if (ret)
goto err_bo; goto err_bo;