Merge tag 'drm-misc-next-2018-11-28' of git://anongit.freedesktop.org/drm/drm-misc...
authorDave Airlie <airlied@redhat.com>
Thu, 29 Nov 2018 00:21:23 +0000 (10:21 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 29 Nov 2018 00:28:49 +0000 (10:28 +1000)
drm-misc-next for v4.21:

Core Changes:
- Merge drm_info.c into drm_debugfs.c
- Complete the fake drm_crtc_commit's hw_done/flip_done sooner.
- Remove deprecated drm_obj_ref/unref functions. All drivers use get/put now.
- Decrease stack use of drm_gem_prime_mmap.
- Improve documentation for dumb callbacks.

Driver Changes:
- Add edid support to virtio.
- Wait on implicit fence in meson and sun4i.
- Add support for BGRX8888 to sun4i.
- Preparation patches for sun4i driver to start supporting linear and tiled YUV formats.
- Add support for HDMI 1.4 4k modes to meson, and support for VIC alternate timings.
- Drop custom dumb_map in vkms.
- Small fixes and cleanups to v3d.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/151a3270-b1be-ed75-bd58-6b29d741f592@linux.intel.com
45 files changed:
Documentation/gpu/todo.rst
drivers/gpu/drm/Makefile
drivers/gpu/drm/arc/arcpgu_drv.c
drivers/gpu/drm/bridge/tc358764.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_info.c [deleted file]
drivers/gpu/drm/drm_internal.h
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/etnaviv/etnaviv_drv.c
drivers/gpu/drm/meson/meson_dw_hdmi.c
drivers/gpu/drm/meson/meson_overlay.c
drivers/gpu/drm/meson/meson_plane.c
drivers/gpu/drm/meson/meson_vclk.c
drivers/gpu/drm/meson/meson_vclk.h
drivers/gpu/drm/meson/meson_venc.c
drivers/gpu/drm/mxsfb/mxsfb_drv.c
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_backend.h
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/sun4i/sun4i_frontend.c
drivers/gpu/drm/sun4i/sun4i_frontend.h
drivers/gpu/drm/sun4i/sun4i_layer.c
drivers/gpu/drm/sun4i/sun8i_ui_layer.c
drivers/gpu/drm/sun4i/sun8i_vi_layer.c
drivers/gpu/drm/tve200/tve200_drv.c
drivers/gpu/drm/v3d/v3d_gem.c
drivers/gpu/drm/v3d/v3d_sched.c
drivers/gpu/drm/virtio/virtgpu_display.c
drivers/gpu/drm/virtio/virtgpu_drv.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_kms.c
drivers/gpu/drm/virtio/virtgpu_vq.c
drivers/gpu/drm/vkms/vkms_drv.c
drivers/gpu/drm/vkms/vkms_drv.h
drivers/gpu/drm/vkms/vkms_gem.c
drivers/staging/vboxvideo/vbox_drv.c
include/drm/drm_connector.h
include/drm/drm_drv.h
include/drm/drm_framebuffer.h
include/drm/drm_gem.h
include/uapi/drm/v3d_drm.h
include/uapi/linux/virtio_gpu.h
scripts/coccinelle/api/drm-get-put.cocci [deleted file]

index 31ef4adc91c97a86bb019eb05968137c504ac591..ab347dec507960ae696d026fe2ce4a2cc88a0cc9 100644 (file)
@@ -28,22 +28,16 @@ them, but also all the virtual ones used by KVM, so everyone qualifies).
 
 Contact: Daniel Vetter, Thierry Reding, respective driver maintainers
 
-Switch from reference/unreference to get/put
---------------------------------------------
-
-For some reason DRM core uses ``reference``/``unreference`` suffixes for
-refcounting functions, but kernel uses ``get``/``put`` (e.g.
-``kref_get``/``put()``). It would be good to switch over for consistency, and
-it's shorter. Needs to be done in 3 steps for each pair of functions:
 
-* Create new ``get``/``put`` functions, define the old names as compatibility
-  wrappers
-* Switch over each file/driver using a cocci-generated spatch.
-* Once all users of the old names are gone, remove them.
+Remove custom dumb_map_offset implementations
+---------------------------------------------
 
-This way drivers/patches in the progress of getting merged won't break.
+All GEM based drivers should be using drm_gem_create_mmap_offset() instead.
+Audit each individual driver, make sure it'll work with the generic
+implementation (there's lots of outdated locking leftovers in various
+implementations), and then remove it.
 
-Contact: Daniel Vetter
+Contact: Daniel Vetter, respective driver maintainers
 
 Convert existing KMS drivers to atomic modesetting
 --------------------------------------------------
index 7f3be3506057af368c84a6584b298930166c49c3..1fafc2f8e8f9cd13f8d1ef6bc651941d19de594c 100644 (file)
@@ -10,7 +10,7 @@ drm-y       :=        drm_auth.o drm_bufs.o drm_cache.o \
                drm_scatter.o drm_pci.o \
                drm_sysfs.o drm_hashtab.o drm_mm.o \
                drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \
-               drm_info.o drm_encoder_slave.o \
+               drm_encoder_slave.o \
                drm_trace_points.o drm_prime.o \
                drm_rect.o drm_vma_manager.o drm_flip_work.o \
                drm_modeset_lock.o drm_atomic.o drm_bridge.o \
index 2af847ebca3404d6a3e4adeb9c19d3e27cd066f4..206a76abf77133f0e56ac668041ada8b9ea9859b 100644 (file)
@@ -190,7 +190,7 @@ err_unload:
        arcpgu_unload(drm);
 
 err_unref:
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
 
        return ret;
 }
@@ -201,7 +201,7 @@ static int arcpgu_remove(struct platform_device *pdev)
 
        drm_dev_unregister(drm);
        arcpgu_unload(drm);
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
 
        return 0;
 }
index ee6b98efa9c221015cd7cefb9cd3384dfa9efd16..afd491018bfc55817511ea1d7db9e6fc5f19a99b 100644 (file)
@@ -379,7 +379,7 @@ static void tc358764_detach(struct drm_bridge *bridge)
        drm_fb_helper_remove_one_connector(drm->fb_helper, &ctx->connector);
        drm_panel_detach(ctx->panel);
        ctx->panel = NULL;
-       drm_connector_unreference(&ctx->connector);
+       drm_connector_put(&ctx->connector);
 }
 
 static const struct drm_bridge_funcs tc358764_bridge_funcs = {
index fa95f9974f6d071a8c1929b38be6ba70d8f7cd14..bc9fc9665614f0904f6184be66903d71f93ff9dc 100644 (file)
@@ -1460,6 +1460,9 @@ void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev,
                        DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n",
                                  crtc->base.id, crtc->name);
        }
+
+       if (old_state->fake_commit)
+               complete_all(&old_state->fake_commit->flip_done);
 }
 EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done);
 
@@ -2217,8 +2220,10 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state)
                spin_unlock(&crtc->commit_lock);
        }
 
-       if (old_state->fake_commit)
+       if (old_state->fake_commit) {
                complete_all(&old_state->fake_commit->cleanup_done);
+               WARN_ON(!try_wait_for_completion(&old_state->fake_commit->hw_done));
+       }
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_cleanup_done);
 
index 373bd4c2b698ba1ebcb3b4572cb6c84b3ce448fe..f8468eae05033f7c90242e2203eaacc306fe37ff 100644 (file)
@@ -32,6 +32,8 @@
 #include <drm/drm_debugfs.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_atomic.h>
+#include <drm/drm_auth.h>
+#include <drm/drm_gem.h>
 #include <drm/drmP.h>
 
 #include "drm_internal.h"
  * Initialization, etc.
  **************************************************/
 
