aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2017-07-25 08:02:04 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2017-08-08 08:45:09 -0400
commit144a7999d6334be5237d5926ab19c56bc24d0204 (patch)
tree0d64df2f9de89b0c3632d88313f0ac17b55a185f /drivers/gpu/drm
parent4a97a3da420b82f967083a31fd80706e56ecabf9 (diff)
drm: Handle properties in the core for atomic drivers
The reason behind the original indirection through the helper functions was to allow existing drivers to overwrite how they handle properties. For example when a vendor-specific userspace had expectations that didn't match atomic. That seemed likely, since atomic is standardizing a _lot_ more of the behaviour of a kms driver. But 20 drivers later there's no such need at all. Worse, this forces all drivers to hook up the default behaviour, breaking userspace if they forget to do that. And it forces us to export a bunch of core function just for those helpers. And finally, these helpers are the last places using drm_atomic_legacy_backoff() and the implicit acquire_ctx. This patch here just implements the new behaviour and updates the docs. Follow-up patches will garbage-collect all the dead code. v2: Fixup docs even better! v3: Make it actually work ... v4: Drop the uses_atomic_modeset() checks from the previous patch again, since they're now moved up in the callchain. Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Archit Taneja <architt@codeaurora.org> (v3) Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20170725120204.2107-1-daniel.vetter@ffwll.ch
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/drm_atomic.c60
-rw-r--r--drivers/gpu/drm/drm_connector.c8
-rw-r--r--drivers/gpu/drm/drm_crtc.c2
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c3
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h7
-rw-r--r--drivers/gpu/drm/drm_mode_object.c110
-rw-r--r--drivers/gpu/drm/drm_plane.c2
7 files changed, 153 insertions, 39 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 01192dd3ed79..0fd14aff7add 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1864,9 +1864,60 @@ static struct drm_pending_vblank_event *create_vblank_event(
1864 return e; 1864 return e;
1865} 1865}
1866 1866
1867static int atomic_set_prop(struct drm_atomic_state *state, 1867int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
1868 struct drm_mode_object *obj, struct drm_property *prop, 1868 struct drm_connector *connector,
1869 uint64_t prop_value) 1869 int mode)
1870{
1871 struct drm_connector *tmp_connector;
1872 struct drm_connector_state *new_conn_state;
1873 struct drm_crtc *crtc;
1874 struct drm_crtc_state *crtc_state;
1875 int i, ret, old_mode = connector->dpms;
1876 bool active = false;
1877
1878 ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
1879 state->acquire_ctx);
1880 if (ret)
1881 return ret;
1882
1883 if (mode != DRM_MODE_DPMS_ON)
1884 mode = DRM_MODE_DPMS_OFF;
1885 connector->dpms = mode;
1886
1887 crtc = connector->state->crtc;
1888 if (!crtc)
1889 goto out;
1890 ret = drm_atomic_add_affected_connectors(state, crtc);
1891 if (ret)
1892 goto out;
1893
1894 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1895 if (IS_ERR(crtc_state)) {
1896 ret = PTR_ERR(crtc_state);
1897 goto out;
1898 }
1899
1900 for_each_new_connector_in_state(state, tmp_connector, new_conn_state, i) {
1901 if (new_conn_state->crtc != crtc)
1902 continue;
1903 if (tmp_connector->dpms == DRM_MODE_DPMS_ON) {
1904 active = true;
1905 break;
1906 }
1907 }
1908
1909 crtc_state->active = active;
1910 ret = drm_atomic_commit(state);
1911out:
1912 if (ret != 0)
1913 connector->dpms = old_mode;
1914 return ret;
1915}
1916
1917int drm_atomic_set_property(struct drm_atomic_state *state,
1918 struct drm_mode_object *obj,
1919 struct drm_property *prop,
1920 uint64_t prop_value)
1870{ 1921{
1871 struct drm_mode_object *ref; 1922 struct drm_mode_object *ref;
1872 int ret; 1923 int ret;
@@ -2286,7 +2337,8 @@ retry:
2286 goto out; 2337 goto out;
2287 } 2338 }
2288 2339
2289 ret = atomic_set_prop(state, obj, prop, prop_value); 2340 ret = drm_atomic_set_property(state, obj, prop,
2341 prop_value);
2290 if (ret) { 2342 if (ret) {
2291 drm_mode_object_put(obj); 2343 drm_mode_object_put(obj);
2292 goto out; 2344 goto out;
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 0e9e3161bdd0..ba9f36cef68c 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -717,9 +717,9 @@ DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
717 * drivers, it remaps to controlling the "ACTIVE" property on the CRTC the 717 * drivers, it remaps to controlling the "ACTIVE" property on the CRTC the
718 * connector is linked to. Drivers should never set this property directly, 718 * connector is linked to. Drivers should never set this property directly,
719 * it is handled by the DRM core by calling the &drm_connector_funcs.dpms 719 * it is handled by the DRM core by calling the &drm_connector_funcs.dpms
720 * callback. Atomic drivers should implement this hook using 720 * callback. For atomic drivers the remapping to the "ACTIVE" property is
721 * drm_atomic_helper_connector_dpms(). This is the only property standard 721 * implemented in the DRM core. This is the only standard connector
722 * connector property that userspace can change. 722 * property that userspace can change.
723 * PATH: 723 * PATH:
724 * Connector path property to identify how this sink is physically 724 * Connector path property to identify how this sink is physically
725 * connected. Used by DP MST. This should be set by calling 725 * connected. Used by DP MST. This should be set by calling
@@ -1225,7 +1225,7 @@ int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
1225 } else if (connector->funcs->set_property) 1225 } else if (connector->funcs->set_property)
1226 ret = connector->funcs->set_property(connector, property, value); 1226 ret = connector->funcs->set_property(connector, property, value);
1227 1227
1228 if (!ret && !drm_drv_uses_atomic_modeset(property->dev)) 1228 if (!ret)
1229 drm_object_property_set_value(&connector->base, property, value); 1229 drm_object_property_set_value(&connector->base, property, value);
1230 return ret; 1230 return ret;
1231} 1231}
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9271235d84b0..5af25ce5bf7c 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -736,7 +736,7 @@ int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
736 736
737 if (crtc->funcs->set_property) 737 if (crtc->funcs->set_property)
738 ret = crtc->funcs->set_property(crtc, property, value); 738 ret = crtc->funcs->set_property(crtc, property, value);
739 if (!ret && !drm_drv_uses_atomic_modeset(property->dev)) 739 if (!ret)
740 drm_object_property_set_value(obj, property, value); 740 drm_object_property_set_value(obj, property, value);
741 741
742 return ret; 742 return ret;
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 4afdf7902eda..eab36a460638 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -863,8 +863,7 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
863 * provided by the driver. 863 * provided by the driver.
864 * 864 *
865 * This function is deprecated. New drivers must implement atomic modeset 865 * This function is deprecated. New drivers must implement atomic modeset
866 * support, for which this function is unsuitable. Instead drivers should use 866 * support, where DPMS is handled in the DRM core.
867 * drm_atomic_helper_connector_dpms().
868 * 867 *
869 * Returns: 868 * Returns:
870 * Always returns 0. 869 * Always returns 0.
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index d077c5490041..a43582076b20 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -178,6 +178,13 @@ struct drm_minor;
178int drm_atomic_debugfs_init(struct drm_minor *minor); 178int drm_atomic_debugfs_init(struct drm_minor *minor);
179#endif 179#endif
180 180
181int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
182 struct drm_connector *connector,
183 int mode);
184int drm_atomic_set_property(struct drm_atomic_state *state,
185 struct drm_mode_object *obj,
186 struct drm_property *prop,
187 uint64_t prop_value);
181int drm_atomic_get_property(struct drm_mode_object *obj, 188int drm_atomic_get_property(struct drm_mode_object *obj,
182 struct drm_property *property, uint64_t *val); 189 struct drm_property *property, uint64_t *val);
183int drm_mode_atomic_ioctl(struct drm_device *dev, 190int drm_mode_atomic_ioctl(struct drm_device *dev,
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index 92743a796bf0..1055533792f3 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -392,6 +392,83 @@ struct drm_property *drm_mode_obj_find_prop_id(struct drm_mode_object *obj,
392 return NULL; 392 return NULL;
393} 393}
394 394
395static int set_property_legacy(struct drm_mode_object *obj,
396 struct drm_property *prop,
397 uint64_t prop_value)
398{
399 struct drm_device *dev = prop->dev;
400 struct drm_mode_object *ref;
401 int ret = -EINVAL;
402
403 if (!drm_property_change_valid_get(prop, prop_value, &ref))
404 return -EINVAL;
405
406 drm_modeset_lock_all(dev);
407 switch (obj->type) {
408 case DRM_MODE_OBJECT_CONNECTOR:
409 ret = drm_mode_connector_set_obj_prop(obj, prop,
410 prop_value);
411 break;
412 case DRM_MODE_OBJECT_CRTC:
413 ret = drm_mode_crtc_set_obj_prop(obj, prop, prop_value);
414 break;
415 case DRM_MODE_OBJECT_PLANE:
416 ret = drm_mode_plane_set_obj_prop(obj_to_plane(obj),
417 prop, prop_value);
418 break;
419 }
420 drm_property_change_valid_put(prop, ref);
421 drm_modeset_unlock_all(dev);
422
423 return ret;
424}
425
426static int set_property_atomic(struct drm_mode_object *obj,
427 struct drm_property *prop,
428 uint64_t prop_value)
429{
430 struct drm_device *dev = prop->dev;
431 struct drm_atomic_state *state;
432 struct drm_modeset_acquire_ctx ctx;
433 int ret;
434
435 drm_modeset_acquire_init(&ctx, 0);
436
437 state = drm_atomic_state_alloc(dev);
438 if (!state)
439 return -ENOMEM;
440 state->acquire_ctx = &ctx;
441retry:
442 if (prop == state->dev->mode_config.dpms_property) {
443 if (obj->type != DRM_MODE_OBJECT_CONNECTOR) {
444 ret = -EINVAL;
445 goto out;
446 }
447
448 ret = drm_atomic_connector_commit_dpms(state,
449 obj_to_connector(obj),
450 prop_value);
451 } else {
452 ret = drm_atomic_set_property(state, obj, prop, prop_value);
453 if (ret)
454 goto out;
455 ret = drm_atomic_commit(state);
456 }
457out:
458 if (ret == -EDEADLK) {
459 drm_atomic_state_clear(state);
460 drm_modeset_backoff(&ctx);
461 goto retry;
462 }
463
464 drm_atomic_state_put(state);
465
466 drm_modeset_drop_locks(&ctx);
467 drm_modeset_acquire_fini(&ctx);
468
469 return ret;
470}
471
395int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, 472int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
396 struct drm_file *file_priv) 473 struct drm_file *file_priv)
397{ 474{
@@ -399,18 +476,13 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
399 struct drm_mode_object *arg_obj; 476 struct drm_mode_object *arg_obj;
400 struct drm_property *property; 477 struct drm_property *property;
401 int ret = -EINVAL; 478 int ret = -EINVAL;
402 struct drm_mode_object *ref;
403 479
404 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 480 if (!drm_core_check_feature(dev, DRIVER_MODESET))
405 return -EINVAL; 481 return -EINVAL;
406 482
407 drm_modeset_lock_all(dev);
408
409 arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); 483 arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
410 if (!arg_obj) { 484 if (!arg_obj)
411 ret = -ENOENT; 485 return -ENOENT;
412 goto out;
413 }
414 486
415 if (!arg_obj->properties) 487 if (!arg_obj->properties)
416 goto out_unref; 488 goto out_unref;
@@ -419,28 +491,12 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
419 if (!property) 491 if (!property)
420 goto out_unref; 492 goto out_unref;
421 493
422 if (!drm_property_change_valid_get(property, arg->value, &ref)) 494 if (drm_drv_uses_atomic_modeset(property->dev))
423 goto out_unref; 495 ret = set_property_atomic(arg_obj, property, arg->value);
424 496 else
425 switch (arg_obj->type) { 497 ret = set_property_legacy(arg_obj, property, arg->value);
426 case DRM_MODE_OBJECT_CONNECTOR:
427 ret = drm_mode_connector_set_obj_prop(arg_obj, property,
428 arg->value);
429 break;
430 case DRM_MODE_OBJECT_CRTC:
431 ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
432 break;
433 case DRM_MODE_OBJECT_PLANE:
434 ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj),
435 property, arg->value);
436 break;
437 }
438
439 drm_property_change_valid_put(property, ref);
440 498
441out_unref: 499out_unref:
442 drm_mode_object_put(arg_obj); 500 drm_mode_object_put(arg_obj);
443out:
444 drm_modeset_unlock_all(dev);
445 return ret; 501 return ret;
446} 502}
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 7889ef7d6954..5c14beee52ff 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -448,7 +448,7 @@ int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
448 448
449 if (plane->funcs->set_property) 449 if (plane->funcs->set_property)
450 ret = plane->funcs->set_property(plane, property, value); 450 ret = plane->funcs->set_property(plane, property, value);
451 if (!ret && !drm_drv_uses_atomic_modeset(property->dev)) 451 if (!ret)
452 drm_object_property_set_value(obj, property, value); 452 drm_object_property_set_value(obj, property, value);
453 453
454 return ret; 454 return ret;