aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_drv.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2017-05-08 18:27:10 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2017-06-02 03:53:42 -0400
commita9e6f9f7d603ef769b4cd33e0a2b61ba48a1058e (patch)
tree0efa5e1970a897747b60a5c1753f6be2ccffce5e /drivers/gpu/drm/omapdrm/omap_drv.c
parentce9a8f1ad7564fa24bc12066b41f2a09eb1a8394 (diff)
drm: omapdrm: Use DRM core's atomic commit helper
The DRM core atomic helper now supports asynchronous commits natively. The custom omapdrm implementation isn't needed anymore, remove it. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c112
1 files changed, 14 insertions, 98 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 663e930a7b0f..b4ef3025e3e3 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -17,8 +17,6 @@
17 * this program. If not, see <http://www.gnu.org/licenses/>. 17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */ 18 */
19 19
20#include <linux/wait.h>
21
22#include <drm/drm_atomic.h> 20#include <drm/drm_atomic.h>
23#include <drm/drm_atomic_helper.h> 21#include <drm/drm_atomic_helper.h>
24#include <drm/drm_crtc_helper.h> 22#include <drm/drm_crtc_helper.h>
@@ -54,13 +52,6 @@ static void omap_fb_output_poll_changed(struct drm_device *dev)
54 drm_fb_helper_hotplug_event(priv->fbdev); 52 drm_fb_helper_hotplug_event(priv->fbdev);
55} 53}
56 54
57struct omap_atomic_state_commit {
58 struct work_struct work;
59 struct drm_device *dev;
60 struct drm_atomic_state *state;
61 u32 crtcs;
62};
63
64static void omap_atomic_wait_for_completion(struct drm_device *dev, 55static void omap_atomic_wait_for_completion(struct drm_device *dev,
65 struct drm_atomic_state *old_state) 56 struct drm_atomic_state *old_state)
66{ 57{
@@ -81,15 +72,14 @@ static void omap_atomic_wait_for_completion(struct drm_device *dev,
81 } 72 }
82} 73}
83 74
84static void omap_atomic_complete(struct omap_atomic_state_commit *commit) 75static void omap_atomic_commit_tail(struct drm_atomic_state *old_state)
85{ 76{
86 struct drm_device *dev = commit->dev; 77 struct drm_device *dev = old_state->dev;
87 struct omap_drm_private *priv = dev->dev_private; 78 struct omap_drm_private *priv = dev->dev_private;
88 struct drm_atomic_state *old_state = commit->state;
89 79
90 /* Apply the atomic update. */
91 priv->dispc_ops->runtime_get(); 80 priv->dispc_ops->runtime_get();
92 81
82 /* Apply the atomic update. */
93 drm_atomic_helper_commit_modeset_disables(dev, old_state); 83 drm_atomic_helper_commit_modeset_disables(dev, old_state);
94 84
95 /* With the current dss dispc implementation we have to enable 85 /* With the current dss dispc implementation we have to enable
@@ -108,101 +98,28 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
108 98
109 drm_atomic_helper_commit_planes(dev, old_state, 0); 99 drm_atomic_helper_commit_planes(dev, old_state, 0);
110 100
101 drm_atomic_helper_commit_hw_done(old_state);
102
103 /*
104 * Wait for completion of the page flips to ensure that old buffers
105 * can't be touched by the hardware anymore before cleaning up planes.
106 */
111 omap_atomic_wait_for_completion(dev, old_state); 107 omap_atomic_wait_for_completion(dev, old_state);
112 108
113 drm_atomic_helper_cleanup_planes(dev, old_state); 109 drm_atomic_helper_cleanup_planes(dev, old_state);
114 110
115 priv->dispc_ops->runtime_put(); 111 priv->dispc_ops->runtime_put();
116
117 drm_atomic_state_put(old_state);
118
119 /* Complete the commit, wake up any waiter. */
120 spin_lock(&priv->commit.lock);
121 priv->commit.pending &= ~commit->crtcs;
122 spin_unlock(&priv->commit.lock);
123
124 wake_up_all(&priv->commit.wait);
125
126 kfree(commit);
127}
128
129static void omap_atomic_work(struct work_struct *work)
130{
131 struct omap_atomic_state_commit *commit =
132 container_of(work, struct omap_atomic_state_commit, work);
133
134 omap_atomic_complete(commit);
135} 112}
136 113
137static bool omap_atomic_is_pending(struct omap_drm_private *priv, 114static const struct drm_mode_config_helper_funcs omap_mode_config_helper_funcs = {
138 struct omap_atomic_state_commit *commit) 115 .atomic_commit_tail = omap_atomic_commit_tail,
139{ 116};
140 bool pending;
141
142 spin_lock(&priv->commit.lock);
143 pending = priv->commit.pending & commit->crtcs;
144 spin_unlock(&priv->commit.lock);
145
146 return pending;
147}
148
149static int omap_atomic_commit(struct drm_device *dev,
150 struct drm_atomic_state *state, bool nonblock)
151{
152 struct omap_drm_private *priv = dev->dev_private;
153 struct omap_atomic_state_commit *commit;
154 struct drm_crtc *crtc;
155 struct drm_crtc_state *crtc_state;
156 int i, ret;
157
158 ret = drm_atomic_helper_prepare_planes(dev, state);
159 if (ret)
160 return ret;
161
162 /* Allocate the commit object. */
163 commit = kzalloc(sizeof(*commit), GFP_KERNEL);
164 if (commit == NULL) {
165 ret = -ENOMEM;
166 goto error;
167 }
168
169 INIT_WORK(&commit->work, omap_atomic_work);
170 commit->dev = dev;
171 commit->state = state;
172
173 /* Wait until all affected CRTCs have completed previous commits and
174 * mark them as pending.
175 */
176 for_each_crtc_in_state(state, crtc, crtc_state, i)
177 commit->crtcs |= drm_crtc_mask(crtc);
178
179 wait_event(priv->commit.wait, !omap_atomic_is_pending(priv, commit));
180
181 spin_lock(&priv->commit.lock);
182 priv->commit.pending |= commit->crtcs;
183 spin_unlock(&priv->commit.lock);
184
185 /* Swap the state, this is the point of no return. */
186 drm_atomic_helper_swap_state(state, true);
187
188 drm_atomic_state_get(state);
189 if (nonblock)
190 schedule_work(&commit->work);
191 else
192 omap_atomic_complete(commit);
193
194 return 0;
195
196error:
197 drm_atomic_helper_cleanup_planes(dev, state);
198 return ret;
199}
200 117
201static const struct drm_mode_config_funcs omap_mode_config_funcs = { 118static const struct drm_mode_config_funcs omap_mode_config_funcs = {
202 .fb_create = omap_framebuffer_create, 119 .fb_create = omap_framebuffer_create,
203 .output_poll_changed = omap_fb_output_poll_changed, 120 .output_poll_changed = omap_fb_output_poll_changed,
204 .atomic_check = drm_atomic_helper_check, 121 .atomic_check = drm_atomic_helper_check,
205 .atomic_commit = omap_atomic_commit, 122 .atomic_commit = drm_atomic_helper_commit,
206}; 123};
207 124
208static int get_connector_type(struct omap_dss_device *dssdev) 125static int get_connector_type(struct omap_dss_device *dssdev)
@@ -385,6 +302,7 @@ static int omap_modeset_init(struct drm_device *dev)
385 dev->mode_config.max_height = 2048; 302 dev->mode_config.max_height = 2048;
386 303
387 dev->mode_config.funcs = &omap_mode_config_funcs; 304 dev->mode_config.funcs = &omap_mode_config_funcs;
305 dev->mode_config.helper_private = &omap_mode_config_helper_funcs;
388 306
389 drm_mode_config_reset(dev); 307 drm_mode_config_reset(dev);
390 308
@@ -674,8 +592,6 @@ static int pdev_probe(struct platform_device *pdev)
674 priv->omaprev = pdata->omaprev; 592 priv->omaprev = pdata->omaprev;
675 priv->wq = alloc_ordered_workqueue("omapdrm", 0); 593 priv->wq = alloc_ordered_workqueue("omapdrm", 0);
676 594
677 init_waitqueue_head(&priv->commit.wait);
678 spin_lock_init(&priv->commit.lock);
679 spin_lock_init(&priv->list_lock); 595 spin_lock_init(&priv->list_lock);
680 INIT_LIST_HEAD(&priv->obj_list); 596 INIT_LIST_HEAD(&priv->obj_list);
681 597