This patch series contains the gpu sharing layer for kernel that I've mentioned before. It should apply against Linus's git tree.
Why do we want this?
Currently the kernel cannot provide both the fb and drm drivers with access to the device model and this means the drm cannot get any suspend/resume callbacks.
This layer attempts to fix this problem by adding a bus for the gpu drivers
to attach to. Currently a lowlevel binding driver is needed along with optional
fb and drm components.
This patch series only covers the generic code and radeon initially, I'll
probably target intel next.
All the patches are available at:
http://www.skynet.ie/~airlied/patches/gpu
I think maybe the radeonfb patch may not make it pass the list filter..
Dave.
From: Dave Airlie <[email protected]>
This is the new Linux GPU driver layer generic portion. It registers a bus
at system init time, and this bus can be used by lowlevel drivers to
create subdevices on the GPU bus. The other GPU drivers can be registered
via the lowlevel driver on the other subdevices.
Signed-off-by: Dave Airlie <[email protected]>
---
drivers/video/Kconfig | 4
drivers/video/Makefile | 1
drivers/video/gpu_layer.c | 410 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/gpu_layer.h | 118 +++++++++++++
4 files changed, 533 insertions(+), 0 deletions(-)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4e83f01..acf2df0 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -4,6 +4,10 @@ #
menu "Graphics support"
+config GPU
+ bool
+ default y
+
config FIRMWARE_EDID
bool "Enable firmware EDID"
default y
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 309a26d..49c5d86 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -5,6 +5,7 @@ # Rewritten to use lists instead of if-s
# Each configuration option enables a list of files.
obj-y += fb_notify.o
+obj-$(CONFIG_GPU) += gpu_layer.o
obj-$(CONFIG_FB) += fb.o
fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
modedb.o fbcvt.o
diff --git a/drivers/video/gpu_layer.c b/drivers/video/gpu_layer.c
new file mode 100644
index 0000000..55bab96
--- /dev/null
+++ b/drivers/video/gpu_layer.c
@@ -0,0 +1,410 @@
+/*
+ * drivers/video/gpu_layer.c
+ *
+ * (C) Copyright Dave Airlie 2006
+ *
+ */
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/gpu_layer.h>
+
+/* GPUs we manage */
+static LIST_HEAD(gpu_bus_list);
+
+/* used when allocating bus numbers */
+#define GPU_MAXBUS 64
+struct gpu_busmap {
+ unsigned long busmap [GPU_MAXBUS / (8*sizeof (unsigned long))];
+};
+static struct gpu_busmap busmap;
+
+/* used when updating list of gpus */
+static DEFINE_MUTEX(gpu_bus_list_lock);
+
+
+/**
+ * gpu_bus_pci_match - Match a device using a PCI GPU
+ *
+ * Call the PCI match function using the generic identifier pointer to a PCI ID list.
+ */
+void *gpu_bus_pci_match(struct gpu_device *dev, struct gpu_driver *drv)
+{
+ struct pci_dev *pdev = to_pci_dev(dev->bus->gpu);
+ const struct pci_device_id *ids = (const struct pci_device_id *)drv->id_table, *match;
+
+ match = pci_match_id(ids, pdev);
+ return (void *)match;
+}
+EXPORT_SYMBOL(gpu_bus_pci_match);
+
+/**
+ * gpu_bus_match - Match a sub driver against a sub device
+ *
+ * If the driver type matches the device, call the bus match function.
+ */
+int gpu_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct gpu_device *gdev = to_gpu_device(dev);
+ struct gpu_driver *gdrv = to_gpu_driver(drv);
+
+ if (gdrv->drv_type == gdev->devnum) {
+ if (gdev->bus->match)
+ if (gdev->bus->match(gdev, gdrv))
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(gpu_bus_match);
+
+/**
+ * gpu_uevent - empty so far
+ */
+static int gpu_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ if (!dev)
+ return -ENODEV;
+
+ return 0;
+
+}
+
+/* Forward references */
+#ifdef CONFIG_PM
+static int gpu_suspend(struct device *dev, pm_message_t message);
+static int gpu_resume(struct device *dev);
+#endif
+
+/* GPU bus structure */
+struct bus_type gpu_bus_type = {
+ .name = "gpu",
+ .match = gpu_bus_match,
+ .uevent = gpu_uevent,
+#ifdef CONFIG_PM
+ .suspend = gpu_suspend,
+ .resume = gpu_resume,
+#endif
+};
+EXPORT_SYMBOL(gpu_bus_type);
+
+/**
+ * gpu_init - GPU subsystem initialise
+ *
+ * Register the GPU bus type
+ */
+static int __init gpu_init(void)
+{
+ return bus_register(&gpu_bus_type);
+}
+
+/**
+ * gpu_exit - GPU subsystem cleanup
+ *
+ * Unregister the bus
+ */
+static void __exit gpu_exit(void)
+{
+ bus_unregister(&gpu_bus_type);
+}
+
+/**
+ * gpu_bus_get - Reference count bus driver
+ */
+struct gpu_bus *gpu_bus_get(struct gpu_bus *bus)
+{
+ kref_get(&bus->kref);
+ return bus;
+}
+
+/**
+ * gpu_bus_release - Call bus release method
+ */
+static void gpu_bus_release(struct kref *kref)
+{
+ struct gpu_bus *bus = container_of(kref, struct gpu_bus, kref);
+
+ if (bus->release)
+ bus->release(bus);
+}
+
+/*
+ * gpu_bus_put - dereference count bus driver
+ */
+void gpu_bus_put(struct gpu_bus *bus)
+{
+ if (bus)
+ kref_put(&bus->kref, gpu_bus_release);
+}
+
+/**
+ * gpu_bus_init - init a bus structure
+ */
+void gpu_bus_init(struct gpu_bus *bus)
+{
+ bus->busnum = -1;
+ INIT_LIST_HEAD(&bus->bus_list);
+
+ kref_init(&bus->kref);
+}
+EXPORT_SYMBOL(gpu_bus_init);
+
+/**
+ * gpu_register_bus
+ *
+ * This registers a GPU bus with the GPU layer,
+ * it fills in a default bus match function, and adds the device to the list
+ */
+int gpu_register_bus(struct gpu_bus *bus)
+{
+ int busnum;
+
+ mutex_lock(&gpu_bus_list_lock);
+
+ busnum = find_next_zero_bit(busmap.busmap, GPU_MAXBUS, 1);
+ if (busnum < GPU_MAXBUS) {
+ set_bit(busnum, busmap.busmap);
+ bus->busnum = busnum;
+ } else {
+ printk(KERN_ERR "%s: too many buses\n", "gpu");
+ mutex_unlock(&gpu_bus_list_lock);
+ return -ENOSPC;
+ }
+
+ if (!bus->match)
+ if (bus->card_type==GPU_PCI)
+ bus->match = gpu_bus_pci_match;
+
+ list_add(&bus->bus_list, &gpu_bus_list);
+ mutex_unlock(&gpu_bus_list_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpu_register_bus);
+
+/**
+ * gpu_unregister_bus
+ *
+ * Unregister the bus driver from GPU list
+ */
+void gpu_unregister_bus(struct gpu_bus *bus)
+{
+ mutex_lock(&gpu_bus_list_lock);
+ list_del(&bus->bus_list);
+ clear_bit(bus->busnum, busmap.busmap);
+ mutex_unlock(&gpu_bus_list_lock);
+}
+EXPORT_SYMBOL(gpu_unregister_bus);
+
+/**
+ * gpu_alloc_devices
+ *
+ * Allocate and initialise the GPU sub-devices.
+ */
+int gpu_alloc_devices(struct gpu_bus *bus)
+{
+ struct gpu_device *dev;
+ int i;
+ int retval = 0;
+
+ for (i=0; i<bus->num_subdev; i++) {
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ retval = -ENOMEM;
+ goto cleanup;
+ }
+
+ bus = gpu_bus_get(bus);
+ if (!bus) {
+ kfree(dev);
+ retval = -ENOMEM;
+ goto cleanup;
+ }
+
+ device_initialize(&dev->dev);
+ dev->dev.bus = &gpu_bus_type;
+ dev->dev.parent = bus->gpu;
+ dev->card_type = bus->card_type;
+ sprintf(&dev->dev.bus_id[0], "%s:%d", bus->bus_name, i);
+ dev->bus = bus;
+ dev->devnum = i;
+
+ bus->devices[i] = dev;
+
+ }
+ return 0;
+cleanup:
+ for (i = 0; i < bus->num_subdev; i++) {
+ if (bus->devices[i]) {
+ kfree(bus->devices[i]);
+ bus->devices[i]= NULL;
+ }
+ }
+ return retval;
+}
+EXPORT_SYMBOL(gpu_alloc_devices);
+
+/**
+ * gpu_register_devices
+ *
+ * Add the gpu sub-devices to the device tree
+ */
+int gpu_register_devices(struct gpu_bus *bus)
+{
+ int retval;
+ int i;
+
+ for (i = 0; i < bus->num_subdev; i++) {
+ struct gpu_device *gpu_dev = bus->devices[i];
+
+ retval = device_add(&gpu_dev->dev);
+ if (retval) {
+ dev_err(&gpu_dev->dev, "can't device_add, error %d\n", retval);
+ goto fail;
+ }
+
+ }
+ return 0;
+
+fail:
+ for (i = 0; i < bus->num_subdev; i++) {
+ struct gpu_device *gpu_dev = bus->devices[i];
+
+ device_del(&gpu_dev->dev);
+ }
+ return retval;
+}
+EXPORT_SYMBOL(gpu_register_devices);
+
+/**
+ * gpu_unregister_devices
+ */
+int gpu_unregister_devices(struct gpu_bus *bus)
+{
+ int i;
+
+ for (i = 0; i < bus->num_subdev; i++) {
+ struct gpu_device *gpu_dev = bus->devices[i];
+
+ device_del(&gpu_dev->dev);
+
+ kfree(gpu_dev);
+ bus->devices[i] = NULL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(gpu_unregister_devices);
+
+/**
+ * gpu_probe
+ *
+ * Do a gpu bus probe - probe for GPU sub devices
+ */
+static int gpu_probe(struct device *dev)
+{
+ struct gpu_device *gdev = to_gpu_device(dev);
+ struct gpu_driver *gdrv;
+ int retval;
+ void *driver_id;
+
+ gdrv = to_gpu_driver(dev->driver);
+
+ /* call the bus matching function to get an identifier */
+ driver_id = gdev->bus->match(gdev, gdrv);
+ if (driver_id == NULL)
+ return -EINVAL;
+
+ /* call the driver probe function */
+
+ retval = gdrv->probe(gdev, driver_id);
+
+ printk("gpu probe called %d - %d\n", gdev->devnum, retval);
+ return retval;
+}
+
+/**
+ * gpu_remove
+ *
+ * Call the GPU remove sub device
+ */
+static int gpu_remove(struct device *dev)
+{
+ struct gpu_device *gdev = to_gpu_device(dev);
+ struct gpu_driver *gdrv;
+
+ gdrv = to_gpu_driver(dev->driver);
+
+ if (gdrv && gdrv->remove)
+ gdrv->remove(gdev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+/**
+ * gpu_suspend
+ *
+ * Suspend the devices on the GPU bus
+ */
+static int gpu_suspend(struct device *dev, pm_message_t state)
+{
+ struct gpu_driver *gdrv = to_gpu_driver(dev->driver);
+
+ if (gdrv && gdrv->driver.suspend)
+ return gdrv->driver.suspend(dev, state);
+
+ return 0;
+}
+
+/**
+ * gpu_resume
+ *
+ * Resume the devices on the GPU bus
+ */
+static int gpu_resume(struct device *dev)
+{
+ struct gpu_driver *gdrv = to_gpu_driver(dev->driver);
+
+ if (gdrv && gdrv->driver.resume)
+ return gdrv->driver.resume(dev);
+
+ return 0;
+}
+#endif
+
+/**
+ * gpu_register_driver
+ *
+ * Register a GPU driver and fill in its common structure members
+ */
+int gpu_register_driver(struct gpu_driver *new_driver, struct module *owner)
+{
+ int retval;
+
+ new_driver->driver.bus = &gpu_bus_type;
+ new_driver->driver.name = (char *)new_driver->name;
+ new_driver->driver.probe = gpu_probe;
+ new_driver->driver.remove = gpu_remove;
+ new_driver->driver.owner = owner;
+
+ retval = driver_register(&new_driver->driver);
+
+ return retval;
+}
+EXPORT_SYMBOL(gpu_register_driver);
+
+/**
+ * gpu_unregister_driver
+ *
+ * Call the driver unregister
+ */
+void gpu_unregister_driver(struct gpu_driver *driver)
+{
+ driver_unregister(&driver->driver);
+}
+EXPORT_SYMBOL(gpu_unregister_driver);
+
+subsys_initcall(gpu_init);
+module_exit(gpu_exit);
+
diff --git a/include/linux/gpu_layer.h b/include/linux/gpu_layer.h
new file mode 100644
index 0000000..ac0c003
--- /dev/null
+++ b/include/linux/gpu_layer.h
@@ -0,0 +1,118 @@
+/*
+ * include/linux/gpu_layer.h
+ *
+ * Author : Dave Airlie <[email protected]>
+ * Copyright (C) 2006 David Airlie
+ *
+ */
+
+#ifndef _LINUX_GPU_LAYER_H
+#define _LINUX_GPU_LAYER_H
+
+/* GPU subdevices - 0 is the root hub equivalent */
+#define GPU_LL 0
+#define GPU_FB 1
+#define GPU_DRM 2
+#define GPU_LAST (GPU_DRM+1)
+
+/* GPU device type - PCI only supported so far */
+#define GPU_PCI 1
+#define GPU_USB 2
+
+struct gpu_bus;
+struct gpu_driver;
+
+/*
+ * The gpu_device structure is used to describe GPU devices
+ */
+struct gpu_device {
+ int devnum; /* subdevice number */
+ int card_type; /* type of card - PCI, USB etc. */
+ struct device dev; /* Generic device interface */
+ struct gpu_bus *bus; /* pointer to gpu bus this driver is on */
+};
+#define to_gpu_device(d) container_of(d, struct gpu_device, dev)
+
+/*
+ * This structure stores the GPU virtual bus description.
+ */
+struct gpu_bus {
+ struct device *gpu; /* pointer to the GPU itself device */
+ int num_subdev; /* number of subdevices on this bus */
+
+ int card_type; /* type of card this bus is running on */
+
+ int busnum; /* GPU bus number */
+ char *bus_name; /* bus name */
+
+ void *gpu_priv; /* gpu private data */
+ struct list_head bus_list; /* list of busses */
+
+ struct kref kref; /* kobject reference */
+
+ struct gpu_device *devices[GPU_LAST]; /* array of GPU subdevices */
+
+ void *(*match)(struct gpu_device *dev, struct gpu_driver *drv); /* match function */
+
+ void (*release)(struct gpu_bus *bus); /* bus release function */
+};
+
+/*
+ * This structure stores the GPU driver information
+ */
+struct gpu_driver {
+ struct device_driver driver; /* embedded driver structure */
+
+ /* use a full PCI device table */
+ const void *id_table; /* generic pointer to an ID table - PCI or USB */
+
+ int drv_type; /* driver sub-driver type - LL/DRM/FB */
+ int card_type; /* card type PCI/USB */
+ char *name; /* driver name */
+
+ /* match function */
+ int (*probe)(struct gpu_device *dev, void *driver_id); /* probe function */
+ void (*remove)(struct gpu_device *dev); /* remove function */
+
+};
+#define to_gpu_driver(d) container_of(d, struct gpu_driver, driver)
+
+/*
+ * GPU Information
+ */
+struct gpu_info {
+
+ struct gpu_bus self; /* pointer to the bus on this device */
+
+ struct device *device; /* pointer to device */
+};
+
+/*
+ * driver-specific data. They are really just a wrapper around
+ * the generic device structure functions of these calls.
+ */
+static inline void *gpu_get_drvdata(struct gpu_device *gdev)
+{
+ return dev_get_drvdata(&gdev->dev);
+}
+
+static inline void gpu_set_drvdata(struct gpu_device *gdev, void *data)
+{
+ dev_set_drvdata(&gdev->dev, data);
+}
+
+extern void gpu_bus_init(struct gpu_bus *bus);
+extern int gpu_register_bus(struct gpu_bus *bus);
+extern void gpu_unregister_bus(struct gpu_bus *bus);
+extern int gpu_alloc_devices(struct gpu_bus *bus);
+extern int gpu_register_devices(struct gpu_bus *bus);
+extern int gpu_register_driver(struct gpu_driver *new_driver, struct module *owner);
+extern void gpu_unregister_driver(struct gpu_driver *driver);
+extern int gpu_unregister_devices(struct gpu_bus *bus);
+
+static inline int gpu_register(struct gpu_driver *driver)
+{
+ return gpu_register_driver(driver, THIS_MODULE);
+}
+
+#endif
--
1.4.1.ga3e6
From: Dave Airlie <[email protected]>
This ports the radeon DRM to use the GPU layer to bind to the PCI device.
Signed-off-by: Dave Airlie <[email protected]>
---
drivers/char/drm/Kconfig | 1 +
drivers/char/drm/radeon_drv.c | 54 ++++++++++++++++++++++++++++++++++++-----
drivers/char/drm/radeon_drv.h | 4 ++-
3 files changed, 50 insertions(+), 9 deletions(-)
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index ef833a1..18cf194 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -34,6 +34,7 @@ config DRM_R128
config DRM_RADEON
tristate "ATI Radeon"
depends on DRM && PCI
+ select GPU_RADEON
help
Choose this option if you have an ATI Radeon graphics card. There
are both PCI and AGP versions. You don't need to choose this to
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index 2eb652e..d8911bc 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -31,6 +31,8 @@
#include "drmP.h"
#include "drm.h"
+#include <linux/pm.h>
+#include <linux/radeon_gpu.h>
#include "radeon_drm.h"
#include "radeon_drv.h"
@@ -52,10 +54,23 @@ static int dri_library_name(struct drm_d
"r300"));
}
+static int __devinit radeondrm_gpu_register (struct gpu_device *gdev, void *driver_id);
+static void __devexit radeondrm_gpu_unregister (struct gpu_device *gdev);
+
static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
};
+static int radeondrm_suspend(struct device *dev, pm_message_t state)
+{
+ return 0;
+}
+
+static int radeondrm_resume(struct device *dev)
+{
+ return 0;
+}
+
static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
@@ -92,12 +107,18 @@ #ifdef CONFIG_COMPAT
.compat_ioctl = radeon_compat_ioctl,
#endif
},
-
- .pci_driver = {
+ .drv_type = DRM_DRV_GPU,
+ .gpu_driver = {
.name = DRIVER_NAME,
- .id_table = pciidlist,
- },
-
+ .drv_type = GPU_DRM,
+ .driver = {
+ .suspend = radeondrm_suspend,
+ .resume = radeondrm_resume,
+ },
+ .probe = radeondrm_gpu_register,
+ .remove = __devexit_p(radeondrm_gpu_unregister),
+ .id_table = (void *)pciidlist,
+ },
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
@@ -106,15 +127,34 @@ #endif
.patchlevel = DRIVER_PATCHLEVEL,
};
+
+static int __devinit radeondrm_gpu_register(struct gpu_device *gdev, void *driver_id)
+{
+ int retval;
+ struct radeon_gpu_info *gpu_info;
+
+ gpu_info = dev_get_drvdata(gdev->dev.parent);
+
+ retval = drm_gpu_get_dev(gdev, &driver, driver_id, gpu_info->pdev);
+ return retval;
+}
+
+static void __devexit radeondrm_gpu_unregister (struct gpu_device *gdev)
+{
+ drm_gpu_cleanup(gdev);
+}
+
static int __init radeon_init(void)
{
driver.num_ioctls = radeon_max_ioctl;
- return drm_init(&driver);
+ drm_mem_init();
+
+ return radeon_gpu_register_driver(&driver.gpu_driver, THIS_MODULE);
}
static void __exit radeon_exit(void)
{
- drm_exit(&driver);
+ gpu_unregister_driver(&driver.gpu_driver);
}
module_init(radeon_init);
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 8b105f1..650fc8e 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -103,7 +103,7 @@ #define DRIVER_PATCHLEVEL 0
/*
* Radeon chip families
*/
-enum radeon_family {
+enum radeondrm_family {
CHIP_R100,
CHIP_RV100,
CHIP_RS100,
@@ -132,7 +132,7 @@ enum radeon_cp_microcode_version {
/*
* Chip flags
*/
-enum radeon_chip_flags {
+enum radeondrm_chip_flags {
RADEON_FAMILY_MASK = 0x0000ffffUL,
RADEON_FLAGS_MASK = 0xffff0000UL,
RADEON_IS_MOBILITY = 0x00010000UL,
--
1.4.1.ga3e6
From: Dave Airlie <[email protected]>
This creates a lowlevel radeon driver which detects the card and
sets up the GPU layer to use it.
Signed-off-by: Dave Airlie <[email protected]>
---
drivers/video/Kconfig | 5 +
drivers/video/Makefile | 2
drivers/video/radeon_gpu.c | 343 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/radeon_gpu.h | 92 ++++++++++++
4 files changed, 442 insertions(+), 0 deletions(-)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index acf2df0..0a00588 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -8,6 +8,11 @@ config GPU
bool
default y
+config GPU_RADEON
+ tristate "ATI Radeon gpu driver"
+ select GPU
+ default n
+
config FIRMWARE_EDID
bool "Enable firmware EDID"
default y
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 49c5d86..5634725 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -7,6 +7,8 @@ # Each configuration option enables a li
obj-y += fb_notify.o
obj-$(CONFIG_GPU) += gpu_layer.o
obj-$(CONFIG_FB) += fb.o
+obj-$(CONFIG_GPU_RADEON) += radeon_gpu.o
+
fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
modedb.o fbcvt.o
fb-objs := $(fb-y)
diff --git a/drivers/video/radeon_gpu.c b/drivers/video/radeon_gpu.c
new file mode 100644
index 0000000..2eecf3b
--- /dev/null
+++ b/drivers/video/radeon_gpu.c
@@ -0,0 +1,343 @@
+/*
+ * drivers/video/radeon_gpu.c
+ *
+ * Copyright (C) 2006 Dave Airlie
+ *
+ * some of this code is derived from the radeon framebuffer code
+ * Copyright 2003 Ben. Herrenschmidt <[email protected]>
+ * Copyright 2000 Ani Joshi <[email protected]>
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+
+#include <linux/gpu_layer.h>
+#include <linux/radeon_gpu.h>
+
+#include <video/radeon.h>
+#include "aty/ati_ids.h"
+
+
+#define CHIP_DEF(id, family, flags) \
+ { PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) }
+
+static struct pci_device_id radeon_gpu_pci_table[] = {
+ /* Mobility M6 */
+ CHIP_DEF(PCI_CHIP_RADEON_LY, RV100, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RADEON_LZ, RV100, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ /* Radeon VE/7000 */
+ CHIP_DEF(PCI_CHIP_RV100_QY, RV100, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV100_QZ, RV100, CHIP_HAS_CRTC2),
+ /* Radeon IGP320M (U1) */
+ CHIP_DEF(PCI_CHIP_RS100_4336, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+ /* Radeon IGP320 (A3) */
+ CHIP_DEF(PCI_CHIP_RS100_4136, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+ /* IGP330M/340M/350M (U2) */
+ CHIP_DEF(PCI_CHIP_RS200_4337, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+ /* IGP330/340/350 (A4) */
+ CHIP_DEF(PCI_CHIP_RS200_4137, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+ /* Mobility 7000 IGP */
+ CHIP_DEF(PCI_CHIP_RS250_4437, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+ /* 7000 IGP (A4+) */
+ CHIP_DEF(PCI_CHIP_RS250_4237, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+ /* 8500 AIW */
+ CHIP_DEF(PCI_CHIP_R200_BB, R200, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R200_BC, R200, CHIP_HAS_CRTC2),
+ /* 8700/8800 */
+ CHIP_DEF(PCI_CHIP_R200_QH, R200, CHIP_HAS_CRTC2),
+ /* 8500 */
+ CHIP_DEF(PCI_CHIP_R200_QL, R200, CHIP_HAS_CRTC2),
+ /* 9100 */
+ CHIP_DEF(PCI_CHIP_R200_QM, R200, CHIP_HAS_CRTC2),
+ /* Mobility M7 */
+ CHIP_DEF(PCI_CHIP_RADEON_LW, RV200, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RADEON_LX, RV200, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ /* 7500 */
+ CHIP_DEF(PCI_CHIP_RV200_QW, RV200, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV200_QX, RV200, CHIP_HAS_CRTC2),
+ /* Mobility M9 */
+ CHIP_DEF(PCI_CHIP_RV250_Ld, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV250_Le, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV250_Lf, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV250_Lg, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ /* 9000/Pro */
+ CHIP_DEF(PCI_CHIP_RV250_If, RV250, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV250_Ig, RV250, CHIP_HAS_CRTC2),
+ /* Mobility 9100 IGP (U3) */
+ CHIP_DEF(PCI_CHIP_RS300_5835, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RS350_7835, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+ /* 9100 IGP (A5) */
+ CHIP_DEF(PCI_CHIP_RS300_5834, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+ CHIP_DEF(PCI_CHIP_RS350_7834, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+ /* Mobility 9200 (M9+) */
+ CHIP_DEF(PCI_CHIP_RV280_5C61, RV280, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV280_5C63, RV280, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ /* 9200 */
+ CHIP_DEF(PCI_CHIP_RV280_5960, RV280, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV280_5961, RV280, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV280_5962, RV280, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV280_5964, RV280, CHIP_HAS_CRTC2),
+ /* 9500 */
+ CHIP_DEF(PCI_CHIP_R300_AD, R300, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R300_AE, R300, CHIP_HAS_CRTC2),
+ /* 9600TX / FireGL Z1 */
+ CHIP_DEF(PCI_CHIP_R300_AF, R300, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R300_AG, R300, CHIP_HAS_CRTC2),
+ /* 9700/9500/Pro/FireGL X1 */
+ CHIP_DEF(PCI_CHIP_R300_ND, R300, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R300_NE, R300, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R300_NF, R300, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R300_NG, R300, CHIP_HAS_CRTC2),
+ /* Mobility M10/M11 */
+ CHIP_DEF(PCI_CHIP_RV350_NP, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV350_NQ, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV350_NR, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV350_NS, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV350_NT, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV350_NV, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ /* 9600/FireGL T2 */
+ CHIP_DEF(PCI_CHIP_RV350_AP, RV350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV350_AQ, RV350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV360_AR, RV350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV350_AS, RV350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV350_AT, RV350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV350_AV, RV350, CHIP_HAS_CRTC2),
+ /* 9800/Pro/FileGL X2 */
+ CHIP_DEF(PCI_CHIP_R350_AH, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_AI, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_AJ, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_AK, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_NH, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_NI, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R360_NJ, R350, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R350_NK, R350, CHIP_HAS_CRTC2),
+ /* Newer stuff */
+ CHIP_DEF(PCI_CHIP_RV380_3E50, RV380, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV380_3E54, RV380, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV380_3150, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV380_3154, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV370_5B60, RV380, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV370_5B62, RV380, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV370_5B64, RV380, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV370_5B65, RV380, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RV370_5460, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_RV370_5464, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_R420_JH, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R420_JI, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R420_JJ, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R420_JK, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R420_JL, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R420_JM, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R420_JN, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+ CHIP_DEF(PCI_CHIP_R420_JP, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R423_UH, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R423_UI, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R423_UJ, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R423_UK, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R423_UQ, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R423_UR, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R423_UT, R420, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_R423_5D57, R420, CHIP_HAS_CRTC2),
+ /* Original Radeon/7200 */
+ CHIP_DEF(PCI_CHIP_RADEON_QD, RADEON, 0),
+ CHIP_DEF(PCI_CHIP_RADEON_QE, RADEON, 0),
+ CHIP_DEF(PCI_CHIP_RADEON_QF, RADEON, 0),
+ CHIP_DEF(PCI_CHIP_RADEON_QG, RADEON, 0),
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, radeon_gpu_pci_table);
+
+MODULE_AUTHOR("Dave Airlie");
+MODULE_DESCRIPTION("GPU layer driver for Radeon Chipset");
+MODULE_LICENSE("GPL");
+
+struct gpu_driver radeon_lowlevel_driver = {
+ .name = "radeon_gpu",
+ .card_type = GPU_PCI,
+ .drv_type = GPU_LL,
+};
+
+/**
+ * radeon_gpu_pci_probe
+ */
+int radeon_gpu_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+ struct radeon_gpu_info *rinfo;
+ int ret;
+
+ if (pci_enable_device(dev) < 0)
+ return -EINVAL;
+
+ rinfo = kzalloc(sizeof(*rinfo), GFP_KERNEL);
+ if (!rinfo) {
+ dev_dbg(dev->dev, "radeon info alloc failed\n");
+ return -ENOMEM;
+ }
+ dev_set_drvdata(&dev->dev, rinfo);
+
+ rinfo->family = ent->driver_data & CHIP_FAMILY_MASK;
+ rinfo->chipset = dev->device;
+ rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0;
+ rinfo->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0;
+ rinfo->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0;
+
+ /* Set base addrs */
+ rinfo->fb_base_phys = pci_resource_start(dev, 0);
+ rinfo->mmio_base_phys = pci_resource_start(dev, 2);
+
+ rinfo->ati_name[0] = ent->device >> 8;
+ rinfo->ati_name[1] = ent->device & 0xff;
+
+ rinfo->pdev = dev;
+ /*
+ * Check for errata
+ */
+ rinfo->errata = 0;
+
+ if (rinfo->family == CHIP_FAMILY_RV200 ||
+ rinfo->family == CHIP_FAMILY_RS200)
+ rinfo->errata |= CHIP_ERRATA_PLL_DUMMYREADS;
+
+ if (rinfo->family == CHIP_FAMILY_RV100 ||
+ rinfo->family == CHIP_FAMILY_RS100 ||
+ rinfo->family == CHIP_FAMILY_RS200)
+ rinfo->errata |= CHIP_ERRATA_PLL_DELAY;
+
+ gpu_bus_init(&rinfo->info.self);
+ rinfo->info.self.bus_name = pci_name(dev);
+ rinfo->info.self.gpu = &dev->dev;
+ rinfo->info.self.card_type = GPU_PCI;
+ rinfo->info.self.num_subdev = GPU_LAST;
+
+ if ((ret = gpu_register_bus(&rinfo->info.self)) < 0)
+ goto err_register_bus;
+
+ if ((ret = gpu_alloc_devices(&rinfo->info.self)) < 0) {
+ dev_err(rinfo->info.self.gpu, "unable to alloc lowlayer device\n");
+ ret = -ENOMEM;
+ goto err_allocate_low_layer;
+ }
+
+ /* the first device driver is always the lowlevel driver */
+ rinfo->info.self.devices[0]->dev.driver = &radeon_lowlevel_driver.driver;
+
+ ret = gpu_register_devices(&rinfo->info.self);
+
+ return ret;
+
+err_allocate_low_layer:
+ gpu_unregister_bus(&rinfo->info.self);
+err_register_bus:
+ dev_set_drvdata(&dev->dev, NULL);
+ kfree(rinfo);
+ return ret;
+}
+
+/**
+ * radeon_gpu_pci_remove
+ */
+void radeon_gpu_pci_remove(struct pci_dev *dev)
+{
+ struct radeon_gpu_info *rinfo;
+
+ rinfo = dev_get_drvdata(&dev->dev);
+
+ gpu_unregister_devices(&rinfo->info.self);
+
+ gpu_unregister_bus(&rinfo->info.self);
+ dev_set_drvdata(&dev->dev, NULL);
+
+ kfree(rinfo);
+}
+
+/**
+ * radeon_gpu_pci_suspend
+ *
+ * These are null methods so
+ * we don't get defaults,
+ * do not use them use the lowlevel driver
+ */
+int radeon_gpu_pci_suspend(struct pci_dev *dev, pm_message_t message)
+{
+ return 0;
+}
+
+/**
+ * radeon_gpu_pci_resume
+ *
+ * These are null methods so
+ * we don't get defaults,
+ * do not use them use the lowlevel driver
+ */
+int radeon_gpu_pci_resume(struct pci_dev *dev)
+{
+ return 0;
+}
+
+static struct pci_driver radeon_gpu_driver = {
+ .name = "radeon_gpu",
+ .id_table = radeon_gpu_pci_table,
+ .probe = radeon_gpu_pci_probe,
+ .remove = __devexit_p(radeon_gpu_pci_remove),
+#ifdef CONFIG_PM
+ .suspend = radeon_gpu_pci_suspend,
+ .resume = radeon_gpu_pci_resume,
+#endif /* CONFIG_PM */
+};
+
+/**
+ * radeon_gpu_register_driver
+ *
+ * This wraps the GPU register function
+ * It is needed so that loading a higher layer module
+ * will force this module to load.
+ */
+int radeon_gpu_register_driver(struct gpu_driver *new_driver, struct module *owner)
+{
+ return gpu_register_driver(new_driver, owner);
+}
+EXPORT_SYMBOL(radeon_gpu_register_driver);
+
+/**
+ * radeon_gpu_unregister_driver
+ */
+void radeon_gpu_unregister_driver(struct gpu_driver *driver)
+{
+ gpu_unregister_driver(driver);
+}
+EXPORT_SYMBOL(radeon_gpu_unregister_driver);
+
+/**
+ * radeon_gpu_init
+ *
+ * Register the GPU driver and PCI driver
+ */
+static int __init radeon_gpu_init(void)
+{
+ int retval;
+
+ retval = gpu_register(&radeon_lowlevel_driver);
+ if (retval)
+ return retval;
+
+ return pci_register_driver (&radeon_gpu_driver);
+}
+
+/**
+ * radeon_gpu_exit
+ *
+ * Unregister the drivers.
+ */
+static void __exit radeon_gpu_exit(void)
+{
+ pci_unregister_driver (&radeon_gpu_driver);
+
+ gpu_unregister_driver(&radeon_lowlevel_driver);
+
+}
+
+module_init(radeon_gpu_init);
+module_exit(radeon_gpu_exit);
diff --git a/include/linux/radeon_gpu.h b/include/linux/radeon_gpu.h
new file mode 100644
index 0000000..defea65
--- /dev/null
+++ b/include/linux/radeon_gpu.h
@@ -0,0 +1,92 @@
+/*
+ * include/linux/radeon_gpu.h
+ */
+#ifndef _LINUX_RADEON_GPU_H
+#define _LINUX_RADEON_GPU_H
+
+/*
+ * Chip families. Must fit in the low 16 bits of a long word
+ */
+enum radeon_family {
+ CHIP_FAMILY_UNKNOW,
+ CHIP_FAMILY_LEGACY,
+ CHIP_FAMILY_RADEON,
+ CHIP_FAMILY_RV100,
+ CHIP_FAMILY_RS100, /* U1 (IGP320M) or A3 (IGP320)*/
+ CHIP_FAMILY_RV200,
+ CHIP_FAMILY_RS200, /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350),
+ RS250 (IGP 7000) */
+ CHIP_FAMILY_R200,
+ CHIP_FAMILY_RV250,
+ CHIP_FAMILY_RS300, /* Radeon 9000 IGP */
+ CHIP_FAMILY_RV280,
+ CHIP_FAMILY_R300,
+ CHIP_FAMILY_R350,
+ CHIP_FAMILY_RV350,
+ CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */
+ CHIP_FAMILY_R420, /* R420/R423/M18 */
+ CHIP_FAMILY_LAST,
+};
+
+
+/*
+ * Chip flags
+ */
+enum radeon_chip_flags {
+ CHIP_FAMILY_MASK = 0x0000ffffUL,
+ CHIP_FLAGS_MASK = 0xffff0000UL,
+ CHIP_IS_MOBILITY = 0x00010000UL,
+ CHIP_IS_IGP = 0x00020000UL,
+ CHIP_HAS_CRTC2 = 0x00040000UL,
+};
+
+/*
+ * Errata workarounds
+ */
+enum radeon_errata {
+ CHIP_ERRATA_R300_CG = 0x00000001,
+ CHIP_ERRATA_PLL_DUMMYREADS = 0x00000002,
+ CHIP_ERRATA_PLL_DELAY = 0x00000004,
+};
+
+#define IS_RV100_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_RV100) || \
+ ((rinfo)->family == CHIP_FAMILY_RV200) || \
+ ((rinfo)->family == CHIP_FAMILY_RS100) || \
+ ((rinfo)->family == CHIP_FAMILY_RS200) || \
+ ((rinfo)->family == CHIP_FAMILY_RV250) || \
+ ((rinfo)->family == CHIP_FAMILY_RV280) || \
+ ((rinfo)->family == CHIP_FAMILY_RS300))
+
+
+#define IS_R300_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_R300) || \
+ ((rinfo)->family == CHIP_FAMILY_RV350) || \
+ ((rinfo)->family == CHIP_FAMILY_R350) || \
+ ((rinfo)->family == CHIP_FAMILY_RV380) || \
+ ((rinfo)->family == CHIP_FAMILY_R420))
+
+
+
+struct radeon_gpu_info {
+ struct gpu_info info;
+
+ struct pci_dev *pdev;
+
+ int chipset;
+ u8 family;
+ u8 rev;
+ unsigned int errata;
+
+ unsigned long mmio_base_phys;
+ unsigned long fb_base_phys;
+
+ int has_CRTC2;
+ int is_mobility;
+ int is_IGP;
+
+ char ati_name[2];
+
+};
+
+extern int radeon_gpu_register_driver(struct gpu_driver *new_driver, struct module *owner);
+extern void radeon_gpu_unregister_driver(struct gpu_driver *driver);
+#endif
--
1.4.1.ga3e6
From: Dave Airlie <[email protected]>
This patch adds support to the radeonfb driver to use the new
GPU layer to driver the radeon.
Signed-off-by: Dave Airlie <[email protected]>
Cc: Ben Herrenschmidt <[email protected]>
---
drivers/video/Kconfig | 1
drivers/video/aty/radeon_accel.c | 18 +--
drivers/video/aty/radeon_base.c | 255 +++++++++++++++++-------------------
drivers/video/aty/radeon_i2c.c | 8 +
drivers/video/aty/radeon_monitor.c | 10 +
drivers/video/aty/radeon_pm.c | 130 +++++++++---------
drivers/video/aty/radeonfb.h | 84 +-----------
7 files changed, 217 insertions(+), 289 deletions(-)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 0a00588..83a6002 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1030,6 +1030,7 @@ config FB_MATROX_MULTIHEAD
config FB_RADEON
tristate "ATI Radeon display support"
depends on FB && PCI
+ select GPU_RADEON
select I2C_ALGOBIT if FB_RADEON_I2C
select I2C if FB_RADEON_I2C
select FB_DDC if FB_RADEON_I2C
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c
index 3ca27cb..b0413d3 100644
--- a/drivers/video/aty/radeon_accel.c
+++ b/drivers/video/aty/radeon_accel.c
@@ -203,9 +203,9 @@ void radeonfb_engine_reset(struct radeon
host_path_cntl = INREG(HOST_PATH_CNTL);
rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
- if (rinfo->family == CHIP_FAMILY_R300 ||
- rinfo->family == CHIP_FAMILY_R350 ||
- rinfo->family == CHIP_FAMILY_RV350) {
+ if (rinfo->gpu_info->family == CHIP_FAMILY_R300 ||
+ rinfo->gpu_info->family == CHIP_FAMILY_R350 ||
+ rinfo->gpu_info->family == CHIP_FAMILY_RV350) {
u32 tmp;
OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset |
@@ -241,9 +241,9 @@ void radeonfb_engine_reset(struct radeon
INREG(HOST_PATH_CNTL);
OUTREG(HOST_PATH_CNTL, host_path_cntl);
- if (rinfo->family != CHIP_FAMILY_R300 ||
- rinfo->family != CHIP_FAMILY_R350 ||
- rinfo->family != CHIP_FAMILY_RV350)
+ if (rinfo->gpu_info->family != CHIP_FAMILY_R300 ||
+ rinfo->gpu_info->family != CHIP_FAMILY_R350 ||
+ rinfo->gpu_info->family != CHIP_FAMILY_RV350)
OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
@@ -260,9 +260,9 @@ void radeonfb_engine_init (struct radeon
radeonfb_engine_reset(rinfo);
radeon_fifo_wait (1);
- if ((rinfo->family != CHIP_FAMILY_R300) &&
- (rinfo->family != CHIP_FAMILY_R350) &&
- (rinfo->family != CHIP_FAMILY_RV350))
+ if ((rinfo->gpu_info->family != CHIP_FAMILY_R300) &&
+ (rinfo->gpu_info->family != CHIP_FAMILY_R350) &&
+ (rinfo->gpu_info->family != CHIP_FAMILY_RV350))
OUTREG(RB2D_DSTCACHE_MODE, 0);
radeon_fifo_wait (3);
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 0ed577e..f634c43 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -68,6 +68,9 @@ #include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/device.h>
+#include <linux/gpu_layer.h>
+#include <linux/radeon_gpu.h>
+
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -224,7 +227,7 @@ static struct pci_device_id radeonfb_pci
CHIP_DEF(PCI_CHIP_RADEON_QG, RADEON, 0),
{ 0, }
};
-MODULE_DEVICE_TABLE(pci, radeonfb_pci_table);
+MODULE_DEVICE_TABLE(gpu, radeonfb_pci_table);
typedef struct {
@@ -303,7 +306,7 @@ static int __devinit radeon_map_ROM(stru
rom = pci_map_rom(dev, &rom_size);
if (!rom) {
printk(KERN_ERR "radeonfb (%s): ROM failed to map\n",
- pci_name(rinfo->pdev));
+ pci_name(rinfo->gpu_info->pdev));
return -ENOMEM;
}
@@ -313,7 +316,7 @@ static int __devinit radeon_map_ROM(stru
if (BIOS_IN16(0) != 0xaa55) {
printk(KERN_DEBUG "radeonfb (%s): Invalid ROM signature %x "
"should be 0xaa55\n",
- pci_name(rinfo->pdev), BIOS_IN16(0));
+ pci_name(rinfo->gpu_info->pdev), BIOS_IN16(0));
goto failed;
}
/* Look for the PCI data to check the ROM type */
@@ -345,7 +348,7 @@ static int __devinit radeon_map_ROM(stru
*/
if (BIOS_IN32(dptr) != (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
printk(KERN_WARNING "radeonfb (%s): PCI DATA signature in ROM"
- "incorrect: %08x\n", pci_name(rinfo->pdev), BIOS_IN32(dptr));
+ "incorrect: %08x\n", pci_name(rinfo->gpu_info->pdev), BIOS_IN32(dptr));
goto anyway;
}
rom_type = BIOS_IN8(dptr + 0x14);
@@ -585,7 +588,7 @@ static void __devinit radeon_get_pllinfo
* incomplete, however. It does provide ppll_max and _min values
* even for most other methods, however.
*/
- switch (rinfo->chipset) {
+ switch (rinfo->gpu_info->chipset) {
case PCI_DEVICE_ID_ATI_RADEON_QW:
case PCI_DEVICE_ID_ATI_RADEON_QX:
rinfo->pll.ppll_max = 35000;
@@ -861,7 +864,7 @@ static int radeonfb_ioctl (struct fb_inf
* routing to second output
*/
case FBIO_RADEON_SET_MIRROR:
- if (!rinfo->is_mobility)
+ if (!rinfo->gpu_info->is_mobility)
return -EINVAL;
rc = get_user(value, (__u32 __user *)arg);
@@ -898,7 +901,7 @@ static int radeonfb_ioctl (struct fb_inf
return 0;
case FBIO_RADEON_GET_MIRROR:
- if (!rinfo->is_mobility)
+ if (!rinfo->gpu_info->is_mobility)
return -EINVAL;
tmp = INREG(LVDS_GEN_CNTL);
@@ -1002,7 +1005,7 @@ int radeon_screen_blank(struct radeonfb_
* RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
*/
tmp_pix_clks = INPLL(PIXCLKS_CNTL);
- if (rinfo->is_mobility || rinfo->is_IGP)
+ if (rinfo->gpu_info->is_mobility || rinfo->gpu_info->is_IGP)
OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
val &= ~(LVDS_BL_MOD_EN);
OUTREG(LVDS_GEN_CNTL, val);
@@ -1016,7 +1019,7 @@ int radeon_screen_blank(struct radeonfb_
msecs_to_jiffies(rinfo->panel_info.pwr_delay));
rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
rinfo->init_state.lvds_gen_cntl |= val & LVDS_STATE_MASK;
- if (rinfo->is_mobility || rinfo->is_IGP)
+ if (rinfo->gpu_info->is_mobility || rinfo->gpu_info->is_IGP)
OUTPLL(PIXCLKS_CNTL, tmp_pix_clks);
}
break;
@@ -1121,14 +1124,14 @@ static int radeonfb_setcolreg (unsigned
int rc;
if (!rinfo->asleep) {
- if (rinfo->is_mobility) {
+ if (rinfo->gpu_info->is_mobility) {
vclk_cntl = INPLL(VCLK_ECP_CNTL);
OUTPLL(VCLK_ECP_CNTL,
vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
}
/* Make sure we are on first palette */
- if (rinfo->has_CRTC2) {
+ if (rinfo->gpu_info->has_CRTC2) {
dac_cntl2 = INREG(DAC_CNTL2);
dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
OUTREG(DAC_CNTL2, dac_cntl2);
@@ -1137,7 +1140,7 @@ static int radeonfb_setcolreg (unsigned
rc = radeon_setcolreg (regno, red, green, blue, transp, rinfo);
- if (!rinfo->asleep && rinfo->is_mobility)
+ if (!rinfo->asleep && rinfo->gpu_info->is_mobility)
OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
return rc;
@@ -1151,14 +1154,14 @@ static int radeonfb_setcmap(struct fb_cm
int i, start, rc = 0;
if (!rinfo->asleep) {
- if (rinfo->is_mobility) {
+ if (rinfo->gpu_info->is_mobility) {
vclk_cntl = INPLL(VCLK_ECP_CNTL);
OUTPLL(VCLK_ECP_CNTL,
vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
}
/* Make sure we are on first palette */
- if (rinfo->has_CRTC2) {
+ if (rinfo->gpu_info->has_CRTC2) {
dac_cntl2 = INREG(DAC_CNTL2);
dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
OUTREG(DAC_CNTL2, dac_cntl2);
@@ -1185,7 +1188,7 @@ static int radeonfb_setcmap(struct fb_cm
break;
}
- if (!rinfo->asleep && rinfo->is_mobility)
+ if (!rinfo->asleep && rinfo->gpu_info->is_mobility)
OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
return rc;
@@ -1235,7 +1238,7 @@ static void radeon_write_pll_regs(struct
radeon_fifo_wait(20);
/* Workaround from XFree */
- if (rinfo->is_mobility) {
+ if (rinfo->gpu_info->is_mobility) {
/* A temporal workaround for the occational blanking on certain laptop
* panels. This appears to related to the PLL divider registers
* (fail to lock?). It occurs even when all dividers are the same
@@ -1274,10 +1277,10 @@ static void radeon_write_pll_regs(struct
radeon_pll_errata_after_data(rinfo);
/* Set PPLL ref. div */
- if (rinfo->family == CHIP_FAMILY_R300 ||
- rinfo->family == CHIP_FAMILY_RS300 ||
- rinfo->family == CHIP_FAMILY_R350 ||
- rinfo->family == CHIP_FAMILY_RV350) {
+ if (rinfo->gpu_info->family == CHIP_FAMILY_R300 ||
+ rinfo->gpu_info->family == CHIP_FAMILY_RS300 ||
+ rinfo->gpu_info->family == CHIP_FAMILY_R350 ||
+ rinfo->gpu_info->family == CHIP_FAMILY_RV350) {
if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
/* When restoring console mode, use saved PPLL_REF_DIV
* setting.
@@ -1437,7 +1440,7 @@ #if 1
* divider. I'll find a better fix once I have more infos on the
* real cause of the problem.
*/
- while (rinfo->has_CRTC2) {
+ while (rinfo->gpu_info->has_CRTC2) {
u32 fp2_gen_cntl = INREG(FP2_GEN_CNTL);
u32 disp_output_cntl;
int source;
@@ -1448,10 +1451,10 @@ #if 1
/* Not all chip revs have the same format for this register,
* extract the source selection
*/
- if (rinfo->family == CHIP_FAMILY_R200 ||
- rinfo->family == CHIP_FAMILY_R300 ||
- rinfo->family == CHIP_FAMILY_R350 ||
- rinfo->family == CHIP_FAMILY_RV350) {
+ if (rinfo->gpu_info->family == CHIP_FAMILY_R200 ||
+ rinfo->gpu_info->family == CHIP_FAMILY_R300 ||
+ rinfo->gpu_info->family == CHIP_FAMILY_R350 ||
+ rinfo->gpu_info->family == CHIP_FAMILY_RV350) {
source = (fp2_gen_cntl >> 10) & 0x3;
/* sourced from transform unit, check for transform unit
* own source
@@ -1774,8 +1777,8 @@ #endif
FP_CRTC_DONT_SHADOW_HEND |
FP_PANEL_FORMAT);
- if (IS_R300_VARIANT(rinfo) ||
- (rinfo->family == CHIP_FAMILY_R200)) {
+ if (IS_R300_VARIANT(rinfo->gpu_info) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_R200)) {
newmode->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
if (use_rmx)
newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
@@ -1797,8 +1800,8 @@ #endif
newmode->fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
newmode->tmds_transmitter_cntl &= ~(TMDS_PLLRST);
/* TMDS_PLL_EN bit is reversed on RV (and mobility) chips */
- if (IS_R300_VARIANT(rinfo) ||
- (rinfo->family == CHIP_FAMILY_R200) || !rinfo->has_CRTC2)
+ if (IS_R300_VARIANT(rinfo->gpu_info) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_R200) || !rinfo->gpu_info->has_CRTC2)
newmode->tmds_transmitter_cntl &= ~TMDS_PLL_EN;
else
newmode->tmds_transmitter_cntl |= TMDS_PLL_EN;
@@ -1875,7 +1878,7 @@ static int __devinit radeon_set_fbinfo (
info->screen_size = rinfo->mapped_vram;
/* Fill fix common fields */
strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
- info->fix.smem_start = rinfo->fb_base_phys;
+ info->fix.smem_start = rinfo->gpu_info->fb_base_phys;
info->fix.smem_len = rinfo->video_ram;
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -1883,7 +1886,7 @@ static int __devinit radeon_set_fbinfo (
info->fix.ypanstep = 1;
info->fix.ywrapstep = 0;
info->fix.type_aux = 0;
- info->fix.mmio_start = rinfo->mmio_base_phys;
+ info->fix.mmio_start = rinfo->gpu_info->mmio_base_phys;
info->fix.mmio_len = RADEON_REGSIZE;
info->fix.accel = FB_ACCEL_ATI_RADEON;
@@ -1916,7 +1919,7 @@ static void fixup_memory_mappings(struct
u32 agp_base;
/* First, we disable display to avoid interfering */
- if (rinfo->has_CRTC2) {
+ if (rinfo->gpu_info->has_CRTC2) {
save_crtc2_gen_cntl = INREG(CRTC2_GEN_CNTL);
OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl | CRTC2_DISP_REQ_EN_B);
}
@@ -1958,12 +1961,12 @@ #endif
*/
#ifdef SET_MC_FB_FROM_APERTURE
OUTREG(DISPLAY_BASE_ADDR, aper_base);
- if (rinfo->has_CRTC2)
+ if (rinfo->gpu_info->has_CRTC2)
OUTREG(CRTC2_DISPLAY_BASE_ADDR, aper_base);
OUTREG(OV0_BASE_ADDR, aper_base);
#else
OUTREG(DISPLAY_BASE_ADDR, 0);
- if (rinfo->has_CRTC2)
+ if (rinfo->gpu_info->has_CRTC2)
OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0);
OUTREG(OV0_BASE_ADDR, 0);
#endif
@@ -1972,7 +1975,7 @@ #endif
/* Restore display settings */
OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl);
OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl);
- if (rinfo->has_CRTC2)
+ if (rinfo->gpu_info->has_CRTC2)
OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl);
RTRACE("aper_base: %08x MC_FB_LOC to: %08x, MC_AGP_LOC to: %08x\n",
@@ -1988,9 +1991,9 @@ static void radeon_identify_vram(struct
u32 tmp;
/* framebuffer size */
- if ((rinfo->family == CHIP_FAMILY_RS100) ||
- (rinfo->family == CHIP_FAMILY_RS200) ||
- (rinfo->family == CHIP_FAMILY_RS300)) {
+ if ((rinfo->gpu_info->family == CHIP_FAMILY_RS100) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_RS200) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_RS300)) {
u32 tom = INREG(NB_TOM);
tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
@@ -2003,8 +2006,8 @@ static void radeon_identify_vram(struct
/* This is supposed to fix the crtc2 noise problem. */
OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
- if ((rinfo->family == CHIP_FAMILY_RS100) ||
- (rinfo->family == CHIP_FAMILY_RS200)) {
+ if ((rinfo->gpu_info->family == CHIP_FAMILY_RS100) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_RS200)) {
/* This is to workaround the asic bug for RMX, some versions
of BIOS dosen't have this register initialized correctly.
*/
@@ -2023,7 +2026,7 @@ static void radeon_identify_vram(struct
* reporting no ram
*/
if (rinfo->video_ram == 0) {
- switch (rinfo->pdev->device) {
+ switch (rinfo->gpu_info->pdev->device) {
case PCI_CHIP_RADEON_LY:
case PCI_CHIP_RADEON_LZ:
rinfo->video_ram = 8192 * 1024;
@@ -2037,14 +2040,14 @@ static void radeon_identify_vram(struct
/*
* Now try to identify VRAM type
*/
- if (rinfo->is_IGP || (rinfo->family >= CHIP_FAMILY_R300) ||
+ if (rinfo->gpu_info->is_IGP || (rinfo->gpu_info->family >= CHIP_FAMILY_R300) ||
(INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
rinfo->vram_ddr = 1;
else
rinfo->vram_ddr = 0;
tmp = INREG(MEM_CNTL);
- if (IS_R300_VARIANT(rinfo)) {
+ if (IS_R300_VARIANT(rinfo->gpu_info)) {
tmp &= R300_MEM_NUM_CHANNELS_MASK;
switch (tmp) {
case 0: rinfo->vram_width = 64; break;
@@ -2052,9 +2055,9 @@ static void radeon_identify_vram(struct
case 2: rinfo->vram_width = 256; break;
default: rinfo->vram_width = 128; break;
}
- } else if ((rinfo->family == CHIP_FAMILY_RV100) ||
- (rinfo->family == CHIP_FAMILY_RS100) ||
- (rinfo->family == CHIP_FAMILY_RS200)){
+ } else if ((rinfo->gpu_info->family == CHIP_FAMILY_RV100) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_RS100) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_RS200)){
if (tmp & RV100_MEM_HALF_MODE)
rinfo->vram_width = 32;
else
@@ -2071,7 +2074,7 @@ static void radeon_identify_vram(struct
*/
RTRACE("radeonfb (%s): Found %ldk of %s %d bits wide videoram\n",
- pci_name(rinfo->pdev),
+ pci_name(rinfo->gpu_info->pdev),
rinfo->video_ram / 1024,
rinfo->vram_ddr ? "DDR" : "SDRAM",
rinfo->vram_width);
@@ -2098,8 +2101,8 @@ static ssize_t radeon_show_one_edid(char
static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct pci_dev *pdev = to_pci_dev(dev);
- struct fb_info *info = pci_get_drvdata(pdev);
+ struct gpu_device *gdev = to_gpu_device(dev);
+ struct fb_info *info = gpu_get_drvdata(gdev);
struct radeonfb_info *rinfo = info->par;
return radeon_show_one_edid(buf, off, count, rinfo->mon1_EDID);
@@ -2109,8 +2112,8 @@ static ssize_t radeon_show_edid1(struct
static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct pci_dev *pdev = to_pci_dev(dev);
- struct fb_info *info = pci_get_drvdata(pdev);
+ struct gpu_device *gdev = to_gpu_device(dev);
+ struct fb_info *info = gpu_get_drvdata(gdev);
struct radeonfb_info *rinfo = info->par;
return radeon_show_one_edid(buf, off, count, rinfo->mon2_EDID);
@@ -2137,72 +2140,64 @@ static struct bin_attribute edid2_attr =
};
-static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __devinit radeonfb_gpu_register (struct gpu_device *gdev, void *driver_id)
{
struct fb_info *info;
struct radeonfb_info *rinfo;
+ struct radeon_gpu_info *gpu_info;
int ret;
+ struct pci_dev *pdev;
- RTRACE("radeonfb_pci_register BEGIN\n");
-
- /* Enable device in PCI config */
- ret = pci_enable_device(pdev);
- if (ret < 0) {
- printk(KERN_ERR "radeonfb (%s): Cannot enable PCI device\n",
- pci_name(pdev));
- goto err_out;
- }
+ /* get the radeon GPU info */
+ gpu_info = dev_get_drvdata(gdev->dev.parent);
+
+ pdev = gpu_info->pdev;
+ printk("radeonfb: %08lX\n", gpu_info->mmio_base_phys);
+
+ RTRACE("radeonfb_gpu_register BEGIN\n");
- info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev);
+ info = framebuffer_alloc(sizeof(struct radeonfb_info), &gdev->dev);
if (!info) {
- printk (KERN_ERR "radeonfb (%s): could not allocate memory\n",
- pci_name(pdev));
+ printk (KERN_ERR "radeonfb : could not allocate memory\n");
ret = -ENOMEM;
goto err_disable;
}
rinfo = info->par;
rinfo->info = info;
- rinfo->pdev = pdev;
+ rinfo->gpu_info = gpu_info;
+ rinfo->gdev = gdev;
+
spin_lock_init(&rinfo->reg_lock);
init_timer(&rinfo->lvds_timer);
rinfo->lvds_timer.function = radeon_lvds_timer_func;
rinfo->lvds_timer.data = (unsigned long)rinfo;
strcpy(rinfo->name, "ATI Radeon XX ");
- rinfo->name[11] = ent->device >> 8;
- rinfo->name[12] = ent->device & 0xFF;
- rinfo->family = ent->driver_data & CHIP_FAMILY_MASK;
- rinfo->chipset = pdev->device;
- rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0;
- rinfo->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0;
- rinfo->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0;
-
- /* Set base addrs */
- rinfo->fb_base_phys = pci_resource_start (pdev, 0);
- rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
+
+ rinfo->name[11] = rinfo->gpu_info->ati_name[0];
+ rinfo->name[12] = rinfo->gpu_info->ati_name[1];
/* request the mem regions */
- ret = pci_request_region(pdev, 0, "radeonfb framebuffer");
+ ret = pci_request_region(gpu_info->pdev, 0, "radeonfb framebuffer");
if (ret < 0) {
printk( KERN_ERR "radeonfb (%s): cannot request region 0.\n",
- pci_name(rinfo->pdev));
+ pci_name(rinfo->gpu_info->pdev));
goto err_release_fb;
}
- ret = pci_request_region(pdev, 2, "radeonfb mmio");
+ ret = pci_request_region(gpu_info->pdev, 2, "radeonfb mmio");
if (ret < 0) {
printk( KERN_ERR "radeonfb (%s): cannot request region 2.\n",
- pci_name(rinfo->pdev));
+ pci_name(rinfo->gpu_info->pdev));
goto err_release_pci0;
}
/* map the regions */
- rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, RADEON_REGSIZE);
+ rinfo->mmio_base = ioremap(rinfo->gpu_info->mmio_base_phys, RADEON_REGSIZE);
if (!rinfo->mmio_base) {
printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n",
- pci_name(rinfo->pdev));
+ pci_name(rinfo->gpu_info->pdev));
ret = -EIO;
goto err_release_pci2;
}
@@ -2210,22 +2205,12 @@ static int __devinit radeonfb_pci_regist
rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
/*
- * Check for errata
+ * Check for additional errata
*/
- rinfo->errata = 0;
- if (rinfo->family == CHIP_FAMILY_R300 &&
+ if (rinfo->gpu_info->family == CHIP_FAMILY_R300 &&
(INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
== CFG_ATI_REV_A11)
- rinfo->errata |= CHIP_ERRATA_R300_CG;
-
- if (rinfo->family == CHIP_FAMILY_RV200 ||
- rinfo->family == CHIP_FAMILY_RS200)
- rinfo->errata |= CHIP_ERRATA_PLL_DUMMYREADS;
-
- if (rinfo->family == CHIP_FAMILY_RV100 ||
- rinfo->family == CHIP_FAMILY_RS100 ||
- rinfo->family == CHIP_FAMILY_RS200)
- rinfo->errata |= CHIP_ERRATA_PLL_DELAY;
+ rinfo->gpu_info->errata |= CHIP_ERRATA_R300_CG;
#ifdef CONFIG_PPC_OF
/* On PPC, we obtain the OF device-node pointer to the firmware
@@ -2234,7 +2219,7 @@ #ifdef CONFIG_PPC_OF
rinfo->of_node = pci_device_to_OF_node(pdev);
if (rinfo->of_node == NULL)
printk(KERN_WARNING "radeonfb (%s): Cannot match card to OF node !\n",
- pci_name(rinfo->pdev));
+ pci_name(rinfo->gpu_info->pdev));
/* On PPC, the firmware sets up a memory mapping that tends
* to cause lockups when enabling the engine. We reconfigure
@@ -2249,19 +2234,19 @@ #endif /* CONFIG_PPC_OF */
rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM, rinfo->video_ram);
do {
- rinfo->fb_base = ioremap (rinfo->fb_base_phys,
+ rinfo->fb_base = ioremap (rinfo->gpu_info->fb_base_phys,
rinfo->mapped_vram);
} while ( rinfo->fb_base == 0 &&
((rinfo->mapped_vram /=2) >= MIN_MAPPED_VRAM) );
if (rinfo->fb_base == NULL) {
printk (KERN_ERR "radeonfb (%s): cannot map FB\n",
- pci_name(rinfo->pdev));
+ pci_name(rinfo->gpu_info->pdev));
ret = -EIO;
goto err_unmap_rom;
}
- RTRACE("radeonfb (%s): mapped %ldk videoram\n", pci_name(rinfo->pdev),
+ RTRACE("radeonfb (%s): mapped %ldk videoram\n", pci_name(rinfo->gpu_info->pdev),
rinfo->mapped_vram/1024);
/*
@@ -2275,8 +2260,8 @@ #endif /* CONFIG_PPC_OF */
* archs who would store that elsewhere and/or could initialize
* more than one adapter during boot).
*/
- if (!rinfo->is_mobility)
- radeon_map_ROM(rinfo, pdev);
+ if (!rinfo->gpu_info->is_mobility)
+ radeon_map_ROM(rinfo, rinfo->gpu_info->pdev);
/*
* On x86, the primary display on laptop may have it's BIOS
@@ -2292,8 +2277,8 @@ #endif
/* If both above failed, try the BIOS ROM again for mobility
* chips
*/
- if (rinfo->bios_seg == NULL && rinfo->is_mobility)
- radeon_map_ROM(rinfo, pdev);
+ if (rinfo->bios_seg == NULL && rinfo->gpu_info->is_mobility)
+ radeon_map_ROM(rinfo, rinfo->gpu_info->pdev);
/* Get informations about the board's PLL */
radeon_get_pllinfo(rinfo);
@@ -2314,9 +2299,9 @@ #endif
/* Register some sysfs stuff (should be done better) */
if (rinfo->mon1_EDID)
- sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr);
+ sysfs_create_bin_file(&gdev->dev.kobj, &edid1_attr);
if (rinfo->mon2_EDID)
- sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
+ sysfs_create_bin_file(&gdev->dev.kobj, &edid2_attr);
/* save current mode regs before we switch into the new one
* so we can restore this upon __exit
@@ -2329,29 +2314,29 @@ #endif
/* -2 is special: means ON on mobility chips and do not
* change on others
*/
- radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1, ignore_devlist, force_sleep);
+ radeonfb_pm_init(rinfo, rinfo->gpu_info->is_mobility ? 1 : -1, ignore_devlist, force_sleep);
} else
radeonfb_pm_init(rinfo, default_dynclk, ignore_devlist, force_sleep);
- pci_set_drvdata(pdev, info);
+ gpu_set_drvdata(gdev, info);
/* Register with fbdev layer */
ret = register_framebuffer(info);
if (ret < 0) {
printk (KERN_ERR "radeonfb (%s): could not register framebuffer\n",
- pci_name(rinfo->pdev));
+ pci_name(rinfo->gpu_info->pdev));
goto err_unmap_fb;
}
#ifdef CONFIG_MTRR
- rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys,
+ rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->gpu_info->fb_base_phys,
rinfo->video_ram,
MTRR_TYPE_WRCOMB, 1);
#endif
radeonfb_bl_init(rinfo);
- printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name);
+ printk ("radeonfb (%s): %s\n", pci_name(rinfo->gpu_info->pdev), rinfo->name);
if (rinfo->bios_seg)
radeon_unmap_ROM(rinfo, pdev);
@@ -2370,7 +2355,7 @@ #ifdef CONFIG_FB_RADEON_I2C
radeon_delete_i2c_busses(rinfo);
#endif
if (rinfo->bios_seg)
- radeon_unmap_ROM(rinfo, pdev);
+ radeon_unmap_ROM(rinfo, rinfo->gpu_info->pdev);
iounmap(rinfo->mmio_base);
err_release_pci2:
pci_release_region(pdev, 2);
@@ -2379,27 +2364,27 @@ err_release_pci0:
err_release_fb:
framebuffer_release(info);
err_disable:
-err_out:
return ret;
}
-static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
+static void __devexit radeonfb_gpu_unregister(struct gpu_device *gdev)
{
- struct fb_info *info = pci_get_drvdata(pdev);
- struct radeonfb_info *rinfo = info->par;
-
- if (!rinfo)
- return;
+ struct fb_info *info = gpu_get_drvdata(gdev);
+ struct radeonfb_info *rinfo = info->par;
+ struct pci_dev *pdev = rinfo->gpu_info->pdev;
+
+ if (!rinfo)
+ return;
radeonfb_bl_exit(rinfo);
radeonfb_pm_exit(rinfo);
if (rinfo->mon1_EDID)
- sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr);
+ sysfs_remove_bin_file(&gdev->dev.kobj, &edid1_attr);
if (rinfo->mon2_EDID)
- sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
+ sysfs_remove_bin_file(&gdev->dev.kobj, &edid2_attr);
#if 0
/* restore original state
@@ -2418,11 +2403,12 @@ #ifdef CONFIG_MTRR
mtrr_del(rinfo->mtrr_hdl, 0, 0);
#endif
- unregister_framebuffer(info);
+ gpu_set_drvdata(gdev, NULL);
+ unregister_framebuffer(info);
+
+ iounmap(rinfo->mmio_base);
+ iounmap(rinfo->fb_base);
- iounmap(rinfo->mmio_base);
- iounmap(rinfo->fb_base);
-
pci_release_region(pdev, 2);
pci_release_region(pdev, 0);
@@ -2438,14 +2424,17 @@ #endif
}
-static struct pci_driver radeonfb_driver = {
+static struct gpu_driver radeonfb_driver = {
.name = "radeonfb",
- .id_table = radeonfb_pci_table,
- .probe = radeonfb_pci_register,
- .remove = __devexit_p(radeonfb_pci_unregister),
+ .drv_type = GPU_FB,
+ .probe = radeonfb_gpu_register,
+ .remove = __devexit_p(radeonfb_gpu_unregister),
+ .id_table = (void *)radeonfb_pci_table,
#ifdef CONFIG_PM
- .suspend = radeonfb_pci_suspend,
- .resume = radeonfb_pci_resume,
+ .driver = {
+ .suspend = radeonfb_gpu_suspend,
+ .resume = radeonfb_gpu_resume,
+ }
#endif /* CONFIG_PM */
};
@@ -2501,13 +2490,13 @@ #ifndef MODULE
return -ENODEV;
radeonfb_setup(option);
#endif
- return pci_register_driver (&radeonfb_driver);
+ return radeon_gpu_register_driver(&radeonfb_driver, THIS_MODULE);
}
static void __exit radeonfb_exit (void)
{
- pci_unregister_driver (&radeonfb_driver);
+ gpu_unregister_driver (&radeonfb_driver);
}
module_init(radeonfb_init);
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index e7c5b21..09614b3 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -74,7 +74,7 @@ static int radeon_setup_i2c_bus(struct r
chan->adapter.owner = THIS_MODULE;
chan->adapter.id = I2C_HW_B_RADEON;
chan->adapter.algo_data = &chan->algo;
- chan->adapter.dev.parent = &chan->rinfo->pdev->dev;
+ chan->adapter.dev.parent = &chan->rinfo->gdev->dev;
chan->algo.setsda = radeon_gpio_setsda;
chan->algo.setscl = radeon_gpio_setscl;
chan->algo.getsda = radeon_gpio_getsda;
@@ -92,9 +92,9 @@ static int radeon_setup_i2c_bus(struct r
rc = i2c_bit_add_bus(&chan->adapter);
if (rc == 0)
- dev_dbg(&chan->rinfo->pdev->dev, "I2C bus %s registered.\n", name);
+ dev_dbg(&chan->rinfo->gdev->dev, "I2C bus %s registered.\n", name);
else
- dev_warn(&chan->rinfo->pdev->dev, "Failed to register I2C bus %s.\n", name);
+ dev_warn(&chan->rinfo->gdev->dev, "Failed to register I2C bus %s.\n", name);
return rc;
}
@@ -155,7 +155,7 @@ int radeon_probe_i2c_connector(struct ra
}
if (edid[0x14] & 0x80) {
/* Fix detection using BIOS tables */
- if (rinfo->is_mobility /*&& conn == ddc_dvi*/ &&
+ if (rinfo->gpu_info->is_mobility /*&& conn == ddc_dvi*/ &&
(INREG(LVDS_GEN_CNTL) & LVDS_ON)) {
RTRACE("radeonfb: I2C (port %d) ... found LVDS panel\n", conn);
return MT_LCD;
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index 38c7dbf..8625f5d 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -328,8 +328,8 @@ static int __devinit radeon_crt_is_conne
ulData |= (DAC_FORCE_BLANK_OFF_EN
|DAC_FORCE_DATA_EN
|DAC_FORCE_DATA_SEL_MASK);
- if ((rinfo->family == CHIP_FAMILY_RV250) ||
- (rinfo->family == CHIP_FAMILY_RV280))
+ if ((rinfo->gpu_info->family == CHIP_FAMILY_RV250) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_RV280))
ulData |= (0x01b6 << DAC_FORCE_DATA_SHIFT);
else
ulData |= (0x01ac << DAC_FORCE_DATA_SHIFT);
@@ -494,7 +494,7 @@ #endif /* DEBUG */
/*
* Old single head cards
*/
- if (!rinfo->has_CRTC2) {
+ if (!rinfo->gpu_info->has_CRTC2) {
#ifdef CONFIG_PPC_OF
if (rinfo->mon1_type == MT_NONE)
rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
@@ -560,7 +560,7 @@ #ifdef CONFIG_FB_RADEON_I2C
ddc_crt2_used = 1;
}
#endif /* CONFIG_FB_RADEON_I2C */
- if (rinfo->mon1_type == MT_NONE && rinfo->is_mobility &&
+ if (rinfo->mon1_type == MT_NONE && rinfo->gpu_info->is_mobility &&
((rinfo->bios_seg && (INREG(BIOS_4_SCRATCH) & 4))
|| (INREG(LVDS_GEN_CNTL) & LVDS_ON))) {
rinfo->mon1_type = MT_LCD;
@@ -632,7 +632,7 @@ #endif /* CONFIG_FB_RADEON_I2C */
radeon_get_mon_name(rinfo->mon1_type));
if (rinfo->mon1_EDID)
printk(KERN_INFO "radeonfb: EDID probed\n");
- if (!rinfo->has_CRTC2)
+ if (!rinfo->gpu_info->has_CRTC2)
return;
printk(KERN_INFO "radeonfb: Monitor 2 type %s found\n",
radeon_get_mon_name(rinfo->mon2_type));
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 9a2b0d6..9a59804 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -97,8 +97,8 @@ static int radeon_apply_workarounds(stru
struct radeon_device_id *id;
for (id = radeon_workaround_list; id->ident != NULL; id++ )
- if ((id->subsystem_vendor == rinfo->pdev->subsystem_vendor ) &&
- (id->subsystem_device == rinfo->pdev->subsystem_device )) {
+ if ((id->subsystem_vendor == rinfo->gpu_info->pdev->subsystem_vendor ) &&
+ (id->subsystem_device == rinfo->gpu_info->pdev->subsystem_device )) {
/* we found a device that requires workaround */
printk(KERN_DEBUG "radeonfb: %s detected"
@@ -128,8 +128,8 @@ static void radeon_pm_disable_dynamic_mo
u32 tmp;
/* RV100 */
- if ((rinfo->family == CHIP_FAMILY_RV100) && (!rinfo->is_mobility)) {
- if (rinfo->has_CRTC2) {
+ if ((rinfo->gpu_info->family == CHIP_FAMILY_RV100) && (!rinfo->gpu_info->is_mobility)) {
+ if (rinfo->gpu_info->has_CRTC2) {
tmp = INPLL(pllSCLK_CNTL);
tmp &= ~SCLK_CNTL__DYN_STOP_LAT_MASK;
tmp |= SCLK_CNTL__CP_MAX_DYN_STOP_LAT | SCLK_CNTL__FORCEON_MASK;
@@ -146,7 +146,7 @@ static void radeon_pm_disable_dynamic_mo
return;
}
/* R100 */
- if (!rinfo->has_CRTC2) {
+ if (!rinfo->gpu_info->has_CRTC2) {
tmp = INPLL(pllSCLK_CNTL);
tmp |= (SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_HDP |
SCLK_CNTL__FORCE_DISP1 | SCLK_CNTL__FORCE_TOP |
@@ -159,7 +159,7 @@ static void radeon_pm_disable_dynamic_mo
return;
}
/* RV350 (M10/M11) */
- if (rinfo->family == CHIP_FAMILY_RV350) {
+ if (rinfo->gpu_info->family == CHIP_FAMILY_RV350) {
/* for RV350/M10/M11, no delays are required. */
tmp = INPLL(pllSCLK_CNTL2);
tmp |= (SCLK_CNTL2__R300_FORCE_TCL |
@@ -226,7 +226,7 @@ static void radeon_pm_disable_dynamic_mo
/* XFree doesn't do that case, but we had this code from Apple and it
* seem necessary for proper suspend/resume operations
*/
- if (rinfo->is_mobility) {
+ if (rinfo->gpu_info->is_mobility) {
tmp |= SCLK_CNTL__FORCE_HDP|
SCLK_CNTL__FORCE_DISP1|
SCLK_CNTL__FORCE_DISP2|
@@ -243,8 +243,8 @@ static void radeon_pm_disable_dynamic_mo
SCLK_CNTL__FORCE_SUBPIC|
SCLK_CNTL__FORCE_OV0;
}
- else if (rinfo->family == CHIP_FAMILY_R300 ||
- rinfo->family == CHIP_FAMILY_R350) {
+ else if (rinfo->gpu_info->family == CHIP_FAMILY_R300 ||
+ rinfo->gpu_info->family == CHIP_FAMILY_R350) {
tmp |= SCLK_CNTL__FORCE_HDP |
SCLK_CNTL__FORCE_DISP1 |
SCLK_CNTL__FORCE_DISP2 |
@@ -255,7 +255,7 @@ static void radeon_pm_disable_dynamic_mo
OUTPLL(pllSCLK_CNTL, tmp);
radeon_msleep(16);
- if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) {
+ if (rinfo->gpu_info->family == CHIP_FAMILY_R300 || rinfo->gpu_info->family == CHIP_FAMILY_R350) {
tmp = INPLL(pllSCLK_CNTL2);
tmp |= SCLK_CNTL2__R300_FORCE_TCL |
SCLK_CNTL2__R300_FORCE_GA |
@@ -269,7 +269,7 @@ static void radeon_pm_disable_dynamic_mo
OUTPLL(pllCLK_PIN_CNTL, tmp);
radeon_msleep(15);
- if (rinfo->is_IGP) {
+ if (rinfo->gpu_info->is_IGP) {
/* Weird ... X is _un_ forcing clocks here, I think it's
* doing backward. Imitate it for now...
*/
@@ -280,7 +280,7 @@ static void radeon_pm_disable_dynamic_mo
radeon_msleep(16);
}
/* Hrm... same shit, X doesn't do that but I have to */
- else if (rinfo->is_mobility) {
+ else if (rinfo->gpu_info->is_mobility) {
tmp = INPLL(pllMCLK_CNTL);
tmp |= (MCLK_CNTL__FORCE_MCLKA |
MCLK_CNTL__FORCE_MCLKB |
@@ -298,7 +298,7 @@ static void radeon_pm_disable_dynamic_mo
radeon_msleep(15);
}
- if (rinfo->is_mobility) {
+ if (rinfo->gpu_info->is_mobility) {
tmp = INPLL(pllSCLK_MORE_CNTL);
tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS|
SCLK_MORE_CNTL__FORCE_MC_GUI|
@@ -330,7 +330,7 @@ static void radeon_pm_enable_dynamic_mod
u32 tmp;
/* R100 */
- if (!rinfo->has_CRTC2) {
+ if (!rinfo->gpu_info->has_CRTC2) {
tmp = INPLL(pllSCLK_CNTL);
if ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13)
@@ -345,7 +345,7 @@ static void radeon_pm_enable_dynamic_mod
}
/* M10/M11 */
- if (rinfo->family == CHIP_FAMILY_RV350) {
+ if (rinfo->gpu_info->family == CHIP_FAMILY_RV350) {
tmp = INPLL(pllSCLK_CNTL2);
tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL |
SCLK_CNTL2__R300_FORCE_GA |
@@ -430,7 +430,7 @@ static void radeon_pm_enable_dynamic_mod
}
/* R300 */
- if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) {
+ if (rinfo->gpu_info->family == CHIP_FAMILY_R300 || rinfo->gpu_info->family == CHIP_FAMILY_R350) {
tmp = INPLL(pllSCLK_CNTL);
tmp &= ~(SCLK_CNTL__R300_FORCE_VAP);
tmp |= SCLK_CNTL__FORCE_CP;
@@ -467,9 +467,9 @@ static void radeon_pm_enable_dynamic_mod
tmp &= ~SCLK_CNTL__FORCEON_MASK;
/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
- if ((rinfo->family == CHIP_FAMILY_RV250 &&
+ if ((rinfo->gpu_info->family == CHIP_FAMILY_RV250 &&
((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
- ((rinfo->family == CHIP_FAMILY_RV100) &&
+ ((rinfo->gpu_info->family == CHIP_FAMILY_RV100) &&
((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) {
tmp |= SCLK_CNTL__FORCE_CP;
tmp |= SCLK_CNTL__FORCE_VIP;
@@ -477,15 +477,15 @@ static void radeon_pm_enable_dynamic_mod
OUTPLL(pllSCLK_CNTL, tmp);
radeon_msleep(15);
- if ((rinfo->family == CHIP_FAMILY_RV200) ||
- (rinfo->family == CHIP_FAMILY_RV250) ||
- (rinfo->family == CHIP_FAMILY_RV280)) {
+ if ((rinfo->gpu_info->family == CHIP_FAMILY_RV200) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_RV250) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_RV280)) {
tmp = INPLL(pllSCLK_MORE_CNTL);
tmp &= ~SCLK_MORE_CNTL__FORCEON;
/* RV200::A11 A12 RV250::A11 A12 */
- if (((rinfo->family == CHIP_FAMILY_RV200) ||
- (rinfo->family == CHIP_FAMILY_RV250)) &&
+ if (((rinfo->gpu_info->family == CHIP_FAMILY_RV200) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_RV250)) &&
((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13))
tmp |= SCLK_MORE_CNTL__FORCEON;
@@ -495,8 +495,8 @@ static void radeon_pm_enable_dynamic_mod
/* RV200::A11 A12, RV250::A11 A12 */
- if (((rinfo->family == CHIP_FAMILY_RV200) ||
- (rinfo->family == CHIP_FAMILY_RV250)) &&
+ if (((rinfo->gpu_info->family == CHIP_FAMILY_RV200) ||
+ (rinfo->gpu_info->family == CHIP_FAMILY_RV250)) &&
((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) {
tmp = INPLL(pllPLL_PWRMGT_CNTL);
tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE;
@@ -522,7 +522,7 @@ static void radeon_pm_enable_dynamic_mod
/* X doesn't do that ... hrm, we do on mobility && Macs */
#ifdef CONFIG_PPC_OF
- if (rinfo->is_mobility) {
+ if (rinfo->gpu_info->is_mobility) {
tmp = INPLL(pllMCLK_CNTL);
tmp &= ~(MCLK_CNTL__FORCE_MCLKA |
MCLK_CNTL__FORCE_MCLKB |
@@ -603,7 +603,7 @@ static void radeon_pm_save_regs(struct r
rinfo->save_regs[37] = INREG(MPP_TB_CONFIG);
rinfo->save_regs[38] = INREG(FCP_CNTL);
- if (rinfo->is_mobility) {
+ if (rinfo->gpu_info->is_mobility) {
rinfo->save_regs[12] = INREG(LVDS_PLL_CNTL);
rinfo->save_regs[43] = INPLL(pllSSPLL_CNTL);
rinfo->save_regs[44] = INPLL(pllSSPLL_REF_DIV);
@@ -613,7 +613,7 @@ static void radeon_pm_save_regs(struct r
rinfo->save_regs[81] = INREG(LVDS_GEN_CNTL);
}
- if (rinfo->family >= CHIP_FAMILY_RV200) {
+ if (rinfo->gpu_info->family >= CHIP_FAMILY_RV200) {
rinfo->save_regs[42] = INREG(MEM_REFRESH_CNTL);
rinfo->save_regs[46] = INREG(MC_CNTL);
rinfo->save_regs[47] = INREG(MC_INIT_GFX_LAT_TIMER);
@@ -629,7 +629,7 @@ static void radeon_pm_save_regs(struct r
rinfo->save_regs[56] = INREG(PAD_CTLR_MISC);
rinfo->save_regs[57] = INREG(FW_CNTL);
- if (rinfo->family >= CHIP_FAMILY_R300) {
+ if (rinfo->gpu_info->family >= CHIP_FAMILY_R300) {
rinfo->save_regs[58] = INMC(rinfo, ixR300_MC_MC_INIT_WR_LAT_TIMER);
rinfo->save_regs[59] = INMC(rinfo, ixR300_MC_IMP_CNTL);
rinfo->save_regs[60] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_C0);
@@ -694,7 +694,7 @@ static void radeon_pm_restore_regs(struc
OUTPLL(VCLK_ECP_CNTL, rinfo->save_regs[5]);
OUTPLL(PIXCLKS_CNTL, rinfo->save_regs[6]);
OUTPLL(MCLK_MISC, rinfo->save_regs[7]);
- if (rinfo->family == CHIP_FAMILY_RV350)
+ if (rinfo->gpu_info->family == CHIP_FAMILY_RV350)
OUTPLL(SCLK_MORE_CNTL, rinfo->save_regs[34]);
OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
@@ -745,7 +745,7 @@ static void radeon_pm_disable_iopad(stru
static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo)
{
/* Set v2clk to 65MHz */
- if (rinfo->family <= CHIP_FAMILY_RV280) {
+ if (rinfo->gpu_info->family <= CHIP_FAMILY_RV280) {
OUTPLL(pllPIXCLKS_CNTL,
__INPLL(rinfo, pllPIXCLKS_CNTL)
& ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK);
@@ -777,7 +777,7 @@ static void radeon_pm_low_current(struct
u32 reg;
reg = INREG(BUS_CNTL1);
- if (rinfo->family <= CHIP_FAMILY_RV280) {
+ if (rinfo->gpu_info->family <= CHIP_FAMILY_RV280) {
reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK;
reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT);
} else {
@@ -857,7 +857,7 @@ static void radeon_pm_setup_for_suspend(
SCLK_CNTL__FORCE_TV_SCLK|
SCLK_CNTL__FORCE_SUBPIC|
SCLK_CNTL__FORCE_OV0;
- if (rinfo->family <= CHIP_FAMILY_RV280)
+ if (rinfo->gpu_info->family <= CHIP_FAMILY_RV280)
sclk_cntl |= SCLK_CNTL__FORCE_RE;
else
sclk_cntl |= SCLK_CNTL__SE_MAX_DYN_STOP_LAT |
@@ -1260,7 +1260,7 @@ static void radeon_pm_full_reset_sdram(s
OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) );
/* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */
- if (rinfo->family == CHIP_FAMILY_RV350) {
+ if (rinfo->gpu_info->family == CHIP_FAMILY_RV350) {
u32 sdram_mode_reg = rinfo->save_regs[35];
static u32 default_mrtable[] =
{ 0x21320032,
@@ -1321,7 +1321,7 @@ #endif /* CONFIG_PPC_OF */
}
/* Here come the desktop RV200 "QW" card */
- else if (!rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV200) {
+ else if (!rinfo->gpu_info->is_mobility && rinfo->gpu_info->family == CHIP_FAMILY_RV200) {
/* Disable refresh */
memRefreshCntl = INREG( MEM_REFRESH_CNTL)
& ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS;
@@ -1344,7 +1344,7 @@ #endif /* CONFIG_PPC_OF */
}
/* The M6 */
- else if (rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV100) {
+ else if (rinfo->gpu_info->is_mobility && rinfo->gpu_info->family == CHIP_FAMILY_RV100) {
/* Disable refresh */
memRefreshCntl = INREG(EXT_MEM_CNTL) & ~(1 << 20);
OUTREG( EXT_MEM_CNTL, memRefreshCntl | (1 << 20));
@@ -1374,7 +1374,7 @@ #endif /* CONFIG_PPC_OF */
OUTREG(EXT_MEM_CNTL, memRefreshCntl);
}
/* And finally, the M7..M9 models, including M9+ (RV280) */
- else if (rinfo->is_mobility) {
+ else if (rinfo->gpu_info->is_mobility) {
/* Disable refresh */
memRefreshCntl = INREG( MEM_REFRESH_CNTL)
@@ -1394,7 +1394,7 @@ #endif /* CONFIG_PPC_OF */
radeon_pm_yclk_mclk_sync(rinfo);
/* M6, M7 and M9 so far ... */
- if (rinfo->family <= CHIP_FAMILY_RV250) {
+ if (rinfo->gpu_info->family <= CHIP_FAMILY_RV250) {
radeon_pm_program_mode_reg(rinfo, 0x2000, 1);
radeon_pm_program_mode_reg(rinfo, 0x2001, 1);
radeon_pm_program_mode_reg(rinfo, 0x2002, 1);
@@ -1402,7 +1402,7 @@ #endif /* CONFIG_PPC_OF */
radeon_pm_program_mode_reg(rinfo, 0x0032, 1);
}
/* M9+ (iBook G4) */
- else if (rinfo->family == CHIP_FAMILY_RV280) {
+ else if (rinfo->gpu_info->family == CHIP_FAMILY_RV280) {
radeon_pm_program_mode_reg(rinfo, 0x2000, 1);
radeon_pm_program_mode_reg(rinfo, 0x0132, 1);
radeon_pm_program_mode_reg(rinfo, 0x0032, 1);
@@ -2522,7 +2522,7 @@ static void radeon_set_suspend(struct ra
*/
if (suspend) {
printk(KERN_DEBUG "radeonfb (%s): switching to D2 state...\n",
- pci_name(rinfo->pdev));
+ pci_name(rinfo->gpu_info->pdev));
/* Disable dynamic power management of clocks for the
* duration of the suspend/resume process
@@ -2534,7 +2534,7 @@ static void radeon_set_suspend(struct ra
/* Prepare mobility chips for suspend.
*/
- if (rinfo->is_mobility) {
+ if (rinfo->gpu_info->is_mobility) {
/* Program V2CLK */
radeon_pm_program_v2clk(rinfo);
@@ -2547,7 +2547,7 @@ static void radeon_set_suspend(struct ra
/* Prepare chip for power management */
radeon_pm_setup_for_suspend(rinfo);
- if (rinfo->family <= CHIP_FAMILY_RV280) {
+ if (rinfo->gpu_info->family <= CHIP_FAMILY_RV280) {
/* Reset the MDLL */
/* because both INPLL and OUTPLL take the same
* lock, that's why. */
@@ -2558,32 +2558,32 @@ static void radeon_set_suspend(struct ra
}
for (i = 0; i < 64; ++i)
- pci_read_config_dword(rinfo->pdev, i * 4,
+ pci_read_config_dword(rinfo->gpu_info->pdev, i * 4,
&rinfo->cfg_save[i]);
/* Switch PCI power managment to D2. */
- pci_disable_device(rinfo->pdev);
+ pci_disable_device(rinfo->gpu_info->pdev);
for (;;) {
pci_read_config_word(
- rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
+ rinfo->gpu_info->pdev, rinfo->pm_reg+PCI_PM_CTRL,
&pwr_cmd);
if (pwr_cmd & 2)
break;
pci_write_config_word(
- rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
+ rinfo->gpu_info->pdev, rinfo->pm_reg+PCI_PM_CTRL,
(pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2);
mdelay(500);
}
} else {
printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
- pci_name(rinfo->pdev));
+ pci_name(rinfo->gpu_info->pdev));
/* Switch back PCI powermanagment to D0 */
mdelay(200);
- pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0);
+ pci_write_config_word(rinfo->gpu_info->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0);
mdelay(500);
- if (rinfo->family <= CHIP_FAMILY_RV250) {
+ if (rinfo->gpu_info->family <= CHIP_FAMILY_RV250) {
/* Reset the SDRAM controller */
radeon_pm_full_reset_sdram(rinfo);
@@ -2604,7 +2604,7 @@ static int radeon_restore_pci_cfg(struct
static u32 radeon_cfg_after_resume[64];
for (i = 0; i < 64; ++i)
- pci_read_config_dword(rinfo->pdev, i * 4,
+ pci_read_config_dword(rinfo->gpu_info->pdev, i * 4,
&radeon_cfg_after_resume[i]);
if (radeon_cfg_after_resume[PCI_BASE_ADDRESS_0/4]
@@ -2613,21 +2613,23 @@ static int radeon_restore_pci_cfg(struct
for (i = PCI_BASE_ADDRESS_0/4; i < 64; ++i) {
if (radeon_cfg_after_resume[i] != rinfo->cfg_save[i])
- pci_write_config_dword(rinfo->pdev, i * 4,
+ pci_write_config_dword(rinfo->gpu_info->pdev, i * 4,
rinfo->cfg_save[i]);
}
- pci_write_config_word(rinfo->pdev, PCI_CACHE_LINE_SIZE,
+ pci_write_config_word(rinfo->gpu_info->pdev, PCI_CACHE_LINE_SIZE,
rinfo->cfg_save[PCI_CACHE_LINE_SIZE/4]);
- pci_write_config_word(rinfo->pdev, PCI_COMMAND,
+ pci_write_config_word(rinfo->gpu_info->pdev, PCI_COMMAND,
rinfo->cfg_save[PCI_COMMAND/4]);
return 1;
}
-int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
+int radeonfb_gpu_suspend(struct device *dev, pm_message_t mesg)
{
- struct fb_info *info = pci_get_drvdata(pdev);
- struct radeonfb_info *rinfo = info->par;
+ struct gpu_device *gdev = to_gpu_device(dev);
+ struct fb_info *info = gpu_get_drvdata(gdev);
+ struct radeonfb_info *rinfo = info->par;
+ struct pci_dev *pdev = rinfo->gpu_info->pdev;
int i;
if (mesg.event == pdev->dev.power.power_state.event)
@@ -2688,7 +2690,7 @@ #endif /* CONFIG_PPC_PMAC */
mdelay(50);
radeon_pm_save_regs(rinfo, 1);
- if (rinfo->is_mobility && !(rinfo->pm_mode & radeon_pm_d2)) {
+ if (rinfo->gpu_info->is_mobility && !(rinfo->pm_mode & radeon_pm_d2)) {
/* Switch off LVDS interface */
mdelay(1);
OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_BL_MOD_EN));
@@ -2717,10 +2719,12 @@ #endif /* CONFIG_PPC_PMAC */
return 0;
}
-int radeonfb_pci_resume(struct pci_dev *pdev)
+int radeonfb_gpu_resume(struct device *dev)
{
- struct fb_info *info = pci_get_drvdata(pdev);
- struct radeonfb_info *rinfo = info->par;
+ struct gpu_device *gdev = to_gpu_device(dev);
+ struct fb_info *info = gpu_get_drvdata(gdev);
+ struct radeonfb_info *rinfo = info->par;
+ struct pci_dev *pdev = rinfo->gpu_info->pdev;
int rc = 0;
if (pdev->dev.power.power_state.event == PM_EVENT_ON)
@@ -2823,7 +2827,7 @@ #endif /* CONFIG_PM */
void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep)
{
/* Find PM registers in config space if any*/
- rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM);
+ rinfo->pm_reg = pci_find_capability(rinfo->gpu_info->pdev, PCI_CAP_ID_PM);
/* Enable/Disable dynamic clocks: TODO add sysfs access */
rinfo->dynclk = dynclk;
@@ -2844,8 +2848,8 @@ #if defined(CONFIG_PPC_PMAC)
* reason. --BenH
*/
if (machine_is(powermac) && rinfo->of_node) {
- if (rinfo->is_mobility && rinfo->pm_reg &&
- rinfo->family <= CHIP_FAMILY_RV250)
+ if (rinfo->gpu_info->is_mobility && rinfo->pm_reg &&
+ rinfo->gpu_info->family <= CHIP_FAMILY_RV250)
rinfo->pm_mode |= radeon_pm_d2;
/* We can restart Jasper (M10 chip in albooks), BlueStone (7500 chip
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index d5ff224..423dc24 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -20,6 +20,8 @@ #ifdef CONFIG_PPC_OF
#include <asm/prom.h>
#endif
+#include <linux/gpu_layer.h>
+#include <linux/radeon_gpu.h>
#include <video/radeon.h>
/***************************************************************
@@ -27,65 +29,6 @@ #include <video/radeon.h>
***************************************************************/
-/*
- * Chip families. Must fit in the low 16 bits of a long word
- */
-enum radeon_family {
- CHIP_FAMILY_UNKNOW,
- CHIP_FAMILY_LEGACY,
- CHIP_FAMILY_RADEON,
- CHIP_FAMILY_RV100,
- CHIP_FAMILY_RS100, /* U1 (IGP320M) or A3 (IGP320)*/
- CHIP_FAMILY_RV200,
- CHIP_FAMILY_RS200, /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350),
- RS250 (IGP 7000) */
- CHIP_FAMILY_R200,
- CHIP_FAMILY_RV250,
- CHIP_FAMILY_RS300, /* Radeon 9000 IGP */
- CHIP_FAMILY_RV280,
- CHIP_FAMILY_R300,
- CHIP_FAMILY_R350,
- CHIP_FAMILY_RV350,
- CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */
- CHIP_FAMILY_R420, /* R420/R423/M18 */
- CHIP_FAMILY_LAST,
-};
-
-#define IS_RV100_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_RV100) || \
- ((rinfo)->family == CHIP_FAMILY_RV200) || \
- ((rinfo)->family == CHIP_FAMILY_RS100) || \
- ((rinfo)->family == CHIP_FAMILY_RS200) || \
- ((rinfo)->family == CHIP_FAMILY_RV250) || \
- ((rinfo)->family == CHIP_FAMILY_RV280) || \
- ((rinfo)->family == CHIP_FAMILY_RS300))
-
-
-#define IS_R300_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_R300) || \
- ((rinfo)->family == CHIP_FAMILY_RV350) || \
- ((rinfo)->family == CHIP_FAMILY_R350) || \
- ((rinfo)->family == CHIP_FAMILY_RV380) || \
- ((rinfo)->family == CHIP_FAMILY_R420))
-
-/*
- * Chip flags
- */
-enum radeon_chip_flags {
- CHIP_FAMILY_MASK = 0x0000ffffUL,
- CHIP_FLAGS_MASK = 0xffff0000UL,
- CHIP_IS_MOBILITY = 0x00010000UL,
- CHIP_IS_IGP = 0x00020000UL,
- CHIP_HAS_CRTC2 = 0x00040000UL,
-};
-
-/*
- * Errata workarounds
- */
-enum radeon_errata {
- CHIP_ERRATA_R300_CG = 0x00000001,
- CHIP_ERRATA_PLL_DUMMYREADS = 0x00000002,
- CHIP_ERRATA_PLL_DELAY = 0x00000004,
-};
-
/*
* Monitor types
@@ -278,20 +221,18 @@ typedef void (*reinit_function_ptr)(stru
struct radeonfb_info {
struct fb_info *info;
+ struct radeon_gpu_info *gpu_info;
struct radeon_regs state;
struct radeon_regs init_state;
+ struct gpu_device *gdev;
char name[DEVICE_NAME_SIZE];
- unsigned long mmio_base_phys;
- unsigned long fb_base_phys;
-
void __iomem *mmio_base;
void __iomem *fb_base;
unsigned long fb_local_base;
- struct pci_dev *pdev;
#ifdef CONFIG_PPC_OF
struct device_node *of_node;
#endif
@@ -303,10 +244,6 @@ #endif
struct { u8 red, green, blue, pad; }
palette[256];
- int chipset;
- u8 family;
- u8 rev;
- unsigned int errata;
unsigned long video_ram;
unsigned long mapped_vram;
int vram_width;
@@ -314,9 +251,6 @@ #endif
int pitch, bpp, depth;
- int has_CRTC2;
- int is_mobility;
- int is_IGP;
int reversed_DAC;
int reversed_TMDS;
struct panel_info panel_info;
@@ -437,7 +371,7 @@ #define OUTREGP(addr,val,mask) _OUTREGP(
*/
static inline void radeon_pll_errata_after_index(struct radeonfb_info *rinfo)
{
- if (!(rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS))
+ if (!(rinfo->gpu_info->errata & CHIP_ERRATA_PLL_DUMMYREADS))
return;
(void)INREG(CLOCK_CNTL_DATA);
@@ -446,11 +380,11 @@ static inline void radeon_pll_errata_aft
static inline void radeon_pll_errata_after_data(struct radeonfb_info *rinfo)
{
- if (rinfo->errata & CHIP_ERRATA_PLL_DELAY) {
+ if (rinfo->gpu_info->errata & CHIP_ERRATA_PLL_DELAY) {
/* we can't deal with posted writes here ... */
_radeon_msleep(rinfo, 5);
}
- if (rinfo->errata & CHIP_ERRATA_R300_CG) {
+ if (rinfo->gpu_info->errata & CHIP_ERRATA_R300_CG) {
u32 save, tmp;
save = INREG(CLOCK_CNTL_INDEX);
tmp = save & ~(0x3f | PLL_WR_EN);
@@ -600,8 +534,8 @@ extern void radeon_delete_i2c_busses(str
extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid);
/* PM Functions */
-extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state);
-extern int radeonfb_pci_resume(struct pci_dev *pdev);
+extern int radeonfb_gpu_suspend(struct device *dev, pm_message_t state);
+extern int radeonfb_gpu_resume(struct device *dev);
extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep);
extern void radeonfb_pm_exit(struct radeonfb_info *rinfo);
--
1.4.1.ga3e6
From: Dave Airlie <[email protected]>
This patch adds the GPU layer support to the drm library.
It doesn't touch any drivers just adds the gpu layer to the drm code.
Signed-off-by: Dave Airlie <[email protected]>
---
drivers/char/drm/Makefile | 2 +
drivers/char/drm/drmP.h | 16 ++++++++++
drivers/char/drm/drm_drv.c | 10 +++++--
drivers/char/drm/drm_gpu.c | 63 +++++++++++++++++++++++++++++++++++++++++
drivers/char/drm/drm_ioctl.c | 8 +++--
drivers/char/drm/drm_memory.c | 1 +
drivers/char/drm/drm_stub.c | 31 ++++++++++----------
drivers/char/drm/drm_sysfs.c | 8 +++++
8 files changed, 114 insertions(+), 25 deletions(-)
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index 3ad0f64..7438e29 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -6,7 +6,7 @@ drm-objs := drm_auth.o drm_bufs.o drm
drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \
drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
- drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o
+ drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o drm_gpu.o
tdfx-objs := tdfx_drv.o
r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 6dcdceb..7fb9ec9 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -52,6 +52,7 @@ #include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/file.h>
#include <linux/pci.h>
+#include <linux/gpu_layer.h>
#include <linux/jiffies.h>
#include <linux/smp_lock.h> /* For (un)lock_kernel */
#include <linux/mm.h>
@@ -544,6 +545,10 @@ typedef struct drm_mm {
* a family of cards. There will one drm_device for each card present
* in this family
*/
+
+#define DRM_DRV_PCI 1
+#define DRM_DRV_GPU 2
+
struct drm_device;
struct drm_driver {
@@ -604,6 +609,9 @@ struct drm_driver {
drm_ioctl_desc_t *ioctls;
int num_ioctls;
struct file_operations fops;
+ int drv_type;
+
+ struct gpu_driver gpu_driver;
struct pci_driver pci_driver;
};
@@ -728,6 +736,8 @@ typedef struct drm_device {
drm_agp_head_t *agp; /**< AGP data */
+ /* a pointer to the GPU device */
+ struct gpu_device *gdev;
struct pci_dev *pdev; /**< PCI device structure */
int pci_vendor; /**< PCI vendor id */
int pci_device; /**< PCI device id */
@@ -817,9 +827,12 @@ #endif
/******************************************************************/
/** \name Internal function definitions */
/*@{*/
+extern void drm_gpu_cleanup(struct gpu_device *gdev);
+extern int drm_gpu_get_dev(struct gpu_device *gdev, struct drm_driver *driver, void *driver_id, struct pci_dev *pdev);
/* Driver support (drm_drv.h) */
extern int drm_init(struct drm_driver *driver);
+extern void drm_cleanup(drm_device_t * dev);
extern void drm_exit(struct drm_driver *driver);
extern int drm_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
@@ -1003,9 +1016,12 @@ extern int drm_agp_bind_memory(DRM_AGP_M
extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
/* Stub support (drm_stub.h) */
+extern int drm_fill_in_dev(drm_device_t * dev, unsigned long driver_data,
+ struct drm_driver *driver);
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
struct drm_driver *driver);
extern int drm_put_dev(drm_device_t * dev);
+extern int drm_get_head(drm_device_t * dev, drm_head_t * head);
extern int drm_put_head(drm_head_t * head);
extern unsigned int drm_debug;
extern unsigned int drm_cards_limit;
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index a70af0d..2c94231 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -275,6 +275,8 @@ int drm_init(struct drm_driver *driver)
drm_mem_init();
+ driver->drv_type = DRM_DRV_PCI;
+
for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];
@@ -300,7 +302,7 @@ EXPORT_SYMBOL(drm_init);
*
* \sa drm_init
*/
-static void drm_cleanup(drm_device_t * dev)
+void drm_cleanup(drm_device_t * dev)
{
DRM_DEBUG("\n");
@@ -360,8 +362,10 @@ void drm_exit(struct drm_driver *driver)
dev = head->dev;
if (dev) {
/* release the pci driver */
- if (dev->pdev)
- pci_dev_put(dev->pdev);
+ if (dev->pdev && (dev->driver->drv_type == DRM_DRV_PCI)) {
+ if (dev->pdev)
+ pci_dev_put(dev->pdev);
+ }
drm_cleanup(dev);
}
}
diff --git a/drivers/char/drm/drm_gpu.c b/drivers/char/drm/drm_gpu.c
new file mode 100644
index 0000000..4c34d6d
--- /dev/null
+++ b/drivers/char/drm/drm_gpu.c
@@ -0,0 +1,63 @@
+/*
+ * drivers/char/drm/drm_gpu.c
+ *
+ * Copyright (C) Dave Airlie <[email protected]>
+ *
+ * Unlike the rest of the DRM this is actually GPL licensed
+ * as it doesn't make much sense for it to be MIT.
+ */
+#include "drmP.h"
+
+/* DRM GPU Interface layer */
+
+int drm_gpu_get_dev(struct gpu_device *gdev, struct drm_driver *driver, void *driver_id, struct pci_dev *pdev)
+{
+ drm_device_t *dev;
+ int ret;
+ struct pci_device_id *id = (struct pci_device_id *)driver_id;
+ unsigned long driver_data = id->driver_data;
+
+ DRM_DEBUG("gdev is %p, driver is %p, void is %p, pdev is %p\n", gdev, driver, driver_id, pdev);
+
+ dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->gdev = gdev;
+ dev->pdev = pdev;
+#ifdef __alpha__
+ dev->hose = pdev->sysdata;
+#endif
+ dev->irq = pdev->irq;
+
+ if ((ret = drm_fill_in_dev(dev, driver_data, driver))) {
+ printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+ goto err_g1;
+ }
+
+ if ((ret = drm_get_head(dev, &dev->primary)))
+ goto err_g1;
+
+ gpu_set_drvdata(gdev, dev);
+
+ DRM_INFO("Initialized GPU %s %d.%d.%d %s on minor %d\n",
+ driver->name, driver->major, driver->minor, driver->patchlevel,
+ driver->date, dev->primary.minor);
+ return 0;
+
+err_g1:
+ drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+ return 0;
+}
+EXPORT_SYMBOL(drm_gpu_get_dev);
+
+void drm_gpu_cleanup(struct gpu_device *gdev)
+{
+ drm_device_t *dev = gpu_get_drvdata(gdev);
+
+ gpu_set_drvdata(gdev, NULL);
+ if (dev)
+ drm_cleanup(dev);
+}
+EXPORT_SYMBOL(drm_gpu_cleanup);
+
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index 5658955..a34f9c4 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -110,12 +110,12 @@ int drm_setunique(struct inode *inode, s
dev->unique[dev->unique_len] = '\0';
dev->devname =
- drm_alloc(strlen(dev->driver->pci_driver.name) +
+ drm_alloc(strlen(dev->driver->name) +
strlen(dev->unique) + 2, DRM_MEM_DRIVER);
if (!dev->devname)
return -ENOMEM;
- sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
+ sprintf(dev->devname, "%s@%s", dev->driver->name,
dev->unique);
/* Return error if the busid submitted doesn't match the device's actual
@@ -157,12 +157,12 @@ static int drm_set_busid(drm_device_t *
DRM_ERROR("Unique buffer overflowed\n");
dev->devname =
- drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
+ drm_alloc(strlen(dev->driver->name) + dev->unique_len +
2, DRM_MEM_DRIVER);
if (dev->devname == NULL)
return -ENOMEM;
- sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
+ sprintf(dev->devname, "%s@%s", dev->driver->name,
dev->unique);
return 0;
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index 5681cae..96d962d 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -44,6 +44,7 @@ #else
void drm_mem_init(void)
{
}
+EXPORT_SYMBOL(drm_mem_init);
/**
* Called when "/proc/dri/%dev%/mem" is read.
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 120d102..6b0fef4 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -53,9 +53,8 @@ drm_head_t **drm_heads;
struct class *drm_class;
struct proc_dir_entry *drm_proc_root;
-static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
- const struct pci_device_id *ent,
- struct drm_driver *driver)
+int drm_fill_in_dev(drm_device_t * dev, unsigned long driver_data,
+ struct drm_driver *driver)
{
int retcode;
@@ -66,15 +65,6 @@ static int drm_fill_in_dev(drm_device_t
mutex_init(&dev->struct_mutex);
mutex_init(&dev->ctxlist_mutex);
- dev->pdev = pdev;
- dev->pci_device = pdev->device;
- dev->pci_vendor = pdev->vendor;
-
-#ifdef __alpha__
- dev->hose = pdev->sysdata;
-#endif
- dev->irq = pdev->irq;
-
dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
if (dev->maplist == NULL)
return -ENOMEM;
@@ -96,7 +86,7 @@ #endif
dev->driver = driver;
if (dev->driver->load)
- if ((retcode = dev->driver->load(dev, ent->driver_data)))
+ if ((retcode = dev->driver->load(dev, driver_data)))
goto error_out_unreg;
if (drm_core_has_AGP(dev)) {
@@ -142,7 +132,7 @@ #endif
* create the proc init entry via proc_init(). This routines assigns
* minor numbers to secondary heads of multi-headed cards
*/
-static int drm_get_head(drm_device_t * dev, drm_head_t * head)
+int drm_get_head(drm_device_t * dev, drm_head_t * head)
{
drm_head_t **heads = drm_heads;
int ret;
@@ -215,14 +205,23 @@ int drm_get_dev(struct pci_dev *pdev, co
if (ret)
goto err_g1;
- if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
+ dev->pdev = pdev;
+ dev->pci_device = pdev->device;
+ dev->pci_vendor = pdev->vendor;
+
+#ifdef __alpha__
+ dev->hose = pdev->sysdata;
+#endif
+ dev->irq = pdev->irq;
+
+ if ((ret = drm_fill_in_dev(dev, ent->driver_data, driver))) {
printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
goto err_g2;
}
if ((ret = drm_get_head(dev, &dev->primary)))
goto err_g2;
- DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+ DRM_INFO("Initialized PCI %s %d.%d.%d %s on minor %d\n",
driver->name, driver->major, driver->minor, driver->patchlevel,
driver->date, dev->primary.minor);
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index cc8e2eb..fd25766 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -108,10 +108,16 @@ struct class_device *drm_sysfs_device_ad
{
struct class_device *class_dev;
int i, j, err;
+ struct device *dev;
+
+ if (head->dev->driver->drv_type == DRM_DRV_PCI)
+ dev = &(head->dev->pdev)->dev;
+ else
+ dev = &(head->dev->gdev)->dev;
class_dev = class_device_create(cs, NULL,
MKDEV(DRM_MAJOR, head->minor),
- &(head->dev->pdev)->dev,
+ dev,
"card%d", head->minor);
if (IS_ERR(class_dev)) {
err = PTR_ERR(class_dev);
--
1.4.1.ga3e6
On Wed, Jan 24, 2007 at 10:20:18PM +1100, [email protected] wrote:
> This patch series contains the gpu sharing layer for kernel that I've
> mentioned before. It should apply against Linus's git tree.
Yeah!
> Why do we want this?
>
> Currently the kernel cannot provide both the fb and drm drivers with
> access to the device model and this means the drm cannot get any
> suspend/resume callbacks. This layer attempts to fix this problem by
> adding a bus for the gpu drivers to attach to. Currently a lowlevel
> binding driver is needed along with optional fb and drm components.
If we were to allow this kind of "sharing" for all PCI devices would
that work out instead? Or would this layer still be needed?
thanks,
greg k-h
On Wed, 2007-01-24 at 17:30 +0100, Roger While wrote:
> @@ -241,9 +241,9 @@ void radeonfb_engine_reset(struct radeon
> INREG(HOST_PATH_CNTL);
> OUTREG(HOST_PATH_CNTL, host_path_cntl);
>
> - if (rinfo->family != CHIP_FAMILY_R300 ||
> - rinfo->family != CHIP_FAMILY_R350 ||
> - rinfo->family != CHIP_FAMILY_RV350)
> + if (rinfo->gpu_info->family != CHIP_FAMILY_R300 ||
> + rinfo->gpu_info->family != CHIP_FAMILY_R350 ||
> + rinfo->gpu_info->family != CHIP_FAMILY_RV350)
> OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
>
> Alarm bells going off - "!=" combined with "||" ?
> Looks like a reset will always be done.
Wow, good catch ! That's a bug that has been in radeonfb pretty much for
ever ! Might have come from earlier versions of X before we had
IS_R300_VARIANT...
B
> > Why do we want this?
> >
> > Currently the kernel cannot provide both the fb and drm drivers with
> > access to the device model and this means the drm cannot get any
> > suspend/resume callbacks. This layer attempts to fix this problem by
> > adding a bus for the gpu drivers to attach to. Currently a lowlevel
> > binding driver is needed along with optional fb and drm components.
>
> If we were to allow this kind of "sharing" for all PCI devices would
> that work out instead? Or would this layer still be needed?
Initially this layer wouldn't be needed, but I'd like to add some
awareness to the drivers, so the drm can tell the fb to stop doing
stuff and vice-versa if necessary.... but perhaps that could be done
with a generic layer also.. or via the lowlevel driver I have...
Dave.
On Wed, 2007-01-24 at 22:20 +1100, [email protected] wrote:
> From: Dave Airlie <[email protected]>
>
> This patch adds support to the radeonfb driver to use the new
> GPU layer to driver the radeon.
Unfortunately, that also massively collides with a giant radeonfb update
that's been simmering on my HD for some time (mostly the work of Solomon
Peachy to support ATOM BIOS and newer cards).
I really need to finish some bits in there and push it out. Dave, you
want to push your stuff first or you prefer re-adapting your stuff on
top of mine ? I'll try to dig a patch to put in -mm for a while next
week.
Ben.
Hi Dave,
[email protected] writes:
> This patch series contains the gpu sharing layer for kernel that
> I've mentioned before. It should apply against Linus's git tree.
I gave the patches a go on my PowerBook. I had to make a few changes
to get it to compile. Works fine so far: I switched between VTs and X
with an accelerated GLX client active a few times, no problems.
When I did a sleep/resume cycle it wedged on resume, but I expect this
is due to my hacking up radeonfb_early_resume(), as seen in the last
hunk below, which was just aimed at just getting it to compile.
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 3abfd4a..560568b 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -105,7 +105,7 @@ static int radeon_bl_update_status(struct backlight_device *bd)
RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
*/
tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
- if (rinfo->is_mobility || rinfo->is_IGP)
+ if (rinfo->gpu_info->is_mobility || rinfo->gpu_info->is_IGP)
OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) <<
@@ -119,7 +119,7 @@ static int radeon_bl_update_status(struct backlight_device *bd)
rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
mod_timer(&rinfo->lvds_timer,
jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
- if (rinfo->is_mobility || rinfo->is_IGP)
+ if (rinfo->gpu_info->is_mobility || rinfo->gpu_info->is_IGP)
OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
}
rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
@@ -176,10 +176,10 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
* direction backlight should work on a given panel?
*/
pdata->negative =
- (rinfo->family != CHIP_FAMILY_RV200 &&
- rinfo->family != CHIP_FAMILY_RV250 &&
- rinfo->family != CHIP_FAMILY_RV280 &&
- rinfo->family != CHIP_FAMILY_RV350);
+ (rinfo->gpu_info->family != CHIP_FAMILY_RV200 &&
+ rinfo->gpu_info->family != CHIP_FAMILY_RV250 &&
+ rinfo->gpu_info->family != CHIP_FAMILY_RV280 &&
+ rinfo->gpu_info->family != CHIP_FAMILY_RV350);
#ifdef CONFIG_PMAC_BACKLIGHT
pdata->negative = pdata->negative ||
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index f634c43..c8cc173 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -1837,7 +1837,8 @@ static int radeonfb_set_par(struct fb_info *info)
#ifdef CONFIG_BOOTX_TEXT
/* Update debug text engine */
- btext_update_display(rinfo->fb_base_phys, mode->xres, mode->yres,
+ btext_update_display(rinfo->gpu_info->fb_base_phys,
+ mode->xres, mode->yres,
rinfo->depth, info->fix.line_length);
#endif
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index 8625f5d..4cd4f34 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -122,7 +122,7 @@ static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_
while (dp == NULL)
return MT_NONE;
- if (rinfo->has_CRTC2) {
+ if (rinfo->gpu_info->has_CRTC2) {
const char *pname;
int len, second = 0;
@@ -141,7 +141,7 @@ static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_
/* Maybe check for LVDS_GEN_CNTL here ? I need to check out
* what OF does when booting with lid closed
*/
- if (mt == MT_DFP && rinfo->is_mobility)
+ if (mt == MT_DFP && rinfo->gpu_info->is_mobility)
mt = MT_LCD;
return mt;
} else if (pname[len-1] == 'B' && head_no == 1)
@@ -655,7 +655,7 @@ static void radeon_fixup_panel_info(struct radeonfb_info *rinfo)
* PPC only for now...
*/
if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type == MT_LCD
- && rinfo->is_mobility) {
+ && rinfo->gpu_info->is_mobility) {
int ppll_div_sel;
u32 ppll_divn;
ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 9a59804..f113616 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -957,7 +957,7 @@ static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo)
#ifdef CONFIG_PPC_PMAC
if (machine_is(powermac)) {
/* AGP PLL control */
- if (rinfo->family <= CHIP_FAMILY_RV280) {
+ if (rinfo->gpu_info->family <= CHIP_FAMILY_RV280) {
OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID);
OUTREG(BUS_CNTL1,
(INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK)
@@ -2817,7 +2817,7 @@ static void radeonfb_early_resume(void *data)
struct radeonfb_info *rinfo = data;
rinfo->no_schedule = 1;
- radeonfb_pci_resume(rinfo->pdev);
+ radeonfb_gpu_resume(rinfo->gpu_info->info.device);
rinfo->no_schedule = 0;
}
#endif /* CONFIG_PPC_OF */
--
Paul Collins
Wellington, New Zealand
Dag vijandelijk luchtschip de huismeester is dood
On Thu, Jan 25, 2007 at 09:39:47AM +1100, Dave Airlie wrote:
> >> Why do we want this?
> >>
> >> Currently the kernel cannot provide both the fb and drm drivers with
> >> access to the device model and this means the drm cannot get any
> >> suspend/resume callbacks. This layer attempts to fix this problem by
> >> adding a bus for the gpu drivers to attach to. Currently a lowlevel
> >> binding driver is needed along with optional fb and drm components.
> >
> >If we were to allow this kind of "sharing" for all PCI devices would
> >that work out instead? Or would this layer still be needed?
>
> Initially this layer wouldn't be needed, but I'd like to add some
> awareness to the drivers, so the drm can tell the fb to stop doing
> stuff and vice-versa if necessary.... but perhaps that could be done
> with a generic layer also.. or via the lowlevel driver I have...
Ok, I have no objection to this layer right now, as it solves your
problem, and while I would like some time in the future to add such a
layer for the PCI devices, it is no where on my todo plate just yet...
thanks,
greg k-h
On Thu, Jan 25, 2007 at 02:06:31PM -0800, Greg Kroah-Hartman wrote:
> On Thu, Jan 25, 2007 at 09:39:47AM +1100, Dave Airlie wrote:
> > >> Why do we want this?
> > >>
> > >> Currently the kernel cannot provide both the fb and drm drivers with
> > >> access to the device model and this means the drm cannot get any
> > >> suspend/resume callbacks. This layer attempts to fix this problem by
> > >> adding a bus for the gpu drivers to attach to. Currently a lowlevel
> > >> binding driver is needed along with optional fb and drm components.
> > >
> > >If we were to allow this kind of "sharing" for all PCI devices would
> > >that work out instead? Or would this layer still be needed?
> >
> > Initially this layer wouldn't be needed, but I'd like to add some
> > awareness to the drivers, so the drm can tell the fb to stop doing
> > stuff and vice-versa if necessary.... but perhaps that could be done
> > with a generic layer also.. or via the lowlevel driver I have...
>
> Ok, I have no objection to this layer right now, as it solves your
> problem, and while I would like some time in the future to add such a
> layer for the PCI devices, it is no where on my todo plate just yet...
It's been bubbling its way up my todo too, as agpgart is starting to
get bug reports due to conflicts when the EDAC drivers or watchdog
drivers 'claim' the south bridge ID before agp gets a chance to init.
Someone sent me some patches a few weeks back, but I seem to have mislaid
them. I'll turf them up and get the sender to send them to lkml.
They should at the least, make a starting point.
Dave
--
http://www.codemonkey.org.uk
>
> [email protected] writes:
>
> > This patch series contains the gpu sharing layer for kernel that
> > I've mentioned before. It should apply against Linus's git tree.
>
> I gave the patches a go on my PowerBook. I had to make a few changes
> to get it to compile. Works fine so far: I switched between VTs and X
> with an accelerated GLX client active a few times, no problems.
>
> When I did a sleep/resume cycle it wedged on resume, but I expect this
> is due to my hacking up radeonfb_early_resume(), as seen in the last
> hunk below, which was just aimed at just getting it to compile.
>
Hi Paul,
I suspected some problem on PPC alright as I didn't have a radeon
based one to test on, I'll incorporate your changes and I'll fix the
suspend/resume to work properly :-)
Dave.
> >
> > This patch adds support to the radeonfb driver to use the new
> > GPU layer to driver the radeon.
>
> Unfortunately, that also massively collides with a giant radeonfb update
> that's been simmering on my HD for some time (mostly the work of Solomon
> Peachy to support ATOM BIOS and newer cards).
>
> I really need to finish some bits in there and push it out. Dave, you
> want to push your stuff first or you prefer re-adapting your stuff on
> top of mine ? I'll try to dig a patch to put in -mm for a while next
> week.
I can wait for yours as gpu_layer has become a background task that I
just pick up every few weeks and dust off.. :-)
Dave.
> On Wed, Jan 24, 2007 at 10:20:18PM +1100, [email protected] wrote:
> > This patch series contains the gpu sharing layer for kernel that I've
> > mentioned before. It should apply against Linus's git tree.
>
> Yeah!
Finally after all these years!!!! Sorry about the delayed response I was
busy with work.
> > Why do we want this?
> >
> > Currently the kernel cannot provide both the fb and drm drivers with
> > access to the device model and this means the drm cannot get any
> > suspend/resume callbacks. This layer attempts to fix this problem by
> > adding a bus for the gpu drivers to attach to. Currently a lowlevel
> > binding driver is needed along with optional fb and drm components.
>
> If we were to allow this kind of "sharing" for all PCI devices would
> that work out instead? Or would this layer still be needed?
Please do this. Its not only fbdev but backlight and display support.
Note display support is not main stream yet. Greg sent me a email about
the DRM team needing a CRT class as well. That will be a different
discussion. Plus some cards have tuners as well. So this device sharing is
needed. It would also be really nice to prevent driver collisions. For
example vesafb and a fbdev driver controlling the same hardware or acpi
backlight versus the graphics card backlight support.
> > > Why do we want this?
> > >
> > > Currently the kernel cannot provide both the fb and drm drivers with
> > > access to the device model and this means the drm cannot get any
> > > suspend/resume callbacks. This layer attempts to fix this problem by
> > > adding a bus for the gpu drivers to attach to. Currently a lowlevel
> > > binding driver is needed along with optional fb and drm components.
> >
> > If we were to allow this kind of "sharing" for all PCI devices would
> > that work out instead? Or would this layer still be needed?
>
> Initially this layer wouldn't be needed, but I'd like to add some
> awareness to the drivers, so the drm can tell the fb to stop doing
> stuff and vice-versa if necessary.... but perhaps that could be done
> with a generic layer also.. or via the lowlevel driver I have...
I have a idea. Greg asked me to move my display class away from the
class_device method. One of the nice things about using
class_device_register is that it handles all the attributes for you :-)
So while going throught the core code for device handling I discovered
that struct device has a struct class. I found it alot easier to have
class field in the device point to the class you want to use. With
device registeration the class is setup up for you.
The idea was to have the a linked list of classes inside of
struct device. Then have a way to register/unregister that class with
the device. This way struct device and struct device_driver are per
hardware but struct class could be used to handle different interfaces
to that same hardware. What do you think? I could do a example with
hardware that registers a fbdev drivers as well as a backlight. Plus
nobody is using the class field in struct device at this time.