This commit adds an initial framework that can be used to plug SoC graphics devices into the DRM/KMS subsystem. SoCs often don't have a dedicated device to which a DRM driver can bind, but instead the graphics complex typically consists of several platform- type devices that work together. The DRM SoC support code therefore adds a dummy device that is associated with the DRM driver, which typically provides some kind of API for other drivers to register with. Signed-off-by: Thierry Reding <thierry.reding@xxxxxxxxxxxxxxxxx> --- drivers/gpu/drm/Kconfig | 4 ++ drivers/gpu/drm/Makefile | 2 + drivers/gpu/drm/drm_soc.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++ include/drm/drmP.h | 5 ++ 4 files changed, 162 insertions(+) create mode 100644 drivers/gpu/drm/drm_soc.c diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 23120c0..529dede 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -24,6 +24,10 @@ config DRM_USB depends on DRM select USB +config DRM_SOC + tristate + depends on DRM + config DRM_KMS_HELPER tristate depends on DRM diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index f65f65e..4731cbc 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -17,6 +17,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-usb-y := drm_usb.o +drm-soc-y := drm_soc.o drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o @@ -27,6 +28,7 @@ CFLAGS_drm_trace_points.o := -I$(src) obj-$(CONFIG_DRM) += drm.o obj-$(CONFIG_DRM_USB) += drm_usb.o +obj-$(CONFIG_DRM_SOC) += drm-soc.o obj-$(CONFIG_DRM_TTM) += ttm/ obj-$(CONFIG_DRM_TDFX) += tdfx/ obj-$(CONFIG_DRM_R128) += r128/ diff --git a/drivers/gpu/drm/drm_soc.c b/drivers/gpu/drm/drm_soc.c new file mode 100644 index 0000000..bc120ae --- /dev/null +++ b/drivers/gpu/drm/drm_soc.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2012 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <drm/drmP.h> +#include <drm/drm_sysfs.h> + +static const char *drm_soc_get_name(struct drm_device *dev) +{ + DRM_DEBUG("\n"); + return dev_name(dev->dev); +} + +static int drm_soc_set_busid(struct drm_device *dev, struct drm_master *master) +{ + DRM_DEBUG("\n"); + return -ENOSYS; +} + +static int drm_soc_set_unique(struct drm_device *dev, struct drm_master *master, + struct drm_unique *unique) +{ + DRM_DEBUG("\n"); + return -ENOSYS; +} + +static struct drm_bus drm_soc_bus = { + .bus_type = DRIVER_BUS_SOC, + .get_name = drm_soc_get_name, + .set_busid = drm_soc_set_busid, + .set_unique = drm_soc_set_unique, +}; + +static struct device_type drm_soc_device_type = { + .name = "soc", +}; + +static void drm_soc_device_release(struct device *dev) +{ + kfree(dev); +} + +static struct device *drm_create_soc_device(const char *name) +{ + struct device *dev; + int err; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + + dev->release = drm_soc_device_release; + dev->type = &drm_soc_device_type; + dev_set_name(dev, name); + + err = drm_class_device_register(dev); + if (err < 0) + goto put; + + return dev; + +put: + put_device(dev); + return NULL; +} + +int drm_soc_init(struct drm_driver *driver, const char *name) +{ + struct drm_device *dev; + int ret; + + INIT_LIST_HEAD(&driver->device_list); + driver->bus = &drm_soc_bus; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + dev->dev = drm_create_soc_device(name); + if (!dev->dev) { + ret = -ENOMEM; + goto free; + } + + ret = drm_fill_in_dev(dev, NULL, driver); + if (ret < 0) + goto unregister; + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); + if (ret < 0) + goto unregister; + } + + ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY); + if (ret < 0) + goto put_control; + + if (dev->driver->load) { + ret = dev->driver->load(dev, 0); + if (ret < 0) + goto put_legacy; + } + + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group); + if (ret < 0) + goto put_legacy; + } + + list_add_tail(&dev->driver_item, &driver->device_list); + + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, + driver->major, driver->minor, driver->patchlevel, + driver->date, dev->primary->index); + + return 0; + +put_legacy: + drm_put_minor(&dev->primary); +put_control: + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_put_minor(&dev->control); +unregister: + drm_class_device_unregister(dev->dev); +free: + kfree(dev); + return ret; +} +EXPORT_SYMBOL_GPL(drm_soc_init); + +void drm_soc_exit(struct drm_driver *driver) +{ + struct drm_device *drm, *tmp; + + list_for_each_entry_safe(drm, tmp, &driver->device_list, driver_item) { + struct device *dev = drm->dev; + drm_put_dev(drm); + drm_class_device_unregister(dev); + } +} +EXPORT_SYMBOL_GPL(drm_soc_exit); + +MODULE_AUTHOR("Thierry Reding <thierry.reding@xxxxxxxxxxxxxxxxx>"); +MODULE_DESCRIPTION("SoC DRM support"); +MODULE_LICENSE("GPL"); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 31ad880..bc1edd1 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -156,6 +156,7 @@ int drm_err(const char *func, const char *format, ...); #define DRIVER_BUS_PCI 0x1 #define DRIVER_BUS_PLATFORM 0x2 #define DRIVER_BUS_USB 0x3 +#define DRIVER_BUS_SOC 0x4 /***********************************************************************/ /** \name Begin the DRM... */ @@ -1769,6 +1770,10 @@ extern void drm_platform_exit(struct drm_driver *driver, struct platform_device extern int drm_get_platform_dev(struct platform_device *pdev, struct drm_driver *driver); +/* SoC section */ +extern int drm_soc_init(struct drm_driver *driver, const char *name); +extern void drm_soc_exit(struct drm_driver *driver); + /* returns true if currently okay to sleep */ static __inline__ bool drm_can_sleep(void) { -- 1.7.11.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel