aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/imx/imx-drm-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/imx/imx-drm-core.c')
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c120
1 files changed, 78 insertions, 42 deletions
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 7746418a4c08..9f7dafce3a4c 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -15,10 +15,14 @@
15 */ 15 */
16#include <linux/component.h> 16#include <linux/component.h>
17#include <linux/device.h> 17#include <linux/device.h>
18#include <linux/dma-buf.h>
18#include <linux/fb.h> 19#include <linux/fb.h>
19#include <linux/module.h> 20#include <linux/module.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/reservation.h>
21#include <drm/drmP.h> 23#include <drm/drmP.h>
24#include <drm/drm_atomic.h>
25#include <drm/drm_atomic_helper.h>
22#include <drm/drm_fb_helper.h> 26#include <drm/drm_fb_helper.h>
23#include <drm/drm_crtc_helper.h> 27#include <drm/drm_crtc_helper.h>
24#include <drm/drm_gem_cma_helper.h> 28#include <drm/drm_gem_cma_helper.h>
@@ -41,6 +45,7 @@ struct imx_drm_device {
41 struct imx_drm_crtc *crtc[MAX_CRTC]; 45 struct imx_drm_crtc *crtc[MAX_CRTC];
42 unsigned int pipes; 46 unsigned int pipes;
43 struct drm_fbdev_cma *fbhelper; 47 struct drm_fbdev_cma *fbhelper;
48 struct drm_atomic_state *state;
44}; 49};
45 50
46struct imx_drm_crtc { 51struct imx_drm_crtc {
@@ -85,45 +90,6 @@ static int imx_drm_driver_unload(struct drm_device *drm)
85 return 0; 90 return 0;
86} 91}
87 92
88static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
89{
90 struct imx_drm_device *imxdrm = crtc->dev->dev_private;
91 unsigned i;
92
93 for (i = 0; i < MAX_CRTC; i++)
94 if (imxdrm->crtc[i] && imxdrm->crtc[i]->crtc == crtc)
95 return imxdrm->crtc[i];
96
97 return NULL;
98}
99
100int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
101 int hsync_pin, int vsync_pin, u32 bus_flags)
102{
103 struct imx_drm_crtc_helper_funcs *helper;
104 struct imx_drm_crtc *imx_crtc;
105
106 imx_crtc = imx_drm_find_crtc(encoder->crtc);
107 if (!imx_crtc)
108 return -EINVAL;
109
110 helper = &imx_crtc->imx_drm_helper_funcs;
111 if (helper->set_interface_pix_fmt)
112 return helper->set_interface_pix_fmt(encoder->crtc,
113 bus_format, hsync_pin, vsync_pin,
114 bus_flags);
115 return 0;
116}
117EXPORT_SYMBOL_GPL(imx_drm_set_bus_config);
118
119int imx_drm_set_bus_format(struct drm_encoder *encoder, u32 bus_format)
120{
121 return imx_drm_set_bus_config(encoder, bus_format, 2, 3,
122 DRM_BUS_FLAG_DE_HIGH |
123 DRM_BUS_FLAG_PIXDATA_NEGEDGE);
124}
125EXPORT_SYMBOL_GPL(imx_drm_set_bus_format);
126
127int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc) 93int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
128{ 94{
129 return drm_crtc_vblank_get(imx_drm_crtc->crtc); 95 return drm_crtc_vblank_get(imx_drm_crtc->crtc);
@@ -208,6 +174,63 @@ static void imx_drm_output_poll_changed(struct drm_device *drm)
208static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = { 174static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
209 .fb_create = drm_fb_cma_create, 175 .fb_create = drm_fb_cma_create,
210 .output_poll_changed = imx_drm_output_poll_changed, 176 .output_poll_changed = imx_drm_output_poll_changed,
177 .atomic_check = drm_atomic_helper_check,
178 .atomic_commit = drm_atomic_helper_commit,
179};
180
181static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
182{
183 struct drm_device *dev = state->dev;
184 struct drm_crtc *crtc;
185 struct drm_crtc_state *crtc_state;
186 struct drm_plane_state *plane_state;
187 struct drm_gem_cma_object *cma_obj;
188 struct fence *excl;
189 unsigned shared_count;
190 struct fence **shared;
191 unsigned int i, j;
192 int ret;
193
194 /* Wait for fences. */
195 for_each_crtc_in_state(state, crtc, crtc_state, i) {
196 plane_state = crtc->primary->state;
197 if (plane_state->fb) {
198 cma_obj = drm_fb_cma_get_gem_obj(plane_state->fb, 0);
199 if (cma_obj->base.dma_buf) {
200 ret = reservation_object_get_fences_rcu(
201 cma_obj->base.dma_buf->resv, &excl,
202 &shared_count, &shared);
203 if (unlikely(ret))
204 DRM_ERROR("failed to get fences "
205 "for buffer\n");
206
207 if (excl) {
208 fence_wait(excl, false);
209 fence_put(excl);
210 }
211 for (j = 0; j < shared_count; i++) {
212 fence_wait(shared[j], false);
213 fence_put(shared[j]);
214 }
215 }
216 }
217 }
218
219 drm_atomic_helper_commit_modeset_disables(dev, state);
220
221 drm_atomic_helper_commit_planes(dev, state, true);
222
223 drm_atomic_helper_commit_modeset_enables(dev, state);
224
225 drm_atomic_helper_commit_hw_done(state);
226
227 drm_atomic_helper_wait_for_vblanks(dev, state);
228
229 drm_atomic_helper_cleanup_planes(dev, state);
230}
231
232static struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
233 .atomic_commit_tail = imx_drm_atomic_commit_tail,
211}; 234};
212 235
213/* 236/*
@@ -249,6 +272,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
249 drm->mode_config.max_width = 4096; 272 drm->mode_config.max_width = 4096;
250 drm->mode_config.max_height = 4096; 273 drm->mode_config.max_height = 4096;
251 drm->mode_config.funcs = &imx_drm_mode_config_funcs; 274 drm->mode_config.funcs = &imx_drm_mode_config_funcs;
275 drm->mode_config.helper_private = &imx_drm_mode_config_helpers;
252 276
253 drm_mode_config_init(drm); 277 drm_mode_config_init(drm);
254 278
@@ -279,6 +303,8 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
279 } 303 }
280 } 304 }
281 305
306 drm_mode_config_reset(drm);
307
282 /* 308 /*
283 * All components are now initialised, so setup the fb helper. 309 * All components are now initialised, so setup the fb helper.
284 * The fb helper takes copies of key hardware information, so the 310 * The fb helper takes copies of key hardware information, so the
@@ -289,7 +315,6 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
289 dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n"); 315 dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n");
290 legacyfb_depth = 16; 316 legacyfb_depth = 16;
291 } 317 }
292 drm_helper_disable_unused_functions(drm);
293 imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth, 318 imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
294 drm->mode_config.num_crtc, MAX_CRTC); 319 drm->mode_config.num_crtc, MAX_CRTC);
295 if (IS_ERR(imxdrm->fbhelper)) { 320 if (IS_ERR(imxdrm->fbhelper)) {
@@ -403,7 +428,8 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = {
403}; 428};
404 429
405static struct drm_driver imx_drm_driver = { 430static struct drm_driver imx_drm_driver = {
406 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, 431 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
432 DRIVER_ATOMIC,
407 .load = imx_drm_driver_load, 433 .load = imx_drm_driver_load,
408 .unload = imx_drm_driver_unload, 434 .unload = imx_drm_driver_unload,
409 .lastclose = imx_drm_driver_lastclose, 435 .lastclose = imx_drm_driver_lastclose,
@@ -491,6 +517,7 @@ static int imx_drm_platform_remove(struct platform_device *pdev)
491static int imx_drm_suspend(struct device *dev) 517static int imx_drm_suspend(struct device *dev)
492{ 518{
493 struct drm_device *drm_dev = dev_get_drvdata(dev); 519 struct drm_device *drm_dev = dev_get_drvdata(dev);
520 struct imx_drm_device *imxdrm;
494 521
495 /* The drm_dev is NULL before .load hook is called */ 522 /* The drm_dev is NULL before .load hook is called */
496 if (drm_dev == NULL) 523 if (drm_dev == NULL)
@@ -498,17 +525,26 @@ static int imx_drm_suspend(struct device *dev)
498 525
499 drm_kms_helper_poll_disable(drm_dev); 526 drm_kms_helper_poll_disable(drm_dev);
500 527
528 imxdrm = drm_dev->dev_private;
529 imxdrm->state = drm_atomic_helper_suspend(drm_dev);
530 if (IS_ERR(imxdrm->state)) {
531 drm_kms_helper_poll_enable(drm_dev);
532 return PTR_ERR(imxdrm->state);
533 }
534
501 return 0; 535 return 0;
502} 536}
503 537
504static int imx_drm_resume(struct device *dev) 538static int imx_drm_resume(struct device *dev)
505{ 539{
506 struct drm_device *drm_dev = dev_get_drvdata(dev); 540 struct drm_device *drm_dev = dev_get_drvdata(dev);
541 struct imx_drm_device *imx_drm;
507 542
508 if (drm_dev == NULL) 543 if (drm_dev == NULL)
509 return 0; 544 return 0;
510 545
511 drm_helper_resume_force_mode(drm_dev); 546 imx_drm = drm_dev->dev_private;
547 drm_atomic_helper_resume(drm_dev, imx_drm->state);
512 drm_kms_helper_poll_enable(drm_dev); 548 drm_kms_helper_poll_enable(drm_dev);
513 549
514 return 0; 550 return 0;