aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-11-19 18:44:50 -0500
committerDave Airlie <airlied@redhat.com>2015-11-19 18:44:50 -0500
commitdb3956372f086eaf1c079dc12c3f03ae9f306ba5 (patch)
treee5d8d6d001790fd9601b1129da843f1c280c1a8a /drivers/gpu
parentf6619ef7508261be2ba3ded313ccc46ce670d0d3 (diff)
parent5481c8fb1da2a573861095fbea078f30c664d0bd (diff)
Merge tag 'topic/drm-fixes-2015-11-19' of git://anongit.freedesktop.org/drm-intel into drm-fixes
Here are some drm core fixes for v4.4 that I've picked up. Atomic fixes from Maarten, and atomic helper fixes from Ville and Daniel. Admittedly the topmost commit didn't sit in our tree for very long, but does come with reviews and testing from trustworthy people. * tag 'topic/drm-fixes-2015-11-19' of git://anongit.freedesktop.org/drm-intel: drm/atomic-helper: Check encoder/crtc constraints drm: Fix primary plane size for stereo doubled modes for legacy setcrtc drm/core: Fix old_fb handling in pan_display_atomic. drm/core: Fix old_fb handling in restore_fbdev_mode_atomic. drm/atomic: add a drm_atomic_clean_old_fb helper. drm/core: Fix old_fb handling in drm_mode_atomic_ioctl. drm/core: Set legacy_cursor_update in drm_atomic_helper_disable_plane.
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/drm_atomic.c61
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c29
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c51
3 files changed, 76 insertions, 65 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 7bb3845d9974..aeee083c7f95 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1432,6 +1432,45 @@ static int atomic_set_prop(struct drm_atomic_state *state,
1432 return ret; 1432 return ret;
1433} 1433}
1434 1434
1435/**
1436 * drm_atomic_update_old_fb -- Unset old_fb pointers and set plane->fb pointers.
1437 *
1438 * @dev: drm device to check.
1439 * @plane_mask: plane mask for planes that were updated.
1440 * @ret: return value, can be -EDEADLK for a retry.
1441 *
1442 * Before doing an update plane->old_fb is set to plane->fb,
1443 * but before dropping the locks old_fb needs to be set to NULL
1444 * and plane->fb updated. This is a common operation for each
1445 * atomic update, so this call is split off as a helper.
1446 */
1447void drm_atomic_clean_old_fb(struct drm_device *dev,
1448 unsigned plane_mask,
1449 int ret)
1450{
1451 struct drm_plane *plane;
1452
1453 /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
1454 * locks (ie. while it is still safe to deref plane->state). We
1455 * need to do this here because the driver entry points cannot
1456 * distinguish between legacy and atomic ioctls.
1457 */
1458 drm_for_each_plane_mask(plane, dev, plane_mask) {
1459 if (ret == 0) {
1460 struct drm_framebuffer *new_fb = plane->state->fb;
1461 if (new_fb)
1462 drm_framebuffer_reference(new_fb);
1463 plane->fb = new_fb;
1464 plane->crtc = plane->state->crtc;
1465
1466 if (plane->old_fb)
1467 drm_framebuffer_unreference(plane->old_fb);
1468 }
1469 plane->old_fb = NULL;
1470 }
1471}
1472EXPORT_SYMBOL(drm_atomic_clean_old_fb);
1473
1435int drm_mode_atomic_ioctl(struct drm_device *dev, 1474int drm_mode_atomic_ioctl(struct drm_device *dev,
1436 void *data, struct drm_file *file_priv) 1475 void *data, struct drm_file *file_priv)
1437{ 1476{
@@ -1446,7 +1485,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
1446 struct drm_plane *plane; 1485 struct drm_plane *plane;
1447 struct drm_crtc *crtc; 1486 struct drm_crtc *crtc;
1448 struct drm_crtc_state *crtc_state; 1487 struct drm_crtc_state *crtc_state;
1449 unsigned plane_mask = 0; 1488 unsigned plane_mask;
1450 int ret = 0; 1489 int ret = 0;
1451 unsigned int i, j; 1490 unsigned int i, j;
1452 1491
@@ -1486,6 +1525,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
1486 state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET); 1525 state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
1487 1526
1488retry: 1527retry:
1528 plane_mask = 0;
1489 copied_objs = 0; 1529 copied_objs = 0;
1490 copied_props = 0; 1530 copied_props = 0;
1491 1531
@@ -1576,24 +1616,7 @@ retry:
1576 } 1616 }
1577 1617
1578out: 1618out:
1579 /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping 1619 drm_atomic_clean_old_fb(dev, plane_mask, ret);
1580 * locks (ie. while it is still safe to deref plane->state). We
1581 * need to do this here because the driver entry points cannot
1582 * distinguish between legacy and atomic ioctls.
1583 */
1584 drm_for_each_plane_mask(plane, dev, plane_mask) {
1585 if (ret == 0) {
1586 struct drm_framebuffer *new_fb = plane->state->fb;
1587 if (new_fb)
1588 drm_framebuffer_reference(new_fb);
1589 plane->fb = new_fb;
1590 plane->crtc = plane->state->crtc;
1591
1592 if (plane->old_fb)
1593 drm_framebuffer_unreference(plane->old_fb);
1594 }
1595 plane->old_fb = NULL;
1596 }
1597 1620
1598 if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { 1621 if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1599 /* 1622 /*
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 0c6f62168776..e5aec45bf985 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -210,6 +210,14 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
210 return -EINVAL; 210 return -EINVAL;
211 } 211 }
212 212
213 if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) {
214 DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d]\n",
215 new_encoder->base.id,
216 new_encoder->name,
217 connector_state->crtc->base.id);
218 return -EINVAL;
219 }
220
213 if (new_encoder == connector_state->best_encoder) { 221 if (new_encoder == connector_state->best_encoder) {
214 DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n", 222 DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n",
215 connector->base.id, 223 connector->base.id,
@@ -1553,6 +1561,9 @@ retry:
1553 goto fail; 1561 goto fail;
1554 } 1562 }
1555 1563
1564 if (plane_state->crtc && (plane == plane->crtc->cursor))
1565 plane_state->state->legacy_cursor_update = true;
1566
1556 ret = __drm_atomic_helper_disable_plane(plane, plane_state); 1567 ret = __drm_atomic_helper_disable_plane(plane, plane_state);
1557 if (ret != 0) 1568 if (ret != 0)
1558 goto fail; 1569 goto fail;
@@ -1605,9 +1616,6 @@ int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
1605 plane_state->src_h = 0; 1616 plane_state->src_h = 0;
1606 plane_state->src_w = 0; 1617 plane_state->src_w = 0;
1607 1618
1608 if (plane->crtc && (plane == plane->crtc->cursor))
1609 plane_state->state->legacy_cursor_update = true;
1610
1611 return 0; 1619 return 0;
1612} 1620}
1613 1621
@@ -1741,6 +1749,7 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
1741 struct drm_crtc_state *crtc_state; 1749 struct drm_crtc_state *crtc_state;
1742 struct drm_plane_state *primary_state; 1750 struct drm_plane_state *primary_state;
1743 struct drm_crtc *crtc = set->crtc; 1751 struct drm_crtc *crtc = set->crtc;
1752 int hdisplay, vdisplay;
1744 int ret; 1753 int ret;
1745 1754
1746 crtc_state = drm_atomic_get_crtc_state(state, crtc); 1755 crtc_state = drm_atomic_get_crtc_state(state, crtc);
@@ -1783,19 +1792,21 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
1783 if (ret != 0) 1792 if (ret != 0)
1784 return ret; 1793 return ret;
1785 1794
1795 drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay);
1796
1786 drm_atomic_set_fb_for_plane(primary_state, set->fb); 1797 drm_atomic_set_fb_for_plane(primary_state, set->fb);
1787 primary_state->crtc_x = 0; 1798 primary_state->crtc_x = 0;
1788 primary_state->crtc_y = 0; 1799 primary_state->crtc_y = 0;
1789 primary_state->crtc_h = set->mode->vdisplay; 1800 primary_state->crtc_h = vdisplay;
1790 primary_state->crtc_w = set->mode->hdisplay; 1801 primary_state->crtc_w = hdisplay;
1791 primary_state->src_x = set->x << 16; 1802 primary_state->src_x = set->x << 16;
1792 primary_state->src_y = set->y << 16; 1803 primary_state->src_y = set->y << 16;
1793 if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) { 1804 if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) {
1794 primary_state->src_h = set->mode->hdisplay << 16; 1805 primary_state->src_h = hdisplay << 16;
1795 primary_state->src_w = set->mode->vdisplay << 16; 1806 primary_state->src_w = vdisplay << 16;
1796 } else { 1807 } else {
1797 primary_state->src_h = set->mode->vdisplay << 16; 1808 primary_state->src_h = vdisplay << 16;
1798 primary_state->src_w = set->mode->hdisplay << 16; 1809 primary_state->src_w = hdisplay << 16;
1799 } 1810 }
1800 1811
1801commit: 1812commit:
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index e673c13c7391..69cbab5e5c81 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -342,6 +342,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
342 struct drm_plane *plane; 342 struct drm_plane *plane;
343 struct drm_atomic_state *state; 343 struct drm_atomic_state *state;
344 int i, ret; 344 int i, ret;
345 unsigned plane_mask;
345 346
346 state = drm_atomic_state_alloc(dev); 347 state = drm_atomic_state_alloc(dev);
347 if (!state) 348 if (!state)
@@ -349,11 +350,10 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
349 350
350 state->acquire_ctx = dev->mode_config.acquire_ctx; 351 state->acquire_ctx = dev->mode_config.acquire_ctx;
351retry: 352retry:
353 plane_mask = 0;
352 drm_for_each_plane(plane, dev) { 354 drm_for_each_plane(plane, dev) {
353 struct drm_plane_state *plane_state; 355 struct drm_plane_state *plane_state;
354 356
355 plane->old_fb = plane->fb;
356
357 plane_state = drm_atomic_get_plane_state(state, plane); 357 plane_state = drm_atomic_get_plane_state(state, plane);
358 if (IS_ERR(plane_state)) { 358 if (IS_ERR(plane_state)) {
359 ret = PTR_ERR(plane_state); 359 ret = PTR_ERR(plane_state);
@@ -362,6 +362,9 @@ retry:
362 362
363 plane_state->rotation = BIT(DRM_ROTATE_0); 363 plane_state->rotation = BIT(DRM_ROTATE_0);
364 364
365 plane->old_fb = plane->fb;
366 plane_mask |= 1 << drm_plane_index(plane);
367
365 /* disable non-primary: */ 368 /* disable non-primary: */
366 if (plane->type == DRM_PLANE_TYPE_PRIMARY) 369 if (plane->type == DRM_PLANE_TYPE_PRIMARY)
367 continue; 370 continue;
@@ -382,19 +385,7 @@ retry:
382 ret = drm_atomic_commit(state); 385 ret = drm_atomic_commit(state);
383 386
384fail: 387fail:
385 drm_for_each_plane(plane, dev) { 388 drm_atomic_clean_old_fb(dev, plane_mask, ret);
386 if (ret == 0) {
387 struct drm_framebuffer *new_fb = plane->state->fb;
388 if (new_fb)
389 drm_framebuffer_reference(new_fb);
390 plane->fb = new_fb;
391 plane->crtc = plane->state->crtc;
392
393 if (plane->old_fb)
394 drm_framebuffer_unreference(plane->old_fb);
395 }
396 plane->old_fb = NULL;
397 }
398 389
399 if (ret == -EDEADLK) 390 if (ret == -EDEADLK)
400 goto backoff; 391 goto backoff;
@@ -1236,7 +1227,9 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
1236 struct drm_fb_helper *fb_helper = info->par; 1227 struct drm_fb_helper *fb_helper = info->par;
1237 struct drm_device *dev = fb_helper->dev; 1228 struct drm_device *dev = fb_helper->dev;
1238 struct drm_atomic_state *state; 1229 struct drm_atomic_state *state;
1230 struct drm_plane *plane;
1239 int i, ret; 1231 int i, ret;
1232 unsigned plane_mask;
1240 1233
1241 state = drm_atomic_state_alloc(dev); 1234 state = drm_atomic_state_alloc(dev);
1242 if (!state) 1235 if (!state)
@@ -1244,19 +1237,22 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
1244 1237
1245 state->acquire_ctx = dev->mode_config.acquire_ctx; 1238 state->acquire_ctx = dev->mode_config.acquire_ctx;
1246retry: 1239retry:
1240 plane_mask = 0;
1247 for(i = 0; i < fb_helper->crtc_count; i++) { 1241 for(i = 0; i < fb_helper->crtc_count; i++) {
1248 struct drm_mode_set *mode_set; 1242 struct drm_mode_set *mode_set;
1249 1243
1250 mode_set = &fb_helper->crtc_info[i].mode_set; 1244 mode_set = &fb_helper->crtc_info[i].mode_set;
1251 1245
1252 mode_set->crtc->primary->old_fb = mode_set->crtc->primary->fb;
1253
1254 mode_set->x = var->xoffset; 1246 mode_set->x = var->xoffset;
1255 mode_set->y = var->yoffset; 1247 mode_set->y = var->yoffset;
1256 1248
1257 ret = __drm_atomic_helper_set_config(mode_set, state); 1249 ret = __drm_atomic_helper_set_config(mode_set, state);
1258 if (ret != 0) 1250 if (ret != 0)
1259 goto fail; 1251 goto fail;
1252
1253 plane = mode_set->crtc->primary;
1254 plane_mask |= drm_plane_index(plane);
1255 plane->old_fb = plane->fb;
1260 } 1256 }
1261 1257
1262 ret = drm_atomic_commit(state); 1258 ret = drm_atomic_commit(state);
@@ -1268,26 +1264,7 @@ retry:
1268 1264
1269 1265
1270fail: 1266fail:
1271 for(i = 0; i < fb_helper->crtc_count; i++) { 1267 drm_atomic_clean_old_fb(dev, plane_mask, ret);
1272 struct drm_mode_set *mode_set;
1273 struct drm_plane *plane;
1274
1275 mode_set = &fb_helper->crtc_info[i].mode_set;
1276 plane = mode_set->crtc->primary;
1277
1278 if (ret == 0) {
1279 struct drm_framebuffer *new_fb = plane->state->fb;
1280
1281 if (new_fb)
1282 drm_framebuffer_reference(new_fb);
1283 plane->fb = new_fb;
1284 plane->crtc = plane->state->crtc;
1285
1286 if (plane->old_fb)
1287 drm_framebuffer_unreference(plane->old_fb);
1288 }
1289 plane->old_fb = NULL;
1290 }
1291 1268
1292 if (ret == -EDEADLK) 1269 if (ret == -EDEADLK)
1293 goto backoff; 1270 goto backoff;