aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2009-10-20 15:52:30 +0200
committerThomas White <taw@bitwiz.org.uk>2010-02-09 23:37:32 +0100
commit6f3094073277b407b8eda06999c4842dcd0b7045 (patch)
tree669754a319e594ff5848c4f95414012a2148e87f
parent2f04ffc8dd97e15ce30358c3bf00cf6a0e7dcc19 (diff)
DRM for platform devices
This modifies the DRM core in a small number of places to allow platform devices to be used for direct rendering, alongside PCI devices. Signed-off-by: Thomas White <taw@bitwiz.org.uk>
-rw-r--r--drivers/gpu/drm/Kconfig2
-rw-r--r--drivers/gpu/drm/drm_bufs.c2
-rw-r--r--drivers/gpu/drm/drm_drv.c27
-rw-r--r--drivers/gpu/drm/drm_info.c27
-rw-r--r--drivers/gpu/drm/drm_ioctl.c118
-rw-r--r--drivers/gpu/drm/drm_stub.c76
-rw-r--r--drivers/gpu/drm/drm_sysfs.c6
-rw-r--r--include/drm/drmP.h13
8 files changed, 224 insertions, 47 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 96eddd17e05..8b050ade874 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -6,7 +6,7 @@
#
menuconfig DRM
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
- depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU
+ depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU
select I2C
select I2C_ALGOBIT
help
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index 3d09e304f6f..d7fd11a5786 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -188,7 +188,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
switch (map->type) {
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
-#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
+#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__arm__)
if (map->offset + (map->size-1) < map->offset ||
map->offset < virt_to_phys(high_memory)) {
kfree(map);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index a75ca63deea..26005d93ad0 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -247,6 +247,7 @@ int drm_lastclose(struct drm_device * dev)
*/
int drm_init(struct drm_driver *driver)
{
+#ifdef CONFIG_PCI
struct pci_dev *pdev = NULL;
const struct pci_device_id *pid;
int i;
@@ -280,11 +281,37 @@ int drm_init(struct drm_driver *driver)
drm_get_dev(pdev, pid, driver);
}
}
+#endif
return 0;
}
EXPORT_SYMBOL(drm_init);
+/**
+ * Call this to associate a drm_driver with a platform_device.
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * This is a replacement for drm_init(), but for platform drivers.
+ * In this case, the caller must provide the matching platform_device
+ *
+ * since there is no physical bus to scan through.
+ *
+ * \sa drm_init
+ *
+ */
+int drm_platform_init(struct drm_driver *driver, struct platform_device *pdev,
+ void *priv)
+{
+ DRM_DEBUG("\n");
+
+ INIT_LIST_HEAD(&driver->device_list);
+
+ return drm_get_platform_dev(pdev, driver, priv);
+}
+
+EXPORT_SYMBOL(drm_platform_init);
+
void drm_exit(struct drm_driver *driver)
{
struct drm_device *dev, *tmp;
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index f0f6c6b93f3..838c2ee2939 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -52,12 +52,28 @@ int drm_name_info(struct seq_file *m, void *data)
return 0;
if (master->unique) {
- seq_printf(m, "%s %s %s\n",
- dev->driver->pci_driver.name,
- pci_name(dev->pdev), master->unique);
+
+ if (drm_core_is_platform(dev)) {
+ seq_printf(m, "%s %s %s\n",
+ dev->driver->name,
+ dev_name(&dev->platform_dev->dev),
+ master->unique);
+ } else {
+ seq_printf(m, "%s %s %s\n",
+ dev->driver->pci_driver.name,
+ pci_name(dev->pdev), master->unique);
+ }
+
} else {
- seq_printf(m, "%s %s\n", dev->driver->pci_driver.name,
- pci_name(dev->pdev));
+
+ if (drm_core_is_platform(dev)) {
+ seq_printf(m, "%s %s\n", dev->driver->name,
+ dev_name(&dev->platform_dev->dev));
+ } else {
+ seq_printf(m, "%s %s\n", dev->driver->pci_driver.name,
+ pci_name(dev->pdev));
+ }
+
}
return 0;
@@ -325,4 +341,3 @@ int drm_vma_info(struct seq_file *m, void *data)
}
#endif
-
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 9b9ff46c237..133ef298de0 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -83,7 +83,6 @@ int drm_setunique(struct drm_device *dev, void *data,
{
struct drm_unique *u = data;
struct drm_master *master = file_priv->master;
- int domain, bus, slot, func, ret;
if (master->unique_len || master->unique)
return -EBUSY;
@@ -101,28 +100,46 @@ int drm_setunique(struct drm_device *dev, void *data,
master->unique[master->unique_len] = '\0';
- dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
- strlen(master->unique) + 2, GFP_KERNEL);
- if (!dev->devname)
- return -ENOMEM;
+ if ( !drm_core_is_platform(dev) ) {
- sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
- master->unique);
+ int domain, bus, slot, func, ret;
- /* Return error if the busid submitted doesn't match the device's actual
- * busid.
- */
- ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
- if (ret != 3)
- return -EINVAL;
- domain = bus >> 8;
- bus &= 0xff;
+ /* PCI device */
+ dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
+ strlen(master->unique) + 2, GFP_KERNEL);
+ if (!dev->devname)
+ return -ENOMEM;
- if ((domain != drm_get_pci_domain(dev)) ||
- (bus != dev->pdev->bus->number) ||
- (slot != PCI_SLOT(dev->pdev->devfn)) ||
- (func != PCI_FUNC(dev->pdev->devfn)))
- return -EINVAL;
+ sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
+ master->unique);
+
+ /* Return error if the busid submitted doesn't match the
+ * device's actual busid.
+ */
+ ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
+ if (ret != 3)
+ return -EINVAL;
+ domain = bus >> 8;
+ bus &= 0xff;
+
+ if ((domain != drm_get_pci_domain(dev)) ||
+ (bus != dev->pdev->bus->number) ||
+ (slot != PCI_SLOT(dev->pdev->devfn)) ||
+ (func != PCI_FUNC(dev->pdev->devfn)))
+ return -EINVAL;
+
+ } else {
+
+ /* Platform device */
+ dev->devname = kmalloc(strlen(dev->driver->name) +
+ strlen(master->unique) + 2, GFP_KERNEL);
+ if (!dev->devname)
+ return -ENOMEM;
+
+ sprintf(dev->devname, "%s@%s", dev->driver->name,
+ master->unique);
+
+ }
return 0;
}
@@ -141,23 +158,52 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
if (master->unique == NULL)
return -ENOMEM;
- len = snprintf(master->unique, master->unique_len, "pci:%04x:%02x:%02x.%d",
- drm_get_pci_domain(dev),
- dev->pdev->bus->number,
- PCI_SLOT(dev->pdev->devfn),
- PCI_FUNC(dev->pdev->devfn));
- if (len >= master->unique_len)
- DRM_ERROR("buffer overflow");
- else
- master->unique_len = len;
-
- dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
- master->unique_len + 2, GFP_KERNEL);
- if (dev->devname == NULL)
- return -ENOMEM;
+ if ( !drm_core_is_platform(dev) ) {
+
+ /* PCI device */
- sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
- master->unique);
+ len = snprintf(master->unique, master->unique_len,
+ "pci:%04x:%02x:%02x.%d",
+ drm_get_pci_domain(dev),
+ dev->pdev->bus->number,
+ PCI_SLOT(dev->pdev->devfn),
+ PCI_FUNC(dev->pdev->devfn));
+ if (len >= master->unique_len)
+ DRM_ERROR("buffer overflow");
+ else
+ master->unique_len = len;
+
+ dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
+ master->unique_len + 2, GFP_KERNEL);
+ if (dev->devname == NULL)
+ return -ENOMEM;
+
+ sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
+ master->unique);
+
+ } else {
+
+ /* Platform device */
+
+ int len;
+
+ len = snprintf(master->unique, master->unique_len,
+ "platform:%s", dev->platform_dev->name);
+
+ if (len >= master->unique_len)
+ DRM_ERROR("buffer overflow");
+ else
+ master->unique_len = len;
+
+ dev->devname = kmalloc(strlen(dev->driver->name)
+ + master->unique_len + 2, GFP_KERNEL);
+ if (dev->devname == NULL)
+ return -ENOMEM;
+
+ sprintf(dev->devname, "%s@%s", dev->driver->name,
+ master->unique);
+
+ }
return 0;
}
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 55bb8a82d61..5e3d65a350f 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -230,8 +230,10 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
idr_init(&dev->drw_idr);
dev->pdev = pdev;
- dev->pci_device = pdev->device;
- dev->pci_vendor = pdev->vendor;
+ if (pdev) {
+ dev->pci_device = pdev->device;
+ dev->pci_vendor = pdev->vendor;
+ }
#ifdef __alpha__
dev->hose = pdev->sysdata;
@@ -449,6 +451,76 @@ err_g1:
EXPORT_SYMBOL(drm_get_dev);
/**
+ *
+ * Register a platform device as a DRM device
+ *
+ * \param pdev - platform device structure
+ * \param driver - the matching drm_driver structure
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to gets inter module "drm" information. If we are first
+ * then register the character device and inter module information.
+ * Try and register, if we fail to register, backout previous work.
+ *
+ * \sa drm_get_dev
+ */
+int drm_get_platform_dev(struct platform_device *pdev,
+ struct drm_driver *driver, void *priv)
+{
+ struct drm_device *dev;
+ int ret;
+ DRM_DEBUG("\n");
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+ dev->dev_private = priv;
+
+ if ((ret = drm_fill_in_dev(dev, NULL, NULL, driver))) {
+ printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+ goto err_g1;
+ }
+ dev->platform_dev = pdev;
+
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
+ if (ret)
+ goto err_g2;
+ }
+
+ if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
+ goto err_g3;
+
+ if (dev->driver->load) {
+ ret = dev->driver->load(dev, 0);
+ if (ret)
+ goto err_g3;
+ }
+
+ /* setup the grouping for the legacy output */
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
+ if (ret)
+ goto err_g3;
+ }
+
+ list_add_tail(&dev->driver_item, &driver->device_list);
+
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+ driver->name, driver->major, driver->minor, driver->patchlevel,
+ driver->date, dev->primary->index);
+
+ return 0;
+
+err_g3:
+ drm_put_minor(&dev->primary);
+err_g2:
+err_g1:
+ kfree(dev);
+ return ret;
+}
+
+/**
* Put a secondary minor number.
*
* \param sec_minor - structure to be released
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 7e42b7e9d43..c08e7b7263c 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -486,7 +486,11 @@ int drm_sysfs_device_add(struct drm_minor *minor)
int err;
char *minor_str;
- minor->kdev.parent = &minor->dev->pdev->dev;
+ if (minor->dev->pdev) {
+ minor->kdev.parent = &minor->dev->pdev->dev;
+ } else {
+ minor->kdev.parent = &minor->dev->platform_dev->dev;
+ }
minor->kdev.class = drm_class;
minor->kdev.release = drm_sysfs_device_release;
minor->kdev.devt = minor->device;
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index c8e64bbadbc..32ac3bc0b89 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -55,6 +55,7 @@
#include <linux/mm.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
+#include <linux/platform_device.h>
#if defined(__alpha__) || defined(__powerpc__)
#include <asm/pgtable.h> /* For pte_wrprotect */
#endif
@@ -143,6 +144,7 @@ extern void drm_ut_debug_printk(unsigned int request_level,
#define DRIVER_IRQ_VBL2 0x800
#define DRIVER_GEM 0x1000
#define DRIVER_MODESET 0x2000
+#define DRIVER_IS_PLATFORM 0x4000
/***********************************************************************/
/** \name Begin the DRM... */
@@ -1008,6 +1010,7 @@ struct drm_device {
wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
struct drm_agp_head *agp; /**< AGP data */
+ struct platform_device *platform_dev; /**< platform device structure */
struct pci_dev *pdev; /**< PCI device structure */
int pci_vendor; /**< PCI vendor id */
@@ -1118,12 +1121,20 @@ static inline int drm_mtrr_del(int handle, unsigned long offset,
}
#endif
+static inline int drm_core_is_platform(struct drm_device *dev)
+{
+ return drm_core_check_feature(dev, DRIVER_IS_PLATFORM);
+}
+
/******************************************************************/
/** \name Internal function definitions */
/*@{*/
/* Driver support (drm_drv.h) */
extern int drm_init(struct drm_driver *driver);
+extern int drm_platform_init(struct drm_driver *driver,
+ struct platform_device *pdev,
+ void *dev_private);
extern void drm_exit(struct drm_driver *driver);
extern int drm_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
@@ -1341,6 +1352,8 @@ extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
struct drm_master *drm_master_create(struct drm_minor *minor);
extern struct drm_master *drm_master_get(struct drm_master *master);
+extern int drm_get_platform_dev(struct platform_device *pdev,
+ struct drm_driver *driver, void *priv);
extern void drm_master_put(struct drm_master **master);
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
struct drm_driver *driver);