amlogic: drm: support fence/cache op and gem_info 38/259138/1
authorSeung-Woo Kim <sw0312.kim@samsung.com>
Mon, 12 Apr 2021 06:40:26 +0000 (15:40 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Tue, 1 Jun 2021 11:18:25 +0000 (20:18 +0900)
Support fence operation, cache operation and geminfo
in debugfs from amlogic meson drm.

Change-Id: I0d7bc71c7d489e65c0c1051df21fc7b034c3af53
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
amlogic: drm: add am_meson_gem_get_ioctl

am_meson_gem_get_ioctl is used by libtbm-meson.

Change-Id: I1f2fd5b8413d26bbf774b0f12a09534fa911d305
Signed-off-by: Sihyun, Park <shwan.park@samsung.com>
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
27 files changed:
drivers/amlogic/drm/Makefile
drivers/amlogic/drm/meson_crtc.c
drivers/amlogic/drm/meson_crtc.h
drivers/amlogic/drm/meson_debugfs.c
drivers/amlogic/drm/meson_drv.c
drivers/amlogic/drm/meson_drv.h
drivers/amlogic/drm/meson_fb.c
drivers/amlogic/drm/meson_fb.h
drivers/amlogic/drm/meson_fence.c [new file with mode: 0644]
drivers/amlogic/drm/meson_fence.h [new file with mode: 0644]
drivers/amlogic/drm/meson_gem.c
drivers/amlogic/drm/meson_gem.h
drivers/amlogic/drm/meson_hdmi.c
drivers/amlogic/drm/meson_lcd.c
drivers/amlogic/drm/meson_plane.c
drivers/amlogic/drm/meson_plane.h
drivers/amlogic/drm/meson_vpu.c
drivers/amlogic/drm/meson_vpu.h
drivers/amlogic/drm/meson_vpu_pipeline.c
drivers/amlogic/drm/meson_vpu_pipeline.h
drivers/amlogic/drm/meson_vpu_util.c
drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c
drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h
drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c
drivers/gpu/drm/drm_fops.c
include/drm/drmP.h
include/uapi/drm/meson_drm.h

index 022ca0b..2159b3a 100644 (file)
@@ -1,3 +1,5 @@
+ccflags-y += -I$(srctree)/drivers/amlogic
+
 ifeq ($(CONFIG_DRM_MESON_USE_ION),y)
         meson-drm-y += meson_gem.o meson_fb.o
         ccflags-y += -Idrivers/staging/android/
@@ -22,6 +24,7 @@ endif
 meson-drm-y += meson_drv.o meson_plane.o meson_vpu_pipeline_traverse.o \
                 meson_crtc.o meson_vpu_pipeline.o meson_vpu_pipeline_private.o \
                meson_debugfs.o meson_vpu_util.o \
+               meson_fence.o
 
 meson-drm-y += \
                 vpu-hw/meson_vpu_osd_mif.o \
index 05e79bd..444155e 100644 (file)
@@ -242,7 +242,8 @@ static const struct drm_crtc_helper_funcs am_crtc_helper_funcs = {
        .atomic_flush           = am_meson_crtc_atomic_flush,
 };
 
-int am_meson_crtc_create(struct am_meson_crtc *amcrtc)
+int am_meson_crtc_create(struct am_meson_crtc *amcrtc,
+       struct osd_device_data_s *osd_dev)
 {
        struct meson_drm *priv = amcrtc->priv;
        struct drm_crtc *crtc = &amcrtc->base;
@@ -254,7 +255,7 @@ int am_meson_crtc_create(struct am_meson_crtc *amcrtc)
 
        DRM_INFO("%s\n", __func__);
        ret = drm_crtc_init_with_planes(priv->drm, crtc,
-                                       priv->primary_plane, priv->cursor_plane,
+                                       priv->primary_plane, NULL,
                                        &am_meson_crtc_funcs, "amlogic vpu");
        if (ret) {
                dev_err(amcrtc->dev, "Failed to init CRTC\n");
@@ -262,7 +263,7 @@ int am_meson_crtc_create(struct am_meson_crtc *amcrtc)
        }
 
        drm_crtc_helper_add(crtc, &am_crtc_helper_funcs);
-       osd_drm_init(&osd_meson_dev);
+       osd_drm_init(osd_dev);
 
        #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
        amvecm_drm_init(0);
@@ -279,4 +280,4 @@ int am_meson_crtc_create(struct am_meson_crtc *amcrtc)
 
        return 0;
 }
-
+EXPORT_SYMBOL(am_meson_crtc_create);
index 7370177..82f4483 100644 (file)
@@ -63,7 +63,7 @@ struct am_meson_crtc {
                struct am_meson_crtc, base)
 #define to_am_meson_crtc_state(x) container_of(x, \
                struct am_meson_crtc_state, base)
-
-int am_meson_crtc_create(struct am_meson_crtc *amcrtc);
+int am_meson_crtc_create(struct am_meson_crtc *amcrtc,
+       struct osd_device_data_s *osd_dev);
 
 #endif
index ff9eea8..8eb3e52 100644 (file)
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
-#endif
+
+#include <drm/drmP.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#endif /* CONFIG_DEBUG_FS */
 
 #include "meson_drv.h"
 #include "meson_crtc.h"
 
 #ifdef CONFIG_DEBUG_FS
 
+struct meson_gem_info_debugfs {
+       struct drm_file *filp;
+       struct seq_file *m;
+};
+
 static int meson_dump_show(struct seq_file *sf, void *data)
 {
        struct drm_crtc *crtc = sf->private;
@@ -266,8 +275,54 @@ static int mm_show(struct seq_file *sf, void *arg)
                        &dev->vma_offset_manager->vm_addr_space_mm);
 }
 
+static int meson_gem_info_print(int id, void *ptr, void *data)
+{
+       struct drm_gem_object *obj = ptr;
+       struct meson_gem_info_debugfs *gem_info = data;
+
+       if(!obj) {
+               pr_err("obj is already null\n");
+               return 0;
+       }
+
+       if(gem_info) {
+               seq_printf(gem_info->m, " %5d %3d %4d  %8zd %3d %3d %6d\n",
+                               gem_info->filp->drm_pid,
+                               obj->name,
+                               id,
+                               obj->size,
+                               atomic_read(&obj->refcount.refcount),
+                               obj->handle_count,
+                               obj->import_attach ? 1 : 0);
+       }
+       return 0;
+}
+
+static int meson_gem_info(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *)m->private;
+       struct drm_device *drm_dev = node->minor->dev;
+       struct meson_gem_info_debugfs gem_info;
+
+       seq_printf(m, "  pid   name  id   size   ref handles import\n");
+
+       gem_info.m = m;
+
+       mutex_lock(&drm_dev->struct_mutex);
+       list_for_each_entry_reverse(gem_info.filp, &drm_dev->filelist, lhead) {
+               spin_lock(&gem_info.filp->table_lock);
+               idr_for_each(&gem_info.filp->object_idr, meson_gem_info_print,
+                               &gem_info);
+               spin_unlock(&gem_info.filp->table_lock);
+       }
+       mutex_unlock(&drm_dev->struct_mutex);
+
+       return 0;
+}
+
 static struct drm_info_list meson_debugfs_list[] = {
        {"mm", mm_show, 0},
+       {"gem_info", meson_gem_info, 0},
 };
 
 int meson_debugfs_init(struct drm_minor *minor)
@@ -295,4 +350,4 @@ void meson_debugfs_cleanup(struct drm_minor *minor)
        drm_debugfs_remove_files(meson_debugfs_list,
                                ARRAY_SIZE(meson_debugfs_list), minor);
 }
-#endif
+#endif /* CONFIG_DEBUG_FS */
index f94d45b..ae1f242 100644 (file)
 #include <drm/drm_rect.h>
 #include <drm/drm_fb_helper.h>
 
+#include "osd_hw.h"
 #include "meson_fbdev.h"
 #ifdef CONFIG_DRM_MESON_USE_ION
 #include "meson_gem.h"
 #include "meson_fb.h"
 #endif
 #include "meson_drv.h"
+#include "meson_vpu.h"
 #include "meson_vpu_pipeline.h"
-
+#include "meson_fence.h"
 
 #define DRIVER_NAME "meson"
 #define DRIVER_DESC "Amlogic Meson DRM driver"
@@ -102,26 +104,40 @@ static void am_meson_disable_vblank(struct drm_device *dev, unsigned int crtc)
 {
 }
 