+static int drm_name_info(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_minor *minor = node->minor;
+       struct drm_device *dev = minor->dev;
+       struct drm_master *master;
+
+       mutex_lock(&dev->master_mutex);
+       master = dev->master;
+       seq_printf(m, "%s", dev->driver->name);
+       if (dev->dev)
+               seq_printf(m, " dev=%s", dev_name(dev->dev));
+       if (master && master->unique)
+               seq_printf(m, " master=%s", master->unique);
+       if (dev->unique)
+               seq_printf(m, " unique=%s", dev->unique);
+       seq_printf(m, "\n");
+       mutex_unlock(&dev->master_mutex);
+
+       return 0;
+}
+
+static int drm_clients_info(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_file *priv;
+       kuid_t uid;
+
+       seq_printf(m,
+                  "%20s %5s %3s master a %5s %10s\n",
+                  "command",
+                  "pid",
+                  "dev",
+                  "uid",
+                  "magic");
+
+       /* dev->filelist is sorted youngest first, but we want to present
+        * oldest first (i.e. kernel, servers, clients), so walk backwardss.
+        */
+       mutex_lock(&dev->filelist_mutex);
+       list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
+               struct task_struct *task;
+
+               rcu_read_lock(); /* locks pid_task()->comm */
+               task = pid_task(priv->pid, PIDTYPE_PID);
+               uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID;
+               seq_printf(m, "%20s %5d %3d   %c    %c %5d %10u\n",
+                          task ? task->comm : "<unknown>",
+                          pid_vnr(priv->pid),
+                          priv->minor->index,
+                          drm_is_current_master(priv) ? 'y' : 'n',
+                          priv->authenticated ? 'y' : 'n',
+                          from_kuid_munged(seq_user_ns(m), uid),
+                          priv->magic);
+               rcu_read_unlock();
+       }
+       mutex_unlock(&dev->filelist_mutex);
+       return 0;
+}
+
+static int drm_gem_one_name_info(int id, void *ptr, void *data)
+{
+       struct drm_gem_object *obj = ptr;
+       struct seq_file *m = data;
+
+       seq_printf(m, "%6d %8zd %7d %8d\n",
+                  obj->name, obj->size,
+                  obj->handle_count,
+                  kref_read(&obj->refcount));
+       return 0;
+}
+
+static int drm_gem_name_info(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+
+       seq_printf(m, "  name     size handles refcount\n");
+
+       mutex_lock(&dev->object_name_lock);
+       idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m);
+       mutex_unlock(&dev->object_name_lock);
+
+       return 0;
+}
+
 static const struct drm_info_list drm_debugfs_list[] = {
        {"name", drm_name_info, 0},
        {"clients", drm_clients_info, 0},
index e2ffecd5e45379c80ed067c93b49215e78c25967..12e5e2be7890e39952947f85594675093f4e8eb9 100644 (file)
@@ -704,19 +704,6 @@ void drm_dev_put(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_dev_put);
 
-/**
- * drm_dev_unref - Drop reference of a DRM device
- * @dev: device to drop reference of or NULL
- *
- * This is a compatibility alias for drm_dev_put() and should not be used by new
- * code.
- */
-void drm_dev_unref(struct drm_device *dev)
-{
-       drm_dev_put(dev);
-}
-EXPORT_SYMBOL(drm_dev_unref);
-
 static int create_compat_control_link(struct drm_device *dev)
 {
        struct drm_minor *minor;
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
deleted file mode 100644 (file)
index 6b68e90..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * \file drm_info.c
- * DRM info file implementations
- *
- * \author Ben Gamari <bgamari@gmail.com>
- */
-
-/*
- * Created: Sun Dec 21 13:09:50 2008 by bgamari@gmail.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * Copyright 2008 Ben Gamari <bgamari@gmail.com>
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/seq_file.h>
-#include <drm/drmP.h>
-#include <drm/drm_gem.h>
-
-#include "drm_internal.h"
-#include "drm_legacy.h"
-
-/**
- * Called when "/proc/dri/.../name" is read.
- *
- * Prints the device name together with the bus id if available.
- */
-int drm_name_info(struct seq_file *m, void *data)
-{
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct drm_minor *minor = node->minor;
-       struct drm_device *dev = minor->dev;
-       struct drm_master *master;
-
-       mutex_lock(&dev->master_mutex);
-       master = dev->master;
-       seq_printf(m, "%s", dev->driver->name);
-       if (dev->dev)
-               seq_printf(m, " dev=%s", dev_name(dev->dev));
-       if (master && master->unique)
-               seq_printf(m, " master=%s", master->unique);
-       if (dev->unique)
-               seq_printf(m, " unique=%s", dev->unique);
-       seq_printf(m, "\n");
-       mutex_unlock(&dev->master_mutex);
-
-       return 0;
-}
-
-/**
- * Called when "/proc/dri/.../clients" is read.
- *
- */
-int drm_clients_info(struct seq_file *m, void *data)
-{
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct drm_device *dev = node->minor->dev;
-       struct drm_file *priv;
-       kuid_t uid;
-
-       seq_printf(m,
-                  "%20s %5s %3s master a %5s %10s\n",
-                  "command",
-                  "pid",
-                  "dev",
-                  "uid",
-                  "magic");
-
-       /* dev->filelist is sorted youngest first, but we want to present
-        * oldest first (i.e. kernel, servers, clients), so walk backwardss.
-        */
-       mutex_lock(&dev->filelist_mutex);
-       list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
-               struct task_struct *task;
-
-               rcu_read_lock(); /* locks pid_task()->comm */
-               task = pid_task(priv->pid, PIDTYPE_PID);
-               uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID;
-               seq_printf(m, "%20s %5d %3d   %c    %c %5d %10u\n",
-                          task ? task->comm : "<unknown>",
-                          pid_vnr(priv->pid),
-                          priv->minor->index,
-                          drm_is_current_master(priv) ? 'y' : 'n',
-                          priv->authenticated ? 'y' : 'n',
-                          from_kuid_munged(seq_user_ns(m), uid),
-                          priv->magic);
-               rcu_read_unlock();
-       }
-       mutex_unlock(&dev->filelist_mutex);
-       return 0;
-}
-
-static int drm_gem_one_name_info(int id, void *ptr, void *data)
-{
-       struct drm_gem_object *obj = ptr;
-       struct seq_file *m = data;
-
-       seq_printf(m, "%6d %8zd %7d %8d\n",
-                  obj->name, obj->size,
-                  obj->handle_count,
-                  kref_read(&obj->refcount));
-       return 0;
-}
-
-int drm_gem_name_info(struct seq_file *m, void *data)
-{
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct drm_device *dev = node->minor->dev;
-
-       seq_printf(m, "  name     size handles refcount\n");
-
-       mutex_lock(&dev->object_name_lock);
-       idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m);
-       mutex_unlock(&dev->object_name_lock);
-
-       return 0;
-}
index 0c4eb4a9ab31f79efff7d6902c542d9a6f69ddd9..c7a7d7ce5d1cbaf1531e329223c0ca2f759ff1cc 100644 (file)
@@ -56,11 +56,6 @@ void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpr
 struct drm_minor *drm_minor_acquire(unsigned int minor_id);
 void drm_minor_release(struct drm_minor *minor);
 
-/* drm_info.c */
-int drm_name_info(struct seq_file *m, void *data);
-int drm_clients_info(struct seq_file *m, void* data);
-int drm_gem_name_info(struct seq_file *m, void *data);
-
 /* drm_vblank.c */
 void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe);
 void drm_vblank_cleanup(struct drm_device *dev);
index 5737cb8c6f0368d40085d479bc54ab0a8d6f52cd..231e3f6d5f4162c243c19c04811b71727f7c50cb 100644 (file)
@@ -663,24 +663,33 @@ EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
  */
 int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
 {
-       /* Used by drm_gem_mmap() to lookup the GEM object */
-       struct drm_file priv = {
-               .minor = obj->dev->primary,
-       };
-       struct file fil = {
-               .private_data = &priv,
-       };
+       struct drm_file *priv;
+       struct file *fil;
        int ret;
 
-       ret = drm_vma_node_allow(&obj->vma_node, &priv);
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       fil = kzalloc(sizeof(*fil), GFP_KERNEL);
+       if (!priv || !fil) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /* Used by drm_gem_mmap() to lookup the GEM object */
+       priv->minor = obj->dev->primary;
+       fil->private_data = priv;
+
+       ret = drm_vma_node_allow(&obj->vma_node, priv);
        if (ret)
-               return ret;
+               goto out;
 
        vma->vm_pgoff += drm_vma_node_start(&obj->vma_node);
 
-       ret = obj->dev->driver->fops->mmap(&fil, vma);
+       ret = obj->dev->driver->fops->mmap(fil, vma);
 
-       drm_vma_node_revoke(&obj->vma_node, &priv);
+       drm_vma_node_revoke(&obj->vma_node, priv);
+out:
+       kfree(priv);
+       kfree(fil);
 
        return ret;
 }
index 83c1f46670bfea9dcbe95e42da598c8665576b03..52802e6049e0adab5045b57cc09bd265708ae34d 100644 (file)
@@ -550,7 +550,7 @@ out_register:
 out_bind:
        kfree(priv);
 out_unref:
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
 
        return ret;
 }
@@ -567,7 +567,7 @@ static void etnaviv_unbind(struct device *dev)
        drm->dev_private = NULL;
        kfree(priv);
 
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
 }
 
 static const struct component_master_ops etnaviv_master_ops = {
index df7247cd93f98f9f237721bb1eddd104cbbdc345..d8c5cc34e22e41886c71bf6eaad9e6b0084f7eeb 100644 (file)
@@ -594,17 +594,7 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
        dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__,
                vclk_freq, venc_freq, hdmi_freq);
 
-       /* Finally filter by configurable vclk frequencies for VIC modes */
-       switch (vclk_freq) {
-       case 54000:
-       case 74250:
-       case 148500:
-       case 297000:
-       case 594000:
-               return MODE_OK;
-       }
-
-       return MODE_CLOCK_RANGE;
+       return meson_vclk_vic_supported_freq(vclk_freq);
 }
 
 /* Encoder */
index 9aebc5e4b418a924f5ed2844c734dd592f4651d1..691a9fd16b3664c0028d9e9359988d915a54cb21 100644 (file)
@@ -16,6 +16,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_rect.h>
 
 #include "meson_overlay.h"
