diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2017-05-08 18:27:10 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2017-06-02 03:53:42 -0400 |
commit | a9e6f9f7d603ef769b4cd33e0a2b61ba48a1058e (patch) | |
tree | 0efa5e1970a897747b60a5c1753f6be2ccffce5e /drivers/gpu/drm/omapdrm/omap_drv.c | |
parent | ce9a8f1ad7564fa24bc12066b41f2a09eb1a8394 (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.c | 112 |
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 | ||
57 | struct 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 | |||
64 | static void omap_atomic_wait_for_completion(struct drm_device *dev, | 55 | static 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 | ||
84 | static void omap_atomic_complete(struct omap_atomic_state_commit *commit) | 75 | static 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 | |||
129 | static 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 | ||
137 | static bool omap_atomic_is_pending(struct omap_drm_private *priv, | 114 | static 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 | |||
149 | static 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 | |||
196 | error: | ||
197 | drm_atomic_helper_cleanup_planes(dev, state); | ||
198 | return ret; | ||
199 | } | ||
200 | 117 | ||
201 | static const struct drm_mode_config_funcs omap_mode_config_funcs = { | 118 | static 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 | ||
208 | static int get_connector_type(struct omap_dss_device *dssdev) | 125 | static 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 | ||