diff options
Diffstat (limited to 'drivers/gpu/drm/drm_atomic_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 106 |
1 files changed, 85 insertions, 21 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index bbdbe4721573..541ba833ed36 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
@@ -330,7 +330,29 @@ mode_fixup(struct drm_atomic_state *state) | |||
330 | return 0; | 330 | return 0; |
331 | } | 331 | } |
332 | 332 | ||
333 | static int | 333 | /** |
334 | * drm_atomic_helper_check - validate state object for modeset changes | ||
335 | * @dev: DRM device | ||
336 | * @state: the driver state object | ||
337 | * | ||
338 | * Check the state object to see if the requested state is physically possible. | ||
339 | * This does all the crtc and connector related computations for an atomic | ||
340 | * update. It computes and updates crtc_state->mode_changed, adds any additional | ||
341 | * connectors needed for full modesets and calls down into ->mode_fixup | ||
342 | * functions of the driver backend. | ||
343 | * | ||
344 | * IMPORTANT: | ||
345 | * | ||
346 | * Drivers which update ->mode_changed (e.g. in their ->atomic_check hooks if a | ||
347 | * plane update can't be done without a full modeset) _must_ call this function | ||
348 | * afterwards after that change. It is permitted to call this function multiple | ||
349 | * times for the same update, e.g. when the ->atomic_check functions depend upon | ||
350 | * the adjusted dotclock for fifo space allocation and watermark computation. | ||
351 | * | ||
352 | * RETURNS | ||
353 | * Zero for success or -errno | ||
354 | */ | ||
355 | int | ||
334 | drm_atomic_helper_check_modeset(struct drm_device *dev, | 356 | drm_atomic_helper_check_modeset(struct drm_device *dev, |
335 | struct drm_atomic_state *state) | 357 | struct drm_atomic_state *state) |
336 | { | 358 | { |
@@ -406,23 +428,23 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, | |||
406 | 428 | ||
407 | return mode_fixup(state); | 429 | return mode_fixup(state); |
408 | } | 430 | } |
431 | EXPORT_SYMBOL(drm_atomic_helper_check_modeset); | ||
409 | 432 | ||
410 | /** | 433 | /** |
411 | * drm_atomic_helper_check - validate state object | 434 | * drm_atomic_helper_check - validate state object for modeset changes |
412 | * @dev: DRM device | 435 | * @dev: DRM device |
413 | * @state: the driver state object | 436 | * @state: the driver state object |
414 | * | 437 | * |
415 | * Check the state object to see if the requested state is physically possible. | 438 | * Check the state object to see if the requested state is physically possible. |
416 | * Only crtcs and planes have check callbacks, so for any additional (global) | 439 | * This does all the plane update related checks using by calling into the |
417 | * checking that a driver needs it can simply wrap that around this function. | 440 | * ->atomic_check hooks provided by the driver. |
418 | * Drivers without such needs can directly use this as their ->atomic_check() | ||
419 | * callback. | ||
420 | * | 441 | * |
421 | * RETURNS | 442 | * RETURNS |
422 | * Zero for success or -errno | 443 | * Zero for success or -errno |
423 | */ | 444 | */ |
424 | int drm_atomic_helper_check(struct drm_device *dev, | 445 | int |
425 | struct drm_atomic_state *state) | 446 | drm_atomic_helper_check_planes(struct drm_device *dev, |
447 | struct drm_atomic_state *state) | ||
426 | { | 448 | { |
427 | int nplanes = dev->mode_config.num_total_plane; | 449 | int nplanes = dev->mode_config.num_total_plane; |
428 | int ncrtcs = dev->mode_config.num_crtc; | 450 | int ncrtcs = dev->mode_config.num_crtc; |
@@ -445,7 +467,7 @@ int drm_atomic_helper_check(struct drm_device *dev, | |||
445 | 467 | ||
446 | ret = funcs->atomic_check(plane, plane_state); | 468 | ret = funcs->atomic_check(plane, plane_state); |
447 | if (ret) { | 469 | if (ret) { |
448 | DRM_DEBUG_KMS("[PLANE:%d] atomic check failed\n", | 470 | DRM_DEBUG_KMS("[PLANE:%d] atomic driver check failed\n", |
449 | plane->base.id); | 471 | plane->base.id); |
450 | return ret; | 472 | return ret; |
451 | } | 473 | } |
@@ -465,16 +487,49 @@ int drm_atomic_helper_check(struct drm_device *dev, | |||
465 | 487 | ||
466 | ret = funcs->atomic_check(crtc, state->crtc_states[i]); | 488 | ret = funcs->atomic_check(crtc, state->crtc_states[i]); |
467 | if (ret) { | 489 | if (ret) { |
468 | DRM_DEBUG_KMS("[CRTC:%d] atomic check failed\n", | 490 | DRM_DEBUG_KMS("[CRTC:%d] atomic driver check failed\n", |
469 | crtc->base.id); | 491 | crtc->base.id); |
470 | return ret; | 492 | return ret; |
471 | } | 493 | } |
472 | } | 494 | } |
473 | 495 | ||
496 | return ret; | ||
497 | } | ||
498 | EXPORT_SYMBOL(drm_atomic_helper_check_planes); | ||
499 | |||
500 | /** | ||
501 | * drm_atomic_helper_check - validate state object | ||
502 | * @dev: DRM device | ||
503 | * @state: the driver state object | ||
504 | * | ||
505 | * Check the state object to see if the requested state is physically possible. | ||
506 | * Only crtcs and planes have check callbacks, so for any additional (global) | ||
507 | * checking that a driver needs it can simply wrap that around this function. | ||
508 | * Drivers without such needs can directly use this as their ->atomic_check() | ||
509 | * callback. | ||
510 | * | ||
511 | * This just wraps the two parts of the state checking for planes and modeset | ||
512 | * state in the default order: First it calls drm_atomic_helper_check_modeset() | ||
513 | * and then drm_atomic_helper_check_planes(). The assumption is that the | ||
514 | * ->atomic_check functions depend upon an updated adjusted_mode.clock to | ||
515 | * e.g. properly compute watermarks. | ||
516 | * | ||
517 | * RETURNS | ||
518 | * Zero for success or -errno | ||
519 | */ | ||
520 | int drm_atomic_helper_check(struct drm_device *dev, | ||
521 | struct drm_atomic_state *state) | ||
522 | { | ||
523 | int ret; | ||
524 | |||
474 | ret = drm_atomic_helper_check_modeset(dev, state); | 525 | ret = drm_atomic_helper_check_modeset(dev, state); |
475 | if (ret) | 526 | if (ret) |
476 | return ret; | 527 | return ret; |
477 | 528 | ||
529 | ret = drm_atomic_helper_check_planes(dev, state); | ||
530 | if (ret) | ||
531 | return ret; | ||
532 | |||
478 | return ret; | 533 | return ret; |
479 | } | 534 | } |
480 | EXPORT_SYMBOL(drm_atomic_helper_check); | 535 | EXPORT_SYMBOL(drm_atomic_helper_check); |
@@ -1222,7 +1277,7 @@ retry: | |||
1222 | goto fail; | 1277 | goto fail; |
1223 | } | 1278 | } |
1224 | 1279 | ||
1225 | ret = drm_atomic_set_crtc_for_plane(state, plane, crtc); | 1280 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); |
1226 | if (ret != 0) | 1281 | if (ret != 0) |
1227 | goto fail; | 1282 | goto fail; |
1228 | drm_atomic_set_fb_for_plane(plane_state, fb); | 1283 | drm_atomic_set_fb_for_plane(plane_state, fb); |
@@ -1301,7 +1356,7 @@ retry: | |||
1301 | goto fail; | 1356 | goto fail; |
1302 | } | 1357 | } |
1303 | 1358 | ||
1304 | ret = drm_atomic_set_crtc_for_plane(state, plane, NULL); | 1359 | ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); |
1305 | if (ret != 0) | 1360 | if (ret != 0) |
1306 | goto fail; | 1361 | goto fail; |
1307 | drm_atomic_set_fb_for_plane(plane_state, NULL); | 1362 | drm_atomic_set_fb_for_plane(plane_state, NULL); |
@@ -1464,7 +1519,7 @@ retry: | |||
1464 | 1519 | ||
1465 | crtc_state->enable = false; | 1520 | crtc_state->enable = false; |
1466 | 1521 | ||
1467 | ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, NULL); | 1522 | ret = drm_atomic_set_crtc_for_plane(primary_state, NULL); |
1468 | if (ret != 0) | 1523 | if (ret != 0) |
1469 | goto fail; | 1524 | goto fail; |
1470 | 1525 | ||
@@ -1479,7 +1534,7 @@ retry: | |||
1479 | crtc_state->enable = true; | 1534 | crtc_state->enable = true; |
1480 | drm_mode_copy(&crtc_state->mode, set->mode); | 1535 | drm_mode_copy(&crtc_state->mode, set->mode); |
1481 | 1536 | ||
1482 | ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, crtc); | 1537 | ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); |
1483 | if (ret != 0) | 1538 | if (ret != 0) |
1484 | goto fail; | 1539 | goto fail; |
1485 | drm_atomic_set_fb_for_plane(primary_state, set->fb); | 1540 | drm_atomic_set_fb_for_plane(primary_state, set->fb); |
@@ -1558,8 +1613,8 @@ retry: | |||
1558 | goto fail; | 1613 | goto fail; |
1559 | } | 1614 | } |
1560 | 1615 | ||
1561 | ret = crtc->funcs->atomic_set_property(crtc, crtc_state, | 1616 | ret = drm_atomic_crtc_set_property(crtc, crtc_state, |
1562 | property, val); | 1617 | property, val); |
1563 | if (ret) | 1618 | if (ret) |
1564 | goto fail; | 1619 | goto fail; |
1565 | 1620 | ||
@@ -1617,8 +1672,8 @@ retry: | |||
1617 | goto fail; | 1672 | goto fail; |
1618 | } | 1673 | } |
1619 | 1674 | ||
1620 | ret = plane->funcs->atomic_set_property(plane, plane_state, | 1675 | ret = drm_atomic_plane_set_property(plane, plane_state, |
1621 | property, val); | 1676 | property, val); |
1622 | if (ret) | 1677 | if (ret) |
1623 | goto fail; | 1678 | goto fail; |
1624 | 1679 | ||
@@ -1676,8 +1731,8 @@ retry: | |||
1676 | goto fail; | 1731 | goto fail; |
1677 | } | 1732 | } |
1678 | 1733 | ||
1679 | ret = connector->funcs->atomic_set_property(connector, connector_state, | 1734 | ret = drm_atomic_connector_set_property(connector, connector_state, |
1680 | property, val); | 1735 | property, val); |
1681 | if (ret) | 1736 | if (ret) |
1682 | goto fail; | 1737 | goto fail; |
1683 | 1738 | ||
@@ -1751,7 +1806,7 @@ retry: | |||
1751 | goto fail; | 1806 | goto fail; |
1752 | } | 1807 | } |
1753 | 1808 | ||
1754 | ret = drm_atomic_set_crtc_for_plane(state, plane, crtc); | 1809 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); |
1755 | if (ret != 0) | 1810 | if (ret != 0) |
1756 | goto fail; | 1811 | goto fail; |
1757 | drm_atomic_set_fb_for_plane(plane_state, fb); | 1812 | drm_atomic_set_fb_for_plane(plane_state, fb); |
@@ -1814,6 +1869,9 @@ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) | |||
1814 | { | 1869 | { |
1815 | kfree(crtc->state); | 1870 | kfree(crtc->state); |
1816 | crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); | 1871 | crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); |
1872 | |||
1873 | if (crtc->state) | ||
1874 | crtc->state->crtc = crtc; | ||
1817 | } | 1875 | } |
1818 | EXPORT_SYMBOL(drm_atomic_helper_crtc_reset); | 1876 | EXPORT_SYMBOL(drm_atomic_helper_crtc_reset); |
1819 | 1877 | ||
@@ -1873,6 +1931,9 @@ void drm_atomic_helper_plane_reset(struct drm_plane *plane) | |||
1873 | 1931 | ||
1874 | kfree(plane->state); | 1932 | kfree(plane->state); |
1875 | plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); | 1933 | plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); |
1934 | |||
1935 | if (plane->state) | ||
1936 | plane->state->plane = plane; | ||
1876 | } | 1937 | } |
1877 | EXPORT_SYMBOL(drm_atomic_helper_plane_reset); | 1938 | EXPORT_SYMBOL(drm_atomic_helper_plane_reset); |
1878 | 1939 | ||
@@ -1930,6 +1991,9 @@ void drm_atomic_helper_connector_reset(struct drm_connector *connector) | |||
1930 | { | 1991 | { |
1931 | kfree(connector->state); | 1992 | kfree(connector->state); |
1932 | connector->state = kzalloc(sizeof(*connector->state), GFP_KERNEL); | 1993 | connector->state = kzalloc(sizeof(*connector->state), GFP_KERNEL); |
1994 | |||
1995 | if (connector->state) | ||
1996 | connector->state->connector = connector; | ||
1933 | } | 1997 | } |
1934 | EXPORT_SYMBOL(drm_atomic_helper_connector_reset); | 1998 | EXPORT_SYMBOL(drm_atomic_helper_connector_reset); |
1935 | 1999 | ||