@@ -532,6 +533,7 @@ static const struct drm_plane_helper_funcs meson_overlay_helper_funcs = {
        .atomic_check   = meson_overlay_atomic_check,
        .atomic_disable = meson_overlay_atomic_disable,
        .atomic_update  = meson_overlay_atomic_update,
+       .prepare_fb     = drm_gem_fb_prepare_fb,
 };
 
 static const struct drm_plane_funcs meson_overlay_funcs = {
index 12a47b4f65a533eee9210b571738a41248ed357e..8ee2cf9e47cdc020dfbdbe978725c38645874c0f 100644 (file)
@@ -32,6 +32,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_rect.h>
 
 #include "meson_plane.h"
@@ -322,6 +323,7 @@ static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
        .atomic_check   = meson_plane_atomic_check,
        .atomic_disable = meson_plane_atomic_disable,
        .atomic_update  = meson_plane_atomic_update,
+       .prepare_fb     = drm_gem_fb_prepare_fb,
 };
 
 static const struct drm_plane_funcs meson_plane_funcs = {
index ae5473257f727cd446b2aba0b3dd172a86b276f1..f6ba35a405f8dea95f4ec531df0df46372ae8ffc 100644 (file)
 #define HDMI_PLL_RESET         BIT(28)
 #define HDMI_PLL_LOCK          BIT(31)
 
+#define FREQ_1000_1001(_freq)  DIV_ROUND_CLOSEST(_freq * 1000, 1001)
+
 /* VID PLL Dividers */
 enum {
        VID_PLL_DIV_1 = 0,
@@ -323,7 +325,7 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
 enum {
 /* PLL O1 O2 O3 VP DV     EN TX */
 /* 4320 /4 /4 /1 /5 /1  => /2 /2 */
-       MESON_VCLK_HDMI_ENCI_54000 = 1,
+       MESON_VCLK_HDMI_ENCI_54000 = 0,
 /* 4320 /4 /4 /1 /5 /1  => /1 /2 */
        MESON_VCLK_HDMI_DDR_54000,
 /* 2970 /4 /1 /1 /5 /1  => /1 /2 */
@@ -339,6 +341,7 @@ enum {
 };
 
 struct meson_vclk_params {
+       unsigned int pixel_freq;
        unsigned int pll_base_freq;
        unsigned int pll_od1;
        unsigned int pll_od2;
@@ -347,6 +350,7 @@ struct meson_vclk_params {
        unsigned int vclk_div;
 } params[] = {
        [MESON_VCLK_HDMI_ENCI_54000] = {
+               .pixel_freq = 54000,
                .pll_base_freq = 4320000,
                .pll_od1 = 4,
                .pll_od2 = 4,
@@ -355,6 +359,7 @@ struct meson_vclk_params {
                .vclk_div = 1,
        },
        [MESON_VCLK_HDMI_DDR_54000] = {
+               .pixel_freq = 54000,
                .pll_base_freq = 4320000,
                .pll_od1 = 4,
                .pll_od2 = 4,
@@ -363,6 +368,7 @@ struct meson_vclk_params {
                .vclk_div = 1,
        },
        [MESON_VCLK_HDMI_DDR_148500] = {
+               .pixel_freq = 148500,
                .pll_base_freq = 2970000,
                .pll_od1 = 4,
                .pll_od2 = 1,
@@ -371,6 +377,7 @@ struct meson_vclk_params {
                .vclk_div = 1,
        },
        [MESON_VCLK_HDMI_74250] = {
+               .pixel_freq = 74250,
                .pll_base_freq = 2970000,
                .pll_od1 = 2,
                .pll_od2 = 2,
@@ -379,6 +386,7 @@ struct meson_vclk_params {
                .vclk_div = 1,
        },
        [MESON_VCLK_HDMI_148500] = {
+               .pixel_freq = 148500,
                .pll_base_freq = 2970000,
                .pll_od1 = 1,
                .pll_od2 = 2,
@@ -387,6 +395,7 @@ struct meson_vclk_params {
                .vclk_div = 1,
        },
        [MESON_VCLK_HDMI_297000] = {
+               .pixel_freq = 297000,
                .pll_base_freq = 2970000,
                .pll_od1 = 1,
                .pll_od2 = 1,
@@ -395,6 +404,7 @@ struct meson_vclk_params {
                .vclk_div = 2,
        },
        [MESON_VCLK_HDMI_594000] = {
+               .pixel_freq = 594000,
                .pll_base_freq = 5940000,
                .pll_od1 = 1,
                .pll_od2 = 1,
@@ -402,6 +412,7 @@ struct meson_vclk_params {
                .vid_pll_div = VID_PLL_DIV_5,
                .vclk_div = 1,
        },
+       { /* sentinel */ },
 };
 
 static inline unsigned int pll_od_to_reg(unsigned int od)
@@ -626,12 +637,37 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
                  pll_freq);
 }
 
+enum drm_mode_status
+meson_vclk_vic_supported_freq(unsigned int freq)
+{
+       int i;
+
+       DRM_DEBUG_DRIVER("freq = %d\n", freq);
+
+       for (i = 0 ; params[i].pixel_freq ; ++i) {
+               DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
+                                i, params[i].pixel_freq,
+                                FREQ_1000_1001(params[i].pixel_freq));
+               /* Match strict frequency */
+               if (freq == params[i].pixel_freq)
+                       return MODE_OK;
+               /* Match 1000/1001 variant */
+               if (freq == FREQ_1000_1001(params[i].pixel_freq))
+                       return MODE_OK;
+       }
+
+       return MODE_CLOCK_RANGE;
+}
+EXPORT_SYMBOL_GPL(meson_vclk_vic_supported_freq);
+
 static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
                           unsigned int od1, unsigned int od2, unsigned int od3,
                           unsigned int vid_pll_div, unsigned int vclk_div,
                           unsigned int hdmi_tx_div, unsigned int venc_div,
-                          bool hdmi_use_enci)
+                          bool hdmi_use_enci, bool vic_alternate_clock)
 {
+       unsigned int m = 0, frac = 0;
+
        /* Set HDMI-TX sys clock */
        regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
                           CTS_HDMI_SYS_SEL_MASK, 0);
@@ -646,34 +682,38 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
        } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
                switch (pll_base_freq) {
                case 2970000:
-                       meson_hdmi_pll_set_params(priv, 0x3d, 0xe00,
-                                                 od1, od2, od3);
+                       m = 0x3d;
+                       frac = vic_alternate_clock ? 0xd02 : 0xe00;
                        break;
                case 4320000:
-                       meson_hdmi_pll_set_params(priv, 0x5a, 0,
-                                                 od1, od2, od3);
+                       m = vic_alternate_clock ? 0x59 : 0x5a;
+                       frac = vic_alternate_clock ? 0xe8f : 0;
                        break;
                case 5940000:
-                       meson_hdmi_pll_set_params(priv, 0x7b, 0xc00,
-                                                 od1, od2, od3);
+                       m = 0x7b;
+                       frac = vic_alternate_clock ? 0xa05 : 0xc00;
                        break;
                }
+
+               meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
        } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
                   meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
                switch (pll_base_freq) {
                case 2970000:
-                       meson_hdmi_pll_set_params(priv, 0x7b, 0x300,
-                                                 od1, od2, od3);
+                       m = 0x7b;
+                       frac = vic_alternate_clock ? 0x281 : 0x300;
                        break;
                case 4320000:
-                       meson_hdmi_pll_set_params(priv, 0xb4, 0,
-                                                 od1, od2, od3);
+                       m = vic_alternate_clock ? 0xb3 : 0xb4;
+                       frac = vic_alternate_clock ? 0x347 : 0;
                        break;
                case 5940000:
-                       meson_hdmi_pll_set_params(priv, 0xf7, 0x200,
-                                                 od1, od2, od3);
+                       m = 0xf7;
+                       frac = vic_alternate_clock ? 0x102 : 0x200;
                        break;
                }
+
+               meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
        }
 
        /* Setup vid_pll divider */
@@ -826,6 +866,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
                      unsigned int vclk_freq, unsigned int venc_freq,
                      unsigned int dac_freq, bool hdmi_use_enci)
 {
+       bool vic_alternate_clock = false;
        unsigned int freq;
        unsigned int hdmi_tx_div;
        unsigned int venc_div;
@@ -843,7 +884,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
                 * - encp encoder
                 */
                meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
-                              VID_PLL_DIV_5, 2, 1, 1, false);
+                              VID_PLL_DIV_5, 2, 1, 1, false, false);
                return;
        }
 
@@ -863,31 +904,35 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
                return;
        }
 
-       switch (vclk_freq) {
-       case 54000:
-               if (hdmi_use_enci)
-                       freq = MESON_VCLK_HDMI_ENCI_54000;
-               else
-                       freq = MESON_VCLK_HDMI_DDR_54000;
-               break;
-       case 74250:
-               freq = MESON_VCLK_HDMI_74250;
-               break;
-       case 148500:
-               if (dac_freq != 148500)
-                       freq = MESON_VCLK_HDMI_DDR_148500;
-               else
-                       freq = MESON_VCLK_HDMI_148500;
-               break;
-       case 297000:
-               freq = MESON_VCLK_HDMI_297000;
-               break;
-       case 594000:
-               freq = MESON_VCLK_HDMI_594000;
-               break;
-       default:
-               pr_err("Fatal Error, invalid HDMI vclk freq %d\n",
-                      vclk_freq);
+       for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
+               if (vclk_freq == params[freq].pixel_freq ||
+                   vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
+                       if (vclk_freq != params[freq].pixel_freq)
+                               vic_alternate_clock = true;
+                       else
+                               vic_alternate_clock = false;
+
+                       if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
+                           !hdmi_use_enci)
+                               continue;
+
+                       if (freq == MESON_VCLK_HDMI_DDR_54000 &&
+                           hdmi_use_enci)
+                               continue;
+
+                       if (freq == MESON_VCLK_HDMI_DDR_148500 &&
+                           dac_freq == vclk_freq)
+                               continue;
+
+                       if (freq == MESON_VCLK_HDMI_148500 &&
+                           dac_freq != vclk_freq)
+                               continue;
+                       break;
+               }
+       }
+
+       if (!params[freq].pixel_freq) {
+               pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
                return;
        }
 
@@ -895,6 +940,6 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
                       params[freq].pll_od1, params[freq].pll_od2,
                       params[freq].pll_od3, params[freq].vid_pll_div,
                       params[freq].vclk_div, hdmi_tx_div, venc_div,
-                      hdmi_use_enci);
+                      hdmi_use_enci, vic_alternate_clock);
 }
 EXPORT_SYMBOL_GPL(meson_vclk_setup);
index 869fa3a3073e98c01c9a17a72463f7d060605b72..4bd8752da02ab02c2bd96d9115a2e3aa3e55959b 100644 (file)
@@ -32,6 +32,8 @@ enum {
 
 enum drm_mode_status
 meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq);
