aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_drv.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c180
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