-static void am_meson_load(struct drm_device *dev)
-{
-#if 0
-       struct meson_drm *priv = dev->dev_private;
-       struct drm_crtc *crtc = priv->crtc;
-       int pipe = drm_crtc_index(crtc);
-
-       if (priv->crtc_funcs[pipe] &&
-               priv->crtc_funcs[pipe]->loader_protect)
-               priv->crtc_funcs[pipe]->loader_protect(crtc, true);
-#endif
-}
 
 #ifdef CONFIG_DRM_MESON_USE_ION
 static const struct drm_ioctl_desc meson_ioctls[] = {
        DRM_IOCTL_DEF_DRV(MESON_GEM_CREATE, am_meson_gem_create_ioctl,
-               DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+                         DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(MESON_GEM_GET, am_meson_gem_get_ioctl,
+               DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(MESON_SET_BLANK, am_meson_drv_set_blank_ioctl,
+               DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(MESON_GEM_SYNC, am_meson_gem_sync_ioctl,
+               DRM_UNLOCKED | DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(MESON_GEM_CPU_PREP, am_meson_gem_cpu_prep_ioctl,
+               DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(MESON_GEM_CPU_FINI, am_meson_gem_cpu_fini_ioctl,
+               DRM_UNLOCKED),
 };
 #endif
 
+int am_meson_drv_set_blank_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv)
+{
+       struct drm_meson_plane_blank *args = data;
+       u32 index, enable;
+
+       index = (args->plane_type == DRM_PLANE_TYPE_OVERLAY) ? OSD2 : OSD1;
+       enable = (args->onoff) ? 0 : 1;
+
+       osd_drm_plane_enable_hw(index, enable);
+
+       return 0;
+}
+
 static const struct file_operations fops = {
        .owner          = THIS_MODULE,
        .open           = drm_open,
@@ -155,7 +171,7 @@ static struct drm_driver meson_driver = {
        /* PRIME Ops */
        .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
-
+       .gem_open_object                = am_meson_gem_open_object,
        .gem_prime_export       = drm_gem_prime_export,
        .gem_prime_get_sg_table = am_meson_gem_prime_get_sg_table,
 
@@ -249,9 +265,14 @@ static int am_meson_drm_bind(struct device *dev)
                goto err_gem;
        DRM_INFO("mode_config crtc number:%d\n", drm->mode_config.num_crtc);
 
+       priv->dev_fctx = am_meson_fence_context_create("meson.drm-fence");
+
+       if (IS_ERR(priv->dev_fctx))
+               goto err_unbind_all;
+
        ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
        if (ret)
-               goto err_unbind_all;
+               goto err_fctx;
 
        drm_mode_config_reset(drm);
        drm->mode_config.max_width = 4096;
@@ -266,7 +287,10 @@ static int am_meson_drm_bind(struct device *dev)
 
        drm_kms_helper_poll_init(drm);
 
-       am_meson_load(drm);
+       if (priv->primary_plane != NULL && priv->overlay_plane != NULL) {
+               drm_plane_create_zpos_property(priv->primary_plane, 0, 0, OSD_MAX);
+               drm_plane_create_zpos_property(priv->overlay_plane, 1, 0, OSD_MAX);
+       }
 
 #ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
        ret = am_meson_drm_fbdev_init(drm);
@@ -279,7 +303,6 @@ static int am_meson_drm_bind(struct device *dev)
 
        return 0;
 
-
 err_fbdev_fini:
 #ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
        am_meson_drm_fbdev_fini(drm);
@@ -290,6 +313,8 @@ err_poll_fini:
        drm_vblank_cleanup(drm);
 err_unbind_all:
        component_unbind_all(dev, drm);
+err_fctx:
+       am_meson_fence_context_destroy(priv->dev_fctx);
 err_gem:
        drm_mode_config_cleanup(drm);
 #ifdef CONFIG_DRM_MESON_USE_ION
@@ -307,6 +332,7 @@ err_free1:
 static void am_meson_drm_unbind(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
+       struct meson_drm *priv = dev->driver_data;
 
        drm_dev_unregister(drm);
 #ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
@@ -316,6 +342,7 @@ static void am_meson_drm_unbind(struct device *dev)
        drm->irq_enabled = false;
        drm_vblank_cleanup(drm);
        component_unbind_all(dev, drm);
+       am_meson_fence_context_destroy(priv->dev_fctx);
        drm_mode_config_cleanup(drm);
 #ifdef CONFIG_DRM_MESON_USE_ION
        am_meson_gem_cleanup(drm->dev_private);
@@ -373,10 +400,10 @@ static bool am_meson_drv_use_osd(void)
 
                if (strcmp(str, "okay") && strcmp(str, "ok")) {
                        DRM_INFO("device %s status is %s\n",
-                               node->name, str);
+                                node->name, str);
                } else {
                        DRM_INFO("device %s status is %s\n",
-                               node->name, str);
+                                node->name, str);
                        return true;
                }
        }
@@ -455,6 +482,7 @@ static int am_meson_drv_probe(struct platform_device *pdev)
        struct component_match *match = NULL;
        int i;
 
+       pr_info("[%s] in\n", __func__);
        if (am_meson_drv_use_osd())
                return am_meson_drv_probe_prune(pdev);
 
@@ -507,7 +535,7 @@ static int am_meson_drv_probe(struct platform_device *pdev)
                am_meson_add_endpoints(dev, &match, port);
                of_node_put(port);
        }
-
+       pr_info("[%s] out\n", __func__);
        return component_master_add_with_match(dev, &am_meson_drm_ops, match);
 }
 
index 4260a3c..7047b67 100644 (file)
@@ -50,15 +50,18 @@ struct meson_drm {
        struct drm_fb_helper *fbdev_helper;
        struct drm_gem_object *fbdev_bo;
        struct drm_plane *primary_plane;
-       struct drm_plane *cursor_plane;
+       struct drm_plane *overlay_plane;
        struct drm_property_blob *gamma_lut_blob;
 
 #ifdef CONFIG_DRM_MESON_USE_ION
        struct ion_client *gem_client;
 #endif
 
+       struct meson_fence_context *dev_fctx;
+
        struct meson_vpu_pipeline *pipeline;
        struct meson_vpu_funcs *funcs;
+       struct am_meson_logo *logo;
 
        u32 num_crtcs;
        struct am_meson_crtc *crtcs[MESON_MAX_CRTC];
@@ -67,6 +70,11 @@ struct meson_drm {
        struct am_osd_plane *planes[MESON_MAX_OSD];
 };
 
+int am_meson_drv_set_blank_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv);
+
 static inline int meson_vpu_is_compatible(struct meson_drm *priv,
                                          const char *compat)
 {
@@ -76,6 +84,7 @@ static inline int meson_vpu_is_compatible(struct meson_drm *priv,
 extern int am_meson_register_crtc_funcs(struct drm_crtc *crtc,
                                 const struct meson_crtc_funcs *crtc_funcs);
 extern void am_meson_unregister_crtc_funcs(struct drm_crtc *crtc);
+struct drm_connector *am_meson_hdmi_connector(void);
 
 #ifdef CONFIG_DEBUG_FS
 int meson_debugfs_init(struct drm_minor *minor);
index 1c364da..359ed1f 100644 (file)
@@ -18,8 +18,7 @@
 #include <drm/drm_atomic_helper.h>
 
 #include "meson_fb.h"
-
-#define to_am_meson_fb(x) container_of(x, struct am_meson_fb, base)
+#include "meson_vpu.h"
 
 void am_meson_fb_destroy(struct drm_framebuffer *fb)
 {
@@ -27,6 +26,7 @@ void am_meson_fb_destroy(struct drm_framebuffer *fb)
 
        drm_gem_object_unreference_unlocked(&meson_fb->bufp->base);
        drm_framebuffer_cleanup(fb);
+       DRM_DEBUG("meson_fb=0x%p,\n", meson_fb);
        kfree(meson_fb);
 }
 
@@ -58,9 +58,12 @@ am_meson_fb_alloc(struct drm_device *dev,
        if (!meson_fb)
                return ERR_PTR(-ENOMEM);
 
-       meson_gem = container_of(obj, struct am_meson_gem_object, base);
-       meson_fb->bufp = meson_gem;
-
+       if (obj) {
+               meson_gem = container_of(obj, struct am_meson_gem_object, base);
+               meson_fb->bufp = meson_gem;
+       } else {
+               meson_fb->bufp = NULL;
+       }
        drm_helper_mode_fill_fb_struct(&meson_fb->base, mode_cmd);
 
        ret = drm_framebuffer_init(dev, &meson_fb->base,
@@ -70,6 +73,10 @@ am_meson_fb_alloc(struct drm_device *dev,
                        ret);
                goto err_free_fb;
        }
+       DRM_INFO("meson_fb[id:%d,ref:%d]=0x%p,meson_fb->bufp=0x%p\n",
+                meson_fb->base.base.id,
+                atomic_read(&meson_fb->base.base.refcount.refcount),
+                meson_fb, meson_fb->bufp);
 
        return &meson_fb->base;
 
@@ -113,6 +120,10 @@ struct drm_framebuffer *am_meson_fb_create(struct drm_device *dev,
                kfree(meson_fb);
                return ERR_PTR(ret);
        }
+       DRM_DEBUG("meson_fb[in:%d,ref:%d]=0x%px,meson_fb->bufp=0x%p\n",
+                 meson_fb->base.base.id,
+                 atomic_read(&meson_fb->base.base.refcount.refcount),
+                 meson_fb, meson_fb->bufp);
 
        return &meson_fb->base;
 }
index 9c76d2e..0226ee7 100644 (file)
 
 #include "meson_gem.h"
 
+#define to_am_meson_fb(x) container_of(x, struct am_meson_fb, base)
+
+#define VMODE_NAME_LEN_MAX    64
+
+struct am_meson_logo {
+       struct page *logo_page;
+       phys_addr_t start;
+       u32 size;
+       u32 width;
+       u32 height;
+       u32 bpp;
+       u32 alloc_flag;
+       u32 info_loaded_mask;
+       char *outputmode_t;
+       char outputmode[VMODE_NAME_LEN_MAX];
+};
+
 struct am_meson_fb {
        struct drm_framebuffer base;
        struct am_meson_gem_object *bufp;
+       struct am_meson_logo *logo;
 };
 
-struct drm_framebuffer *am_meson_fb_create(struct drm_device *dev,
-                                    struct drm_file *file_priv,
-                                    const struct drm_mode_fb_cmd2 *mode_cmd);
-struct drm_framebuffer *am_meson_drm_framebuffer_init(
-                                    struct drm_device *dev,
-                                    struct drm_mode_fb_cmd2 *mode_cmd,
-                                    struct drm_gem_object *obj);
+struct drm_framebuffer *
+am_meson_fb_create(struct drm_device *dev,
+                  struct drm_file *file_priv,
+                  const struct drm_mode_fb_cmd2 *mode_cmd);
+struct drm_framebuffer *
+am_meson_drm_framebuffer_init(struct drm_device *dev,
+                             struct drm_mode_fb_cmd2 *mode_cmd,
+                             struct drm_gem_object *obj);
+struct drm_framebuffer *
+am_meson_fb_alloc(struct drm_device *dev,
+                 struct drm_mode_fb_cmd2 *mode_cmd,
+                 struct drm_gem_object *obj);
+
 #endif
diff --git a/drivers/amlogic/drm/meson_fence.c b/drivers/amlogic/drm/meson_fence.c
new file mode 100644 (file)
index 0000000..f1f30f6
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 Samsung Electronics Co.Ltd
+ *
+ * based on: drivers/gpu/drm/tilcdc/
+ *
+ * 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 "meson_fence.h"
+
+#define to_meson_fence(fence) container_of(fence, struct meson_fence, base)
+
+struct meson_fence_context*
+am_meson_fence_context_create(const char *name)
+{
+       struct meson_fence_context *fence_context;
+
+       fence_context = kmalloc(sizeof(*fence_context), GFP_KERNEL);
+       if (!fence_context)
+               return NULL;
+
+       fence_context->context = fence_context_alloc(1);
+       fence_context->name = name;
+       atomic_set(&fence_context->seqno, 0);
+       atomic_set(&fence_context->fence_count, 0);
+
+       return fence_context;
+}
+
+void
+am_meson_fence_context_destroy(
+       struct meson_fence_context *fence_context)
+{
+       unsigned fence_count;
+
+       fence_count = atomic_read(&fence_context->fence_count);
+       if (WARN_ON(fence_count))
+               DRM_DEBUG_DRIVER("%s context has %u fence(s) remaining\n",
+                                fence_context->name, fence_count);
+
+       kfree(fence_context);
+}
+
+static const char*
+am_meson_fence_get_driver_name(struct fence *fence)
+{
+       return "meson.drm";
+}
+
+static const char*
+am_meson_fence_get_timeline_name(struct fence *fence)
+{
+       struct meson_fence *meson_fence = to_meson_fence(fence);
+       return meson_fence->fence_context->name;
+}
+
+static bool
+am_meson_fence_enable_signaling(struct fence *fence)
+{
+       return true;
+}
+
+static void
+am_meson_fence_release(struct fence *fence)
+{
+       struct meson_fence *meson_fence = to_meson_fence(fence);
+
+       atomic_dec(&meson_fence->fence_context->fence_count);
+       kfree(meson_fence);
+}
+
+static struct fence_ops meson_fence_ops = {
+       .get_driver_name = am_meson_fence_get_driver_name,
+       .get_timeline_name = am_meson_fence_get_timeline_name,
+       .enable_signaling = am_meson_fence_enable_signaling,
+       .wait = fence_default_wait,
+       .release = am_meson_fence_release,
+};
+
+static inline unsigned
+am_meson_fence_context_seqno_next(
+       struct meson_fence_context *fence_context)
+{
+       return atomic_inc_return(&fence_context->seqno) - 1;
+}
+
+struct fence *
+am_meson_fence_create(struct meson_fence_context *fence_context)
+{
+       struct meson_fence *meson_fence;
+       unsigned int seqno;
+
+       meson_fence = kmalloc(sizeof(*meson_fence), GFP_KERNEL);
+       if (!meson_fence)
+               return NULL;
+
+       spin_lock_init(&meson_fence->lock);
+       meson_fence->fence_context = fence_context;
+
+       seqno = am_meson_fence_context_seqno_next(fence_context);
+       fence_init(&meson_fence->base, &meson_fence_ops, &meson_fence->lock,
+                  fence_context->context, seqno);
+
+       atomic_inc(&fence_context->fence_count);
+
+       return &meson_fence->base;
+}
+
diff --git a/drivers/amlogic/drm/meson_fence.h b/drivers/amlogic/drm/meson_fence.h
new file mode 100644 (file)
index 0000000..c6fa538
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 Samsung Electronics Co.Ltd
+ *
+ * based on: drivers/gpu/drm/tilcdc/
+ *
+ * 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.
+ */
+#ifndef __MESON_FENCE_H__
+#define __MESON_FENCE_H__
+
+#include <linux/atomic.h>
+#include <linux/fence.h>
+#include <drm/drmP.h>
+
+struct meson_fence_context {
+       unsigned int context;
+       const char *name;
+       atomic_t seqno;
+       atomic_t fence_count;
+};
+
+struct meson_fence {
+       struct meson_fence_context *fence_context;
+       struct fence base;
+       spinlock_t lock;
+};
+
+struct meson_fence_context*
+am_meson_fence_context_create(const char *name);
+
+struct fence *
+am_meson_fence_create(struct meson_fence_context *fence_context);
+
+void
+am_meson_fence_context_destroy(struct meson_fence_context *fence_context);
+
+#endif    /* __MESON_FENCE_H__ */
+
index 7c472e3..6864ed4 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/dma-buf.h>
-#include <linux/meson_ion.h>
+#include <media/common/ion_dev/meson_ion.h>
 #include <ion/ion.h>
 
 #include "meson_gem.h"
+#include "meson_fence.h"
 
 #define to_am_meson_gem_obj(x) container_of(x, struct am_meson_gem_object, base)
 
@@ -45,7 +46,7 @@ static int am_meson_gem_alloc_ion_buff(
 
        //check flags to set different ion heap type.
        //if flags is set to 0, need to use ion dma buffer.
-       if (((flags & (MESON_USE_SCANOUT | MESON_USE_CURSOR)) != 0)
+       if (((flags & (MESON_USE_SCANOUT | MESON_USE_CURSOR | MESON_USE_OVERLAY)) != 0)
                || (flags == 0)) {
                handle = ion_alloc(client, meson_gem_obj->base.size,
                                0, (1 << ION_HEAP_TYPE_DMA), 0);
@@ -55,7 +56,7 @@ static int am_meson_gem_alloc_ion_buff(
                bscatter = true;
        }
 
-       if (IS_ERR(handle)) {
+       if (IS_ERR_OR_NULL(handle)) {
                DRM_ERROR("%s: FAILED, flags:0x%x.\n",
                        __func__, flags);
                return -ENOMEM;
@@ -63,6 +64,7 @@ static int am_meson_gem_alloc_ion_buff(
 
        meson_gem_obj->handle = handle;
        meson_gem_obj->bscatter = bscatter;
+       meson_gem_obj->flags = flags;
        DRM_DEBUG("%s: allocate handle (%p).\n",
                __func__, meson_gem_obj->handle);
        return 0;
@@ -116,6 +118,12 @@ struct am_meson_gem_object *am_meson_gem_object_create(
                goto error;
        }
 
+       /*for release check*/
+       meson_gem_obj->flags = flags;
+       meson_gem_obj->size = size;
+
+       reservation_object_init(&meson_gem_obj->resv);
+
        return meson_gem_obj;
 
 error:
@@ -130,6 +138,8 @@ void am_meson_gem_object_free(struct drm_gem_object *obj)
        DRM_DEBUG("am_meson_gem_object_free %p handle count = %d\n",
                meson_gem_obj, obj->handle_count);
 
+       reservation_object_fini(&meson_gem_obj->resv);
+
        if (obj->import_attach == false)
                am_meson_gem_free_ion_buf(obj->dev, meson_gem_obj);
        else
@@ -212,6 +222,16 @@ int am_meson_gem_mmap(
        return ret;
 }
 
+int am_meson_gem_open_object(
+       struct drm_gem_object *obj,
+       struct drm_file *file_priv)
+{
+       if (obj && file_priv)
+               file_priv->drm_pid = task_tgid_nr(current);
+
+       return 0;
+}
+
 phys_addr_t am_meson_gem_object_get_phyaddr(
        struct meson_drm *drm,
        struct am_meson_gem_object *meson_gem)
@@ -305,8 +325,11 @@ int am_meson_gem_dumb_map_offset(
        }
 
        ret = drm_gem_create_mmap_offset(obj);
-       if (ret)
+       if (ret) {
+               struct am_meson_gem_object *meson_gem_obj = to_am_meson_gem_obj(obj);
+               reservation_object_fini(&meson_gem_obj->resv);
                goto out;
+       }
 
        *offset = drm_vma_node_offset_addr(&obj->vma_node);
        DRM_DEBUG("offset = 0x%lx\n", (unsigned long)*offset);
@@ -376,6 +399,194 @@ void am_meson_gem_cleanup(struct meson_drm  *drmdrv)
        }
 }
 
+int am_meson_gem_get_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv)
+{
+       struct drm_gem_object *obj;
+       struct drm_meson_gem_info *args;
+       struct am_meson_gem_object *meson_gem_obj;
+
+       args = (struct drm_meson_gem_info *)data;
+       obj = drm_gem_object_lookup(file_priv, args->handle);
+       if (!obj) {
+               DRM_ERROR("failed to lookup gem object.\n");
+               return -EINVAL;
+       }
+       meson_gem_obj = to_am_meson_gem_obj(obj);
+       args->flags = meson_gem_obj->flags;
+       args->size = meson_gem_obj->size;
+
+       drm_gem_object_unreference_unlocked(obj);
+
+       return 0;
+}
+
+int am_meson_gem_sync_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv)
+{
+       struct drm_gem_object *obj;
+       struct drm_meson_gem_sync *args;
+       struct am_meson_gem_object *meson_gem_obj;
+       struct ion_buffer *buffer;
+       int ret = 0;
+
+       mutex_lock(&dev->struct_mutex);
+
+       args = (struct drm_meson_gem_sync *)data;
+       obj = drm_gem_object_lookup(file_priv, args->handle);
+       if (!obj) {
+               DRM_ERROR("failed to lookup gem object.\n");
+               ret = -EINVAL;
+               goto unlock;
+       }
+       meson_gem_obj = to_am_meson_gem_obj(obj);
+       if (!meson_gem_obj) {
+               DRM_ERROR("failed to lookup am_meson_gem_object.\n");
+               ret = -EINVAL;
+               goto out;
+       }
+       if (meson_gem_obj->bscatter &&
+               !(meson_gem_obj->flags & MESON_USE_RENDER_VIP)) {
+               buffer = meson_gem_obj->handle->buffer;
+               dma_sync_sg_for_cpu(dev->dev, buffer->sg_table->sgl,
+                       buffer->sg_table->nents, DMA_FROM_DEVICE);
+       }
+
+out:
+       drm_gem_object_unreference(obj);
+unlock:
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
+int am_meson_gem_cpu_prep_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv)
+{
+       int err = 0;
+       struct drm_meson_gem_cpu_access *args = (struct drm_meson_gem_cpu_access *)data;
+       struct meson_drm *priv = dev->dev_private;
+       struct drm_gem_object *obj;
+       bool write = !!(args->flags & MESON_GEM_CPU_PREP_WRITE);
+       bool wait = !(args->flags & MESON_GEM_CPU_PREP_NOWAIT);
+       struct am_meson_gem_object *meson_gem_obj;
+
+       if (args->flags & ~(MESON_GEM_CPU_PREP_READ |
+                                       MESON_GEM_CPU_PREP_WRITE |
+                                       MESON_GEM_CPU_PREP_NOWAIT)) {
+               DRM_ERROR("invalid flags: %#08x\n", args->flags);
+               return -EINVAL;
+       }
+
+       mutex_lock(&dev->struct_mutex);
+       obj = drm_gem_object_lookup(file_priv, args->handle);
+       mutex_unlock(&dev->struct_mutex);
+       if (!obj) {
+               err = -ENOENT;
+               goto exit_unlock;
+       }
+       if (obj->import_attach) {
+               err = -EINVAL;
+               goto exit_unref;
+       }
+
+       meson_gem_obj = to_am_meson_gem_obj(obj);
+       if (meson_gem_obj->prep_data.cpu_prep) {
+               err = -EBUSY;
+               DRM_DEBUG("EBUSY cpu_prep not unlocked yet by caller\n");
+               goto exit_unref;
+       }
+
+       if (wait) {
+               long lerr;
+               lerr = reservation_object_wait_timeout_rcu(&meson_gem_obj->resv, write, true, 10 * HZ);
+               if (!lerr) {
+                       err = -EBUSY;
+                       goto exit_unref;
+               } else if (lerr < 0) {
+                       err = lerr;
+                       goto exit_unref;
+               }
+
+               meson_gem_obj->prep_data.fence = am_meson_fence_create(priv->dev_fctx);
+               if (!meson_gem_obj->prep_data.fence) {
+                       err = -ENOMEM;
+                       goto exit_unref;
+               }
+
+               if (write) {
+                       ww_mutex_lock(&meson_gem_obj->resv.lock, NULL);
+                       reservation_object_add_excl_fence(
+                                               &meson_gem_obj->resv, meson_gem_obj->prep_data.fence);
+                       ww_mutex_unlock(&meson_gem_obj->resv.lock);
+               } else {
+                       ww_mutex_lock(&meson_gem_obj->resv.lock, NULL);
+                       err = reservation_object_reserve_shared(&meson_gem_obj->resv);
+                       if (err) {
+                               fence_put(meson_gem_obj->prep_data.fence);
+                       } else {
+                               reservation_object_add_shared_fence(
+                                               &meson_gem_obj->resv, meson_gem_obj->prep_data.fence);
+                       }
+                       ww_mutex_unlock(&meson_gem_obj->resv.lock);
+               }
+       } else {
+               if (!reservation_object_test_signaled_rcu(&meson_gem_obj->resv, write))
+                       err = -EBUSY;
+       }
+
+       if (!err)
+               meson_gem_obj->prep_data.cpu_prep = true;
+
+exit_unref:
+       drm_gem_object_unreference_unlocked(obj);
+exit_unlock:
+       return err;
+}
+
+int am_meson_gem_cpu_fini_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv)
+{
+       int err = 0;
+       struct drm_meson_gem_cpu_access *args = (struct drm_meson_gem_cpu_access *)data;
+       struct drm_gem_object *obj;
+       struct am_meson_gem_object *meson_gem_obj;
+
+       mutex_lock(&dev->struct_mutex);
+       obj = drm_gem_object_lookup(file_priv, args->handle);
+       if (!obj) {
+               err = -ENOENT;
+               goto exit_unlock;
+       }
+
+       meson_gem_obj = to_am_meson_gem_obj(obj);
+       if (!meson_gem_obj->prep_data.cpu_prep) {
+               err = -EINVAL;
+               goto exit_unref;
+       }
+
+       if (meson_gem_obj->prep_data.fence) {
+               WARN_ON(fence_signal(meson_gem_obj->prep_data.fence)); /* Signal the fence */
+               fence_put(meson_gem_obj->prep_data.fence);
+               meson_gem_obj->prep_data.fence =  NULL;
+       }
+       meson_gem_obj->prep_data.cpu_prep = false;
+
+exit_unref:
+       drm_gem_object_unreference_unlocked(obj);
+exit_unlock:
+       mutex_unlock(&dev->struct_mutex);
+
+       return err;
+}
+
 struct sg_table *am_meson_gem_prime_get_sg_table(
        struct drm_gem_object *obj)
 {
index cab22a5..1c59f9f 100644 (file)
 #include <drm/drm_gem.h>
 #include <uapi/drm/meson_drm.h>
 #include <ion/ion_priv.h>
+#include <linux/reservation.h>
 
 #include "meson_drv.h"
 
+struct fence_prep_data {
+       int cpu_prep;
+       struct fence *fence;
+};
+
 struct am_meson_gem_object {
        struct drm_gem_object base;
        unsigned int flags;
@@ -34,6 +40,10 @@ struct am_meson_gem_object {
        /* for buffer import form other driver */
        phys_addr_t addr;
        struct sg_table *sg;
+
+       struct reservation_object resv;
+       struct fence_prep_data prep_data;
+       unsigned int size;
 };
 
 /* GEM MANAGER CREATE*/
@@ -67,6 +77,26 @@ int am_meson_gem_dumb_map_offset(
        uint32_t handle,
        uint64_t *offset);
 
+int am_meson_gem_get_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv);
+
+int am_meson_gem_sync_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv);
+
+int am_meson_gem_cpu_prep_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv);
+
+int am_meson_gem_cpu_fini_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv);
+
 /* GEM OBJECT OPERATIONS */
 struct am_meson_gem_object *am_meson_gem_object_create(
                struct drm_device *dev, unsigned int flags,
@@ -78,6 +108,10 @@ int am_meson_gem_object_mmap(
        struct am_meson_gem_object *obj,
        struct vm_area_struct *vma);
 
+int am_meson_gem_open_object(
+       struct drm_gem_object *obj,
+       struct drm_file *file_priv);
+
 extern phys_addr_t am_meson_gem_object_get_phyaddr(
        struct meson_drm *drm,
        struct am_meson_gem_object *meson_gem);
index e5f0ce6..7cbe8c1 100644 (file)
 #include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
 #include "meson_hdmi.h"
 #include "meson_hdcp.h"
+#include "meson_vpu.h"
 
 #define DEVICE_NAME "amhdmitx"
 struct am_hdmi_tx am_hdmi_info;
 
-struct am_vout_mode {
-       char name[DRM_DISPLAY_MODE_LEN];
-       enum vmode_e mode;
-       int width, height, vrefresh;
-       unsigned int flags;
-};
-
 static struct am_vout_mode am_vout_modes[] = {
        { "1080p60hz", VMODE_HDMI, 1920, 1080, 60, 0},
        { "1080p30hz", VMODE_HDMI, 1920, 1080, 30, 0},
@@ -300,7 +294,6 @@ void am_hdmi_encoder_enable(struct drm_encoder *encoder)
        vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode);
        set_vout_vmode(vmode);
        vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &vmode);
-       am_hdmi->hdcp_work = NULL;
        mdelay(1000);
        am_hdmi_hdcp_work_state_change(am_hdmi, 0);
 }
@@ -584,6 +577,11 @@ static const struct of_device_id am_meson_hdmi_dt_ids[] = {
 
 MODULE_DEVICE_TABLE(of, am_meson_hdmi_dt_ids);
 
+struct drm_connector *am_meson_hdmi_connector(void)
+{
+       return &am_hdmi_info.connector;
+}
+
 static int am_meson_hdmi_bind(struct device *dev,
        struct device *master, void *data)
 {
@@ -596,12 +594,9 @@ static int am_meson_hdmi_bind(struct device *dev,
        int ret;
        int irq;
 
-       am_hdmi = devm_kzalloc(priv->dev, sizeof(*am_hdmi),
-                                      GFP_KERNEL);
-       if (!am_hdmi)
-               return -ENOMEM;
-       memcpy(&am_hdmi_info, am_hdmi, sizeof(*am_hdmi));
+       DRM_INFO("[%s] in\n", __func__);
        am_hdmi = &am_hdmi_info;
+       memset(am_hdmi, 0, sizeof(*am_hdmi));
 
        DRM_INFO("drm hdmitx init and version:%s\n", DRM_HDMITX_VER);
        am_hdmi->priv = priv;
@@ -662,6 +657,7 @@ static int am_meson_hdmi_bind(struct device *dev,
                                DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
                }
        }
+       DRM_INFO("[%s] out\n", __func__);
        return 0;
 }
 
@@ -679,6 +675,7 @@ static const struct component_ops am_meson_hdmi_ops = {
 
 static int am_meson_hdmi_probe(struct platform_device *pdev)
 {
+       DRM_INFO("[%s] in\n", __func__);
        return component_add(&pdev->dev, &am_meson_hdmi_ops);
 }
 
index e9c6f21..029878e 100644 (file)
@@ -116,6 +116,9 @@ static int am_lcd_connector_get_modes(struct drm_connector *connector)
                __func__, lcd->lcd_drv->lcd_config->lcd_basic.h_active,
                lcd->lcd_drv->lcd_config->lcd_basic.v_active);
 
+       connector->display_info.width_mm = mode->width_mm;
+       connector->display_info.height_mm = mode->height_mm;
+
        drm_mode_probed_add(connector, mode);
        count = 1;
        pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
@@ -607,10 +610,6 @@ int am_drm_lcd_notify_callback(struct notifier_block *block, unsigned long cmd,
        return 0;
 }
 
-static struct notifier_block am_drm_lcd_notifier_nb = {
-       .notifier_call  = am_drm_lcd_notify_callback,
-};
-
 static const struct of_device_id am_meson_lcd_dt_ids[] = {
        { .compatible = "amlogic,drm-lcd", },
        {},
@@ -636,12 +635,7 @@ static int am_meson_lcd_bind(struct device *dev, struct device *master,
                pr_err("invalid lcd driver, exit\n");
                return -ENODEV;
        }
-       /*
-        * register vout client for timing init,
-        * avoid init with null info when lcd probe with unifykey case.
-        */
-       vout_register_client(&am_drm_lcd_notifier_nb);
-
+       am_drm_lcd_display_mode_timing_init(am_drm_lcd);
        drm_panel_init(&am_drm_lcd->panel);
        am_drm_lcd->panel.dev = NULL;
        am_drm_lcd->panel.funcs = &am_drm_lcd_funcs;
index 7a66a9c..855e190 100644 (file)
@@ -42,12 +42,18 @@ static u64 afbc_wb_modifier[] = {
        DRM_FORMAT_MOD_INVALID
 };
 
-static void meson_plane_position_calc(
-       struct meson_vpu_osd_layer_info *plane_info,
-       struct drm_plane_state *state,
-       struct drm_display_mode *mode)
+static void
+meson_plane_position_calc(struct meson_vpu_osd_layer_info *plane_info,
+                         struct drm_plane_state *state,
+                         struct drm_display_mode *disp_mode)
 {
        u32 dst_w, dst_h, src_w, src_h, scan_mode_out;
+       struct drm_display_mode *mode;
+
+       if (IS_ERR_OR_NULL(state->crtc))
+               mode = disp_mode;
+       else
+               mode = &state->crtc->mode;
 
        scan_mode_out = mode->flags & DRM_MODE_FLAG_INTERLACE;
        plane_info->src_x = state->src_x;
@@ -147,7 +153,7 @@ static int meson_plane_fb_check(struct drm_plane *plane,
        #else
        struct drm_gem_cma_object *gem;
        #endif
-       dma_addr_t phyaddr;
+       phys_addr_t phyaddr;
 
        #ifdef CONFIG_DRM_MESON_USE_ION
        meson_fb = container_of(fb, struct am_meson_fb, base);
@@ -155,9 +161,21 @@ static int meson_plane_fb_check(struct drm_plane *plane,
                DRM_DEBUG("meson_fb is NULL!\n");
                return -EINVAL;
        }
-       phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp);
-       if (meson_fb->bufp->bscatter)
-               DRM_ERROR("am_meson_plane meet a scatter framebuffer.\n");
+       DRM_DEBUG("meson_fb[id:%d,ref:%d]=0x%p\n",
+                 meson_fb->base.base.id,
+                 atomic_read(&meson_fb->base.base.refcount.refcount),
+                 meson_fb);
+       if (meson_fb->logo && meson_fb->logo->alloc_flag &&
+           meson_fb->logo->start) {
+               phyaddr = meson_fb->logo->start;
+               DRM_DEBUG("logo->phyaddr=0x%pa\n", &phyaddr);
+       } else  if (meson_fb->bufp) {
+               phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp);
+       } else {
+               phyaddr = 0;
+               DRM_INFO("don't find phyaddr!\n");
+               return -EINVAL;
+       }
        #else
        if (!fb) {
                DRM_INFO("fb is NULL!\n");
@@ -182,12 +200,6 @@ static int meson_plane_get_fb_info(struct drm_plane *plane,
        struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
        struct drm_framebuffer *fb = new_state->fb;
        struct meson_drm *drv = osd_plane->drv;
-       #ifdef CONFIG_DRM_MESON_USE_ION
-       struct am_meson_fb *meson_fb;
-       #else
-       struct drm_gem_cma_object *gem;
-       #endif
-       dma_addr_t phyaddr;
 
        if (!drv) {
                DRM_INFO("%s new_state/meson_drm is NULL!\n", __func__);
@@ -197,29 +209,7 @@ static int meson_plane_get_fb_info(struct drm_plane *plane,
                DRM_INFO("%s invalid plane_index!\n", __func__);
                return -EINVAL;
        }
-
-       #ifdef CONFIG_DRM_MESON_USE_ION
-       meson_fb = container_of(fb, struct am_meson_fb, base);
-       if (!meson_fb) {
-               DRM_INFO("meson_fb is NULL!\n");
-               return 0;
-       }
-       phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp);
-       if (meson_fb->bufp->bscatter)
-               DRM_ERROR("ERROR:am_meson_plane meet a scatter framebuffer.\n");
-       plane_info->fb_size = meson_fb->bufp->base.size;
-       #else
-       if (!fb) {
-               DRM_INFO("fb is NULL!\n");
-               return -EINVAL;
-       }
-       /* Update Canvas with buffer address */
-       gem = drm_fb_cma_get_gem_obj(fb, 0);
-       phyaddr = gem->paddr;
-       #endif
-
        plane_info->pixel_format = fb->pixel_format;
-       plane_info->phy_addr = phyaddr;
        plane_info->byte_stride = fb->pitches[0];
 
        /*setup afbc info*/
@@ -261,6 +251,13 @@ static int meson_plane_atomic_get_property(struct drm_plane *plane,
                                        struct drm_property *property,
                                        uint64_t *val)
 {
+       struct am_osd_plane *osd_plane;
+       struct am_meson_plane_state *plane_state;
+
+       osd_plane = to_am_osd_plane(plane);
+       plane_state = to_am_meson_plane_state(state);
+       if (property == osd_plane->prop_premult_en)
+               *val = plane_state->premult_en;
        return 0;
 }
 
@@ -269,6 +266,14 @@ static int meson_plane_atomic_set_property(struct drm_plane *plane,
                                         struct drm_property *property,
                                         uint64_t val)
 {
+       struct am_osd_plane *osd_plane;
+       struct am_meson_plane_state *plane_state;
+
+       osd_plane = to_am_osd_plane(plane);
+       plane_state = to_am_meson_plane_state(state);
+       if (property == osd_plane->prop_premult_en)
+               plane_state->premult_en = val;
+
        return 0;
 }
 
@@ -333,13 +338,11 @@ bool am_meson_vpu_check_format_mod(struct drm_plane *plane,
                ret = true;
                break;
        case DRM_FORMAT_MOD_MESON_AFBC:
-               if (osd_meson_dev.afbc_type == MESON_AFBC &&
-                   plane->type == DRM_PLANE_TYPE_PRIMARY)
+               if (plane->type == DRM_PLANE_TYPE_PRIMARY)
                        ret = true;
                break;
        case DRM_FORMAT_MOD_MESON_AFBC_WB:
-               if (osd_meson_dev.afbc_type == MALI_AFBC &&
-                   plane->type == DRM_PLANE_TYPE_PRIMARY) {
+               if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
                        if (format == DRM_FORMAT_BGR565)
                                ret = false;
                        else
@@ -376,7 +379,7 @@ static void meson_plane_cleanup_fb(struct drm_plane *plane,
 {
        struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
 
-       DRM_DEBUG("%s osd %d.\n", __func__, osd_plane->plane_index);
+       DRM_DEBUG("osd %d.\n", osd_plane->plane_index);
 }
 
 static void meson_plane_atomic_update(struct drm_plane *plane,
@@ -393,6 +396,7 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
        struct meson_vpu_pipeline_state *mvps;
        struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
        struct meson_drm *drv = osd_plane->drv;
+       struct am_meson_plane_state *plane_state;
        int ret;
 
        if (!state || !drv) {
@@ -431,6 +435,8 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
                return ret;
        }
 
+       plane_state = to_am_meson_plane_state(state);
+       plane_info->premult_en = plane_state->premult_en;
        plane_info->enable = 1;
        DRM_DEBUG("index=%d, zorder=%d\n",
                plane_info->plane_index, plane_info->zorder);
@@ -459,6 +465,24 @@ static const struct drm_plane_helper_funcs am_osd_helper_funcs = {
        .atomic_disable = meson_plane_atomic_disable,
 };
 
+int drm_plane_create_premult_en_property(struct drm_plane *plane)
+{
+       struct drm_device *dev = plane->dev;
+       struct drm_property *prop;
+       struct am_osd_plane *osd_plane;
+
+       osd_plane = to_am_osd_plane(plane);
+       prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
+                                       "PREMULT_EN");
+       if (!prop)
+               return -ENOMEM;
+
+       drm_object_attach_property(&plane->base, prop, 0);
+       osd_plane->prop_premult_en = prop;
+
+       return 0;
+}
+
 static struct am_osd_plane *am_plane_create(struct meson_drm *priv, int i)
 {
        struct am_osd_plane *osd_plane;
@@ -472,10 +496,12 @@ static struct am_osd_plane *am_plane_create(struct meson_drm *priv, int i)
        if (!osd_plane)
                return 0;
 
-       if (i == 0)
+       if (i == OSD1)
+               type = DRM_PLANE_TYPE_OVERLAY;
+       else if (i == OSD2)
                type = DRM_PLANE_TYPE_PRIMARY;
        else
-               type = DRM_PLANE_TYPE_OVERLAY;
+               type = DRM_PLANE_TYPE_CURSOR;
 
        osd_plane->drv = priv;
        osd_plane->plane_index = i;
@@ -490,6 +516,7 @@ static struct am_osd_plane *am_plane_create(struct meson_drm *priv, int i)
                                 format_modifiers,
                                 type, plane_name);
 
+       drm_plane_create_premult_en_property(plane);
        drm_plane_helper_add(plane, &am_osd_helper_funcs);
        osd_drm_debugfs_add(&osd_plane->plane_debugfs_dir,
                            plane_name, osd_plane->plane_index);
@@ -510,9 +537,10 @@ int am_meson_plane_create(struct meson_drm *priv)
                if (!plane)
                        return -ENOMEM;
 
-               if (i == 0)
+               if (i == OSD1)
+                       priv->overlay_plane = &plane->base;
+               else if (i == OSD2)
                        priv->primary_plane = &plane->base;
-
                priv->planes[priv->num_planes++] = plane;
        }
 
@@ -520,3 +548,4 @@ int am_meson_plane_create(struct meson_drm *priv)
 
        return 0;
 }
+EXPORT_SYMBOL(am_meson_plane_create);
index a1e6f4b..5be8adc 100644 (file)
@@ -31,6 +31,7 @@
 
 struct am_meson_plane_state {
        struct drm_plane_state base;
+       u32 premult_en;
 };
 
 struct am_osd_plane {
@@ -38,6 +39,7 @@ struct am_osd_plane {
        struct meson_drm *drv; //point to struct parent.
        struct dentry *plane_debugfs_dir;
        int plane_index;
+       struct drm_property *prop_premult_en;
 };
 
 #define to_am_osd_plane(x) container_of(x, \
index 83caebe..af3262c 100644 (file)
@@ -256,11 +256,9 @@ static struct osd_device_data_s osd_tm2 = {
        .osd0_sc_independ = 1,
 };
 struct osd_device_data_s osd_meson_dev;
-static u32 logo_memsize;
-static struct page *logo_page;
-static struct delayed_work osd_dwork;
 static struct platform_device *gp_dev;
 static unsigned long gem_mem_start, gem_mem_size;
+struct am_meson_logo logo;
 
 int am_meson_crtc_dts_info_set(const void *dt_match_data)
 {
@@ -337,6 +335,28 @@ char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode)
        return NULL;
 }
 
+bool am_meson_crtc_check_mode(struct drm_display_mode *mode, char *outputmode)
+{
+       int i;
+
+       if (!mode || !outputmode)
+               return false;
+       if (!strcmp(mode->name, "panel"))
+               return true;
+
+       for (i = 0; i < ARRAY_SIZE(am_vout_modes); i++) {
+               if (!strcmp(am_vout_modes[i].name, outputmode) &&
+                   am_vout_modes[i].width == mode->hdisplay &&
+                   am_vout_modes[i].height == mode->vdisplay &&
+                   am_vout_modes[i].vrefresh == mode->vrefresh &&
+                   am_vout_modes[i].flags ==
+                   (mode->flags & DRM_MODE_FLAG_INTERLACE)) {
+                       return true;
+               }
+       }
+       return false;
+}
+
 void am_meson_crtc_handle_vsync(struct am_meson_crtc *amcrtc)
 {
        unsigned long flags;
@@ -371,18 +391,26 @@ static irqreturn_t am_meson_vpu_irq(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
-static void mem_free_work(struct work_struct *work)
+static int am_meson_logo_info_update(struct meson_drm *priv)
 {
-       if (logo_memsize > 0) {
-#ifdef CONFIG_CMA
-               pr_info("%s, free memory: addr:0x%x\n",
-                       __func__, logo_memsize);
-
-               dma_release_from_contiguous(&gp_dev->dev,
-                                           logo_page,
-                       logo_memsize >> PAGE_SHIFT);
-#endif
+       logo.start = page_to_phys(logo.logo_page);
+       logo.alloc_flag = 1;
+       /*config 1080p logo as default*/
+       if (!logo.width || !logo.height) {
+               logo.width = 1920;
+               logo.height = 1080;
+       }
+       if (!logo.bpp)
+               logo.bpp = 16;
+       if (!logo.outputmode_t) {
+               strcpy(logo.outputmode, "1080p60hz");
+       } else {
+               strncpy(logo.outputmode, logo.outputmode_t, VMODE_NAME_LEN_MAX);
+               logo.outputmode[VMODE_NAME_LEN_MAX - 1] = '\0';
        }
+       priv->logo = &logo;
+
+       return 0;
 }
 
 static int am_meson_vpu_bind(struct device *dev,
@@ -399,7 +427,7 @@ static int am_meson_vpu_bind(struct device *dev,
        int ret, irq;
 
        /* Allocate crtc struct */
-       pr_info("[%s] in\n", __func__);
+       DRM_INFO("[%s] in\n", __func__);
        amcrtc = devm_kzalloc(dev, sizeof(*amcrtc),
                              GFP_KERNEL);
        if (!amcrtc)
@@ -415,41 +443,46 @@ static int am_meson_vpu_bind(struct device *dev,
        ret = of_reserved_mem_device_init(&pdev->dev);
        if (ret != 0) {
                dev_err(dev, "failed to init reserved memory\n");
+       } else {
 #ifdef CONFIG_CMA
                gp_dev = pdev;
                cma = dev_get_cma_area(&pdev->dev);
                if (cma) {
-                       logo_memsize = cma_get_size(cma);
-                       pr_info("reserved memory base:0x%x, size:0x%x\n",
-                               (u32)cma_get_base(cma), logo_memsize);
-                       if (logo_memsize > 0) {
-                               logo_page =
+                       logo.size = cma_get_size(cma);
+                       DRM_INFO("reserved memory base:0x%x, size:0x%x\n",
+                                (u32)cma_get_base(cma), logo.size);
+                       if (logo.size > 0) {
+                               logo.logo_page =
                                dma_alloc_from_contiguous(&pdev->dev,
-                                                         logo_memsize >>
+                                                         logo.size >>
                                                          PAGE_SHIFT,
                                                          0);
-                               if (!logo_page) {
-                                       pr_err("allocate buffer failed:%d\n",
-                                              logo_memsize);
-                               }
+                               if (!logo.logo_page)
+                                       DRM_INFO("allocate buffer failed\n");
+                               else
+                                       am_meson_logo_info_update(private);
                        }
                } else {
-                       pr_info("------ NO CMA\n");
+                       DRM_INFO("------ NO CMA\n");
                }
 #endif
-       } else {
-               dma_declare_coherent_memory(drm_dev->dev, gem_mem_start,
-                                           gem_mem_start, gem_mem_size,
-                                           DMA_MEMORY_EXCLUSIVE);
-               pr_info("meson drm mem_start = 0x%x, size = 0x%x\n",
-                       (u32)gem_mem_start, (u32)gem_mem_size);
+               if (gem_mem_start) {
+                       dma_declare_coherent_memory(drm_dev->dev,
+                                                   gem_mem_start,
+                                                   gem_mem_start,
+                                                   gem_mem_size,
+                                                   DMA_MEMORY_EXCLUSIVE);
+                       pr_info("meson drm mem_start = 0x%x, size = 0x%x\n",
+                               (u32)gem_mem_start, (u32)gem_mem_size);
+               } else {
+                       DRM_INFO("------ NO reserved dma\n");
+               }
        }
 
        ret = am_meson_plane_create(private);
        if (ret)
                return ret;
-
-       ret = am_meson_crtc_create(amcrtc);
+       ret = am_meson_crtc_create(amcrtc, &osd_meson_dev);
        if (ret)
                return ret;
 
@@ -475,9 +508,7 @@ static int am_meson_vpu_bind(struct device *dev,
        /* IRQ is initially disabled; it gets enabled in crtc_enable */
        disable_irq(amcrtc->irq);
 
-       INIT_DELAYED_WORK(&osd_dwork, mem_free_work);
-       schedule_delayed_work(&osd_dwork, msecs_to_jiffies(60 * 1000));
-       pr_info("[%s] out\n", __func__);
+       DRM_INFO("[%s] out\n", __func__);
        return 0;
 }
 
index e288a33..594fa34 100644 (file)
@@ -31,7 +31,7 @@ struct am_vout_mode {
        unsigned int flags;
 };
 
-extern struct osd_device_data_s osd_meson_dev;
 char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode);
+bool am_meson_crtc_check_mode(struct drm_display_mode *mode, char *outputmode);
 
 #endif /* __AM_MESON_VPU_H */
index bb1d72c..e5a380c 100644 (file)
@@ -345,6 +345,7 @@ void vpu_pipeline_init(struct meson_vpu_pipeline *pipeline)
 
        VPU_PIPELINE_HW_INIT(&pipeline->postblend->base);
 }
+EXPORT_SYMBOL(vpu_pipeline_init);
 
 /* maybe use graph traverse is a good choice */
 int vpu_pipeline_update(struct meson_vpu_pipeline *pipeline,
index 8b26bbd..2ce8d9f 100644 (file)
@@ -39,7 +39,7 @@
 #define MESON_BLOCK_MAX_NAME_LEN 32
 /*ratio base for scaler calc;maybe need bigger than 1000*/
 #define RATIO_BASE 1000
-#define MESON_OSD_INPUT_W_LIMIT 1920
+#define MESON_OSD_INPUT_W_LIMIT 3840
 
 #define MAX_DIN_NUM 4
 #define MAX_DOUT_NUM 2
@@ -169,6 +169,7 @@ struct meson_vpu_osd_layer_info {
        u32 afbc_inter_format;
        u32 afbc_en;
        u32 fb_size;
+       u32 premult_en;
 };
 
 struct meson_vpu_osd {
@@ -205,6 +206,7 @@ struct meson_vpu_osd_state {
        int r_mode;
        u32 plane_index;
        u32 fb_size;
+       u32 premult_en;
 };
 
 struct meson_vpu_afbc {
index 9ad172c..1a97940 100644 (file)
@@ -128,18 +128,3 @@ int meson_drm_clr_reg_mask(u32 addr, u32 mask)
        return 0;
 }
 #endif
-
-/** canvas config  **/
-
-void meson_drm_canvas_config(u32 index, unsigned long addr, u32 width,
-                            u32 height, u32 wrap, u32 blkmode)
-{
-       canvas_config(index, addr, width, height, wrap, blkmode);
-}
-
-int meson_drm_canvas_pool_alloc_table(const char *owner, u32 *table, int size,
-                                     enum canvas_map_type_e type)
-{
-       return canvas_pool_alloc_canvas_table(owner, table, size, type);
-}
-
index 96c2579..c70fcd7 100644 (file)
@@ -80,6 +80,34 @@ static unsigned int __osd_filter_coefs_bicubic[] = { /* bicubic      coef0 */
        0xf84d42f9, 0xf84a45f9, 0xf84848f8
 };
 
+static unsigned int __osd_filter_coefs_2point_binilear[] = {
+       /* 2 point bilinear, bank_length == 2   coef2 */
+       0x80000000, 0x7e020000, 0x7c040000, 0x7a060000, 0x78080000, 0x760a0000,
+       0x740c0000, 0x720e0000, 0x70100000, 0x6e120000, 0x6c140000, 0x6a160000,
+       0x68180000, 0x661a0000, 0x641c0000, 0x621e0000, 0x60200000, 0x5e220000,
+       0x5c240000, 0x5a260000, 0x58280000, 0x562a0000, 0x542c0000, 0x522e0000,
+       0x50300000, 0x4e320000, 0x4c340000, 0x4a360000, 0x48380000, 0x463a0000,
+       0x443c0000, 0x423e0000, 0x40400000
+};
+
+static unsigned int __osd_filter_coefs_4point_triangle[] = {
+       0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101,
+       0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303,
+       0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505,
+       0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707,
+       0x18382808, 0x18382808, 0x17372909, 0x17372909,
+       0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b,
+       0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d,
+       0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f,
+       0x10303010
+};
+
+static unsigned int *osd_scaler_filter_table[] = {
+       __osd_filter_coefs_bicubic,
+       __osd_filter_coefs_2point_binilear,
+       __osd_filter_coefs_4point_triangle
+};
+
 /*********vsc config begin**********/
 /*vsc phase_step=(v_in << 20)/v_out */
 void osd_vsc_phase_step_set(struct osd_scaler_reg_s *reg, u32 phase_step)
@@ -309,7 +337,7 @@ void osd_sc_out_vert_set(struct osd_scaler_reg_s *reg, u32 start, u32 end)
  *1:config horizontal coef
  *0:config vertical coef
  */
-void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag)
+void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag, u32 *coef)
 {
        u8 i;
 
@@ -320,8 +348,7 @@ void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag)
                (flag << 8) |
                (0 << 0)/*coef index 7bits*/);
        for (i = 0; i < 33; i++)
-               VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef,
-                       __osd_filter_coefs_bicubic[i]);
+               VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef, coef[i]);
 }
 /*********sc top ctrl end************/
 static void f2v_get_vertical_phase(
@@ -381,6 +408,8 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg,
        u32 width_out = scaler_state->output_width;
        u32 height_out = scaler_state->output_height;
        u32 scan_mode_out = scaler_state->scan_mode_out;
+       u32 vsc_double_line_mode;
+       u32 *coef_h, *coef_v;
        bool scaler_enable;
 
        if (width_in == width_out && height_in == height_out &&
@@ -389,10 +418,13 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg,
        else
                scaler_enable = true;
 
-       if (width_out > linebuffer)
+       if (width_in > linebuffer) {
                vsc_bank_length = bank_length >> 1;
-       else
+               vsc_double_line_mode = 1;
+       } else {
                vsc_bank_length = bank_length;
+               vsc_double_line_mode = 0;
+       }
        hsc_init_rec_num = bank_length;
        hsc_bank_length = bank_length;
        hsc_init_rpt_p0_num = bank_length / 2 - 1;
@@ -432,6 +464,17 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg,
        phase_step_v <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_HEIGHT_BITS);
        phase_step_h = (width_in << OSD_ZOOM_WIDTH_BITS) / width_out;
        phase_step_h <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_WIDTH_BITS);
+       /*check coef*/
+       if (scan_mode_out && width_out <= 720) {
+               coef_h = osd_scaler_filter_table[COEFS_4POINT_TRIANGLE];
+               coef_v = osd_scaler_filter_table[COEFS_4POINT_TRIANGLE];
+       } else if (vsc_double_line_mode == 1) {
+               coef_h = osd_scaler_filter_table[COEFS_BICUBIC];
+               coef_v = osd_scaler_filter_table[COEFS_2POINT_BINILEAR];
+       } else {
+               coef_h = osd_scaler_filter_table[COEFS_BICUBIC];
+               coef_v = osd_scaler_filter_table[COEFS_BICUBIC];
+       }
 
        /*input size config*/
        osd_sc_in_h_set(reg, height_in);
@@ -449,13 +492,14 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg,
        osd_sc_dummy_data_set(reg, 0x80808080);
 
        /*h/v coef config*/
-       osd_sc_coef_set(reg, 1);
-       osd_sc_coef_set(reg, 0);
+       osd_sc_coef_set(reg, OSD_SCALER_COEFF_H, coef_h);
+       osd_sc_coef_set(reg, OSD_SCALER_COEFF_V, coef_v);
 
        /*init recv line num*/
        osd_vsc_top_ini_rcv_num_set(reg, vsc_top_init_rec_num);
        osd_vsc_bot_ini_rcv_num_set(reg, vsc_bot_init_rec_num);
        osd_hsc_ini_rcv_num0_set(reg, hsc_init_rec_num);
+       osd_vsc_double_line_mode_set(reg, vsc_double_line_mode);
 
        /*repeate line0 num*/
        osd_vsc_top_rpt_l0_num_set(reg, vsc_top_rpt_l0_num);
@@ -650,9 +694,6 @@ static void scaler_hw_init(struct meson_vpu_block *vblk)
        scaler->reg = &osd_scaler_reg[vblk->index];
        scaler->linebuffer = OSD_SCALE_LINEBUFFER;
        scaler->bank_length = OSD_SCALE_BANK_LENGTH;
-       /*disable sc*/
-       osd_sc_en_set(scaler->reg, 0);
-       osd_sc_path_en_set(scaler->reg, 0);
        DRM_DEBUG("%s hw_init called.\n", scaler->base.name);
 }
 
index 34ebb03..91b3d73 100644 (file)
 #define OSD_ZOOM_TOTAL_BITS 24
 #define OSD_PHASE_BITS 16
 
+#define OSD_SCALER_COEFF_H 1
+#define OSD_SCALER_COEFF_V 0
+
+enum scaler_coef_e {
+       COEFS_BICUBIC = 0,
+       COEFS_2POINT_BINILEAR,
+       COEFS_4POINT_TRIANGLE
+};
+
 enum f2v_vphase_type_e {
        F2V_IT2IT = 0,
        F2V_IB2IB,
index 487dfe0..473ba6b 100644 (file)
@@ -227,9 +227,22 @@ void osd_block_enable(struct osd_mif_reg_s *reg, bool flag)
        VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_ctrl_stat, flag, 0, 1);
 }
 
+/*osd alpha_div en
+ *if input is premult,alpha_div=1,else alpha_div=0
+ */
+void osd_alpha_div_enable(struct osd_mif_reg_s *reg, bool flag)
+{
+       VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_mali_unpack_ctrl, flag, 28, 1);
+}
+
 /*osd ctrl config*/
-void osd_ctrl_set(struct osd_mif_reg_s *reg)
+void osd_ctrl_set(struct osd_mif_reg_s *reg, u32 osd_idx, u32 canvas_index)
 {
+       u32 enable = 1;
+
+       if (osd_idx > OSD2)
+               enable = 0;
+
        VSYNCOSD_WR_MPEG_REG(reg->viu_osd_ctrl_stat,
                             (0 << 31) |/*osd_cfg_sync_en*/
                             (0 << 30) |/*Enable free_clk*/
@@ -237,7 +250,8 @@ void osd_ctrl_set(struct osd_mif_reg_s *reg)
                             (0 << 11) |/*TEST_RD_EN*/
                             (0 << 2) |/*osd_mem_mode 0:canvas_addr*/
                             (0 << 1) |/*premult_en*/
-                            (0 << 0)/*OSD_BLK_ENABLE*/);
+                            (enable << 0)/*OSD_BLK_ENABLE*/
+                            );
        VSYNCOSD_WR_MPEG_REG(reg->viu_osd_ctrl_stat2,
                             (1 << 14) |/*replaced_alpha_en*/
                             (0xff << 6) |/*replaced_alpha*/
@@ -268,7 +282,7 @@ void osd_ctrl_set(struct osd_mif_reg_s *reg)
                             (0 << 30) |/*read from ddr[0]/afbc[1]*/
                             (0 << 29) |/*y reverse disable*/
                             (0 << 28) |/*x reverse disable*/
-                            (osd_canvas[0][0] << 16) |/*canvas index*/
+                            (canvas_index << 16) |
                             (1 << 15) |/*little endian in ddr*/
                             (0 << 14) |/*no repeat display y pre line*/
                             (0 << 12) |/*no interpolation per pixel*/
@@ -277,12 +291,6 @@ void osd_ctrl_set(struct osd_mif_reg_s *reg)
                             (1 << 2) |/*ARGB format for 32bit mode*/
                             (0 << 1) |/*interlace en*/
                             (0 << 0)/*output odd/even lines sel*/);
-       VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w1,
-                            (1919 << 16) |/*x_end pixels[13bits]*/
-                            (0 << 0)/*x_start pixels[13bits]*/);
-       VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w2,
-                            (1079 << 16) |/*y_end pixels[13bits]*/
-                            (0 << 0)/*y_start pixels[13bits]*/);
        /*frame addr in linear addr*/
        VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk1_cfg_w4, 0);
        /*line_stride in linear addr*/
@@ -354,6 +362,7 @@ static int osd_check_state(struct meson_vpu_block *vblk,
        mvos->phy_addr = plane_info->phy_addr;
        mvos->pixel_format = plane_info->pixel_format;
        mvos->fb_size = plane_info->fb_size;
+       mvos->premult_en = plane_info->premult_en;
        return 0;
 }
 
@@ -371,6 +380,7 @@ static void osd_set_state(struct meson_vpu_block *vblk,
        u32 pixel_format, canvas_index, src_h, byte_stride, phy_addr;
        struct osd_scope_s scope_src = {0, 1919, 0, 1079};
        struct osd_mif_reg_s *reg = osd->reg;
+       bool alpha_div_en;
 
        crtc = vblk->pipeline->crtc;
        amc = to_am_meson_crtc(crtc);
@@ -379,6 +389,7 @@ static void osd_set_state(struct meson_vpu_block *vblk,
                DRM_DEBUG("set_state break for NULL.\n");
                return;
        }
+       alpha_div_en = mvos->premult_en ? 1 : 0;
        src_h = mvos->src_h;
        byte_stride = mvos->byte_stride;
        phy_addr = mvos->phy_addr;
@@ -388,12 +399,14 @@ static void osd_set_state(struct meson_vpu_block *vblk,
        scope_src.v_end = mvos->src_y + mvos->src_h - 1;
        pixel_format = mvos->pixel_format;
        canvas_index = osd_canvas[vblk->index][osd_canvas_index[vblk->index]];
+       /*Toto: need to separate*/
+       osd_ctrl_set(osd->reg, vblk->index, canvas_index);
        canvas_config(canvas_index, phy_addr, byte_stride, src_h,
                CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
        osd_canvas_index[vblk->index] ^= 1;
-       osd_canvas_config(reg, canvas_index);
        osd_input_size_config(reg, scope_src);
        osd_color_config(reg, pixel_format);
+       osd_alpha_div_enable(reg, alpha_div_en);
        DRM_DEBUG("plane_index=%d,HW-OSD=%d\n",
                mvos->plane_index, vblk->index);
        DRM_DEBUG("canvas_index[%d]=0x%x,phy_addr=0x%x\n",
@@ -519,7 +532,6 @@ static void osd_hw_init(struct meson_vpu_block *vblk)
                return;
        }
        osd->reg = &osd_mif_reg[vblk->index];
-       osd_ctrl_set(osd->reg);
        DRM_DEBUG("%s hw_init done.\n", osd->base.name);
 }
 
index 8d9c190..0743321 100644 (file)
@@ -206,6 +206,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
        /* for compatibility root is always authenticated */
        priv->authenticated = capable(CAP_SYS_ADMIN);
        priv->lock_count = 0;
+       priv->drm_pid = task_tgid_nr(current);
 
        INIT_LIST_HEAD(&priv->lhead);
        INIT_LIST_HEAD(&priv->fbs);
index 0c4f9c6..72542c3 100644 (file)
@@ -431,6 +431,7 @@ struct drm_file {
 
        struct mutex event_read_lock;
 
+       pid_t drm_pid;
        struct drm_prime_file_private prime;
 };
 
index 5b12674..cb1d54a 100644 (file)
 #ifndef _MESON_DRM_H
 #define _MESON_DRM_H
 
-#include <drm/drm.h>
+#include "drm.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
 
 /* Use flags */
 #define MESON_USE_NONE                 0
 #define MESON_USE_CAMERA_WRITE         (1ull << 13)
 #define MESON_USE_CAMERA_READ          (1ull << 14)
 #define MESON_USE_TEXTURE                      (1ull << 17)
+#define MESON_USE_RENDER_VIP           (1ull << 18)
+#define MESON_USE_OVERLAY              (1ull << 19)
 
+/* For Buffer synchronization using dma-buf fence */
+#define MESON_GEM_CPU_PREP_READ                (1 << 0)
+#define MESON_GEM_CPU_PREP_WRITE               (1 << 1)
+#define MESON_GEM_CPU_PREP_NOWAIT      (1 << 2)
 
 /**
  * User-desired buffer creation information structure.
@@ -41,9 +51,57 @@ struct drm_meson_gem_create {
        __u32 handle;
 };
 
+/**
+ * A structure to gem information.
+ *
+ * @handle: a handle to gem object created.
+ * @flags: flag value including memory type and cache attribute and
+ *      this value would be set by driver.
+ * @size: size to memory region allocated by gem and this size would
+ *      be set by driver.
+ */
+struct drm_meson_gem_info {
+        uint32_t handle;
+        uint32_t flags;
+        uint64_t size;
+};
+
+struct drm_meson_plane_blank {
+       uint32_t plane_type;
+       uint32_t onoff;
+};
+
+struct drm_meson_gem_sync {
+       uint32_t handle;
+};
+
+struct drm_meson_gem_cpu_access {
+       uint32_t handle;
+       uint32_t flags;
+};
+
 #define DRM_MESON_GEM_CREATE           0x00
+#define DRM_MESON_GEM_GET              0x01
+#define DRM_MESON_SET_BLANK            0x02
+#define DRM_MESON_GEM_SYNC             0x03
+#define DRM_MESON_GEM_CPU_PREP 0x04
+#define DRM_MESON_GEM_CPU_FINI 0x05
 
 #define DRM_IOCTL_MESON_GEM_CREATE             DRM_IOWR(DRM_COMMAND_BASE + \
                DRM_MESON_GEM_CREATE, struct drm_meson_gem_create)
+#define DRM_IOCTL_MESON_GEM_GET                        DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_MESON_GEM_GET, struct drm_meson_gem_info)
+#define DRM_IOCTL_MESON_SET_BLANK                      DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_MESON_SET_BLANK, struct drm_meson_plane_blank)
+#define DRM_IOCTL_MESON_GEM_SYNC                       DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_MESON_GEM_SYNC, struct drm_meson_gem_sync)
+#define DRM_IOCTL_MESON_GEM_CPU_PREP           DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_MESON_GEM_CPU_PREP, struct drm_meson_gem_cpu_access)
+#define DRM_IOCTL_MESON_GEM_CPU_FINI           DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_MESON_GEM_CPU_FINI, struct drm_meson_gem_cpu_access)
+
+#if defined(__cplusplus)
+}
+#endif
 
 #endif /* _MESON_DRM_H */