+enum drm_mode_status
+meson_vclk_vic_supported_freq(unsigned int freq);
 
 void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
                      unsigned int vclk_freq, unsigned int venc_freq,
index acbbad3e322ca56957ff3b34228b694d12de30b3..e95e0e7a7fa1f3ae6a58be66e4ca0874e7b1ca99 100644 (file)
@@ -697,6 +697,132 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
        },
 };
 
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p24 = {
+       .encp = {
+               .dvi_settings = 0x1,
+               .video_mode = 0x4040,
+               .video_mode_adv = 0x8,
+               /* video_sync_mode */
+               /* video_yc_dly */
+               /* video_rgb_ctrl */
+               .video_filt_ctrl = 0x1000,
+               .video_filt_ctrl_present = true,
+               /* video_ofld_voav_ofst */
+               .yfp1_htime = 140,
+               .yfp2_htime = 140+3840,
+               .max_pxcnt = 3840+1660-1,
+               .hspuls_begin = 2156+1920,
+               .hspuls_end = 44,
+               .hspuls_switch = 44,
+               .vspuls_begin = 140,
+               .vspuls_end = 2059+1920,
+               .vspuls_bline = 0,
+               .vspuls_eline = 4,
+               .havon_begin = 148,
+               .havon_end = 3987,
+               .vavon_bline = 89,
+               .vavon_eline = 2248,
+               /* eqpuls_begin */
+               /* eqpuls_end */
+               /* eqpuls_bline */
+               /* eqpuls_eline */
+               .hso_begin = 44,
+               .hso_end = 2156+1920,
+               .vso_begin = 2100+1920,
+               .vso_end = 2164+1920,
+               .vso_bline = 51,
+               .vso_eline = 53,
+               .vso_eline_present = true,
+               /* sy_val */
+               /* sy2_val */
+               .max_lncnt = 2249,
+       },
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p25 = {
+       .encp = {
+               .dvi_settings = 0x1,
+               .video_mode = 0x4040,
+               .video_mode_adv = 0x8,
+               /* video_sync_mode */
+               /* video_yc_dly */
+               /* video_rgb_ctrl */
+               .video_filt_ctrl = 0x1000,
+               .video_filt_ctrl_present = true,
+               /* video_ofld_voav_ofst */
+               .yfp1_htime = 140,
+               .yfp2_htime = 140+3840,
+               .max_pxcnt = 3840+1440-1,
+               .hspuls_begin = 2156+1920,
+               .hspuls_end = 44,
+               .hspuls_switch = 44,
+               .vspuls_begin = 140,
+               .vspuls_end = 2059+1920,
+               .vspuls_bline = 0,
+               .vspuls_eline = 4,
+               .havon_begin = 148,
+               .havon_end = 3987,
+               .vavon_bline = 89,
+               .vavon_eline = 2248,
+               /* eqpuls_begin */
+               /* eqpuls_end */
+               /* eqpuls_bline */
+               /* eqpuls_eline */
+               .hso_begin = 44,
+               .hso_end = 2156+1920,
+               .vso_begin = 2100+1920,
+               .vso_end = 2164+1920,
+               .vso_bline = 51,
+               .vso_eline = 53,
+               .vso_eline_present = true,
+               /* sy_val */
+               /* sy2_val */
+               .max_lncnt = 2249,
+       },
+};
+
+union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p30 = {
+       .encp = {
+               .dvi_settings = 0x1,
+               .video_mode = 0x4040,
+               .video_mode_adv = 0x8,
+               /* video_sync_mode */
+               /* video_yc_dly */
+               /* video_rgb_ctrl */
+               .video_filt_ctrl = 0x1000,
+               .video_filt_ctrl_present = true,
+               /* video_ofld_voav_ofst */
+               .yfp1_htime = 140,
+               .yfp2_htime = 140+3840,
+               .max_pxcnt = 3840+560-1,
+               .hspuls_begin = 2156+1920,
+               .hspuls_end = 44,
+               .hspuls_switch = 44,
+               .vspuls_begin = 140,
+               .vspuls_end = 2059+1920,
+               .vspuls_bline = 0,
+               .vspuls_eline = 4,
+               .havon_begin = 148,
+               .havon_end = 3987,
+               .vavon_bline = 89,
+               .vavon_eline = 2248,
+               /* eqpuls_begin */
+               /* eqpuls_end */
+               /* eqpuls_bline */
+               /* eqpuls_eline */
+               .hso_begin = 44,
+               .hso_end = 2156+1920,
+               .vso_begin = 2100+1920,
+               .vso_end = 2164+1920,
+               .vso_bline = 51,
+               .vso_eline = 53,
+               .vso_eline_present = true,
+               /* sy_val */
+               /* sy2_val */
+               .max_lncnt = 2249,
+       },
+};
+
 struct meson_hdmi_venc_vic_mode {
        unsigned int vic;
        union meson_hdmi_venc_mode *mode;
@@ -717,6 +843,9 @@ struct meson_hdmi_venc_vic_mode {
        { 34, &meson_hdmi_encp_mode_1080p30 },
        { 31, &meson_hdmi_encp_mode_1080p50 },
        { 16, &meson_hdmi_encp_mode_1080p60 },
+       { 93, &meson_hdmi_encp_mode_2160p24 },
+       { 94, &meson_hdmi_encp_mode_2160p25 },
+       { 95, &meson_hdmi_encp_mode_2160p30 },
        { 0, NULL}, /* sentinel */
 };
 
index 2393e6d16ffd4d4118335a018747e218755cb8e9..88ba003979e6b841cce82bd390282335ebb13028 100644 (file)
@@ -417,7 +417,7 @@ static int mxsfb_probe(struct platform_device *pdev)
 err_unload:
        mxsfb_unload(drm);
 err_free:
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
 
        return ret;
 }
@@ -428,7 +428,7 @@ static int mxsfb_remove(struct platform_device *pdev)
 
        drm_dev_unregister(drm);
        mxsfb_unload(drm);
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
 
        return 0;
 }
index bf49c55b0f2c7de6d62b3ca3dbf34824be512315..9e9255ee59cd83138f5572f0d31df50aec9cc244 100644 (file)
@@ -48,8 +48,12 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
 /*
  * These coefficients are taken from the A33 BSP from Allwinner.
  *
- * The formula is for each component, each coefficient being multiplied by
- * 1024 and each constant being multiplied by 16:
+ * The first three values of each row are coded as 13-bit signed fixed-point
+ * numbers, with 10 bits for the fractional part. The fourth value is a
+ * constant coded as a 14-bit signed fixed-point number with 4 bits for the
+ * fractional part.
+ *
+ * The values in table order give the following colorspace translation:
  * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135
  * R = 1.164 * Y + 1.596 * V - 222
  * B = 1.164 * Y + 2.018 * U + 276
@@ -155,6 +159,36 @@ static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode)
        return 0;
 }
 
+static const uint32_t sun4i_backend_formats[] = {
+       DRM_FORMAT_ARGB1555,
+       DRM_FORMAT_ARGB4444,
+       DRM_FORMAT_ARGB8888,
+       DRM_FORMAT_BGRX8888,
+       DRM_FORMAT_RGB565,
+       DRM_FORMAT_RGB888,
+       DRM_FORMAT_RGBA4444,
+       DRM_FORMAT_RGBA5551,
+       DRM_FORMAT_UYVY,
+       DRM_FORMAT_VYUY,
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_YUYV,
+       DRM_FORMAT_YVYU,
+};
+
+bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier)
+{
+       unsigned int i;
+
+       if (modifier != DRM_FORMAT_MOD_LINEAR)
+               return false;
+
+       for (i = 0; i < ARRAY_SIZE(sun4i_backend_formats); i++)
+               if (sun4i_backend_formats[i] == fmt)
+                       return true;
+
+       return false;
+}
+
 int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
                                     int layer, struct drm_plane *plane)
 {
@@ -395,6 +429,15 @@ int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer,
        return 0;
 }
 
+void sun4i_backend_cleanup_layer(struct sun4i_backend *backend,
+                                int layer)
+{
+       regmap_update_bits(backend->engine.regs,
+                          SUN4I_BACKEND_ATTCTL_REG0(layer),
+                          SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN |
+                          SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN, 0);
+}
+
 static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state)
 {
        u16 src_h = state->src_h >> 16;
@@ -413,11 +456,50 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state)
 {
        struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane);
        struct sun4i_backend *backend = layer->backend;
+       uint32_t format = state->fb->format->format;
+       uint64_t modifier = state->fb->modifier;
 
        if (IS_ERR(backend->frontend))
                return false;
 
-       return sun4i_backend_plane_uses_scaler(state);
+       if (!sun4i_frontend_format_is_supported(format, modifier))
+               return false;
+
+       if (!sun4i_backend_format_is_supported(format, modifier))
+               return true;
+
+       /*
+        * TODO: The backend alone allows 2x and 4x integer scaling, including
+        * support for an alpha component (which the frontend doesn't support).
+        * Use the backend directly instead of the frontend in this case, with
+        * another test to return false.
+        */
+
+       if (sun4i_backend_plane_uses_scaler(state))
+               return true;
+
+       /*
+        * Here the format is supported by both the frontend and the backend
+        * and no frontend scaling is required, so use the backend directly.
+        */
+       return false;
+}
+
+static bool sun4i_backend_plane_is_supported(struct drm_plane_state *state,
+                                            bool *uses_frontend)
+{
+       if (sun4i_backend_plane_uses_frontend(state)) {
+               *uses_frontend = true;
+               return true;
+       }
+
+       *uses_frontend = false;
+
+       /* Scaling is not supported without the frontend. */
+       if (sun4i_backend_plane_uses_scaler(state))
+               return false;
+
+       return true;
 }
 
 static void sun4i_backend_atomic_begin(struct sunxi_engine *engine,
@@ -460,14 +542,19 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
                struct drm_framebuffer *fb = plane_state->fb;
                struct drm_format_name_buf format_name;
 
-               if (sun4i_backend_plane_uses_frontend(plane_state)) {
+               if (!sun4i_backend_plane_is_supported(plane_state,
+                                                     &layer_state->uses_frontend))
+                       return -EINVAL;
+
+               if (layer_state->uses_frontend) {
                        DRM_DEBUG_DRIVER("Using the frontend for plane %d\n",
                                         plane->index);
-
-                       layer_state->uses_frontend = true;
                        num_frontend_planes++;
                } else {
-                       layer_state->uses_frontend = false;
+                       if (fb->format->is_yuv) {
+                               DRM_DEBUG_DRIVER("Plane FB format is YUV\n");
+                               num_yuv_planes++;
+                       }
                }
 
                DRM_DEBUG_DRIVER("Plane FB format is %s\n",
@@ -476,11 +563,6 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
                if (fb->format->has_alpha || (plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE))
                        num_alpha_planes++;
 
-               if (fb->format->is_yuv) {
-                       DRM_DEBUG_DRIVER("Plane FB format is YUV\n");
-                       num_yuv_planes++;
-               }
-
                DRM_DEBUG_DRIVER("Plane zpos is %d\n",
                                 plane_state->normalized_zpos);
 
index e3d4c6035eb2511b32fd8a93f90cc1498a11cb5e..01f66463271b211fe7d3bc7a1d2dcd3ad8e95aae 100644 (file)
@@ -198,6 +198,7 @@ engine_to_sun4i_backend(struct sunxi_engine *engine)
 
 void sun4i_backend_layer_enable(struct sun4i_backend *backend,
                                int layer, bool enable);
+bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier);
 int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
                                     int layer, struct drm_plane *plane);
 int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
@@ -208,5 +209,7 @@ int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend,
                                        int layer, uint32_t in_fmt);
 int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend,
                                    int layer, struct drm_plane *plane);
