diff options
author | Mark Yao <mark.yao@rock-chips.com> | 2015-11-30 05:22:42 -0500 |
---|---|---|
committer | Mark Yao <mark.yao@rock-chips.com> | 2015-12-27 19:49:39 -0500 |
commit | 63ebb9fa7ff06d194362ed4a5d0a31ac7612a89c (patch) | |
tree | 779656965abf60a3ed2461ad504d428c0ad88ad6 /drivers/gpu/drm/rockchip/rockchip_drm_fb.c | |
parent | 0ad3675d9c8f7c7306c954a9c50dc12385d8a508 (diff) |
drm/rockchip: Convert to support atomic API
Rockchip vop not support hw vblank counter, needed check the committed
register if it's really take effect.
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
Diffstat (limited to 'drivers/gpu/drm/rockchip/rockchip_drm_fb.c')
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 621f25c463bd..df1b7b0e9926 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <drm/drm.h> | 16 | #include <drm/drm.h> |
17 | #include <drm/drmP.h> | 17 | #include <drm/drmP.h> |
18 | #include <drm/drm_atomic.h> | ||
18 | #include <drm/drm_fb_helper.h> | 19 | #include <drm/drm_fb_helper.h> |
19 | #include <drm/drm_crtc_helper.h> | 20 | #include <drm/drm_crtc_helper.h> |
20 | 21 | ||
@@ -166,9 +167,103 @@ static void rockchip_drm_output_poll_changed(struct drm_device *dev) | |||
166 | drm_fb_helper_hotplug_event(fb_helper); | 167 | drm_fb_helper_hotplug_event(fb_helper); |
167 | } | 168 | } |
168 | 169 | ||
170 | static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc) | ||
171 | { | ||
172 | struct rockchip_drm_private *priv = crtc->dev->dev_private; | ||
173 | int pipe = drm_crtc_index(crtc); | ||
174 | const struct rockchip_crtc_funcs *crtc_funcs = priv->crtc_funcs[pipe]; | ||
175 | |||
176 | if (crtc_funcs && crtc_funcs->wait_for_update) | ||
177 | crtc_funcs->wait_for_update(crtc); | ||
178 | } | ||
179 | |||
180 | static void | ||
181 | rockchip_atomic_wait_for_complete(struct drm_atomic_state *old_state) | ||
182 | { | ||
183 | struct drm_crtc_state *old_crtc_state; | ||
184 | struct drm_crtc *crtc; | ||
185 | int i, ret; | ||
186 | |||
187 | for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { | ||
188 | /* No one cares about the old state, so abuse it for tracking | ||
189 | * and store whether we hold a vblank reference (and should do a | ||
190 | * vblank wait) in the ->enable boolean. | ||
191 | */ | ||
192 | old_crtc_state->enable = false; | ||
193 | |||
194 | if (!crtc->state->active) | ||
195 | continue; | ||
196 | |||
197 | ret = drm_crtc_vblank_get(crtc); | ||
198 | if (ret != 0) | ||
199 | continue; | ||
200 | |||
201 | old_crtc_state->enable = true; | ||
202 | } | ||
203 | |||
204 | for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { | ||
205 | if (!old_crtc_state->enable) | ||
206 | continue; | ||
207 | |||
208 | rockchip_crtc_wait_for_update(crtc); | ||
209 | drm_crtc_vblank_put(crtc); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | int rockchip_drm_atomic_commit(struct drm_device *dev, | ||
214 | struct drm_atomic_state *state, | ||
215 | bool async) | ||
216 | { | ||
217 | int ret; | ||
218 | |||
219 | if (async) | ||
220 | return -EBUSY; | ||
221 | |||
222 | ret = drm_atomic_helper_prepare_planes(dev, state); | ||
223 | if (ret) | ||
224 | return ret; | ||
225 | |||
226 | drm_atomic_helper_swap_state(dev, state); | ||
227 | |||
228 | /* | ||
229 | * TODO: do fence wait here. | ||
230 | */ | ||
231 | |||
232 | /* | ||
233 | * Rockchip crtc support runtime PM, can't update display planes | ||
234 | * when crtc is disabled. | ||
235 | * | ||
236 | * drm_atomic_helper_commit comments detail that: | ||
237 | * For drivers supporting runtime PM the recommended sequence is | ||
238 | * | ||
239 | * drm_atomic_helper_commit_modeset_disables(dev, state); | ||
240 | * | ||
241 | * drm_atomic_helper_commit_modeset_enables(dev, state); | ||
242 | * | ||
243 | * drm_atomic_helper_commit_planes(dev, state, true); | ||
244 | * | ||
245 | * See the kerneldoc entries for these three functions for more details. | ||
246 | */ | ||
247 | drm_atomic_helper_commit_modeset_disables(dev, state); | ||
248 | |||
249 | drm_atomic_helper_commit_modeset_enables(dev, state); | ||
250 | |||
251 | drm_atomic_helper_commit_planes(dev, state, true); | ||
252 | |||
253 | rockchip_atomic_wait_for_complete(state); | ||
254 | |||
255 | drm_atomic_helper_cleanup_planes(dev, state); | ||
256 | |||
257 | drm_atomic_state_free(state); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
169 | static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = { | 262 | static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = { |
170 | .fb_create = rockchip_user_fb_create, | 263 | .fb_create = rockchip_user_fb_create, |
171 | .output_poll_changed = rockchip_drm_output_poll_changed, | 264 | .output_poll_changed = rockchip_drm_output_poll_changed, |
265 | .atomic_check = drm_atomic_helper_check, | ||
266 | .atomic_commit = rockchip_drm_atomic_commit, | ||
172 | }; | 267 | }; |
173 | 268 | ||
174 | struct drm_framebuffer * | 269 | struct drm_framebuffer * |