diff options
-rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_plane_helper.c | 14 | ||||
-rw-r--r-- | include/drm/drm_atomic.h | 2 |
5 files changed, 60 insertions, 16 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index ad15a88c0f74..ed991ba66e21 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -368,6 +368,34 @@ drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, | |||
368 | EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane); | 368 | EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane); |
369 | 369 | ||
370 | /** | 370 | /** |
371 | * drm_atomic_set_fb_for_plane - set crtc for plane | ||
372 | * @plane_state: atomic state object for the plane | ||
373 | * @fb: fb to use for the plane | ||
374 | * | ||
375 | * Changing the assigned framebuffer for a plane requires us to grab a reference | ||
376 | * to the new fb and drop the reference to the old fb, if there is one. This | ||
377 | * function takes care of all these details besides updating the pointer in the | ||
378 | * state object itself. | ||
379 | */ | ||
380 | void | ||
381 | drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, | ||
382 | struct drm_framebuffer *fb) | ||
383 | { | ||
384 | if (plane_state->fb) | ||
385 | drm_framebuffer_unreference(plane_state->fb); | ||
386 | if (fb) | ||
387 | drm_framebuffer_reference(fb); | ||
388 | plane_state->fb = fb; | ||
389 | |||
390 | if (fb) | ||
391 | DRM_DEBUG_KMS("Set [FB:%d] for plane state %p\n", | ||
392 | fb->base.id, plane_state); | ||
393 | else | ||
394 | DRM_DEBUG_KMS("Set [NOFB] for plane state %p\n", plane_state); | ||
395 | } | ||
396 | EXPORT_SYMBOL(drm_atomic_set_fb_for_plane); | ||
397 | |||
398 | /** | ||
371 | * drm_atomic_set_crtc_for_connector - set crtc for connector | 399 | * drm_atomic_set_crtc_for_connector - set crtc for connector |
372 | * @conn_state: atomic state object for the connector | 400 | * @conn_state: atomic state object for the connector |
373 | * @crtc: crtc to use for the connector | 401 | * @crtc: crtc to use for the connector |
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2b1db0c12fdc..ca839bd9bb0d 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
@@ -1182,7 +1182,7 @@ retry: | |||
1182 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); | 1182 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); |
1183 | if (ret != 0) | 1183 | if (ret != 0) |
1184 | goto fail; | 1184 | goto fail; |
1185 | plane_state->fb = fb; | 1185 | drm_atomic_set_fb_for_plane(plane_state, fb); |
1186 | plane_state->crtc_x = crtc_x; | 1186 | plane_state->crtc_x = crtc_x; |
1187 | plane_state->crtc_y = crtc_y; | 1187 | plane_state->crtc_y = crtc_y; |
1188 | plane_state->crtc_h = crtc_h; | 1188 | plane_state->crtc_h = crtc_h; |
@@ -1250,7 +1250,7 @@ retry: | |||
1250 | ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); | 1250 | ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); |
1251 | if (ret != 0) | 1251 | if (ret != 0) |
1252 | goto fail; | 1252 | goto fail; |
1253 | plane_state->fb = NULL; | 1253 | drm_atomic_set_fb_for_plane(plane_state, NULL); |
1254 | plane_state->crtc_x = 0; | 1254 | plane_state->crtc_x = 0; |
1255 | plane_state->crtc_y = 0; | 1255 | plane_state->crtc_y = 0; |
1256 | plane_state->crtc_h = 0; | 1256 | plane_state->crtc_h = 0; |
@@ -1422,7 +1422,7 @@ retry: | |||
1422 | ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); | 1422 | ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); |
1423 | if (ret != 0) | 1423 | if (ret != 0) |
1424 | goto fail; | 1424 | goto fail; |
1425 | primary_state->fb = set->fb; | 1425 | drm_atomic_set_fb_for_plane(primary_state, set->fb); |
1426 | primary_state->crtc_x = 0; | 1426 | primary_state->crtc_x = 0; |
1427 | primary_state->crtc_y = 0; | 1427 | primary_state->crtc_y = 0; |
1428 | primary_state->crtc_h = set->mode->vdisplay; | 1428 | primary_state->crtc_h = set->mode->vdisplay; |
@@ -1694,7 +1694,7 @@ retry: | |||
1694 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); | 1694 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); |
1695 | if (ret != 0) | 1695 | if (ret != 0) |
1696 | goto fail; | 1696 | goto fail; |
1697 | plane_state->fb = fb; | 1697 | drm_atomic_set_fb_for_plane(plane_state, fb); |
1698 | 1698 | ||
1699 | ret = drm_atomic_async_commit(state); | 1699 | ret = drm_atomic_async_commit(state); |
1700 | if (ret != 0) | 1700 | if (ret != 0) |
@@ -1808,6 +1808,9 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); | |||
1808 | */ | 1808 | */ |
1809 | void drm_atomic_helper_plane_reset(struct drm_plane *plane) | 1809 | void drm_atomic_helper_plane_reset(struct drm_plane *plane) |
1810 | { | 1810 | { |
1811 | if (plane->state && plane->state->fb) | ||
1812 | drm_framebuffer_unreference(plane->state->fb); | ||
1813 | |||
1811 | kfree(plane->state); | 1814 | kfree(plane->state); |
1812 | plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); | 1815 | plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); |
1813 | } | 1816 | } |
@@ -1823,10 +1826,17 @@ EXPORT_SYMBOL(drm_atomic_helper_plane_reset); | |||
1823 | struct drm_plane_state * | 1826 | struct drm_plane_state * |
1824 | drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) | 1827 | drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) |
1825 | { | 1828 | { |
1829 | struct drm_plane_state *state; | ||
1830 | |||
1826 | if (WARN_ON(!plane->state)) | 1831 | if (WARN_ON(!plane->state)) |
1827 | return NULL; | 1832 | return NULL; |
1828 | 1833 | ||
1829 | return kmemdup(plane->state, sizeof(*plane->state), GFP_KERNEL); | 1834 | state = kmemdup(plane->state, sizeof(*plane->state), GFP_KERNEL); |
1835 | |||
1836 | if (state && state->fb) | ||
1837 | drm_framebuffer_reference(state->fb); | ||
1838 | |||
1839 | return state; | ||
1830 | } | 1840 | } |
1831 | EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); | 1841 | EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); |
1832 | 1842 | ||
@@ -1839,8 +1849,11 @@ EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); | |||
1839 | * subclassed plane state structure. | 1849 | * subclassed plane state structure. |
1840 | */ | 1850 | */ |
1841 | void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, | 1851 | void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, |
1842 | struct drm_plane_state *state) | 1852 | struct drm_plane_state *state) |
1843 | { | 1853 | { |
1854 | if (state->fb) | ||
1855 | drm_framebuffer_unreference(state->fb); | ||
1856 | |||
1844 | kfree(state); | 1857 | kfree(state); |
1845 | } | 1858 | } |
1846 | EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); | 1859 | EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 33195e9adaab..d552708409de 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -34,11 +34,13 @@ | |||
34 | #include <linux/moduleparam.h> | 34 | #include <linux/moduleparam.h> |
35 | 35 | ||
36 | #include <drm/drmP.h> | 36 | #include <drm/drmP.h> |
37 | #include <drm/drm_atomic.h> | ||
37 | #include <drm/drm_crtc.h> | 38 | #include <drm/drm_crtc.h> |
38 | #include <drm/drm_fourcc.h> | 39 | #include <drm/drm_fourcc.h> |
39 | #include <drm/drm_crtc_helper.h> | 40 | #include <drm/drm_crtc_helper.h> |
40 | #include <drm/drm_fb_helper.h> | 41 | #include <drm/drm_fb_helper.h> |
41 | #include <drm/drm_plane_helper.h> | 42 | #include <drm/drm_plane_helper.h> |
43 | #include <drm/drm_atomic_helper.h> | ||
42 | #include <drm/drm_edid.h> | 44 | #include <drm/drm_edid.h> |
43 | 45 | ||
44 | /** | 46 | /** |
@@ -998,15 +1000,14 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | |||
998 | if (plane->funcs->atomic_duplicate_state) | 1000 | if (plane->funcs->atomic_duplicate_state) |
999 | plane_state = plane->funcs->atomic_duplicate_state(plane); | 1001 | plane_state = plane->funcs->atomic_duplicate_state(plane); |
1000 | else if (plane->state) | 1002 | else if (plane->state) |
1001 | plane_state = kmemdup(plane->state, sizeof(*plane_state), | 1003 | plane_state = drm_atomic_helper_plane_duplicate_state(plane); |
1002 | GFP_KERNEL); | ||
1003 | else | 1004 | else |
1004 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); | 1005 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); |
1005 | if (!plane_state) | 1006 | if (!plane_state) |
1006 | return -ENOMEM; | 1007 | return -ENOMEM; |
1007 | 1008 | ||
1008 | plane_state->crtc = crtc; | 1009 | plane_state->crtc = crtc; |
1009 | plane_state->fb = crtc->primary->fb; | 1010 | drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb); |
1010 | plane_state->crtc_x = 0; | 1011 | plane_state->crtc_x = 0; |
1011 | plane_state->crtc_y = 0; | 1012 | plane_state->crtc_y = 0; |
1012 | plane_state->crtc_h = crtc->mode.vdisplay; | 1013 | plane_state->crtc_h = crtc->mode.vdisplay; |
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index fa56bb5da6c3..d99c452b0563 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c | |||
@@ -27,7 +27,9 @@ | |||
27 | #include <drm/drmP.h> | 27 | #include <drm/drmP.h> |
28 | #include <drm/drm_plane_helper.h> | 28 | #include <drm/drm_plane_helper.h> |
29 | #include <drm/drm_rect.h> | 29 | #include <drm/drm_rect.h> |
30 | #include <drm/drm_atomic.h> | ||
30 | #include <drm/drm_crtc_helper.h> | 31 | #include <drm/drm_crtc_helper.h> |
32 | #include <drm/drm_atomic_helper.h> | ||
31 | 33 | ||
32 | #define SUBPIXEL_MASK 0xffff | 34 | #define SUBPIXEL_MASK 0xffff |
33 | 35 | ||
@@ -464,7 +466,7 @@ out: | |||
464 | if (plane->funcs->atomic_destroy_state) | 466 | if (plane->funcs->atomic_destroy_state) |
465 | plane->funcs->atomic_destroy_state(plane, plane_state); | 467 | plane->funcs->atomic_destroy_state(plane, plane_state); |
466 | else | 468 | else |
467 | kfree(plane_state); | 469 | drm_atomic_helper_plane_destroy_state(plane, plane_state); |
468 | } | 470 | } |
469 | 471 | ||
470 | return ret; | 472 | return ret; |
@@ -505,15 +507,14 @@ int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
505 | if (plane->funcs->atomic_duplicate_state) | 507 | if (plane->funcs->atomic_duplicate_state) |
506 | plane_state = plane->funcs->atomic_duplicate_state(plane); | 508 | plane_state = plane->funcs->atomic_duplicate_state(plane); |
507 | else if (plane->state) | 509 | else if (plane->state) |
508 | plane_state = kmemdup(plane->state, sizeof(*plane_state), | 510 | plane_state = drm_atomic_helper_plane_duplicate_state(plane); |
509 | GFP_KERNEL); | ||
510 | else | 511 | else |
511 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); | 512 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); |
512 | if (!plane_state) | 513 | if (!plane_state) |
513 | return -ENOMEM; | 514 | return -ENOMEM; |
514 | 515 | ||
515 | plane_state->crtc = crtc; | 516 | plane_state->crtc = crtc; |
516 | plane_state->fb = fb; | 517 | drm_atomic_set_fb_for_plane(plane_state, fb); |
517 | plane_state->crtc_x = crtc_x; | 518 | plane_state->crtc_x = crtc_x; |
518 | plane_state->crtc_y = crtc_y; | 519 | plane_state->crtc_y = crtc_y; |
519 | plane_state->crtc_h = crtc_h; | 520 | plane_state->crtc_h = crtc_h; |
@@ -552,15 +553,14 @@ int drm_plane_helper_disable(struct drm_plane *plane) | |||
552 | if (plane->funcs->atomic_duplicate_state) | 553 | if (plane->funcs->atomic_duplicate_state) |
553 | plane_state = plane->funcs->atomic_duplicate_state(plane); | 554 | plane_state = plane->funcs->atomic_duplicate_state(plane); |
554 | else if (plane->state) | 555 | else if (plane->state) |
555 | plane_state = kmemdup(plane->state, sizeof(*plane_state), | 556 | plane_state = drm_atomic_helper_plane_duplicate_state(plane); |
556 | GFP_KERNEL); | ||
557 | else | 557 | else |
558 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); | 558 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); |
559 | if (!plane_state) | 559 | if (!plane_state) |
560 | return -ENOMEM; | 560 | return -ENOMEM; |
561 | 561 | ||
562 | plane_state->crtc = NULL; | 562 | plane_state->crtc = NULL; |
563 | plane_state->fb = NULL; | 563 | drm_atomic_set_fb_for_plane(plane_state, NULL); |
564 | 564 | ||
565 | return drm_plane_helper_commit(plane, plane_state, plane->fb); | 565 | return drm_plane_helper_commit(plane, plane_state, plane->fb); |
566 | } | 566 | } |
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 5bb15f550c42..9d919168bc11 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h | |||
@@ -46,6 +46,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, | |||
46 | int __must_check | 46 | int __must_check |
47 | drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, | 47 | drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, |
48 | struct drm_crtc *crtc); | 48 | struct drm_crtc *crtc); |
49 | void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, | ||
50 | struct drm_framebuffer *fb); | ||
49 | int __must_check | 51 | int __must_check |
50 | drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, | 52 | drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, |
51 | struct drm_crtc *crtc); | 53 | struct drm_crtc *crtc); |