+void sun4i_backend_cleanup_layer(struct sun4i_backend *backend,
+                                int layer);
 
 #endif /* _SUN4I_BACKEND_H_ */
index ef773d36baf0523fab1b62b2fd5909853106adbb..ccdeae6299ebcad4eff3e345d72861ca10040692 100644 (file)
 #include "sun4i_tcon.h"
 #include "sun8i_tcon_top.h"
 
+static int drm_sun4i_gem_dumb_create(struct drm_file *file_priv,
+                                    struct drm_device *drm,
+                                    struct drm_mode_create_dumb *args)
+{
+       /* The hardware only allows even pitches for YUV buffers. */
+       args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), 2);
+
+       return drm_gem_cma_dumb_create_internal(file_priv, drm, args);
+}
+
 DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops);
 
 static struct drm_driver sun4i_drv_driver = {
@@ -42,7 +52,7 @@ static struct drm_driver sun4i_drv_driver = {
        .minor                  = 0,
 
        /* GEM Operations */
-       .dumb_create            = drm_gem_cma_dumb_create,
+       .dumb_create            = drm_sun4i_gem_dumb_create,
        .gem_free_object_unlocked = drm_gem_cma_free_object,
        .gem_vm_ops             = &drm_gem_cma_vm_ops,
 
index ddf6cfa6dd2353e7fa94b94171ef913f36afd6fd..1a7ebc45747ec9d9c498adb6a793625661eff945 100644 (file)
@@ -107,8 +107,34 @@ EXPORT_SYMBOL(sun4i_frontend_update_buffer);
 static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val)
 {
        switch (fmt) {
-       case DRM_FORMAT_ARGB8888:
-               *val = 5;
+       case DRM_FORMAT_XRGB8888:
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB;
+               return 0;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static int sun4i_frontend_drm_format_to_input_mode(uint32_t fmt, u32 *val)
+{
+       if (drm_format_num_planes(fmt) == 1)
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static int sun4i_frontend_drm_format_to_input_sequence(uint32_t fmt, u32 *val)
+{
+       switch (fmt) {
+       case DRM_FORMAT_BGRX8888:
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX;
+               return 0;
+
+       case DRM_FORMAT_XRGB8888:
+               *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB;
                return 0;
 
        default:
@@ -119,9 +145,12 @@ static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val)
 static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
 {
        switch (fmt) {
+       case DRM_FORMAT_BGRX8888:
+               *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888;
+               return 0;
+
        case DRM_FORMAT_XRGB8888:
-       case DRM_FORMAT_ARGB8888:
-               *val = 2;
+               *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888;
                return 0;
 
        default:
@@ -129,22 +158,54 @@ static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
        }
 }
 
+static const uint32_t sun4i_frontend_formats[] = {
+       DRM_FORMAT_BGRX8888,
+       DRM_FORMAT_XRGB8888,
+};
+
+bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier)
+{
+       unsigned int i;
+
+       if (modifier != DRM_FORMAT_MOD_LINEAR)
+               return false;
+
+       for (i = 0; i < ARRAY_SIZE(sun4i_frontend_formats); i++)
+               if (sun4i_frontend_formats[i] == fmt)
+                       return true;
+
+       return false;
+}
+EXPORT_SYMBOL(sun4i_frontend_format_is_supported);
+
 int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
                                  struct drm_plane *plane, uint32_t out_fmt)
 {
        struct drm_plane_state *state = plane->state;
        struct drm_framebuffer *fb = state->fb;
+       uint32_t format = fb->format->format;
        u32 out_fmt_val;
-       u32 in_fmt_val;
+       u32 in_fmt_val, in_mod_val, in_ps_val;
        int ret;
 
-       ret = sun4i_frontend_drm_format_to_input_fmt(fb->format->format,
-                                                    &in_fmt_val);
+       ret = sun4i_frontend_drm_format_to_input_fmt(format, &in_fmt_val);
        if (ret) {
                DRM_DEBUG_DRIVER("Invalid input format\n");
                return ret;
        }
 
+       ret = sun4i_frontend_drm_format_to_input_mode(format, &in_mod_val);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Invalid input mode\n");
+               return ret;
+       }
+
+       ret = sun4i_frontend_drm_format_to_input_sequence(format, &in_ps_val);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Invalid pixel sequence\n");
+               return ret;
+       }
+
        ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val);
        if (ret) {
                DRM_DEBUG_DRIVER("Invalid output format\n");
@@ -162,10 +223,12 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400);
 
+       regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
+                          SUN4I_FRONTEND_BYPASS_CSC_EN,
+                          SUN4I_FRONTEND_BYPASS_CSC_EN);
+
        regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG,
-                    SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(1) |
-                    SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(in_fmt_val) |
-                    SUN4I_FRONTEND_INPUT_FMT_PS(1));
+                    in_mod_val | in_fmt_val | in_ps_val);
 
        /*
         * TODO: It look like the A31 and A80 at least will need the
@@ -173,7 +236,7 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
         * ARGB8888).
         */
        regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG,
-                    SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(out_fmt_val));
+                    out_fmt_val);
 
        return 0;
 }
@@ -183,16 +246,24 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
                                 struct drm_plane *plane)
 {
        struct drm_plane_state *state = plane->state;
+       struct drm_framebuffer *fb = state->fb;
+       uint32_t luma_width, luma_height;
+       uint32_t chroma_width, chroma_height;
 
        /* Set height and width */
        DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n",
                         state->crtc_w, state->crtc_h);
+
+       luma_width = state->src_w >> 16;
+       luma_height = state->src_h >> 16;
+
+       chroma_width = DIV_ROUND_UP(luma_width, fb->format->hsub);
+       chroma_height = DIV_ROUND_UP(luma_height, fb->format->vsub);
+
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG,
-                    SUN4I_FRONTEND_INSIZE(state->src_h >> 16,
-                                          state->src_w >> 16));
+                    SUN4I_FRONTEND_INSIZE(luma_height, luma_width));
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG,
-                    SUN4I_FRONTEND_INSIZE(state->src_h >> 16,
-                                          state->src_w >> 16));
+                    SUN4I_FRONTEND_INSIZE(chroma_height, chroma_width));
 
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG,
                     SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
@@ -200,14 +271,14 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
                     SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
 
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG,
-                    state->src_w / state->crtc_w);
+                    (luma_width << 16) / state->crtc_w);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG,
-                    state->src_w / state->crtc_w);
+                    (chroma_width << 16) / state->crtc_w);
 
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG,
-                    state->src_h / state->crtc_h);
+                    (luma_height << 16) / state->crtc_h);
        regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG,
-                    state->src_h / state->crtc_h);
+                    (chroma_height << 16) / state->crtc_h);
 
        regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
                          SUN4I_FRONTEND_FRM_CTRL_REG_RDY,
@@ -339,10 +410,6 @@ static int sun4i_frontend_runtime_resume(struct device *dev)
                           SUN4I_FRONTEND_EN_EN,
                           SUN4I_FRONTEND_EN_EN);
 
-       regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
-                          SUN4I_FRONTEND_BYPASS_CSC_EN,
-                          SUN4I_FRONTEND_BYPASS_CSC_EN);
-
        sun4i_frontend_scaler_init(frontend);
 
        return 0;
index 02661ce81f3e31c81e8203b6fcc42f0914937bc8..ad146e8d8d70d1d05e82420cd45bb0f7e4257bef 100644 (file)
 #define SUN4I_FRONTEND_LINESTRD0_REG           0x040
 
 #define SUN4I_FRONTEND_INPUT_FMT_REG           0x04c
