From: Seung-Woo Kim Date: Mon, 12 Apr 2021 06:40:26 +0000 (+0900) Subject: amlogic: drm: support fence/cache op and gem_info X-Git-Tag: submit/tizen/20210602.005153~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F38%2F259138%2F1;p=platform%2Fkernel%2Flinux-amlogic.git amlogic: drm: support fence/cache op and gem_info Support fence operation, cache operation and geminfo in debugfs from amlogic meson drm. Change-Id: I0d7bc71c7d489e65c0c1051df21fc7b034c3af53 Signed-off-by: Seung-Woo Kim 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 Signed-off-by: Seung-Woo Kim --- diff --git a/drivers/amlogic/drm/Makefile b/drivers/amlogic/drm/Makefile index 022ca0b8385d..2159b3ae02ca 100644 --- a/drivers/amlogic/drm/Makefile +++ b/drivers/amlogic/drm/Makefile @@ -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 \ diff --git a/drivers/amlogic/drm/meson_crtc.c b/drivers/amlogic/drm/meson_crtc.c index 05e79bdd97a2..444155ebd0af 100644 --- a/drivers/amlogic/drm/meson_crtc.c +++ b/drivers/amlogic/drm/meson_crtc.c @@ -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); diff --git a/drivers/amlogic/drm/meson_crtc.h b/drivers/amlogic/drm/meson_crtc.h index 7370177015c8..82f4483f4ba0 100644 --- a/drivers/amlogic/drm/meson_crtc.h +++ b/drivers/amlogic/drm/meson_crtc.h @@ -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 diff --git a/drivers/amlogic/drm/meson_debugfs.c b/drivers/amlogic/drm/meson_debugfs.c index ff9eea878463..8eb3e52fb3a3 100644 --- a/drivers/amlogic/drm/meson_debugfs.c +++ b/drivers/amlogic/drm/meson_debugfs.c @@ -18,7 +18,11 @@ #ifdef CONFIG_DEBUG_FS #include #include -#endif + +#include +#include + +#endif /* CONFIG_DEBUG_FS */ #include "meson_drv.h" #include "meson_crtc.h" @@ -26,6 +30,11 @@ #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 */ diff --git a/drivers/amlogic/drm/meson_drv.c b/drivers/amlogic/drm/meson_drv.c index f94d45baab59..ae1f242e0583 100644 --- a/drivers/amlogic/drm/meson_drv.c +++ b/drivers/amlogic/drm/meson_drv.c @@ -34,14 +34,16 @@ #include #include +#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); } diff --git a/drivers/amlogic/drm/meson_drv.h b/drivers/amlogic/drm/meson_drv.h index 4260a3ca00fa..7047b674769d 100644 --- a/drivers/amlogic/drm/meson_drv.h +++ b/drivers/amlogic/drm/meson_drv.h @@ -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); diff --git a/drivers/amlogic/drm/meson_fb.c b/drivers/amlogic/drm/meson_fb.c index 1c364da4bf3e..359ed1f0416b 100644 --- a/drivers/amlogic/drm/meson_fb.c +++ b/drivers/amlogic/drm/meson_fb.c @@ -18,8 +18,7 @@ #include #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; } diff --git a/drivers/amlogic/drm/meson_fb.h b/drivers/amlogic/drm/meson_fb.h index 9c76d2e71f26..0226ee765899 100644 --- a/drivers/amlogic/drm/meson_fb.h +++ b/drivers/amlogic/drm/meson_fb.h @@ -24,16 +24,40 @@ #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 index 000000000000..f1f30f61bf27 --- /dev/null +++ b/drivers/amlogic/drm/meson_fence.c @@ -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 index 000000000000..c6fa5383d563 --- /dev/null +++ b/drivers/amlogic/drm/meson_fence.h @@ -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 +#include +#include + +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__ */ + diff --git a/drivers/amlogic/drm/meson_gem.c b/drivers/amlogic/drm/meson_gem.c index 7c472e3514a6..6864ed4c2fbd 100644 --- a/drivers/amlogic/drm/meson_gem.c +++ b/drivers/amlogic/drm/meson_gem.c @@ -22,10 +22,11 @@ #include #include #include -#include +#include #include #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) { diff --git a/drivers/amlogic/drm/meson_gem.h b/drivers/amlogic/drm/meson_gem.h index cab22a5db073..1c59f9fde7bc 100644 --- a/drivers/amlogic/drm/meson_gem.h +++ b/drivers/amlogic/drm/meson_gem.h @@ -20,9 +20,15 @@ #include #include #include +#include #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); diff --git a/drivers/amlogic/drm/meson_hdmi.c b/drivers/amlogic/drm/meson_hdmi.c index e5f0ce60eae3..7cbe8c165c5d 100644 --- a/drivers/amlogic/drm/meson_hdmi.c +++ b/drivers/amlogic/drm/meson_hdmi.c @@ -35,17 +35,11 @@ #include #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); } diff --git a/drivers/amlogic/drm/meson_lcd.c b/drivers/amlogic/drm/meson_lcd.c index e9c6f21e2f1e..029878e65190 100644 --- a/drivers/amlogic/drm/meson_lcd.c +++ b/drivers/amlogic/drm/meson_lcd.c @@ -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; diff --git a/drivers/amlogic/drm/meson_plane.c b/drivers/amlogic/drm/meson_plane.c index 7a66a9cc1ee7..855e1905a488 100644 --- a/drivers/amlogic/drm/meson_plane.c +++ b/drivers/amlogic/drm/meson_plane.c @@ -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); diff --git a/drivers/amlogic/drm/meson_plane.h b/drivers/amlogic/drm/meson_plane.h index a1e6f4b13cb8..5be8adc5dab0 100644 --- a/drivers/amlogic/drm/meson_plane.h +++ b/drivers/amlogic/drm/meson_plane.h @@ -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, \ diff --git a/drivers/amlogic/drm/meson_vpu.c b/drivers/amlogic/drm/meson_vpu.c index 83caebeda919..af3262c41c7e 100644 --- a/drivers/amlogic/drm/meson_vpu.c +++ b/drivers/amlogic/drm/meson_vpu.c @@ -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; } diff --git a/drivers/amlogic/drm/meson_vpu.h b/drivers/amlogic/drm/meson_vpu.h index e288a33be97d..594fa34dda21 100644 --- a/drivers/amlogic/drm/meson_vpu.h +++ b/drivers/amlogic/drm/meson_vpu.h @@ -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 */ diff --git a/drivers/amlogic/drm/meson_vpu_pipeline.c b/drivers/amlogic/drm/meson_vpu_pipeline.c index bb1d72cae9e3..e5a380c8f3ea 100644 --- a/drivers/amlogic/drm/meson_vpu_pipeline.c +++ b/drivers/amlogic/drm/meson_vpu_pipeline.c @@ -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, diff --git a/drivers/amlogic/drm/meson_vpu_pipeline.h b/drivers/amlogic/drm/meson_vpu_pipeline.h index 8b26bbd5db23..2ce8d9f2215f 100644 --- a/drivers/amlogic/drm/meson_vpu_pipeline.h +++ b/drivers/amlogic/drm/meson_vpu_pipeline.h @@ -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 { diff --git a/drivers/amlogic/drm/meson_vpu_util.c b/drivers/amlogic/drm/meson_vpu_util.c index 9ad172cc175f..1a97940c11b0 100644 --- a/drivers/amlogic/drm/meson_vpu_util.c +++ b/drivers/amlogic/drm/meson_vpu_util.c @@ -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); -} - diff --git a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c index 96c2579e4c78..c70fcd7693fb 100644 --- a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c +++ b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c @@ -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); } diff --git a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h index 34ebb03906ee..91b3d730a669 100644 --- a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h +++ b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h @@ -79,6 +79,15 @@ #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, diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c index 487dfe088ede..473ba6bb657c 100644 --- a/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c +++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c @@ -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); } diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 8d9c1905be00..074332102123 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -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); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 0c4f9c67c221..72542c36f409 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -431,6 +431,7 @@ struct drm_file { struct mutex event_read_lock; + pid_t drm_pid; struct drm_prime_file_private prime; }; diff --git a/include/uapi/drm/meson_drm.h b/include/uapi/drm/meson_drm.h index 5b12674b9a0b..cb1d54a92933 100644 --- a/include/uapi/drm/meson_drm.h +++ b/include/uapi/drm/meson_drm.h @@ -12,7 +12,11 @@ #ifndef _MESON_DRM_H #define _MESON_DRM_H -#include +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif /* Use flags */ #define MESON_USE_NONE 0 @@ -25,7 +29,13 @@ #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 */