diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_drv.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 180 |
1 files changed, 137 insertions, 43 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 340a8d6..90cff3f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -38,12 +38,13 @@ #include "exynos_drm_fb.h" #include "exynos_drm_gem.h" #include "exynos_drm_g2d.h" -#include "exynos_drm_rotator.h" +#include "exynos_drm_ipp.h" #include "exynos_drm_plane.h" #include "exynos_drm_vidi.h" #include "exynos_drm_dmabuf.h" +#include "exynos_drm_iommu.h" -#define DRIVER_NAME "exynos-drm" +#define DRIVER_NAME "exynos" #define DRIVER_DESC "Samsung SoC DRM" #define DRIVER_DATE "20110530" #define DRIVER_MAJOR 1 @@ -51,53 +52,65 @@ #define VBLANK_OFF_DELAY 50000 -static int exynos_drm_list_gem_info(int id, void *ptr, void *data) +struct exynos_drm_gem_info_data { + struct drm_file *filp; + struct seq_file *m; +}; + +static int exynos_drm_gem_one_info(int id, void *ptr, void *data) { struct drm_gem_object *obj = ptr; - struct drm_file *filp = data; - struct exynos_drm_gem_obj *gem = to_exynos_gem_obj(obj); - struct exynos_drm_gem_buf *buf = gem->buffer; - - DRM_INFO("%3d \t%3d \t%2d \t\t%2d \t0x%lx \t0x%x \t0x%lx "\ - "\t%2d \t\t%2d \t\t%2d\n", - filp->pid, - id, - atomic_read(&obj->refcount.refcount), - atomic_read(&obj->handle_count), - gem->size, - gem->flags, - buf->page_size, - buf->pfnmap, - obj->export_dma_buf ? 1 : 0, - obj->import_attach ? 1 : 0); + struct exynos_drm_gem_info_data *gem_info_data = data; + struct drm_exynos_file_private *file_priv = + gem_info_data->filp->driver_priv; + struct exynos_drm_gem_obj *exynos_gem = to_exynos_gem_obj(obj); + struct exynos_drm_gem_buf *buf = exynos_gem->buffer; + + seq_printf(gem_info_data->m, "%3d \t%3d \t%3d \t%2d \t\t%2d \t0x%08lx"\ + " \t0x%x \t0x%08lx \t%2d \t\t%2d \t\t%2d\n", + gem_info_data->filp->pid, + file_priv->tgid, + id, + atomic_read(&obj->refcount.refcount), + atomic_read(&obj->handle_count), + exynos_gem->size, + exynos_gem->flags, + buf->page_size, + buf->pfnmap, + obj->export_dma_buf ? 1 : 0, + obj->import_attach ? 1 : 0); return 0; } -static ssize_t exynos_drm_show_gem_info(struct device *dev, - struct device_attribute *attr, - char *buf) +static int exynos_drm_gem_info(struct seq_file *m, void *data) { - struct drm_device *drm_dev = dev_get_drvdata(dev); - struct drm_file *filp; + struct drm_info_node *node = (struct drm_info_node *)m->private; + struct drm_device *drm_dev = node->minor->dev; + struct exynos_drm_gem_info_data gem_info_data; + + gem_info_data.m = m; - DRM_INFO("pid \thandle \trefcount \thcount \tsize \t\tflags "\ - "\tpage_size \tpfnmap \texport_to_fd \timport_from_fd\n"); + seq_printf(gem_info_data.m, "pid \ttgid \thandle \trefcount \thcount "\ + "\tsize \t\tflags \tpage_size \tpfnmap \t"\ + "exyport_to_fd \timport_from_fd\n"); - list_for_each_entry(filp, &drm_dev->filelist, lhead) - idr_for_each(&filp->object_idr, &exynos_drm_list_gem_info, - filp); + list_for_each_entry(gem_info_data.filp, &drm_dev->filelist, lhead) + idr_for_each(&gem_info_data.filp->object_idr, + exynos_drm_gem_one_info, &gem_info_data); - return strlen(buf); + return 0; } -static const struct device_attribute exynos_device_attrs[] = { - __ATTR(gem_info, S_IRUGO, exynos_drm_show_gem_info, NULL) +static struct drm_info_list exynos_drm_debugfs_list[] = { + {"gem_info", exynos_drm_gem_info, DRIVER_GEM}, }; +#define EXYNOS_DRM_DEBUGFS_ENTRIES ARRAY_SIZE(exynos_drm_debugfs_list) static int exynos_drm_load(struct drm_device *dev, unsigned long flags) { struct exynos_drm_private *private; + struct drm_minor *minor; int ret; int nr; @@ -109,6 +122,17 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) return -ENOMEM; } + /* maximum size of userptr is limited to 16MB as default. */ + private->userptr_limit = SZ_16M; + + /* setup device address space for iommu. */ + private->vmm = exynos_drm_iommu_setup(0x80000000, 0x40000000); + if (IS_ERR(private->vmm)) { + DRM_ERROR("failed to setup iommu.\n"); + kfree(private); + return PTR_ERR(private->vmm); + } + INIT_LIST_HEAD(&private->pageflip_event_list); dev->dev_private = (void *)private; @@ -130,8 +154,11 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) } for (nr = 0; nr < MAX_PLANE; nr++) { - ret = exynos_plane_init(dev, nr); - if (ret) + struct drm_plane *plane; + unsigned int possible_crtcs = (1 << MAX_CRTC) - 1; + + plane = exynos_plane_init(dev, possible_crtcs, false); + if (!plane) goto err_crtc; } @@ -163,9 +190,12 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) drm_vblank_offdelay = VBLANK_OFF_DELAY; - ret = device_create_file(dev->dev, &exynos_device_attrs[0]); - if (ret < 0) - DRM_DEBUG_DRIVER("failed to create sysfs.\n"); + minor = dev->primary; + ret = drm_debugfs_create_files(exynos_drm_debugfs_list, + EXYNOS_DRM_DEBUGFS_ENTRIES, + minor->debugfs_root, minor); + if (ret) + DRM_DEBUG_DRIVER("failed to create exynos-drm debugfs.\n"); return 0; @@ -182,8 +212,15 @@ err_crtc: static int exynos_drm_unload(struct drm_device *dev) { + struct exynos_drm_private *private; + + private = dev->dev_private; + DRM_DEBUG_DRIVER("%s\n", __FILE__); + /* release vmm object and device address space for iommu. */ + exynos_drm_iommu_cleanup(private->vmm); + exynos_drm_fbdev_fini(dev); exynos_drm_device_unregister(dev); drm_vblank_cleanup(dev); @@ -193,6 +230,9 @@ static int exynos_drm_unload(struct drm_device *dev) dev->dev_private = NULL; + drm_debugfs_remove_files(exynos_drm_debugfs_list, + EXYNOS_DRM_DEBUGFS_ENTRIES, dev->primary); + return 0; } @@ -206,6 +246,8 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) if (!file_priv) return -ENOMEM; + file_priv->tgid = task_tgid_nr(current); + drm_prime_init_file_private(&file->prime); file->driver_priv = file_priv; @@ -271,6 +313,9 @@ static struct drm_ioctl_desc exynos_ioctls[] = { exynos_drm_gem_userptr_ioctl, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, exynos_drm_gem_get_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(EXYNOS_USER_LIMIT, + exynos_drm_gem_user_limit_ioctl, DRM_MASTER | + DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(EXYNOS_GEM_EXPORT_UMP, exynos_drm_gem_export_ump_ioctl, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CACHE_OP, @@ -280,8 +325,6 @@ static struct drm_ioctl_desc exynos_ioctls[] = { exynos_drm_gem_get_phy_ioctl, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(EXYNOS_GEM_PHY_IMP, exynos_drm_gem_phy_imp_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(EXYNOS_PLANE_SET_ZPOS, - exynos_plane_set_zpos_ioctl, DRM_UNLOCKED | DRM_AUTH), DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, vidi_connection_ioctl, DRM_UNLOCKED | DRM_AUTH), @@ -292,8 +335,14 @@ static struct drm_ioctl_desc exynos_ioctls[] = { DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, exynos_g2d_exec_ioctl, DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_ROTATOR_EXEC, - exynos_drm_rotator_exec_ioctl, DRM_UNLOCKED | DRM_AUTH), + DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_PROPERTY, + exynos_drm_ipp_get_property, DRM_UNLOCKED | DRM_AUTH), + DRM_IOCTL_DEF_DRV(EXYNOS_IPP_SET_PROPERTY, + exynos_drm_ipp_set_property, DRM_UNLOCKED | DRM_AUTH), + DRM_IOCTL_DEF_DRV(EXYNOS_IPP_BUF, + exynos_drm_ipp_buf, DRM_UNLOCKED | DRM_AUTH), + DRM_IOCTL_DEF_DRV(EXYNOS_IPP_CTRL, + exynos_drm_ipp_ctrl, DRM_UNLOCKED | DRM_AUTH), }; static const struct file_operations exynos_drm_driver_fops = { @@ -307,8 +356,8 @@ static const struct file_operations exynos_drm_driver_fops = { }; static struct drm_driver exynos_drm_driver = { - .driver_features = DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM | - DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, + .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET | + DRIVER_GEM | DRIVER_PRIME, .load = exynos_drm_load, .unload = exynos_drm_unload, .open = exynos_drm_open, @@ -407,6 +456,24 @@ static int __init exynos_drm_init(void) goto out_rotator; #endif +#ifdef CONFIG_DRM_EXYNOS_FIMC + ret = platform_driver_register(&fimc_driver); + if (ret < 0) + goto out_fimc; +#endif + +#ifdef CONFIG_DRM_EXYNOS_GSC + ret = platform_driver_register(&gsc_driver); + if (ret < 0) + goto out_gsc; +#endif + +#ifdef CONFIG_DRM_EXYNOS_IPP + ret = platform_driver_register(&ipp_driver); + if (ret < 0) + goto out_ipp; +#endif + ret = platform_driver_register(&exynos_drm_platform_driver); if (ret < 0) goto out; @@ -414,6 +481,21 @@ static int __init exynos_drm_init(void) return 0; out: +#ifdef CONFIG_DRM_EXYNOS_IPP + platform_driver_unregister(&ipp_driver); +out_ipp: +#endif + +#ifdef CONFIG_DRM_EXYNOS_GSC + platform_driver_unregister(&gsc_driver); +out_gsc: +#endif + +#ifdef CONFIG_DRM_EXYNOS_FIMC + platform_driver_unregister(&fimc_driver); +out_fimc: +#endif + #ifdef CONFIG_DRM_EXYNOS_ROTATOR platform_driver_unregister(&rotator_driver); out_rotator: @@ -451,6 +533,18 @@ static void __exit exynos_drm_exit(void) platform_driver_unregister(&exynos_drm_platform_driver); +#ifdef CONFIG_DRM_EXYNOS_IPP + platform_driver_unregister(&ipp_driver); +#endif + +#ifdef CONFIG_DRM_EXYNOS_GSC + platform_driver_unregister(&gsc_driver); +#endif + +#ifdef CONFIG_DRM_EXYNOS_FIMC + platform_driver_unregister(&fimc_driver); +#endif + #ifdef CONFIG_DRM_EXYNOS_ROTATOR platform_driver_unregister(&rotator_driver); #endif |