-#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(mod)         ((mod) << 8)
-#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(fmt)         ((fmt) << 4)
-#define SUN4I_FRONTEND_INPUT_FMT_PS(ps)                        (ps)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED       (1 << 8)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB          (5 << 4)
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX          0
+#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB          1
 
 #define SUN4I_FRONTEND_OUTPUT_FMT_REG          0x05c
-#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(fmt)                (fmt)
+#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888    1
+#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888    2
 
 #define SUN4I_FRONTEND_CH0_INSIZE_REG          0x100
 #define SUN4I_FRONTEND_INSIZE(h, w)                    ((((h) - 1) << 16) | (((w) - 1)))
@@ -95,5 +97,6 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
                                 struct drm_plane *plane);
 int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
                                  struct drm_plane *plane, uint32_t out_fmt);
+bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier);
 
 #endif /* _SUN4I_FRONTEND_H_ */
index 78f77af8805ace3597295548f37a38462c293111..29631e0efde37ce709023995634dceac8c412f6a 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drmP.h>
 
 #include "sun4i_backend.h"
@@ -92,14 +93,16 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
        struct sun4i_backend *backend = layer->backend;
        struct sun4i_frontend *frontend = backend->frontend;
 
+       sun4i_backend_cleanup_layer(backend, layer->id);
+
        if (layer_state->uses_frontend) {
                sun4i_frontend_init(frontend);
                sun4i_frontend_update_coord(frontend, plane);
                sun4i_frontend_update_buffer(frontend, plane);
                sun4i_frontend_update_formats(frontend, plane,
-                                             DRM_FORMAT_ARGB8888);
+                                             DRM_FORMAT_XRGB8888);
                sun4i_backend_update_layer_frontend(backend, layer->id,
-                                                   DRM_FORMAT_ARGB8888);
+                                                   DRM_FORMAT_XRGB8888);
                sun4i_frontend_enable(frontend);
        } else {
                sun4i_backend_update_layer_formats(backend, layer->id, plane);
@@ -112,6 +115,7 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
 }
 
 static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = {
+       .prepare_fb     = drm_gem_fb_prepare_fb,
        .atomic_disable = sun4i_backend_layer_atomic_disable,
        .atomic_update  = sun4i_backend_layer_atomic_update,
 };
@@ -125,10 +129,11 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
        .update_plane           = drm_atomic_helper_update_plane,
 };
 
-static const uint32_t sun4i_backend_layer_formats[] = {
+static const uint32_t sun4i_layer_formats[] = {
        DRM_FORMAT_ARGB8888,
        DRM_FORMAT_ARGB4444,
        DRM_FORMAT_ARGB1555,
+       DRM_FORMAT_BGRX8888,
        DRM_FORMAT_RGBA5551,
        DRM_FORMAT_RGBA4444,
        DRM_FORMAT_RGB888,
@@ -154,8 +159,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
        /* possible crtcs are set later */
        ret = drm_universal_plane_init(drm, &layer->plane, 0,
                                       &sun4i_backend_layer_funcs,
-                                      sun4i_backend_layer_formats,
-                                      ARRAY_SIZE(sun4i_backend_layer_formats),
+                                      sun4i_layer_formats,
+                                      ARRAY_SIZE(sun4i_layer_formats),
                                       NULL, type, NULL);
        if (ret) {
                dev_err(drm->dev, "Couldn't initialize layer\n");
index e3fc8fa920fbaccc5abce984ef37386af9857ba2..18534263a05d827fe4e87b5e65355f98094ffb46 100644 (file)
@@ -19,6 +19,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drmP.h>
 
@@ -300,6 +301,7 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
 }
 
 static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = {
+       .prepare_fb     = drm_gem_fb_prepare_fb,
        .atomic_check   = sun8i_ui_layer_atomic_check,
        .atomic_disable = sun8i_ui_layer_atomic_disable,
        .atomic_update  = sun8i_ui_layer_atomic_update,
index 4249edfb47ed7b074005d7410e14249906242aaf..87be898f9b7a090cf732e9c9b2187e1986031aaf 100644 (file)
@@ -13,6 +13,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drmP.h>
 
@@ -336,6 +337,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
 }
 
 static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
+       .prepare_fb     = drm_gem_fb_prepare_fb,
        .atomic_check   = sun8i_vi_layer_atomic_check,
        .atomic_disable = sun8i_vi_layer_atomic_disable,
        .atomic_update  = sun8i_vi_layer_atomic_update,
index 72efcecb44f75446fcb3335d7296b0c4304580f8..28e2d03c0ccffa5b7403ec723ea0a676638872cb 100644 (file)
@@ -249,7 +249,7 @@ static int tve200_probe(struct platform_device *pdev)
 clk_disable:
        clk_disable_unprepare(priv->pclk);
 dev_unref:
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
        return ret;
 }
 
@@ -263,7 +263,7 @@ static int tve200_remove(struct platform_device *pdev)
                drm_panel_bridge_remove(priv->bridge);
        drm_mode_config_cleanup(drm);
        clk_disable_unprepare(priv->pclk);
-       drm_dev_unref(drm);
+       drm_dev_put(drm);
 
        return 0;
 }
index b88c9691145390702a4ec7b3e9ef063fb9d84d1a..1e8947c7d954c528634b8b194b753641b0818b34 100644 (file)
@@ -210,14 +210,11 @@ static void
 v3d_attach_object_fences(struct v3d_exec_info *exec)
 {
        struct dma_fence *out_fence = exec->render_done_fence;
-       struct v3d_bo *bo;
        int i;
 
        for (i = 0; i < exec->bo_count; i++) {
-               bo = to_v3d_bo(&exec->bo[i]->base);
-
                /* XXX: Use shared fences for read-only objects. */
-               reservation_object_add_excl_fence(bo->resv, out_fence);
+               reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence);
        }
 }
 
@@ -228,11 +225,8 @@ v3d_unlock_bo_reservations(struct drm_device *dev,
 {
        int i;
 
-       for (i = 0; i < exec->bo_count; i++) {
-               struct v3d_bo *bo = to_v3d_bo(&exec->bo[i]->base);
-
-               ww_mutex_unlock(&bo->resv->lock);
-       }
+       for (i = 0; i < exec->bo_count; i++)
+               ww_mutex_unlock(&exec->bo[i]->resv->lock);
 
        ww_acquire_fini(acquire_ctx);
 }
@@ -251,13 +245,13 @@ v3d_lock_bo_reservations(struct drm_device *dev,
 {
        int contended_lock = -1;
        int i, ret;
-       struct v3d_bo *bo;
 
        ww_acquire_init(acquire_ctx, &reservation_ww_class);
 
 retry:
        if (contended_lock != -1) {
-               bo = to_v3d_bo(&exec->bo[contended_lock]->base);
+               struct v3d_bo *bo = exec->bo[contended_lock];
+
                ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
                                                       acquire_ctx);
                if (ret) {
@@ -270,19 +264,16 @@ retry:
                if (i == contended_lock)
                        continue;
 
-               bo = to_v3d_bo(&exec->bo[i]->base);
-
-               ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx);
+               ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock,
+                                                 acquire_ctx);
                if (ret) {
                        int j;
 
-                       for (j = 0; j < i; j++) {
-                               bo = to_v3d_bo(&exec->bo[j]->base);
-                               ww_mutex_unlock(&bo->resv->lock);
-                       }
+                       for (j = 0; j < i; j++)
+                               ww_mutex_unlock(&exec->bo[j]->resv->lock);
 
                        if (contended_lock != -1 && contended_lock >= i) {
-                               bo = to_v3d_bo(&exec->bo[contended_lock]->base);
+                               struct v3d_bo *bo = exec->bo[contended_lock];
 
                                ww_mutex_unlock(&bo->resv->lock);
                        }
@@ -303,9 +294,7 @@ retry:
         * before we commit the CL to the hardware.
         */
        for (i = 0; i < exec->bo_count; i++) {
-               bo = to_v3d_bo(&exec->bo[i]->base);
-
-               ret = reservation_object_reserve_shared(bo->resv, 1);
+               ret = reservation_object_reserve_shared(exec->bo[i]->resv, 1);
                if (ret) {
                        v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
                        return ret;
index 445b2ef0330346e49e744c035bec3a18940b7e85..c66d0ce21435e4bdc8bec1a4a867688b5f204466 100644 (file)
@@ -41,7 +41,7 @@ v3d_job_free(struct drm_sched_job *sched_job)
 }
 
 /**
- * Returns the fences that the bin job depends on, one by one.
+ * Returns the fences that the bin or render job depends on, one by one.
  * v3d_job_run() won't be called until all of them have been signaled.
  */
 static struct dma_fence *
index 8f8fed471e34b296d7d2efce36deb877656e61a6..b5580b11a063606e79d8d43005b4cf4423ef5629 100644 (file)
@@ -169,6 +169,12 @@ static int virtio_gpu_conn_get_modes(struct drm_connector *connector)
        struct drm_display_mode *mode = NULL;
        int count, width, height;
 
+       if (output->edid) {
+               count = drm_add_edid_modes(connector, output->edid);
+               if (count)
+                       return count;
+       }
+
        width  = le32_to_cpu(output->info.r.width);
        height = le32_to_cpu(output->info.r.height);
        count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
@@ -287,6 +293,8 @@ static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index)
        drm_connector_init(dev, connector, &virtio_gpu_connector_funcs,
                           DRM_MODE_CONNECTOR_VIRTUAL);
        drm_connector_helper_add(connector, &virtio_gpu_conn_helper_funcs);
+       if (vgdev->has_edid)
+               drm_connector_attach_edid_property(connector);
 
        drm_encoder_init(dev, encoder, &virtio_gpu_enc_funcs,
                         DRM_MODE_ENCODER_VIRTUAL, NULL);
@@ -378,6 +386,10 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev)
 
 void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev)
 {
+       int i;
+
+       for (i = 0 ; i < vgdev->num_scanouts; ++i)
+               kfree(vgdev->outputs[i].edid);
        virtio_gpu_fbdev_fini(vgdev);
        drm_mode_config_cleanup(vgdev->ddev);
 }
index d9287c144fe5ea11d15d24aff55c5bf1d2ce2cdd..f7f32a885af79902a4c02ce4c4c801c1a119cc83 100644 (file)
@@ -80,6 +80,7 @@ static unsigned int features[] = {
         */
        VIRTIO_GPU_F_VIRGL,
 #endif
+       VIRTIO_GPU_F_EDID,
 };
 static struct virtio_driver virtio_gpu_driver = {
        .feature_table = features,
index 9db568054d66a1a71d772d673c4ceb4004d2ca87..f7e877857c1fc7083e1d8e8e6c94d6e4cdf34191 100644 (file)
@@ -115,6 +115,7 @@ struct virtio_gpu_output {
        struct drm_encoder enc;
        struct virtio_gpu_display_one info;
        struct virtio_gpu_update_cursor cursor;
+       struct edid *edid;
        int cur_x;
        int cur_y;
        bool enabled;
@@ -201,6 +202,7 @@ struct virtio_gpu_device {
        struct ida      ctx_id_ida;
 
        bool has_virgl_3d;
+       bool has_edid;
 
        struct work_struct config_changed_work;
 
@@ -291,6 +293,7 @@ int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx);
 int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
                              int idx, int version,
                              struct virtio_gpu_drv_cap_cache **cache_p);
+int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev);
 void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
                                   uint32_t nlen, const char *name);
 void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
