aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_atomic.c28
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c25
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c7
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c14
-rw-r--r--include/drm/drm_atomic.h2
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,
368EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane); 368EXPORT_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 */
380void
381drm_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}
396EXPORT_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 */
1809void drm_atomic_helper_plane_reset(struct drm_plane *plane) 1809void 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);
1823struct drm_plane_state * 1826struct drm_plane_state *
1824drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) 1827drm_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}
1831EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); 1841EXPORT_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 */
1841void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, 1851void 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}
1846EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); 1859EXPORT_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,
46int __must_check 46int __must_check
47drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, 47drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
48 struct drm_crtc *crtc); 48 struct drm_crtc *crtc);
49void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
50 struct drm_framebuffer *fb);
49int __must_check 51int __must_check
50drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, 52drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
51 struct drm_crtc *crtc); 53 struct drm_crtc *crtc);