aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/Makefile2
-rw-r--r--drivers/gpu/drm/arc/arcpgu_drv.c4
-rw-r--r--drivers/gpu/drm/bridge/tc358764.c2
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c7
-rw-r--r--drivers/gpu/drm/drm_debugfs.c89
-rw-r--r--drivers/gpu/drm/drm_drv.c13
-rw-r--r--drivers/gpu/drm/drm_info.c137
-rw-r--r--drivers/gpu/drm/drm_internal.h5
-rw-r--r--drivers/gpu/drm/drm_prime.c31
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.c4
-rw-r--r--drivers/gpu/drm/meson/meson_dw_hdmi.c12
-rw-r--r--drivers/gpu/drm/meson/meson_overlay.c2
-rw-r--r--drivers/gpu/drm/meson/meson_plane.c2
-rw-r--r--drivers/gpu/drm/meson/meson_vclk.c127
-rw-r--r--drivers/gpu/drm/meson/meson_vclk.h2
-rw-r--r--drivers/gpu/drm/meson/meson_venc.c129
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.c4
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c106
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.h3
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c12
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_frontend.c113
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_frontend.h11
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_layer.c15
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_ui_layer.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_vi_layer.c2
-rw-r--r--drivers/gpu/drm/tve200/tve200_drv.c4
-rw-r--r--drivers/gpu/drm/v3d/v3d_gem.c33
-rw-r--r--drivers/gpu/drm/v3d/v3d_sched.c2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_display.c12
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.c1
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h3
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_kms.c8
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vq.c67
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.c1
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.h3
-rw-r--r--drivers/gpu/drm/vkms/vkms_gem.c26
-rw-r--r--drivers/staging/vboxvideo/vbox_drv.c1
37 files changed, 669 insertions, 328 deletions
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 7f3be3506057..1fafc2f8e8f9 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -10,7 +10,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
10 drm_scatter.o drm_pci.o \ 10 drm_scatter.o drm_pci.o \
11 drm_sysfs.o drm_hashtab.o drm_mm.o \ 11 drm_sysfs.o drm_hashtab.o drm_mm.o \
12 drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \ 12 drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \
13 drm_info.o drm_encoder_slave.o \ 13 drm_encoder_slave.o \
14 drm_trace_points.o drm_prime.o \ 14 drm_trace_points.o drm_prime.o \
15 drm_rect.o drm_vma_manager.o drm_flip_work.o \ 15 drm_rect.o drm_vma_manager.o drm_flip_work.o \
16 drm_modeset_lock.o drm_atomic.o drm_bridge.o \ 16 drm_modeset_lock.o drm_atomic.o drm_bridge.o \
diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c
index 2af847ebca34..206a76abf771 100644
--- a/drivers/gpu/drm/arc/arcpgu_drv.c
+++ b/drivers/gpu/drm/arc/arcpgu_drv.c
@@ -190,7 +190,7 @@ err_unload:
190 arcpgu_unload(drm); 190 arcpgu_unload(drm);
191 191
192err_unref: 192err_unref:
193 drm_dev_unref(drm); 193 drm_dev_put(drm);
194 194
195 return ret; 195 return ret;
196} 196}
@@ -201,7 +201,7 @@ static int arcpgu_remove(struct platform_device *pdev)
201 201
202 drm_dev_unregister(drm); 202 drm_dev_unregister(drm);
203 arcpgu_unload(drm); 203 arcpgu_unload(drm);
204 drm_dev_unref(drm); 204 drm_dev_put(drm);
205 205
206 return 0; 206 return 0;
207} 207}
diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c
index ee6b98efa9c2..afd491018bfc 100644
--- a/drivers/gpu/drm/bridge/tc358764.c
+++ b/drivers/gpu/drm/bridge/tc358764.c
@@ -379,7 +379,7 @@ static void tc358764_detach(struct drm_bridge *bridge)
379 drm_fb_helper_remove_one_connector(drm->fb_helper, &ctx->connector); 379 drm_fb_helper_remove_one_connector(drm->fb_helper, &ctx->connector);
380 drm_panel_detach(ctx->panel); 380 drm_panel_detach(ctx->panel);
381 ctx->panel = NULL; 381 ctx->panel = NULL;
382 drm_connector_unreference(&ctx->connector); 382 drm_connector_put(&ctx->connector);
383} 383}
384 384
385static const struct drm_bridge_funcs tc358764_bridge_funcs = { 385static const struct drm_bridge_funcs tc358764_bridge_funcs = {
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index fa95f9974f6d..bc9fc9665614 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1460,6 +1460,9 @@ void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev,
1460 DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n", 1460 DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n",
1461 crtc->base.id, crtc->name); 1461 crtc->base.id, crtc->name);
1462 } 1462 }
1463
1464 if (old_state->fake_commit)
1465 complete_all(&old_state->fake_commit->flip_done);
1463} 1466}
1464EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done); 1467EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done);
1465 1468
@@ -2217,8 +2220,10 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state)
2217 spin_unlock(&crtc->commit_lock); 2220 spin_unlock(&crtc->commit_lock);
2218 } 2221 }
2219 2222
2220 if (old_state->fake_commit) 2223 if (old_state->fake_commit) {
2221 complete_all(&old_state->fake_commit->cleanup_done); 2224 complete_all(&old_state->fake_commit->cleanup_done);
2225 WARN_ON(!try_wait_for_completion(&old_state->fake_commit->hw_done));
2226 }
2222} 2227}
2223EXPORT_SYMBOL(drm_atomic_helper_commit_cleanup_done); 2228EXPORT_SYMBOL(drm_atomic_helper_commit_cleanup_done);
2224 2229
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 373bd4c2b698..f8468eae0503 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -32,6 +32,8 @@
32#include <drm/drm_debugfs.h> 32#include <drm/drm_debugfs.h>
33#include <drm/drm_edid.h> 33#include <drm/drm_edid.h>
34#include <drm/drm_atomic.h> 34#include <drm/drm_atomic.h>
35#include <drm/drm_auth.h>
36#include <drm/drm_gem.h>
35#include <drm/drmP.h> 37#include <drm/drmP.h>
36 38
37#include "drm_internal.h" 39#include "drm_internal.h"
@@ -43,6 +45,93 @@
43 * Initialization, etc. 45 * Initialization, etc.
44 **************************************************/ 46 **************************************************/
45 47
48static int drm_name_info(struct seq_file *m, void *data)
49{
50 struct drm_info_node *node = (struct drm_info_node *) m->private;
51 struct drm_minor *minor = node->minor;
52 struct drm_device *dev = minor->dev;
53 struct drm_master *master;
54
55 mutex_lock(&dev->master_mutex);
56 master = dev->master;
57 seq_printf(m, "%s", dev->driver->name);
58 if (dev->dev)
59 seq_printf(m, " dev=%s", dev_name(dev->dev));
60 if (master && master->unique)
61 seq_printf(m, " master=%s", master->unique);
62 if (dev->unique)
63 seq_printf(m, " unique=%s", dev->unique);
64 seq_printf(m, "\n");
65 mutex_unlock(&dev->master_mutex);
66
67 return 0;
68}
69
70static int drm_clients_info(struct seq_file *m, void *data)
71{
72 struct drm_info_node *node = (struct drm_info_node *) m->private;
73 struct drm_device *dev = node->minor->dev;
74 struct drm_file *priv;
75 kuid_t uid;
76
77 seq_printf(m,
78 "%20s %5s %3s master a %5s %10s\n",
79 "command",
80 "pid",
81 "dev",
82 "uid",
83 "magic");
84
85 /* dev->filelist is sorted youngest first, but we want to present
86 * oldest first (i.e. kernel, servers, clients), so walk backwardss.
87 */
88 mutex_lock(&dev->filelist_mutex);
89 list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
90 struct task_struct *task;
91
92 rcu_read_lock(); /* locks pid_task()->comm */
93 task = pid_task(priv->pid, PIDTYPE_PID);
94 uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID;
95 seq_printf(m, "%20s %5d %3d %c %c %5d %10u\n",
96 task ? task->comm : "<unknown>",
97 pid_vnr(priv->pid),
98 priv->minor->index,
99 drm_is_current_master(priv) ? 'y' : 'n',
100 priv->authenticated ? 'y' : 'n',
101 from_kuid_munged(seq_user_ns(m), uid),
102 priv->magic);
103 rcu_read_unlock();
104 }
105 mutex_unlock(&dev->filelist_mutex);
106 return 0;
107}
108
109static int drm_gem_one_name_info(int id, void *ptr, void *data)
110{
111 struct drm_gem_object *obj = ptr;
112 struct seq_file *m = data;
113
114 seq_printf(m, "%6d %8zd %7d %8d\n",
115 obj->name, obj->size,
116 obj->handle_count,
117 kref_read(&obj->refcount));
118 return 0;
119}
120
121static int drm_gem_name_info(struct seq_file *m, void *data)
122{
123 struct drm_info_node *node = (struct drm_info_node *) m->private;
124 struct drm_device *dev = node->minor->dev;
125
126 seq_printf(m, " name size handles refcount\n");
127
128 mutex_lock(&dev->object_name_lock);
129 idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m);
130 mutex_unlock(&dev->object_name_lock);
131
132 return 0;
133}
134
46static const struct drm_info_list drm_debugfs_list[] = { 135static const struct drm_info_list drm_debugfs_list[] = {
47 {"name", drm_name_info, 0}, 136 {"name", drm_name_info, 0},
48 {"clients", drm_clients_info, 0}, 137 {"clients", drm_clients_info, 0},
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index e2ffecd5e453..12e5e2be7890 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -704,19 +704,6 @@ void drm_dev_put(struct drm_device *dev)
704} 704}
705EXPORT_SYMBOL(drm_dev_put); 705EXPORT_SYMBOL(drm_dev_put);
706 706
707/**
708 * drm_dev_unref - Drop reference of a DRM device
709 * @dev: device to drop reference of or NULL
710 *
711 * This is a compatibility alias for drm_dev_put() and should not be used by new
712 * code.
713 */
714void drm_dev_unref(struct drm_device *dev)
715{
716 drm_dev_put(dev);
717}
718EXPORT_SYMBOL(drm_dev_unref);
719
720static int create_compat_control_link(struct drm_device *dev) 707static int create_compat_control_link(struct drm_device *dev)
721{ 708{
722 struct drm_minor *minor; 709 struct drm_minor *minor;
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
deleted file mode 100644
index 6b68e9088436..000000000000
--- a/drivers/gpu/drm/drm_info.c
+++ /dev/null
@@ -1,137 +0,0 @@
1/**
2 * \file drm_info.c
3 * DRM info file implementations
4 *
5 * \author Ben Gamari <bgamari@gmail.com>
6 */
7
8/*
9 * Created: Sun Dec 21 13:09:50 2008 by bgamari@gmail.com
10 *
11 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
12 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
13 * Copyright 2008 Ben Gamari <bgamari@gmail.com>
14 * All Rights Reserved.
15 *
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice (including the next
24 * paragraph) shall be included in all copies or substantial portions of the
25 * Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 */
35
36#include <linux/seq_file.h>
37#include <drm/drmP.h>
38#include <drm/drm_gem.h>
39
40#include "drm_internal.h"
41#include "drm_legacy.h"
42
43/**
44 * Called when "/proc/dri/.../name" is read.
45 *
46 * Prints the device name together with the bus id if available.
47 */
48int drm_name_info(struct seq_file *m, void *data)
49{
50 struct drm_info_node *node = (struct drm_info_node *) m->private;
51 struct drm_minor *minor = node->minor;
52 struct drm_device *dev = minor->dev;
53 struct drm_master *master;
54
55 mutex_lock(&dev->master_mutex);
56 master = dev->master;
57 seq_printf(m, "%s", dev->driver->name);
58 if (dev->dev)
59 seq_printf(m, " dev=%s", dev_name(dev->dev));
60 if (master && master->unique)
61 seq_printf(m, " master=%s", master->unique);
62 if (dev->unique)
63 seq_printf(m, " unique=%s", dev->unique);
64 seq_printf(m, "\n");
65 mutex_unlock(&dev->master_mutex);
66
67 return 0;
68}
69
70/**
71 * Called when "/proc/dri/.../clients" is read.
72 *
73 */
74int drm_clients_info(struct seq_file *m, void *data)
75{
76 struct drm_info_node *node = (struct drm_info_node *) m->private;
77 struct drm_device *dev = node->minor->dev;
78 struct drm_file *priv;
79 kuid_t uid;
80
81 seq_printf(m,
82 "%20s %5s %3s master a %5s %10s\n",
83 "command",
84 "pid",
85 "dev",
86 "uid",
87 "magic");
88
89 /* dev->filelist is sorted youngest first, but we want to present
90 * oldest first (i.e. kernel, servers, clients), so walk backwardss.
91 */
92 mutex_lock(&dev->filelist_mutex);
93 list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
94 struct task_struct *task;
95
96 rcu_read_lock(); /* locks pid_task()->comm */
97 task = pid_task(priv->pid, PIDTYPE_PID);
98 uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID;
99 seq_printf(m, "%20s %5d %3d %c %c %5d %10u\n",
100 task ? task->comm : "<unknown>",
101 pid_vnr(priv->pid),
102 priv->minor->index,
103 drm_is_current_master(priv) ? 'y' : 'n',
104 priv->authenticated ? 'y' : 'n',
105 from_kuid_munged(seq_user_ns(m), uid),
106 priv->magic);
107 rcu_read_unlock();
108 }
109 mutex_unlock(&dev->filelist_mutex);
110 return 0;
111}
112
113static int drm_gem_one_name_info(int id, void *ptr, void *data)
114{
115 struct drm_gem_object *obj = ptr;
116 struct seq_file *m = data;
117
118 seq_printf(m, "%6d %8zd %7d %8d\n",
119 obj->name, obj->size,
120 obj->handle_count,
121 kref_read(&obj->refcount));
122 return 0;
123}
124
125int drm_gem_name_info(struct seq_file *m, void *data)
126{
127 struct drm_info_node *node = (struct drm_info_node *) m->private;
128 struct drm_device *dev = node->minor->dev;
129
130 seq_printf(m, " name size handles refcount\n");
131
132 mutex_lock(&dev->object_name_lock);
133 idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m);
134 mutex_unlock(&dev->object_name_lock);
135
136 return 0;
137}
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 0c4eb4a9ab31..c7a7d7ce5d1c 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -56,11 +56,6 @@ void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpr
56struct drm_minor *drm_minor_acquire(unsigned int minor_id); 56struct drm_minor *drm_minor_acquire(unsigned int minor_id);
57void drm_minor_release(struct drm_minor *minor); 57void drm_minor_release(struct drm_minor *minor);
58 58
59/* drm_info.c */
60int drm_name_info(struct seq_file *m, void *data);
61int drm_clients_info(struct seq_file *m, void* data);
62int drm_gem_name_info(struct seq_file *m, void *data);
63
64/* drm_vblank.c */ 59/* drm_vblank.c */
65void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe); 60void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe);
66void drm_vblank_cleanup(struct drm_device *dev); 61void drm_vblank_cleanup(struct drm_device *dev);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 5737cb8c6f03..231e3f6d5f41 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -663,24 +663,33 @@ EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
663 */ 663 */
664int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) 664int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
665{ 665{
666 /* Used by drm_gem_mmap() to lookup the GEM object */ 666 struct drm_file *priv;
667 struct drm_file priv = { 667 struct file *fil;
668 .minor = obj->dev->primary,
669 };
670 struct file fil = {
671 .private_data = &priv,
672 };
673 int ret; 668 int ret;
674 669
675 ret = drm_vma_node_allow(&obj->vma_node, &priv); 670 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
671 fil = kzalloc(sizeof(*fil), GFP_KERNEL);
672 if (!priv || !fil) {
673 ret = -ENOMEM;
674 goto out;
675 }
676
677 /* Used by drm_gem_mmap() to lookup the GEM object */
678 priv->minor = obj->dev->primary;
679 fil->private_data = priv;
680
681 ret = drm_vma_node_allow(&obj->vma_node, priv);
676 if (ret) 682 if (ret)
677 return ret; 683 goto out;
678 684
679 vma->vm_pgoff += drm_vma_node_start(&obj->vma_node); 685 vma->vm_pgoff += drm_vma_node_start(&obj->vma_node);
680 686
681 ret = obj->dev->driver->fops->mmap(&fil, vma); 687 ret = obj->dev->driver->fops->mmap(fil, vma);
682 688
683 drm_vma_node_revoke(&obj->vma_node, &priv); 689 drm_vma_node_revoke(&obj->vma_node, priv);
690out:
691 kfree(priv);
692 kfree(fil);
684 693
685 return ret; 694 return ret;
686} 695}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 83c1f46670bf..52802e6049e0 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -550,7 +550,7 @@ out_register:
550out_bind: 550out_bind:
551 kfree(priv); 551 kfree(priv);
552out_unref: 552out_unref:
553 drm_dev_unref(drm); 553 drm_dev_put(drm);
554 554
555 return ret; 555 return ret;
556} 556}
@@ -567,7 +567,7 @@ static void etnaviv_unbind(struct device *dev)
567 drm->dev_private = NULL; 567 drm->dev_private = NULL;
568 kfree(priv); 568 kfree(priv);
569 569
570 drm_dev_unref(drm); 570 drm_dev_put(drm);
571} 571}
572 572
573static const struct component_master_ops etnaviv_master_ops = { 573static const struct component_master_ops etnaviv_master_ops = {
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
index df7247cd93f9..d8c5cc34e22e 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
@@ -594,17 +594,7 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
594 dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__, 594 dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__,
595 vclk_freq, venc_freq, hdmi_freq); 595 vclk_freq, venc_freq, hdmi_freq);
596 596
597 /* Finally filter by configurable vclk frequencies for VIC modes */ 597 return meson_vclk_vic_supported_freq(vclk_freq);
598 switch (vclk_freq) {
599 case 54000:
600 case 74250:
601 case 148500:
602 case 297000:
603 case 594000:
604 return MODE_OK;
605 }
606
607 return MODE_CLOCK_RANGE;
608} 598}
609 599
610/* Encoder */ 600/* Encoder */
diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c
index 9aebc5e4b418..691a9fd16b36 100644
--- a/drivers/gpu/drm/meson/meson_overlay.c
+++ b/drivers/gpu/drm/meson/meson_overlay.c
@@ -16,6 +16,7 @@
16#include <drm/drm_plane_helper.h> 16#include <drm/drm_plane_helper.h>
17#include <drm/drm_gem_cma_helper.h> 17#include <drm/drm_gem_cma_helper.h>
18#include <drm/drm_fb_cma_helper.h> 18#include <drm/drm_fb_cma_helper.h>
19#include <drm/drm_gem_framebuffer_helper.h>
19#include <drm/drm_rect.h> 20#include <drm/drm_rect.h>
20 21
21#include "meson_overlay.h" 22#include "meson_overlay.h"
@@ -532,6 +533,7 @@ static const struct drm_plane_helper_funcs meson_overlay_helper_funcs = {
532 .atomic_check = meson_overlay_atomic_check, 533 .atomic_check = meson_overlay_atomic_check,
533 .atomic_disable = meson_overlay_atomic_disable, 534 .atomic_disable = meson_overlay_atomic_disable,
534 .atomic_update = meson_overlay_atomic_update, 535 .atomic_update = meson_overlay_atomic_update,
536 .prepare_fb = drm_gem_fb_prepare_fb,
535}; 537};
536 538
537static const struct drm_plane_funcs meson_overlay_funcs = { 539static const struct drm_plane_funcs meson_overlay_funcs = {
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index 12a47b4f65a5..8ee2cf9e47cd 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -32,6 +32,7 @@
32#include <drm/drm_plane_helper.h> 32#include <drm/drm_plane_helper.h>
33#include <drm/drm_gem_cma_helper.h> 33#include <drm/drm_gem_cma_helper.h>
34#include <drm/drm_fb_cma_helper.h> 34#include <drm/drm_fb_cma_helper.h>
35#include <drm/drm_gem_framebuffer_helper.h>
35#include <drm/drm_rect.h> 36#include <drm/drm_rect.h>
36 37
37#include "meson_plane.h" 38#include "meson_plane.h"
@@ -322,6 +323,7 @@ static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
322 .atomic_check = meson_plane_atomic_check, 323 .atomic_check = meson_plane_atomic_check,
323 .atomic_disable = meson_plane_atomic_disable, 324 .atomic_disable = meson_plane_atomic_disable,
324 .atomic_update = meson_plane_atomic_update, 325 .atomic_update = meson_plane_atomic_update,
326 .prepare_fb = drm_gem_fb_prepare_fb,
325}; 327};
326 328
327static const struct drm_plane_funcs meson_plane_funcs = { 329static const struct drm_plane_funcs meson_plane_funcs = {
diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
index ae5473257f72..f6ba35a405f8 100644
--- a/drivers/gpu/drm/meson/meson_vclk.c
+++ b/drivers/gpu/drm/meson/meson_vclk.c
@@ -117,6 +117,8 @@
117#define HDMI_PLL_RESET BIT(28) 117#define HDMI_PLL_RESET BIT(28)
118#define HDMI_PLL_LOCK BIT(31) 118#define HDMI_PLL_LOCK BIT(31)
119 119
120#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
121
120/* VID PLL Dividers */ 122/* VID PLL Dividers */
121enum { 123enum {
122 VID_PLL_DIV_1 = 0, 124 VID_PLL_DIV_1 = 0,
@@ -323,7 +325,7 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
323enum { 325enum {
324/* PLL O1 O2 O3 VP DV EN TX */ 326/* PLL O1 O2 O3 VP DV EN TX */
325/* 4320 /4 /4 /1 /5 /1 => /2 /2 */ 327/* 4320 /4 /4 /1 /5 /1 => /2 /2 */
326 MESON_VCLK_HDMI_ENCI_54000 = 1, 328 MESON_VCLK_HDMI_ENCI_54000 = 0,
327/* 4320 /4 /4 /1 /5 /1 => /1 /2 */ 329/* 4320 /4 /4 /1 /5 /1 => /1 /2 */
328 MESON_VCLK_HDMI_DDR_54000, 330 MESON_VCLK_HDMI_DDR_54000,
329/* 2970 /4 /1 /1 /5 /1 => /1 /2 */ 331/* 2970 /4 /1 /1 /5 /1 => /1 /2 */
@@ -339,6 +341,7 @@ enum {
339}; 341};
340 342
341struct meson_vclk_params { 343struct meson_vclk_params {
344 unsigned int pixel_freq;
342 unsigned int pll_base_freq; 345 unsigned int pll_base_freq;
343 unsigned int pll_od1; 346 unsigned int pll_od1;
344 unsigned int pll_od2; 347 unsigned int pll_od2;
@@ -347,6 +350,7 @@ struct meson_vclk_params {
347 unsigned int vclk_div; 350 unsigned int vclk_div;
348} params[] = { 351} params[] = {
349 [MESON_VCLK_HDMI_ENCI_54000] = { 352 [MESON_VCLK_HDMI_ENCI_54000] = {
353 .pixel_freq = 54000,
350 .pll_base_freq = 4320000, 354 .pll_base_freq = 4320000,
351 .pll_od1 = 4, 355 .pll_od1 = 4,
352 .pll_od2 = 4, 356 .pll_od2 = 4,
@@ -355,6 +359,7 @@ struct meson_vclk_params {
355 .vclk_div = 1, 359 .vclk_div = 1,
356 }, 360 },
357 [MESON_VCLK_HDMI_DDR_54000] = { 361 [MESON_VCLK_HDMI_DDR_54000] = {
362 .pixel_freq = 54000,
358 .pll_base_freq = 4320000, 363 .pll_base_freq = 4320000,
359 .pll_od1 = 4, 364 .pll_od1 = 4,
360 .pll_od2 = 4, 365 .pll_od2 = 4,
@@ -363,6 +368,7 @@ struct meson_vclk_params {
363 .vclk_div = 1, 368 .vclk_div = 1,
364 }, 369 },
365 [MESON_VCLK_HDMI_DDR_148500] = { 370 [MESON_VCLK_HDMI_DDR_148500] = {
371 .pixel_freq = 148500,
366 .pll_base_freq = 2970000, 372 .pll_base_freq = 2970000,
367 .pll_od1 = 4, 373 .pll_od1 = 4,
368 .pll_od2 = 1, 374 .pll_od2 = 1,
@@ -371,6 +377,7 @@ struct meson_vclk_params {
371 .vclk_div = 1, 377 .vclk_div = 1,
372 }, 378 },
373 [MESON_VCLK_HDMI_74250] = { 379 [MESON_VCLK_HDMI_74250] = {
380 .pixel_freq = 74250,
374 .pll_base_freq = 2970000, 381 .pll_base_freq = 2970000,
375 .pll_od1 = 2, 382 .pll_od1 = 2,
376 .pll_od2 = 2, 383 .pll_od2 = 2,
@@ -379,6 +386,7 @@ struct meson_vclk_params {
379 .vclk_div = 1, 386 .vclk_div = 1,
380 }, 387 },
381 [MESON_VCLK_HDMI_148500] = { 388 [MESON_VCLK_HDMI_148500] = {
389 .pixel_freq = 148500,
382 .pll_base_freq = 2970000, 390 .pll_base_freq = 2970000,
383 .pll_od1 = 1, 391 .pll_od1 = 1,
384 .pll_od2 = 2, 392 .pll_od2 = 2,
@@ -387,6 +395,7 @@ struct meson_vclk_params {
387 .vclk_div = 1, 395 .vclk_div = 1,
388 }, 396 },
389 [MESON_VCLK_HDMI_297000] = { 397 [MESON_VCLK_HDMI_297000] = {
398 .pixel_freq = 297000,
390 .pll_base_freq = 2970000, 399 .pll_base_freq = 2970000,
391 .pll_od1 = 1, 400 .pll_od1 = 1,
392 .pll_od2 = 1, 401 .pll_od2 = 1,
@@ -395,6 +404,7 @@ struct meson_vclk_params {
395 .vclk_div = 2, 404 .vclk_div = 2,
396 }, 405 },
397 [MESON_VCLK_HDMI_594000] = { 406 [MESON_VCLK_HDMI_594000] = {
407 .pixel_freq = 594000,
398 .pll_base_freq = 5940000, 408 .pll_base_freq = 5940000,
399 .pll_od1 = 1, 409 .pll_od1 = 1,
400 .pll_od2 = 1, 410 .pll_od2 = 1,
@@ -402,6 +412,7 @@ struct meson_vclk_params {
402 .vid_pll_div = VID_PLL_DIV_5, 412 .vid_pll_div = VID_PLL_DIV_5,
403 .vclk_div = 1, 413 .vclk_div = 1,
404 }, 414 },
415 { /* sentinel */ },
405}; 416};
406 417
407static inline unsigned int pll_od_to_reg(unsigned int od) 418static 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,
626 pll_freq); 637 pll_freq);
627} 638}
628 639
640enum drm_mode_status
641meson_vclk_vic_supported_freq(unsigned int freq)
642{
643 int i;
644
645 DRM_DEBUG_DRIVER("freq = %d\n", freq);
646
647 for (i = 0 ; params[i].pixel_freq ; ++i) {
648 DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
649 i, params[i].pixel_freq,
650 FREQ_1000_1001(params[i].pixel_freq));
651 /* Match strict frequency */
652 if (freq == params[i].pixel_freq)
653 return MODE_OK;
654 /* Match 1000/1001 variant */
655 if (freq == FREQ_1000_1001(params[i].pixel_freq))
656 return MODE_OK;
657 }
658
659 return MODE_CLOCK_RANGE;
660}
661EXPORT_SYMBOL_GPL(meson_vclk_vic_supported_freq);
662
629static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq, 663static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
630 unsigned int od1, unsigned int od2, unsigned int od3, 664 unsigned int od1, unsigned int od2, unsigned int od3,
631 unsigned int vid_pll_div, unsigned int vclk_div, 665 unsigned int vid_pll_div, unsigned int vclk_div,
632 unsigned int hdmi_tx_div, unsigned int venc_div, 666 unsigned int hdmi_tx_div, unsigned int venc_div,
633 bool hdmi_use_enci) 667 bool hdmi_use_enci, bool vic_alternate_clock)
634{ 668{
669 unsigned int m = 0, frac = 0;
670
635 /* Set HDMI-TX sys clock */ 671 /* Set HDMI-TX sys clock */
636 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 672 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
637 CTS_HDMI_SYS_SEL_MASK, 0); 673 CTS_HDMI_SYS_SEL_MASK, 0);
@@ -646,34 +682,38 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
646 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) { 682 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
647 switch (pll_base_freq) { 683 switch (pll_base_freq) {
648 case 2970000: 684 case 2970000:
649 meson_hdmi_pll_set_params(priv, 0x3d, 0xe00, 685 m = 0x3d;
650 od1, od2, od3); 686 frac = vic_alternate_clock ? 0xd02 : 0xe00;
651 break; 687 break;
652 case 4320000: 688 case 4320000:
653 meson_hdmi_pll_set_params(priv, 0x5a, 0, 689 m = vic_alternate_clock ? 0x59 : 0x5a;
654 od1, od2, od3); 690 frac = vic_alternate_clock ? 0xe8f : 0;
655 break; 691 break;
656 case 5940000: 692 case 5940000:
657 meson_hdmi_pll_set_params(priv, 0x7b, 0xc00, 693 m = 0x7b;
658 od1, od2, od3); 694 frac = vic_alternate_clock ? 0xa05 : 0xc00;
659 break; 695 break;
660 } 696 }
697
698 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
661 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || 699 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
662 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) { 700 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
663 switch (pll_base_freq) { 701 switch (pll_base_freq) {
664 case 2970000: 702 case 2970000:
665 meson_hdmi_pll_set_params(priv, 0x7b, 0x300, 703 m = 0x7b;
666 od1, od2, od3); 704 frac = vic_alternate_clock ? 0x281 : 0x300;
667 break; 705 break;
668 case 4320000: 706 case 4320000:
669 meson_hdmi_pll_set_params(priv, 0xb4, 0, 707 m = vic_alternate_clock ? 0xb3 : 0xb4;
670 od1, od2, od3); 708 frac = vic_alternate_clock ? 0x347 : 0;
671 break; 709 break;
672 case 5940000: 710 case 5940000:
673 meson_hdmi_pll_set_params(priv, 0xf7, 0x200, 711 m = 0xf7;
674 od1, od2, od3); 712 frac = vic_alternate_clock ? 0x102 : 0x200;
675 break; 713 break;
676 } 714 }
715
716 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
677 } 717 }
678 718
679 /* Setup vid_pll divider */ 719 /* Setup vid_pll divider */
@@ -826,6 +866,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
826 unsigned int vclk_freq, unsigned int venc_freq, 866 unsigned int vclk_freq, unsigned int venc_freq,
827 unsigned int dac_freq, bool hdmi_use_enci) 867 unsigned int dac_freq, bool hdmi_use_enci)
828{ 868{
869 bool vic_alternate_clock = false;
829 unsigned int freq; 870 unsigned int freq;
830 unsigned int hdmi_tx_div; 871 unsigned int hdmi_tx_div;
831 unsigned int venc_div; 872 unsigned int venc_div;
@@ -843,7 +884,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
843 * - encp encoder 884 * - encp encoder
844 */ 885 */
845 meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0, 886 meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
846 VID_PLL_DIV_5, 2, 1, 1, false); 887 VID_PLL_DIV_5, 2, 1, 1, false, false);
847 return; 888 return;
848 } 889 }
849 890
@@ -863,31 +904,35 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
863 return; 904 return;
864 } 905 }
865 906
866 switch (vclk_freq) { 907 for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
867 case 54000: 908 if (vclk_freq == params[freq].pixel_freq ||
868 if (hdmi_use_enci) 909 vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
869 freq = MESON_VCLK_HDMI_ENCI_54000; 910 if (vclk_freq != params[freq].pixel_freq)
870 else 911 vic_alternate_clock = true;
871 freq = MESON_VCLK_HDMI_DDR_54000; 912 else
872 break; 913 vic_alternate_clock = false;
873 case 74250: 914
874 freq = MESON_VCLK_HDMI_74250; 915 if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
875 break; 916 !hdmi_use_enci)
876 case 148500: 917 continue;
877 if (dac_freq != 148500) 918
878 freq = MESON_VCLK_HDMI_DDR_148500; 919 if (freq == MESON_VCLK_HDMI_DDR_54000 &&
879 else 920 hdmi_use_enci)
880 freq = MESON_VCLK_HDMI_148500; 921 continue;
881 break; 922
882 case 297000: 923 if (freq == MESON_VCLK_HDMI_DDR_148500 &&
883 freq = MESON_VCLK_HDMI_297000; 924 dac_freq == vclk_freq)
884 break; 925 continue;
885 case 594000: 926
886 freq = MESON_VCLK_HDMI_594000; 927 if (freq == MESON_VCLK_HDMI_148500 &&
887 break; 928 dac_freq != vclk_freq)
888 default: 929 continue;
889 pr_err("Fatal Error, invalid HDMI vclk freq %d\n", 930 break;
890 vclk_freq); 931 }
932 }
933
934 if (!params[freq].pixel_freq) {
935 pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
891 return; 936 return;
892 } 937 }
893 938
@@ -895,6 +940,6 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
895 params[freq].pll_od1, params[freq].pll_od2, 940 params[freq].pll_od1, params[freq].pll_od2,
896 params[freq].pll_od3, params[freq].vid_pll_div, 941 params[freq].pll_od3, params[freq].vid_pll_div,
897 params[freq].vclk_div, hdmi_tx_div, venc_div, 942 params[freq].vclk_div, hdmi_tx_div, venc_div,
898 hdmi_use_enci); 943 hdmi_use_enci, vic_alternate_clock);
899} 944}
900EXPORT_SYMBOL_GPL(meson_vclk_setup); 945EXPORT_SYMBOL_GPL(meson_vclk_setup);
diff --git a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h
index 869fa3a3073e..4bd8752da02a 100644
--- a/drivers/gpu/drm/meson/meson_vclk.h
+++ b/drivers/gpu/drm/meson/meson_vclk.h
@@ -32,6 +32,8 @@ enum {
32 32
33enum drm_mode_status 33enum drm_mode_status
34meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq); 34meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq);
35enum drm_mode_status
36meson_vclk_vic_supported_freq(unsigned int freq);
35 37
36void meson_vclk_setup(struct meson_drm *priv, unsigned int target, 38void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
37 unsigned int vclk_freq, unsigned int venc_freq, 39 unsigned int vclk_freq, unsigned int venc_freq,
diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
index acbbad3e322c..e95e0e7a7fa1 100644
--- a/drivers/gpu/drm/meson/meson_venc.c
+++ b/drivers/gpu/drm/meson/meson_venc.c
@@ -697,6 +697,132 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
697 }, 697 },
698}; 698};
699 699
700union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p24 = {
701 .encp = {
702 .dvi_settings = 0x1,
703 .video_mode = 0x4040,
704 .video_mode_adv = 0x8,
705 /* video_sync_mode */
706 /* video_yc_dly */
707 /* video_rgb_ctrl */
708 .video_filt_ctrl = 0x1000,
709 .video_filt_ctrl_present = true,
710 /* video_ofld_voav_ofst */
711 .yfp1_htime = 140,
712 .yfp2_htime = 140+3840,
713 .max_pxcnt = 3840+1660-1,
714 .hspuls_begin = 2156+1920,
715 .hspuls_end = 44,
716 .hspuls_switch = 44,
717 .vspuls_begin = 140,
718 .vspuls_end = 2059+1920,
719 .vspuls_bline = 0,
720 .vspuls_eline = 4,
721 .havon_begin = 148,
722 .havon_end = 3987,
723 .vavon_bline = 89,
724 .vavon_eline = 2248,
725 /* eqpuls_begin */
726 /* eqpuls_end */
727 /* eqpuls_bline */
728 /* eqpuls_eline */
729 .hso_begin = 44,
730 .hso_end = 2156+1920,
731 .vso_begin = 2100+1920,
732 .vso_end = 2164+1920,
733 .vso_bline = 51,
734 .vso_eline = 53,
735 .vso_eline_present = true,
736 /* sy_val */
737 /* sy2_val */
738 .max_lncnt = 2249,
739 },
740};
741
742union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p25 = {
743 .encp = {
744 .dvi_settings = 0x1,
745 .video_mode = 0x4040,
746 .video_mode_adv = 0x8,
747 /* video_sync_mode */
748 /* video_yc_dly */
749 /* video_rgb_ctrl */
750 .video_filt_ctrl = 0x1000,
751 .video_filt_ctrl_present = true,
752 /* video_ofld_voav_ofst */
753 .yfp1_htime = 140,
754 .yfp2_htime = 140+3840,
755 .max_pxcnt = 3840+1440-1,
756 .hspuls_begin = 2156+1920,
757 .hspuls_end = 44,
758 .hspuls_switch = 44,
759 .vspuls_begin = 140,
760 .vspuls_end = 2059+1920,
761 .vspuls_bline = 0,
762 .vspuls_eline = 4,
763 .havon_begin = 148,
764 .havon_end = 3987,
765 .vavon_bline = 89,
766 .vavon_eline = 2248,
767 /* eqpuls_begin */
768 /* eqpuls_end */
769 /* eqpuls_bline */
770 /* eqpuls_eline */
771 .hso_begin = 44,
772 .hso_end = 2156+1920,
773 .vso_begin = 2100+1920,
774 .vso_end = 2164+1920,
775 .vso_bline = 51,
776 .vso_eline = 53,
777 .vso_eline_present = true,
778 /* sy_val */
779 /* sy2_val */
780 .max_lncnt = 2249,
781 },
782};
783
784union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p30 = {
785 .encp = {
786 .dvi_settings = 0x1,
787 .video_mode = 0x4040,
788 .video_mode_adv = 0x8,
789 /* video_sync_mode */
790 /* video_yc_dly */
791 /* video_rgb_ctrl */
792 .video_filt_ctrl = 0x1000,
793 .video_filt_ctrl_present = true,
794 /* video_ofld_voav_ofst */
795 .yfp1_htime = 140,
796 .yfp2_htime = 140+3840,
797 .max_pxcnt = 3840+560-1,
798 .hspuls_begin = 2156+1920,
799 .hspuls_end = 44,
800 .hspuls_switch = 44,
801 .vspuls_begin = 140,
802 .vspuls_end = 2059+1920,
803 .vspuls_bline = 0,
804 .vspuls_eline = 4,
805 .havon_begin = 148,
806 .havon_end = 3987,
807 .vavon_bline = 89,
808 .vavon_eline = 2248,
809 /* eqpuls_begin */
810 /* eqpuls_end */
811 /* eqpuls_bline */
812 /* eqpuls_eline */
813 .hso_begin = 44,
814 .hso_end = 2156+1920,
815 .vso_begin = 2100+1920,
816 .vso_end = 2164+1920,
817 .vso_bline = 51,
818 .vso_eline = 53,
819 .vso_eline_present = true,
820 /* sy_val */
821 /* sy2_val */
822 .max_lncnt = 2249,
823 },
824};
825
700struct meson_hdmi_venc_vic_mode { 826struct meson_hdmi_venc_vic_mode {
701 unsigned int vic; 827 unsigned int vic;
702 union meson_hdmi_venc_mode *mode; 828 union meson_hdmi_venc_mode *mode;
@@ -717,6 +843,9 @@ struct meson_hdmi_venc_vic_mode {
717 { 34, &meson_hdmi_encp_mode_1080p30 }, 843 { 34, &meson_hdmi_encp_mode_1080p30 },
718 { 31, &meson_hdmi_encp_mode_1080p50 }, 844 { 31, &meson_hdmi_encp_mode_1080p50 },
719 { 16, &meson_hdmi_encp_mode_1080p60 }, 845 { 16, &meson_hdmi_encp_mode_1080p60 },
846 { 93, &meson_hdmi_encp_mode_2160p24 },
847 { 94, &meson_hdmi_encp_mode_2160p25 },
848 { 95, &meson_hdmi_encp_mode_2160p30 },
720 { 0, NULL}, /* sentinel */ 849 { 0, NULL}, /* sentinel */
721}; 850};
722 851
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 2393e6d16ffd..88ba003979e6 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -417,7 +417,7 @@ static int mxsfb_probe(struct platform_device *pdev)
417err_unload: 417err_unload:
418 mxsfb_unload(drm); 418 mxsfb_unload(drm);
419err_free: 419err_free:
420 drm_dev_unref(drm); 420 drm_dev_put(drm);
421 421
422 return ret; 422 return ret;
423} 423}
@@ -428,7 +428,7 @@ static int mxsfb_remove(struct platform_device *pdev)
428 428
429 drm_dev_unregister(drm); 429 drm_dev_unregister(drm);
430 mxsfb_unload(drm); 430 mxsfb_unload(drm);
431 drm_dev_unref(drm); 431 drm_dev_put(drm);
432 432
433 return 0; 433 return 0;
434} 434}
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index bf49c55b0f2c..9e9255ee59cd 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -48,8 +48,12 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
48/* 48/*
49 * These coefficients are taken from the A33 BSP from Allwinner. 49 * These coefficients are taken from the A33 BSP from Allwinner.
50 * 50 *
51 * The formula is for each component, each coefficient being multiplied by 51 * The first three values of each row are coded as 13-bit signed fixed-point
52 * 1024 and each constant being multiplied by 16: 52 * numbers, with 10 bits for the fractional part. The fourth value is a
53 * constant coded as a 14-bit signed fixed-point number with 4 bits for the
54 * fractional part.
55 *
56 * The values in table order give the following colorspace translation:
53 * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135 57 * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135
54 * R = 1.164 * Y + 1.596 * V - 222 58 * R = 1.164 * Y + 1.596 * V - 222
55 * B = 1.164 * Y + 2.018 * U + 276 59 * B = 1.164 * Y + 2.018 * U + 276
@@ -155,6 +159,36 @@ static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode)
155 return 0; 159 return 0;
156} 160}
157 161
162static const uint32_t sun4i_backend_formats[] = {
163 DRM_FORMAT_ARGB1555,
164 DRM_FORMAT_ARGB4444,
165 DRM_FORMAT_ARGB8888,
166 DRM_FORMAT_BGRX8888,
167 DRM_FORMAT_RGB565,
168 DRM_FORMAT_RGB888,
169 DRM_FORMAT_RGBA4444,
170 DRM_FORMAT_RGBA5551,
171 DRM_FORMAT_UYVY,
172 DRM_FORMAT_VYUY,
173 DRM_FORMAT_XRGB8888,
174 DRM_FORMAT_YUYV,
175 DRM_FORMAT_YVYU,
176};
177
178bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier)
179{
180 unsigned int i;
181
182 if (modifier != DRM_FORMAT_MOD_LINEAR)
183 return false;
184
185 for (i = 0; i < ARRAY_SIZE(sun4i_backend_formats); i++)
186 if (sun4i_backend_formats[i] == fmt)
187 return true;
188
189 return false;
190}
191
158int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, 192int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
159 int layer, struct drm_plane *plane) 193 int layer, struct drm_plane *plane)
160{ 194{
@@ -395,6 +429,15 @@ int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer,
395 return 0; 429 return 0;
396} 430}
397 431
432void sun4i_backend_cleanup_layer(struct sun4i_backend *backend,
433 int layer)
434{
435 regmap_update_bits(backend->engine.regs,
436 SUN4I_BACKEND_ATTCTL_REG0(layer),
437 SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN |
438 SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN, 0);
439}
440
398static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state) 441static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state)
399{ 442{
400 u16 src_h = state->src_h >> 16; 443 u16 src_h = state->src_h >> 16;
@@ -413,11 +456,50 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state)
413{ 456{
414 struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane); 457 struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane);
415 struct sun4i_backend *backend = layer->backend; 458 struct sun4i_backend *backend = layer->backend;
459 uint32_t format = state->fb->format->format;
460 uint64_t modifier = state->fb->modifier;
416 461
417 if (IS_ERR(backend->frontend)) 462 if (IS_ERR(backend->frontend))
418 return false; 463 return false;
419 464
420 return sun4i_backend_plane_uses_scaler(state); 465 if (!sun4i_frontend_format_is_supported(format, modifier))
466 return false;
467
468 if (!sun4i_backend_format_is_supported(format, modifier))
469 return true;
470
471 /*
472 * TODO: The backend alone allows 2x and 4x integer scaling, including
473 * support for an alpha component (which the frontend doesn't support).
474 * Use the backend directly instead of the frontend in this case, with
475 * another test to return false.
476 */
477
478 if (sun4i_backend_plane_uses_scaler(state))
479 return true;
480
481 /*
482 * Here the format is supported by both the frontend and the backend
483 * and no frontend scaling is required, so use the backend directly.
484 */
485 return false;
486}
487
488static bool sun4i_backend_plane_is_supported(struct drm_plane_state *state,
489 bool *uses_frontend)
490{
491 if (sun4i_backend_plane_uses_frontend(state)) {
492 *uses_frontend = true;
493 return true;
494 }
495
496 *uses_frontend = false;
497
498 /* Scaling is not supported without the frontend. */
499 if (sun4i_backend_plane_uses_scaler(state))
500 return false;
501
502 return true;
421} 503}
422 504
423static void sun4i_backend_atomic_begin(struct sunxi_engine *engine, 505static void sun4i_backend_atomic_begin(struct sunxi_engine *engine,
@@ -460,14 +542,19 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
460 struct drm_framebuffer *fb = plane_state->fb; 542 struct drm_framebuffer *fb = plane_state->fb;
461 struct drm_format_name_buf format_name; 543 struct drm_format_name_buf format_name;
462 544
463 if (sun4i_backend_plane_uses_frontend(plane_state)) { 545 if (!sun4i_backend_plane_is_supported(plane_state,
546 &layer_state->uses_frontend))
547 return -EINVAL;
548
549 if (layer_state->uses_frontend) {
464 DRM_DEBUG_DRIVER("Using the frontend for plane %d\n", 550 DRM_DEBUG_DRIVER("Using the frontend for plane %d\n",
465 plane->index); 551 plane->index);
466
467 layer_state->uses_frontend = true;
468 num_frontend_planes++; 552 num_frontend_planes++;
469 } else { 553 } else {
470 layer_state->uses_frontend = false; 554 if (fb->format->is_yuv) {
555 DRM_DEBUG_DRIVER("Plane FB format is YUV\n");
556 num_yuv_planes++;
557 }
471 } 558 }
472 559
473 DRM_DEBUG_DRIVER("Plane FB format is %s\n", 560 DRM_DEBUG_DRIVER("Plane FB format is %s\n",
@@ -476,11 +563,6 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
476 if (fb->format->has_alpha || (plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE)) 563 if (fb->format->has_alpha || (plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE))
477 num_alpha_planes++; 564 num_alpha_planes++;
478 565
479 if (fb->format->is_yuv) {
480 DRM_DEBUG_DRIVER("Plane FB format is YUV\n");
481 num_yuv_planes++;
482 }
483
484 DRM_DEBUG_DRIVER("Plane zpos is %d\n", 566 DRM_DEBUG_DRIVER("Plane zpos is %d\n",
485 plane_state->normalized_zpos); 567 plane_state->normalized_zpos);
486 568
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index e3d4c6035eb2..01f66463271b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -198,6 +198,7 @@ engine_to_sun4i_backend(struct sunxi_engine *engine)
198 198
199void sun4i_backend_layer_enable(struct sun4i_backend *backend, 199void sun4i_backend_layer_enable(struct sun4i_backend *backend,
200 int layer, bool enable); 200 int layer, bool enable);
201bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier);
201int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, 202int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
202 int layer, struct drm_plane *plane); 203 int layer, struct drm_plane *plane);
203int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, 204int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
@@ -208,5 +209,7 @@ int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend,
208 int layer, uint32_t in_fmt); 209 int layer, uint32_t in_fmt);
209int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, 210int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend,
210 int layer, struct drm_plane *plane); 211 int layer, struct drm_plane *plane);
212void sun4i_backend_cleanup_layer(struct sun4i_backend *backend,
213 int layer);
211 214
212#endif /* _SUN4I_BACKEND_H_ */ 215#endif /* _SUN4I_BACKEND_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index ef773d36baf0..ccdeae6299eb 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -28,6 +28,16 @@
28#include "sun4i_tcon.h" 28#include "sun4i_tcon.h"
29#include "sun8i_tcon_top.h" 29#include "sun8i_tcon_top.h"
30 30
31static int drm_sun4i_gem_dumb_create(struct drm_file *file_priv,
32 struct drm_device *drm,
33 struct drm_mode_create_dumb *args)
34{
35 /* The hardware only allows even pitches for YUV buffers. */
36 args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), 2);
37
38 return drm_gem_cma_dumb_create_internal(file_priv, drm, args);
39}
40
31DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); 41DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops);
32 42
33static struct drm_driver sun4i_drv_driver = { 43static struct drm_driver sun4i_drv_driver = {
@@ -42,7 +52,7 @@ static struct drm_driver sun4i_drv_driver = {
42 .minor = 0, 52 .minor = 0,
43 53
44 /* GEM Operations */ 54 /* GEM Operations */
45 .dumb_create = drm_gem_cma_dumb_create, 55 .dumb_create = drm_sun4i_gem_dumb_create,
46 .gem_free_object_unlocked = drm_gem_cma_free_object, 56 .gem_free_object_unlocked = drm_gem_cma_free_object,
47 .gem_vm_ops = &drm_gem_cma_vm_ops, 57 .gem_vm_ops = &drm_gem_cma_vm_ops,
48 58
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c
index ddf6cfa6dd23..1a7ebc45747e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_frontend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c
@@ -107,8 +107,34 @@ EXPORT_SYMBOL(sun4i_frontend_update_buffer);
107static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val) 107static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val)
108{ 108{
109 switch (fmt) { 109 switch (fmt) {
110 case DRM_FORMAT_ARGB8888: 110 case DRM_FORMAT_XRGB8888:
111 *val = 5; 111 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB;
112 return 0;
113
114 default:
115 return -EINVAL;
116 }
117}
118
119static int sun4i_frontend_drm_format_to_input_mode(uint32_t fmt, u32 *val)
120{
121 if (drm_format_num_planes(fmt) == 1)
122 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED;
123 else
124 return -EINVAL;
125
126 return 0;
127}
128
129static int sun4i_frontend_drm_format_to_input_sequence(uint32_t fmt, u32 *val)
130{
131 switch (fmt) {
132 case DRM_FORMAT_BGRX8888:
133 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX;
134 return 0;
135
136 case DRM_FORMAT_XRGB8888:
137 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB;
112 return 0; 138 return 0;
113 139
114 default: 140 default:
@@ -119,9 +145,12 @@ static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val)
119static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) 145static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
120{ 146{
121 switch (fmt) { 147 switch (fmt) {
148 case DRM_FORMAT_BGRX8888:
149 *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888;
150 return 0;
151
122 case DRM_FORMAT_XRGB8888: 152 case DRM_FORMAT_XRGB8888:
123 case DRM_FORMAT_ARGB8888: 153 *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888;
124 *val = 2;
125 return 0; 154 return 0;
126 155
127 default: 156 default:
@@ -129,22 +158,54 @@ static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
129 } 158 }
130} 159}
131 160
161static const uint32_t sun4i_frontend_formats[] = {
162 DRM_FORMAT_BGRX8888,
163 DRM_FORMAT_XRGB8888,
164};
165
166bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier)
167{
168 unsigned int i;
169
170 if (modifier != DRM_FORMAT_MOD_LINEAR)
171 return false;
172
173 for (i = 0; i < ARRAY_SIZE(sun4i_frontend_formats); i++)
174 if (sun4i_frontend_formats[i] == fmt)
175 return true;
176
177 return false;
178}
179EXPORT_SYMBOL(sun4i_frontend_format_is_supported);
180
132int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, 181int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
133 struct drm_plane *plane, uint32_t out_fmt) 182 struct drm_plane *plane, uint32_t out_fmt)
134{ 183{
135 struct drm_plane_state *state = plane->state; 184 struct drm_plane_state *state = plane->state;
136 struct drm_framebuffer *fb = state->fb; 185 struct drm_framebuffer *fb = state->fb;
186 uint32_t format = fb->format->format;
137 u32 out_fmt_val; 187 u32 out_fmt_val;
138 u32 in_fmt_val; 188 u32 in_fmt_val, in_mod_val, in_ps_val;
139 int ret; 189 int ret;
140 190
141 ret = sun4i_frontend_drm_format_to_input_fmt(fb->format->format, 191 ret = sun4i_frontend_drm_format_to_input_fmt(format, &in_fmt_val);
142 &in_fmt_val);
143 if (ret) { 192 if (ret) {
144 DRM_DEBUG_DRIVER("Invalid input format\n"); 193 DRM_DEBUG_DRIVER("Invalid input format\n");
145 return ret; 194 return ret;
146 } 195 }
147 196
197 ret = sun4i_frontend_drm_format_to_input_mode(format, &in_mod_val);
198 if (ret) {
199 DRM_DEBUG_DRIVER("Invalid input mode\n");
200 return ret;
201 }
202
203 ret = sun4i_frontend_drm_format_to_input_sequence(format, &in_ps_val);
204 if (ret) {
205 DRM_DEBUG_DRIVER("Invalid pixel sequence\n");
206 return ret;
207 }
208
148 ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val); 209 ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val);
149 if (ret) { 210 if (ret) {
150 DRM_DEBUG_DRIVER("Invalid output format\n"); 211 DRM_DEBUG_DRIVER("Invalid output format\n");
@@ -162,10 +223,12 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
162 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400); 223 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400);
163 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400); 224 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400);
164 225
226 regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
227 SUN4I_FRONTEND_BYPASS_CSC_EN,
228 SUN4I_FRONTEND_BYPASS_CSC_EN);
229
165 regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG, 230 regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG,
166 SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(1) | 231 in_mod_val | in_fmt_val | in_ps_val);
167 SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(in_fmt_val) |
168 SUN4I_FRONTEND_INPUT_FMT_PS(1));
169 232
170 /* 233 /*
171 * TODO: It look like the A31 and A80 at least will need the 234 * 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,
173 * ARGB8888). 236 * ARGB8888).
174 */ 237 */
175 regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG, 238 regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG,
176 SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(out_fmt_val)); 239 out_fmt_val);
177 240
178 return 0; 241 return 0;
179} 242}
@@ -183,16 +246,24 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
183 struct drm_plane *plane) 246 struct drm_plane *plane)
184{ 247{
185 struct drm_plane_state *state = plane->state; 248 struct drm_plane_state *state = plane->state;
249 struct drm_framebuffer *fb = state->fb;
250 uint32_t luma_width, luma_height;
251 uint32_t chroma_width, chroma_height;
186 252
187 /* Set height and width */ 253 /* Set height and width */
188 DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n", 254 DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n",
189 state->crtc_w, state->crtc_h); 255 state->crtc_w, state->crtc_h);
256
257 luma_width = state->src_w >> 16;
258 luma_height = state->src_h >> 16;
259
260 chroma_width = DIV_ROUND_UP(luma_width, fb->format->hsub);
261 chroma_height = DIV_ROUND_UP(luma_height, fb->format->vsub);
262
190 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG, 263 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG,
191 SUN4I_FRONTEND_INSIZE(state->src_h >> 16, 264 SUN4I_FRONTEND_INSIZE(luma_height, luma_width));
192 state->src_w >> 16));
193 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG, 265 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG,
194 SUN4I_FRONTEND_INSIZE(state->src_h >> 16, 266 SUN4I_FRONTEND_INSIZE(chroma_height, chroma_width));
195 state->src_w >> 16));
196 267
197 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG, 268 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG,
198 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); 269 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
@@ -200,14 +271,14 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
200 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); 271 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
201 272
202 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG, 273 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG,
203 state->src_w / state->crtc_w); 274 (luma_width << 16) / state->crtc_w);
204 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG, 275 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG,
205 state->src_w / state->crtc_w); 276 (chroma_width << 16) / state->crtc_w);
206 277
207 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG, 278 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG,
208 state->src_h / state->crtc_h); 279 (luma_height << 16) / state->crtc_h);
209 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG, 280 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG,
210 state->src_h / state->crtc_h); 281 (chroma_height << 16) / state->crtc_h);
211 282
212 regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG, 283 regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
213 SUN4I_FRONTEND_FRM_CTRL_REG_RDY, 284 SUN4I_FRONTEND_FRM_CTRL_REG_RDY,
@@ -339,10 +410,6 @@ static int sun4i_frontend_runtime_resume(struct device *dev)
339 SUN4I_FRONTEND_EN_EN, 410 SUN4I_FRONTEND_EN_EN,
340 SUN4I_FRONTEND_EN_EN); 411 SUN4I_FRONTEND_EN_EN);
341 412
342 regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
343 SUN4I_FRONTEND_BYPASS_CSC_EN,
344 SUN4I_FRONTEND_BYPASS_CSC_EN);
345
346 sun4i_frontend_scaler_init(frontend); 413 sun4i_frontend_scaler_init(frontend);
347 414
348 return 0; 415 return 0;
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.h b/drivers/gpu/drm/sun4i/sun4i_frontend.h
index 02661ce81f3e..ad146e8d8d70 100644
--- a/drivers/gpu/drm/sun4i/sun4i_frontend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.h
@@ -26,12 +26,14 @@
26#define SUN4I_FRONTEND_LINESTRD0_REG 0x040 26#define SUN4I_FRONTEND_LINESTRD0_REG 0x040
27 27
28#define SUN4I_FRONTEND_INPUT_FMT_REG 0x04c 28#define SUN4I_FRONTEND_INPUT_FMT_REG 0x04c
29#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(mod) ((mod) << 8) 29#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED (1 << 8)
30#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(fmt) ((fmt) << 4) 30#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB (5 << 4)
31#define SUN4I_FRONTEND_INPUT_FMT_PS(ps) (ps) 31#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX 0
32#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB 1
32 33
33#define SUN4I_FRONTEND_OUTPUT_FMT_REG 0x05c 34#define SUN4I_FRONTEND_OUTPUT_FMT_REG 0x05c
34#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(fmt) (fmt) 35#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888 1
36#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888 2
35 37
36#define SUN4I_FRONTEND_CH0_INSIZE_REG 0x100 38#define SUN4I_FRONTEND_CH0_INSIZE_REG 0x100
37#define SUN4I_FRONTEND_INSIZE(h, w) ((((h) - 1) << 16) | (((w) - 1))) 39#define SUN4I_FRONTEND_INSIZE(h, w) ((((h) - 1) << 16) | (((w) - 1)))
@@ -95,5 +97,6 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
95 struct drm_plane *plane); 97 struct drm_plane *plane);
96int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, 98int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
97 struct drm_plane *plane, uint32_t out_fmt); 99 struct drm_plane *plane, uint32_t out_fmt);
100bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier);
98 101
99#endif /* _SUN4I_FRONTEND_H_ */ 102#endif /* _SUN4I_FRONTEND_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index 78f77af8805a..29631e0efde3 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -12,6 +12,7 @@
12 12
13#include <drm/drm_atomic_helper.h> 13#include <drm/drm_atomic_helper.h>
14#include <drm/drm_plane_helper.h> 14#include <drm/drm_plane_helper.h>
15#include <drm/drm_gem_framebuffer_helper.h>
15#include <drm/drmP.h> 16#include <drm/drmP.h>
16 17
17#include "sun4i_backend.h" 18#include "sun4i_backend.h"
@@ -92,14 +93,16 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
92 struct sun4i_backend *backend = layer->backend; 93 struct sun4i_backend *backend = layer->backend;
93 struct sun4i_frontend *frontend = backend->frontend; 94 struct sun4i_frontend *frontend = backend->frontend;
94 95
96 sun4i_backend_cleanup_layer(backend, layer->id);
97
95 if (layer_state->uses_frontend) { 98 if (layer_state->uses_frontend) {
96 sun4i_frontend_init(frontend); 99 sun4i_frontend_init(frontend);
97 sun4i_frontend_update_coord(frontend, plane); 100 sun4i_frontend_update_coord(frontend, plane);
98 sun4i_frontend_update_buffer(frontend, plane); 101 sun4i_frontend_update_buffer(frontend, plane);
99 sun4i_frontend_update_formats(frontend, plane, 102 sun4i_frontend_update_formats(frontend, plane,
100 DRM_FORMAT_ARGB8888); 103 DRM_FORMAT_XRGB8888);
101 sun4i_backend_update_layer_frontend(backend, layer->id, 104 sun4i_backend_update_layer_frontend(backend, layer->id,
102 DRM_FORMAT_ARGB8888); 105 DRM_FORMAT_XRGB8888);
103 sun4i_frontend_enable(frontend); 106 sun4i_frontend_enable(frontend);
104 } else { 107 } else {
105 sun4i_backend_update_layer_formats(backend, layer->id, plane); 108 sun4i_backend_update_layer_formats(backend, layer->id, plane);
@@ -112,6 +115,7 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
112} 115}
113 116
114static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = { 117static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = {
118 .prepare_fb = drm_gem_fb_prepare_fb,
115 .atomic_disable = sun4i_backend_layer_atomic_disable, 119 .atomic_disable = sun4i_backend_layer_atomic_disable,
116 .atomic_update = sun4i_backend_layer_atomic_update, 120 .atomic_update = sun4i_backend_layer_atomic_update,
117}; 121};
@@ -125,10 +129,11 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
125 .update_plane = drm_atomic_helper_update_plane, 129 .update_plane = drm_atomic_helper_update_plane,
126}; 130};
127 131
128static const uint32_t sun4i_backend_layer_formats[] = { 132static const uint32_t sun4i_layer_formats[] = {
129 DRM_FORMAT_ARGB8888, 133 DRM_FORMAT_ARGB8888,
130 DRM_FORMAT_ARGB4444, 134 DRM_FORMAT_ARGB4444,
131 DRM_FORMAT_ARGB1555, 135 DRM_FORMAT_ARGB1555,
136 DRM_FORMAT_BGRX8888,
132 DRM_FORMAT_RGBA5551, 137 DRM_FORMAT_RGBA5551,
133 DRM_FORMAT_RGBA4444, 138 DRM_FORMAT_RGBA4444,
134 DRM_FORMAT_RGB888, 139 DRM_FORMAT_RGB888,
@@ -154,8 +159,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
154 /* possible crtcs are set later */ 159 /* possible crtcs are set later */
155 ret = drm_universal_plane_init(drm, &layer->plane, 0, 160 ret = drm_universal_plane_init(drm, &layer->plane, 0,
156 &sun4i_backend_layer_funcs, 161 &sun4i_backend_layer_funcs,
157 sun4i_backend_layer_formats, 162 sun4i_layer_formats,
158 ARRAY_SIZE(sun4i_backend_layer_formats), 163 ARRAY_SIZE(sun4i_layer_formats),
159 NULL, type, NULL); 164 NULL, type, NULL);
160 if (ret) { 165 if (ret) {
161 dev_err(drm->dev, "Couldn't initialize layer\n"); 166 dev_err(drm->dev, "Couldn't initialize layer\n");
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index e3fc8fa920fb..18534263a05d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -19,6 +19,7 @@
19#include <drm/drm_crtc_helper.h> 19#include <drm/drm_crtc_helper.h>
20#include <drm/drm_fb_cma_helper.h> 20#include <drm/drm_fb_cma_helper.h>
21#include <drm/drm_gem_cma_helper.h> 21#include <drm/drm_gem_cma_helper.h>
22#include <drm/drm_gem_framebuffer_helper.h>
22#include <drm/drm_plane_helper.h> 23#include <drm/drm_plane_helper.h>
23#include <drm/drmP.h> 24#include <drm/drmP.h>
24 25
@@ -300,6 +301,7 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
300} 301}
301 302
302static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = { 303static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = {
304 .prepare_fb = drm_gem_fb_prepare_fb,
303 .atomic_check = sun8i_ui_layer_atomic_check, 305 .atomic_check = sun8i_ui_layer_atomic_check,
304 .atomic_disable = sun8i_ui_layer_atomic_disable, 306 .atomic_disable = sun8i_ui_layer_atomic_disable,
305 .atomic_update = sun8i_ui_layer_atomic_update, 307 .atomic_update = sun8i_ui_layer_atomic_update,
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 4249edfb47ed..87be898f9b7a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -13,6 +13,7 @@
13#include <drm/drm_crtc_helper.h> 13#include <drm/drm_crtc_helper.h>
14#include <drm/drm_fb_cma_helper.h> 14#include <drm/drm_fb_cma_helper.h>
15#include <drm/drm_gem_cma_helper.h> 15#include <drm/drm_gem_cma_helper.h>
16#include <drm/drm_gem_framebuffer_helper.h>
16#include <drm/drm_plane_helper.h> 17#include <drm/drm_plane_helper.h>
17#include <drm/drmP.h> 18#include <drm/drmP.h>
18 19
@@ -336,6 +337,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
336} 337}
337 338
338static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { 339static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
340 .prepare_fb = drm_gem_fb_prepare_fb,
339 .atomic_check = sun8i_vi_layer_atomic_check, 341 .atomic_check = sun8i_vi_layer_atomic_check,
340 .atomic_disable = sun8i_vi_layer_atomic_disable, 342 .atomic_disable = sun8i_vi_layer_atomic_disable,
341 .atomic_update = sun8i_vi_layer_atomic_update, 343 .atomic_update = sun8i_vi_layer_atomic_update,
diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c
index 72efcecb44f7..28e2d03c0ccf 100644
--- a/drivers/gpu/drm/tve200/tve200_drv.c
+++ b/drivers/gpu/drm/tve200/tve200_drv.c
@@ -249,7 +249,7 @@ static int tve200_probe(struct platform_device *pdev)
249clk_disable: 249clk_disable:
250 clk_disable_unprepare(priv->pclk); 250 clk_disable_unprepare(priv->pclk);
251dev_unref: 251dev_unref:
252 drm_dev_unref(drm); 252 drm_dev_put(drm);
253 return ret; 253 return ret;
254} 254}
255 255
@@ -263,7 +263,7 @@ static int tve200_remove(struct platform_device *pdev)
263 drm_panel_bridge_remove(priv->bridge); 263 drm_panel_bridge_remove(priv->bridge);
264 drm_mode_config_cleanup(drm); 264 drm_mode_config_cleanup(drm);
265 clk_disable_unprepare(priv->pclk); 265 clk_disable_unprepare(priv->pclk);
266 drm_dev_unref(drm); 266 drm_dev_put(drm);
267 267
268 return 0; 268 return 0;
269} 269}
diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
index b88c96911453..1e8947c7d954 100644
--- a/drivers/gpu/drm/v3d/v3d_gem.c
+++ b/drivers/gpu/drm/v3d/v3d_gem.c
@@ -210,14 +210,11 @@ static void
210v3d_attach_object_fences(struct v3d_exec_info *exec) 210v3d_attach_object_fences(struct v3d_exec_info *exec)
211{ 211{
212 struct dma_fence *out_fence = exec->render_done_fence; 212 struct dma_fence *out_fence = exec->render_done_fence;
213 struct v3d_bo *bo;
214 int i; 213 int i;
215 214
216 for (i = 0; i < exec->bo_count; i++) { 215 for (i = 0; i < exec->bo_count; i++) {
217 bo = to_v3d_bo(&exec->bo[i]->base);
218
219 /* XXX: Use shared fences for read-only objects. */ 216 /* XXX: Use shared fences for read-only objects. */
220 reservation_object_add_excl_fence(bo->resv, out_fence); 217 reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence);
221 } 218 }
222} 219}
223 220
@@ -228,11 +225,8 @@ v3d_unlock_bo_reservations(struct drm_device *dev,
228{ 225{
229 int i; 226 int i;
230 227
231 for (i = 0; i < exec->bo_count; i++) { 228 for (i = 0; i < exec->bo_count; i++)
232 struct v3d_bo *bo = to_v3d_bo(&exec->bo[i]->base); 229 ww_mutex_unlock(&exec->bo[i]->resv->lock);
233
234 ww_mutex_unlock(&bo->resv->lock);
235 }
236 230
237 ww_acquire_fini(acquire_ctx); 231 ww_acquire_fini(acquire_ctx);
238} 232}
@@ -251,13 +245,13 @@ v3d_lock_bo_reservations(struct drm_device *dev,
251{ 245{
252 int contended_lock = -1; 246 int contended_lock = -1;
253 int i, ret; 247 int i, ret;
254 struct v3d_bo *bo;
255 248
256 ww_acquire_init(acquire_ctx, &reservation_ww_class); 249 ww_acquire_init(acquire_ctx, &reservation_ww_class);
257 250
258retry: 251retry:
259 if (contended_lock != -1) { 252 if (contended_lock != -1) {
260 bo = to_v3d_bo(&exec->bo[contended_lock]->base); 253 struct v3d_bo *bo = exec->bo[contended_lock];
254
261 ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock, 255 ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
262 acquire_ctx); 256 acquire_ctx);
263 if (ret) { 257 if (ret) {
@@ -270,19 +264,16 @@ retry:
270 if (i == contended_lock) 264 if (i == contended_lock)
271 continue; 265 continue;
272 266
273 bo = to_v3d_bo(&exec->bo[i]->base); 267 ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock,
274 268 acquire_ctx);
275 ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx);
276 if (ret) { 269 if (ret) {
277 int j; 270 int j;
278 271
279 for (j = 0; j < i; j++) { 272 for (j = 0; j < i; j++)
280 bo = to_v3d_bo(&exec->bo[j]->base); 273 ww_mutex_unlock(&exec->bo[j]->resv->lock);
281 ww_mutex_unlock(&bo->resv->lock);
282 }
283 274
284 if (contended_lock != -1 && contended_lock >= i) { 275 if (contended_lock != -1 && contended_lock >= i) {
285 bo = to_v3d_bo(&exec->bo[contended_lock]->base); 276 struct v3d_bo *bo = exec->bo[contended_lock];
286 277
287 ww_mutex_unlock(&bo->resv->lock); 278 ww_mutex_unlock(&bo->resv->lock);
288 } 279 }
@@ -303,9 +294,7 @@ retry:
303 * before we commit the CL to the hardware. 294 * before we commit the CL to the hardware.
304 */ 295 */
305 for (i = 0; i < exec->bo_count; i++) { 296 for (i = 0; i < exec->bo_count; i++) {
306 bo = to_v3d_bo(&exec->bo[i]->base); 297 ret = reservation_object_reserve_shared(exec->bo[i]->resv, 1);
307
308 ret = reservation_object_reserve_shared(bo->resv, 1);
309 if (ret) { 298 if (ret) {
310 v3d_unlock_bo_reservations(dev, exec, acquire_ctx); 299 v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
311 return ret; 300 return ret;
diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
index 445b2ef03303..c66d0ce21435 100644
--- a/drivers/gpu/drm/v3d/v3d_sched.c
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
@@ -41,7 +41,7 @@ v3d_job_free(struct drm_sched_job *sched_job)
41} 41}
42 42
43/** 43/**
44 * Returns the fences that the bin job depends on, one by one. 44 * Returns the fences that the bin or render job depends on, one by one.
45 * v3d_job_run() won't be called until all of them have been signaled. 45 * v3d_job_run() won't be called until all of them have been signaled.
46 */ 46 */
47static struct dma_fence * 47static struct dma_fence *
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
index 8f8fed471e34..b5580b11a063 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -169,6 +169,12 @@ static int virtio_gpu_conn_get_modes(struct drm_connector *connector)
169 struct drm_display_mode *mode = NULL; 169 struct drm_display_mode *mode = NULL;
170 int count, width, height; 170 int count, width, height;
171 171
172 if (output->edid) {
173 count = drm_add_edid_modes(connector, output->edid);
174 if (count)
175 return count;
176 }
177
172 width = le32_to_cpu(output->info.r.width); 178 width = le32_to_cpu(output->info.r.width);
173 height = le32_to_cpu(output->info.r.height); 179 height = le32_to_cpu(output->info.r.height);
174 count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); 180 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)
287 drm_connector_init(dev, connector, &virtio_gpu_connector_funcs, 293 drm_connector_init(dev, connector, &virtio_gpu_connector_funcs,
288 DRM_MODE_CONNECTOR_VIRTUAL); 294 DRM_MODE_CONNECTOR_VIRTUAL);
289 drm_connector_helper_add(connector, &virtio_gpu_conn_helper_funcs); 295 drm_connector_helper_add(connector, &virtio_gpu_conn_helper_funcs);
296 if (vgdev->has_edid)
297 drm_connector_attach_edid_property(connector);
290 298
291 drm_encoder_init(dev, encoder, &virtio_gpu_enc_funcs, 299 drm_encoder_init(dev, encoder, &virtio_gpu_enc_funcs,
292 DRM_MODE_ENCODER_VIRTUAL, NULL); 300 DRM_MODE_ENCODER_VIRTUAL, NULL);
@@ -378,6 +386,10 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev)
378 386
379void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) 387void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev)
380{ 388{
389 int i;
390
391 for (i = 0 ; i < vgdev->num_scanouts; ++i)
392 kfree(vgdev->outputs[i].edid);
381 virtio_gpu_fbdev_fini(vgdev); 393 virtio_gpu_fbdev_fini(vgdev);
382 drm_mode_config_cleanup(vgdev->ddev); 394 drm_mode_config_cleanup(vgdev->ddev);
383} 395}
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index d9287c144fe5..f7f32a885af7 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -80,6 +80,7 @@ static unsigned int features[] = {
80 */ 80 */
81 VIRTIO_GPU_F_VIRGL, 81 VIRTIO_GPU_F_VIRGL,
82#endif 82#endif
83 VIRTIO_GPU_F_EDID,
83}; 84};
84static struct virtio_driver virtio_gpu_driver = { 85static struct virtio_driver virtio_gpu_driver = {
85 .feature_table = features, 86 .feature_table = features,
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 9db568054d66..f7e877857c1f 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -115,6 +115,7 @@ struct virtio_gpu_output {
115 struct drm_encoder enc; 115 struct drm_encoder enc;
116 struct virtio_gpu_display_one info; 116 struct virtio_gpu_display_one info;
117 struct virtio_gpu_update_cursor cursor; 117 struct virtio_gpu_update_cursor cursor;
118 struct edid *edid;
118 int cur_x; 119 int cur_x;
119 int cur_y; 120 int cur_y;
120 bool enabled; 121 bool enabled;
@@ -201,6 +202,7 @@ struct virtio_gpu_device {
201 struct ida ctx_id_ida; 202 struct ida ctx_id_ida;
202 203
203 bool has_virgl_3d; 204 bool has_virgl_3d;
205 bool has_edid;
204 206
205 struct work_struct config_changed_work; 207 struct work_struct config_changed_work;
206 208
@@ -291,6 +293,7 @@ int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx);
291int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev, 293int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
292 int idx, int version, 294 int idx, int version,
293 struct virtio_gpu_drv_cap_cache **cache_p); 295 struct virtio_gpu_drv_cap_cache **cache_p);
296int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev);
294void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, 297void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
295 uint32_t nlen, const char *name); 298 uint32_t nlen, const char *name);
296void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev, 299void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 691b842d5f3a..3af6181c05a8 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -44,6 +44,8 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
44 virtio_cread(vgdev->vdev, struct virtio_gpu_config, 44 virtio_cread(vgdev->vdev, struct virtio_gpu_config,
45 events_read, &events_read); 45 events_read, &events_read);
46 if (events_read & VIRTIO_GPU_EVENT_DISPLAY) { 46 if (events_read & VIRTIO_GPU_EVENT_DISPLAY) {
47 if (vgdev->has_edid)
48 virtio_gpu_cmd_get_edids(vgdev);
47 virtio_gpu_cmd_get_display_info(vgdev); 49 virtio_gpu_cmd_get_display_info(vgdev);
48 drm_helper_hpd_irq_event(vgdev->ddev); 50 drm_helper_hpd_irq_event(vgdev->ddev);
49 events_clear |= VIRTIO_GPU_EVENT_DISPLAY; 51 events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
@@ -156,6 +158,10 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
156#else 158#else
157 DRM_INFO("virgl 3d acceleration not supported by guest\n"); 159 DRM_INFO("virgl 3d acceleration not supported by guest\n");
158#endif 160#endif
161 if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_EDID)) {
162 vgdev->has_edid = true;
163 DRM_INFO("EDID support available.\n");
164 }
159 165
160 ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL); 166 ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL);
161 if (ret) { 167 if (ret) {
@@ -201,6 +207,8 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
201 207
202 if (num_capsets) 208 if (num_capsets)
203 virtio_gpu_get_capsets(vgdev, num_capsets); 209 virtio_gpu_get_capsets(vgdev, num_capsets);
210 if (vgdev->has_edid)
211 virtio_gpu_cmd_get_edids(vgdev);
204 virtio_gpu_cmd_get_display_info(vgdev); 212 virtio_gpu_cmd_get_display_info(vgdev);
205 wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, 213 wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending,
206 5 * HZ); 214 5 * HZ);
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 93f2c3a51ee8..2c6764f08f18 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -584,6 +584,45 @@ static void virtio_gpu_cmd_capset_cb(struct virtio_gpu_device *vgdev,
584 wake_up(&vgdev->resp_wq); 584 wake_up(&vgdev->resp_wq);
585} 585}
586 586
587static int virtio_get_edid_block(void *data, u8 *buf,
588 unsigned int block, size_t len)
589{
590 struct virtio_gpu_resp_edid *resp = data;
591 size_t start = block * EDID_LENGTH;
592
593 if (start + len > le32_to_cpu(resp->size))
594 return -1;
595 memcpy(buf, resp->edid + start, len);
596 return 0;
597}
598
599static void virtio_gpu_cmd_get_edid_cb(struct virtio_gpu_device *vgdev,
600 struct virtio_gpu_vbuffer *vbuf)
601{
602 struct virtio_gpu_cmd_get_edid *cmd =
603 (struct virtio_gpu_cmd_get_edid *)vbuf->buf;
604 struct virtio_gpu_resp_edid *resp =
605 (struct virtio_gpu_resp_edid *)vbuf->resp_buf;
606 uint32_t scanout = le32_to_cpu(cmd->scanout);
607 struct virtio_gpu_output *output;
608 struct edid *new_edid, *old_edid;
609
610 if (scanout >= vgdev->num_scanouts)
611 return;
612 output = vgdev->outputs + scanout;
613
614 new_edid = drm_do_get_edid(&output->conn, virtio_get_edid_block, resp);
615
616 spin_lock(&vgdev->display_info_lock);
617 old_edid = output->edid;
618 output->edid = new_edid;
619 drm_connector_update_edid_property(&output->conn, output->edid);
620 spin_unlock(&vgdev->display_info_lock);
621
622 kfree(old_edid);
623 wake_up(&vgdev->resp_wq);
624}
625
587int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev) 626int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev)
588{ 627{
589 struct virtio_gpu_ctrl_hdr *cmd_p; 628 struct virtio_gpu_ctrl_hdr *cmd_p;
@@ -686,6 +725,34 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
686 return 0; 725 return 0;
687} 726}
688 727
728int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev)
729{
730 struct virtio_gpu_cmd_get_edid *cmd_p;
731 struct virtio_gpu_vbuffer *vbuf;
732 void *resp_buf;
733 int scanout;
734
735 if (WARN_ON(!vgdev->has_edid))
736 return -EINVAL;
737
738 for (scanout = 0; scanout < vgdev->num_scanouts; scanout++) {
739 resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_edid),
740 GFP_KERNEL);
741 if (!resp_buf)
742 return -ENOMEM;
743
744 cmd_p = virtio_gpu_alloc_cmd_resp
745 (vgdev, &virtio_gpu_cmd_get_edid_cb, &vbuf,
746 sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_edid),
747 resp_buf);
748 cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_EDID);
749 cmd_p->scanout = cpu_to_le32(scanout);
750 virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
751 }
752
753 return 0;
754}
755
689void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, 756void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
690 uint32_t nlen, const char *name) 757 uint32_t nlen, const char *name)
691{ 758{
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index a3d57e0f5ee5..83087877565c 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -68,7 +68,6 @@ static struct drm_driver vkms_driver = {
68 .release = vkms_release, 68 .release = vkms_release,
69 .fops = &vkms_driver_fops, 69 .fops = &vkms_driver_fops,
70 .dumb_create = vkms_dumb_create, 70 .dumb_create = vkms_dumb_create,
71 .dumb_map_offset = vkms_dumb_map,
72 .gem_vm_ops = &vkms_gem_vm_ops, 71 .gem_vm_ops = &vkms_gem_vm_ops,
73 .gem_free_object_unlocked = vkms_gem_free_object, 72 .gem_free_object_unlocked = vkms_gem_free_object,
74 .get_vblank_timestamp = vkms_get_vblank_timestamp, 73 .get_vblank_timestamp = vkms_get_vblank_timestamp,
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index 1c93990693e3..e4469cd3d254 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -127,9 +127,6 @@ vm_fault_t vkms_gem_fault(struct vm_fault *vmf);
127int vkms_dumb_create(struct drm_file *file, struct drm_device *dev, 127int vkms_dumb_create(struct drm_file *file, struct drm_device *dev,
128 struct drm_mode_create_dumb *args); 128 struct drm_mode_create_dumb *args);
129 129
130int vkms_dumb_map(struct drm_file *file, struct drm_device *dev,
131 u32 handle, u64 *offset);
132
133void vkms_gem_free_object(struct drm_gem_object *obj); 130void vkms_gem_free_object(struct drm_gem_object *obj);
134 131
135int vkms_gem_vmap(struct drm_gem_object *obj); 132int vkms_gem_vmap(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c
index d04e988b4cbe..80311daed47a 100644
--- a/drivers/gpu/drm/vkms/vkms_gem.c
+++ b/drivers/gpu/drm/vkms/vkms_gem.c
@@ -153,32 +153,6 @@ int vkms_dumb_create(struct drm_file *file, struct drm_device *dev,
153 return 0; 153 return 0;
154} 154}
155 155
156int vkms_dumb_map(struct drm_file *file, struct drm_device *dev,
157 u32 handle, u64 *offset)
158{
159 struct drm_gem_object *obj;
160 int ret;
161
162 obj = drm_gem_object_lookup(file, handle);
163 if (!obj)
164 return -ENOENT;
165
166 if (!obj->filp) {
167 ret = -EINVAL;
168 goto unref;
169 }
170
171 ret = drm_gem_create_mmap_offset(obj);
172 if (ret)
173 goto unref;
174
175 *offset = drm_vma_node_offset_addr(&obj->vma_node);
176unref:
177 drm_gem_object_put_unlocked(obj);
178
179 return ret;
180}
181
182static struct page **_get_pages(struct vkms_gem_object *vkms_obj) 156static struct page **_get_pages(struct vkms_gem_object *vkms_obj)
183{ 157{
184 struct drm_gem_object *gem_obj = &vkms_obj->gem; 158 struct drm_gem_object *gem_obj = &vkms_obj->gem;
diff --git a/drivers/staging/vboxvideo/vbox_drv.c b/drivers/staging/vboxvideo/vbox_drv.c
index 257030460fb6..d3e23dd70c1b 100644
--- a/drivers/staging/vboxvideo/vbox_drv.c
+++ b/drivers/staging/vboxvideo/vbox_drv.c
@@ -279,7 +279,6 @@ static struct drm_driver driver = {
279 .gem_free_object_unlocked = vbox_gem_free_object, 279 .gem_free_object_unlocked = vbox_gem_free_object,
280 .dumb_create = vbox_dumb_create, 280 .dumb_create = vbox_dumb_create,
281 .dumb_map_offset = vbox_dumb_mmap_offset, 281 .dumb_map_offset = vbox_dumb_mmap_offset,
282 .dumb_destroy = drm_gem_dumb_destroy,
283 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 282 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
284 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 283 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
285 .gem_prime_export = drm_gem_prime_export, 284 .gem_prime_export = drm_gem_prime_export,