index 691b842d5f3a4ed6f374953f857894b952f8c324..3af6181c05a852cccf91880e34388f78723e1835 100644 (file)
@@ -44,6 +44,8 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
        virtio_cread(vgdev->vdev, struct virtio_gpu_config,
                     events_read, &events_read);
        if (events_read & VIRTIO_GPU_EVENT_DISPLAY) {
+               if (vgdev->has_edid)
+                       virtio_gpu_cmd_get_edids(vgdev);
                virtio_gpu_cmd_get_display_info(vgdev);
                drm_helper_hpd_irq_event(vgdev->ddev);
                events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
@@ -156,6 +158,10 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
 #else
        DRM_INFO("virgl 3d acceleration not supported by guest\n");
 #endif
+       if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_EDID)) {
+               vgdev->has_edid = true;
+               DRM_INFO("EDID support available.\n");
+       }
 
        ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL);
        if (ret) {
@@ -201,6 +207,8 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
 
        if (num_capsets)
                virtio_gpu_get_capsets(vgdev, num_capsets);
+       if (vgdev->has_edid)
+               virtio_gpu_cmd_get_edids(vgdev);
        virtio_gpu_cmd_get_display_info(vgdev);
        wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending,
                           5 * HZ);
index 93f2c3a51ee8bbca0d9d5a95c93d2104fabb2841..2c6764f08f18c5e230fbbf46f0b7be167c49520a 100644 (file)
@@ -584,6 +584,45 @@ static void virtio_gpu_cmd_capset_cb(struct virtio_gpu_device *vgdev,
        wake_up(&vgdev->resp_wq);
 }
 
+static int virtio_get_edid_block(void *data, u8 *buf,
+                                unsigned int block, size_t len)
+{
+       struct virtio_gpu_resp_edid *resp = data;
+       size_t start = block * EDID_LENGTH;
+
+       if (start + len > le32_to_cpu(resp->size))
+               return -1;
+       memcpy(buf, resp->edid + start, len);
+       return 0;
+}
+
+static void virtio_gpu_cmd_get_edid_cb(struct virtio_gpu_device *vgdev,
+                                      struct virtio_gpu_vbuffer *vbuf)
+{
+       struct virtio_gpu_cmd_get_edid *cmd =
+               (struct virtio_gpu_cmd_get_edid *)vbuf->buf;
+       struct virtio_gpu_resp_edid *resp =
+               (struct virtio_gpu_resp_edid *)vbuf->resp_buf;
+       uint32_t scanout = le32_to_cpu(cmd->scanout);
+       struct virtio_gpu_output *output;
+       struct edid *new_edid, *old_edid;
+
+       if (scanout >= vgdev->num_scanouts)
+               return;
+       output = vgdev->outputs + scanout;
+
+       new_edid = drm_do_get_edid(&output->conn, virtio_get_edid_block, resp);
+
+       spin_lock(&vgdev->display_info_lock);
+       old_edid = output->edid;
+       output->edid = new_edid;
+       drm_connector_update_edid_property(&output->conn, output->edid);
+       spin_unlock(&vgdev->display_info_lock);
+
+       kfree(old_edid);
+       wake_up(&vgdev->resp_wq);
+}
+
 int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev)
 {
        struct virtio_gpu_ctrl_hdr *cmd_p;
@@ -686,6 +725,34 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
        return 0;
 }
 
+int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev)
+{
+       struct virtio_gpu_cmd_get_edid *cmd_p;
+       struct virtio_gpu_vbuffer *vbuf;
+       void *resp_buf;
+       int scanout;
+
+       if (WARN_ON(!vgdev->has_edid))
+               return -EINVAL;
+
+       for (scanout = 0; scanout < vgdev->num_scanouts; scanout++) {
+               resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_edid),
+                                  GFP_KERNEL);
+               if (!resp_buf)
+                       return -ENOMEM;
+
+               cmd_p = virtio_gpu_alloc_cmd_resp
+                       (vgdev, &virtio_gpu_cmd_get_edid_cb, &vbuf,
+                        sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_edid),
+                        resp_buf);
+               cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_EDID);
+               cmd_p->scanout = cpu_to_le32(scanout);
+               virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+       }
+
+       return 0;
+}
+
 void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
                                   uint32_t nlen, const char *name)
 {
index a3d57e0f5ee523486dc8e64ec2da033212259747..83087877565cf77b9104d67636c183231fdd19c4 100644 (file)
@@ -68,7 +68,6 @@ static struct drm_driver vkms_driver = {
        .release                = vkms_release,
        .fops                   = &vkms_driver_fops,
        .dumb_create            = vkms_dumb_create,
-       .dumb_map_offset        = vkms_dumb_map,
        .gem_vm_ops             = &vkms_gem_vm_ops,
        .gem_free_object_unlocked = vkms_gem_free_object,
        .get_vblank_timestamp   = vkms_get_vblank_timestamp,
index 1c93990693e3d0e65a70fcb4ee7dea34826d3a89..e4469cd3d25491198209e3898189fc52e54e5ed7 100644 (file)
@@ -127,9 +127,6 @@ vm_fault_t vkms_gem_fault(struct vm_fault *vmf);
 int vkms_dumb_create(struct drm_file *file, struct drm_device *dev,
                     struct drm_mode_create_dumb *args);
 
-int vkms_dumb_map(struct drm_file *file, struct drm_device *dev,
-                 u32 handle, u64 *offset);
-
 void vkms_gem_free_object(struct drm_gem_object *obj);
 
 int vkms_gem_vmap(struct drm_gem_object *obj);
index d04e988b4cbef88dacc54db05681078b5b29d529..80311daed47a0ac752a3e1e68bd54f9d8b60d412 100644 (file)
@@ -153,32 +153,6 @@ int vkms_dumb_create(struct drm_file *file, struct drm_device *dev,
        return 0;
 }
 
-int vkms_dumb_map(struct drm_file *file, struct drm_device *dev,
-                 u32 handle, u64 *offset)
-{
-       struct drm_gem_object *obj;
-       int ret;
-
-       obj = drm_gem_object_lookup(file, handle);
-       if (!obj)
-               return -ENOENT;
-
-       if (!obj->filp) {
-               ret = -EINVAL;
-               goto unref;
-       }
-
-       ret = drm_gem_create_mmap_offset(obj);
-       if (ret)
-               goto unref;
-
-       *offset = drm_vma_node_offset_addr(&obj->vma_node);
-unref:
-       drm_gem_object_put_unlocked(obj);
-
-       return ret;
-}
-
 static struct page **_get_pages(struct vkms_gem_object *vkms_obj)
 {
        struct drm_gem_object *gem_obj = &vkms_obj->gem;
index 257030460fb620dd848977c971c9a2df7c4fcec4..d3e23dd70c1b1ec75c73a850c759cd7288ac2db6 100644 (file)
@@ -279,7 +279,6 @@ static struct drm_driver driver = {
        .gem_free_object_unlocked = vbox_gem_free_object,
        .dumb_create = vbox_dumb_create,
        .dumb_map_offset = vbox_dumb_mmap_offset,
-       .dumb_destroy = drm_gem_dumb_destroy,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_export = drm_gem_prime_export,
index af0a761f52f0ef7d2ff055431c4f990a95de627b..665b9cae7f43c88ed6444f86467d05fab0781a94 100644 (file)
@@ -1210,30 +1210,6 @@ static inline void drm_connector_put(struct drm_connector *connector)
        drm_mode_object_put(&connector->base);
 }
 
-/**
- * drm_connector_reference - acquire a connector reference
- * @connector: DRM connector
- *
- * This is a compatibility alias for drm_connector_get() and should not be
- * used by new code.
- */
-static inline void drm_connector_reference(struct drm_connector *connector)
-{
-       drm_connector_get(connector);
-}
-
-/**
- * drm_connector_unreference - release a connector reference
- * @connector: DRM connector
- *
- * This is a compatibility alias for drm_connector_put() and should not be
- * used by new code.
- */
-static inline void drm_connector_unreference(struct drm_connector *connector)
-{
-       drm_connector_put(connector);
-}
-
 /**
  * drm_connector_is_unregistered - has the connector been unregistered from
  * userspace?
index dbb2f6ad184aacdbdb9a8d4df9ea3ba39136d9fb..35af23f5fa0d081a97eef6fa8e2e805b1e768669 100644 (file)
@@ -527,8 +527,10 @@ struct drm_driver {
         * @dumb_map_offset:
         *
         * Allocate an offset in the drm device node's address space to be able to
-        * memory map a dumb buffer. GEM-based drivers must use
-        * drm_gem_create_mmap_offset() to implement this.
+        * memory map a dumb buffer.
+        *
+        * The default implementation is drm_gem_create_mmap_offset(). GEM based
+        * drivers must not overwrite this.
         *
         * Called by the user via ioctl.
         *
@@ -548,6 +550,9 @@ struct drm_driver {
         *
         * Called by the user via ioctl.
         *
+        * The default implementation is drm_gem_dumb_destroy(). GEM based drivers
+        * must not overwrite this.
+        *
         * Returns:
         *
         * Zero on success, negative errno on failure.
@@ -625,7 +630,6 @@ void drm_dev_unregister(struct drm_device *dev);
 
 void drm_dev_get(struct drm_device *dev);
 void drm_dev_put(struct drm_device *dev);
-void drm_dev_unref(struct drm_device *dev);
 void drm_put_dev(struct drm_device *dev);
 bool drm_dev_enter(struct drm_device *dev, int *idx);
 void drm_dev_exit(int idx);
index c50502c656e5751374ed4e088540285fb1ee95f4..c94acedfb08ebf4efcd3adba8365d64860905012 100644 (file)
@@ -240,30 +240,6 @@ static inline void drm_framebuffer_put(struct drm_framebuffer *fb)
        drm_mode_object_put(&fb->base);
 }
 
-/**
- * drm_framebuffer_reference - acquire a framebuffer reference
- * @fb: DRM framebuffer
- *
- * This is a compatibility alias for drm_framebuffer_get() and should not be
- * used by new code.
- */
-static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
-{
-       drm_framebuffer_get(fb);
-}
-
-/**
- * drm_framebuffer_unreference - release a framebuffer reference
- * @fb: DRM framebuffer
- *
- * This is a compatibility alias for drm_framebuffer_put() and should not be
- * used by new code.
- */
-static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
-{
-       drm_framebuffer_put(fb);
-}
-
 /**
  * drm_framebuffer_read_refcount - read the framebuffer reference count.
  * @fb: framebuffer
index f466ce5bde0ea32f051b417666fdde44369ff4e0..c957274252844fc1d332bc04908a803161ed4c4c 100644 (file)
@@ -348,56 +348,6 @@ __drm_gem_object_put(struct drm_gem_object *obj)
 void drm_gem_object_put_unlocked(struct drm_gem_object *obj);
 void drm_gem_object_put(struct drm_gem_object *obj);
 
-/**
- * drm_gem_object_reference - acquire a GEM buffer object reference
- * @obj: GEM buffer object
- *
- * This is a compatibility alias for drm_gem_object_get() and should not be
- * used by new code.
- */
-static inline void drm_gem_object_reference(struct drm_gem_object *obj)
-{
-       drm_gem_object_get(obj);
-}
-
-/**
- * __drm_gem_object_unreference - raw function to release a GEM buffer object
- *                                reference
- * @obj: GEM buffer object
- *
- * This is a compatibility alias for __drm_gem_object_put() and should not be
- * used by new code.
- */
-static inline void __drm_gem_object_unreference(struct drm_gem_object *obj)
-{
-       __drm_gem_object_put(obj);
-}
-
-/**
- * drm_gem_object_unreference_unlocked - release a GEM buffer object reference
- * @obj: GEM buffer object
- *
- * This is a compatibility alias for drm_gem_object_put_unlocked() and should
- * not be used by new code.
- */
-static inline void
-drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
-{
-       drm_gem_object_put_unlocked(obj);
-}
-
-/**
- * drm_gem_object_unreference - release a GEM buffer object reference
- * @obj: GEM buffer object
- *
- * This is a compatibility alias for drm_gem_object_put() and should not be
- * used by new code.
- */
-static inline void drm_gem_object_unreference(struct drm_gem_object *obj)
-{
-       drm_gem_object_put(obj);
-}
-
 int drm_gem_handle_create(struct drm_file *file_priv,
                          struct drm_gem_object *obj,
                          u32 *handlep);
index f446656d00b1d335cdfd767c1aa2336e06a54d33..b1e5de076b0f46e3042782a1b1a0b3e11c00075b 100644 (file)
@@ -66,7 +66,7 @@ struct drm_v3d_submit_cl {
         */
        __u32 bcl_start;
 
-        /** End address of the BCL (first byte after the BCL) */
+       /** End address of the BCL (first byte after the BCL) */
        __u32 bcl_end;
 
        /* Offset of the render command list.
@@ -82,7 +82,7 @@ struct drm_v3d_submit_cl {
         */
        __u32 rcl_start;
 
-        /** End address of the RCL (first byte after the RCL) */
+       /** End address of the RCL (first byte after the RCL) */
        __u32 rcl_end;
 
        /** An optional sync object to wait on before starting the BCL. */
index f43c3c6171ffeb3725ef4d55e4f22b99a8f86a51..8e88eba1fa7a1c457d519a62f1dd51747cfad504 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/types.h>
 
 #define VIRTIO_GPU_F_VIRGL 0
+#define VIRTIO_GPU_F_EDID  1
 
 enum virtio_gpu_ctrl_type {
        VIRTIO_GPU_UNDEFINED = 0,
@@ -56,6 +57,7 @@ enum virtio_gpu_ctrl_type {
        VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING,
        VIRTIO_GPU_CMD_GET_CAPSET_INFO,
        VIRTIO_GPU_CMD_GET_CAPSET,
+       VIRTIO_GPU_CMD_GET_EDID,
 
        /* 3d commands */
        VIRTIO_GPU_CMD_CTX_CREATE = 0x0200,
@@ -76,6 +78,7 @@ enum virtio_gpu_ctrl_type {
        VIRTIO_GPU_RESP_OK_DISPLAY_INFO,
        VIRTIO_GPU_RESP_OK_CAPSET_INFO,
        VIRTIO_GPU_RESP_OK_CAPSET,
+       VIRTIO_GPU_RESP_OK_EDID,
 
        /* error responses */
        VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200,
@@ -291,6 +294,21 @@ struct virtio_gpu_resp_capset {
        __u8 capset_data[];
 };
 
+/* VIRTIO_GPU_CMD_GET_EDID */
+struct virtio_gpu_cmd_get_edid {
+       struct virtio_gpu_ctrl_hdr hdr;
+       __le32 scanout;
+       __le32 padding;
+};
+
+/* VIRTIO_GPU_RESP_OK_EDID */
+struct virtio_gpu_resp_edid {
+       struct virtio_gpu_ctrl_hdr hdr;
+       __le32 size;
+       __le32 padding;
+       __u8 edid[1024];
+};
+
 #define VIRTIO_GPU_EVENT_DISPLAY (1 << 0)
 
 struct virtio_gpu_config {
diff --git a/scripts/coccinelle/api/drm-get-put.cocci b/scripts/coccinelle/api/drm-get-put.cocci
deleted file mode 100644 (file)
index 3a09c97..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-///
-/// Use drm_*_get() and drm_*_put() helpers instead of drm_*_reference() and
-/// drm_*_unreference() helpers.
-///
-// Confidence: High
-// Copyright: (C) 2017 NVIDIA Corporation
-// Options: --no-includes --include-headers
-//
-
-virtual patch
-virtual report
-
-@depends on patch@
-expression object;
-@@
-
-(
-- drm_connector_reference(object)
-+ drm_connector_get(object)
-|
-- drm_connector_unreference(object)
-+ drm_connector_put(object)
-|
-- drm_framebuffer_reference(object)
-+ drm_framebuffer_get(object)
-|
-- drm_framebuffer_unreference(object)
-+ drm_framebuffer_put(object)
-|
-- drm_gem_object_reference(object)
-+ drm_gem_object_get(object)
-|
-- drm_gem_object_unreference(object)
-+ drm_gem_object_put(object)
-|
-- __drm_gem_object_unreference(object)
-+ __drm_gem_object_put(object)
-|
-- drm_gem_object_unreference_unlocked(object)
-+ drm_gem_object_put_unlocked(object)
-|
-- drm_dev_unref(object)
-+ drm_dev_put(object)
-)
-
-@r depends on report@
-expression object;
-position p;
-@@
-
-(
-drm_connector_unreference@p(object)
-|
-drm_connector_reference@p(object)
-|
-drm_framebuffer_unreference@p(object)
-|
-drm_framebuffer_reference@p(object)
-|
-drm_gem_object_unreference@p(object)
-|
-drm_gem_object_reference@p(object)
-|
-__drm_gem_object_unreference(object)
-|
-drm_gem_object_unreference_unlocked(object)
-|
-drm_dev_unref@p(object)
-)
-
-@script:python depends on report@
-object << r.object;
-p << r.p;
-@@
-
-msg="WARNING: use get/put helpers to reference and dereference %s" % (object)
-coccilib.report.print_report(p[0], msg)