diff options
Diffstat (limited to 'drivers/gpu/drm/drm_atomic.c')
-rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 87 |
1 files changed, 80 insertions, 7 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index f32506a7c1d6..cdec19a86af3 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -57,6 +57,7 @@ void drm_atomic_state_default_release(struct drm_atomic_state *state) | |||
57 | kfree(state->connectors); | 57 | kfree(state->connectors); |
58 | kfree(state->crtcs); | 58 | kfree(state->crtcs); |
59 | kfree(state->planes); | 59 | kfree(state->planes); |
60 | kfree(state->private_objs); | ||
60 | } | 61 | } |
61 | EXPORT_SYMBOL(drm_atomic_state_default_release); | 62 | EXPORT_SYMBOL(drm_atomic_state_default_release); |
62 | 63 | ||
@@ -184,6 +185,17 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) | |||
184 | state->planes[i].ptr = NULL; | 185 | state->planes[i].ptr = NULL; |
185 | state->planes[i].state = NULL; | 186 | state->planes[i].state = NULL; |
186 | } | 187 | } |
188 | |||
189 | for (i = 0; i < state->num_private_objs; i++) { | ||
190 | void *obj_state = state->private_objs[i].obj_state; | ||
191 | |||
192 | state->private_objs[i].funcs->destroy_state(obj_state); | ||
193 | state->private_objs[i].obj = NULL; | ||
194 | state->private_objs[i].obj_state = NULL; | ||
195 | state->private_objs[i].funcs = NULL; | ||
196 | } | ||
197 | state->num_private_objs = 0; | ||
198 | |||
187 | } | 199 | } |
188 | EXPORT_SYMBOL(drm_atomic_state_default_clear); | 200 | EXPORT_SYMBOL(drm_atomic_state_default_clear); |
189 | 201 | ||
@@ -425,7 +437,7 @@ drm_atomic_replace_property_blob(struct drm_property_blob **blob, | |||
425 | } | 437 | } |
426 | 438 | ||
427 | static int | 439 | static int |
428 | drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc, | 440 | drm_atomic_replace_property_blob_from_id(struct drm_device *dev, |
429 | struct drm_property_blob **blob, | 441 | struct drm_property_blob **blob, |
430 | uint64_t blob_id, | 442 | uint64_t blob_id, |
431 | ssize_t expected_size, | 443 | ssize_t expected_size, |
@@ -434,7 +446,7 @@ drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc, | |||
434 | struct drm_property_blob *new_blob = NULL; | 446 | struct drm_property_blob *new_blob = NULL; |
435 | 447 | ||
436 | if (blob_id != 0) { | 448 | if (blob_id != 0) { |
437 | new_blob = drm_property_lookup_blob(crtc->dev, blob_id); | 449 | new_blob = drm_property_lookup_blob(dev, blob_id); |
438 | if (new_blob == NULL) | 450 | if (new_blob == NULL) |
439 | return -EINVAL; | 451 | return -EINVAL; |
440 | 452 | ||
@@ -483,7 +495,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, | |||
483 | drm_property_blob_put(mode); | 495 | drm_property_blob_put(mode); |
484 | return ret; | 496 | return ret; |
485 | } else if (property == config->degamma_lut_property) { | 497 | } else if (property == config->degamma_lut_property) { |
486 | ret = drm_atomic_replace_property_blob_from_id(crtc, | 498 | ret = drm_atomic_replace_property_blob_from_id(dev, |
487 | &state->degamma_lut, | 499 | &state->degamma_lut, |
488 | val, | 500 | val, |
489 | -1, | 501 | -1, |
@@ -491,7 +503,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, | |||
491 | state->color_mgmt_changed |= replaced; | 503 | state->color_mgmt_changed |= replaced; |
492 | return ret; | 504 | return ret; |
493 | } else if (property == config->ctm_property) { | 505 | } else if (property == config->ctm_property) { |
494 | ret = drm_atomic_replace_property_blob_from_id(crtc, | 506 | ret = drm_atomic_replace_property_blob_from_id(dev, |
495 | &state->ctm, | 507 | &state->ctm, |
496 | val, | 508 | val, |
497 | sizeof(struct drm_color_ctm), | 509 | sizeof(struct drm_color_ctm), |
@@ -499,7 +511,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, | |||
499 | state->color_mgmt_changed |= replaced; | 511 | state->color_mgmt_changed |= replaced; |
500 | return ret; | 512 | return ret; |
501 | } else if (property == config->gamma_lut_property) { | 513 | } else if (property == config->gamma_lut_property) { |
502 | ret = drm_atomic_replace_property_blob_from_id(crtc, | 514 | ret = drm_atomic_replace_property_blob_from_id(dev, |
503 | &state->gamma_lut, | 515 | &state->gamma_lut, |
504 | val, | 516 | val, |
505 | -1, | 517 | -1, |
@@ -978,6 +990,59 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, | |||
978 | } | 990 | } |
979 | 991 | ||
980 | /** | 992 | /** |
993 | * drm_atomic_get_private_obj_state - get private object state | ||
994 | * @state: global atomic state | ||
995 | * @obj: private object to get the state for | ||
996 | * @funcs: pointer to the struct of function pointers that identify the object | ||
997 | * type | ||
998 | * | ||
999 | * This function returns the private object state for the given private object, | ||
1000 | * allocating the state if needed. It does not grab any locks as the caller is | ||
1001 | * expected to care of any required locking. | ||
1002 | * | ||
1003 | * RETURNS: | ||
1004 | * | ||
1005 | * Either the allocated state or the error code encoded into a pointer. | ||
1006 | */ | ||
1007 | void * | ||
1008 | drm_atomic_get_private_obj_state(struct drm_atomic_state *state, void *obj, | ||
1009 | const struct drm_private_state_funcs *funcs) | ||
1010 | { | ||
1011 | int index, num_objs, i; | ||
1012 | size_t size; | ||
1013 | struct __drm_private_objs_state *arr; | ||
1014 | |||
1015 | for (i = 0; i < state->num_private_objs; i++) | ||
1016 | if (obj == state->private_objs[i].obj && | ||
1017 | state->private_objs[i].obj_state) | ||
1018 | return state->private_objs[i].obj_state; | ||
1019 | |||
1020 | num_objs = state->num_private_objs + 1; | ||
1021 | size = sizeof(*state->private_objs) * num_objs; | ||
1022 | arr = krealloc(state->private_objs, size, GFP_KERNEL); | ||
1023 | if (!arr) | ||
1024 | return ERR_PTR(-ENOMEM); | ||
1025 | |||
1026 | state->private_objs = arr; | ||
1027 | index = state->num_private_objs; | ||
1028 | memset(&state->private_objs[index], 0, sizeof(*state->private_objs)); | ||
1029 | |||
1030 | state->private_objs[index].obj_state = funcs->duplicate_state(state, obj); | ||
1031 | if (!state->private_objs[index].obj_state) | ||
1032 | return ERR_PTR(-ENOMEM); | ||
1033 | |||
1034 | state->private_objs[index].obj = obj; | ||
1035 | state->private_objs[index].funcs = funcs; | ||
1036 | state->num_private_objs = num_objs; | ||
1037 | |||
1038 | DRM_DEBUG_ATOMIC("Added new private object state %p to %p\n", | ||
1039 | state->private_objs[index].obj_state, state); | ||
1040 | |||
1041 | return state->private_objs[index].obj_state; | ||
1042 | } | ||
1043 | EXPORT_SYMBOL(drm_atomic_get_private_obj_state); | ||
1044 | |||
1045 | /** | ||
981 | * drm_atomic_get_connector_state - get connector state | 1046 | * drm_atomic_get_connector_state - get connector state |
982 | * @state: global atomic state object | 1047 | * @state: global atomic state object |
983 | * @connector: connector to get state object for | 1048 | * @connector: connector to get state object for |
@@ -1123,6 +1188,10 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, | |||
1123 | */ | 1188 | */ |
1124 | if (state->link_status != DRM_LINK_STATUS_GOOD) | 1189 | if (state->link_status != DRM_LINK_STATUS_GOOD) |
1125 | state->link_status = val; | 1190 | state->link_status = val; |
1191 | } else if (property == config->aspect_ratio_property) { | ||
1192 | state->picture_aspect_ratio = val; | ||
1193 | } else if (property == connector->scaling_mode_property) { | ||
1194 | state->scaling_mode = val; | ||
1126 | } else if (connector->funcs->atomic_set_property) { | 1195 | } else if (connector->funcs->atomic_set_property) { |
1127 | return connector->funcs->atomic_set_property(connector, | 1196 | return connector->funcs->atomic_set_property(connector, |
1128 | state, property, val); | 1197 | state, property, val); |
@@ -1199,6 +1268,10 @@ drm_atomic_connector_get_property(struct drm_connector *connector, | |||
1199 | *val = state->tv.hue; | 1268 | *val = state->tv.hue; |
1200 | } else if (property == config->link_status_property) { | 1269 | } else if (property == config->link_status_property) { |
1201 | *val = state->link_status; | 1270 | *val = state->link_status; |
1271 | } else if (property == config->aspect_ratio_property) { | ||
1272 | *val = state->picture_aspect_ratio; | ||
1273 | } else if (property == connector->scaling_mode_property) { | ||
1274 | *val = state->scaling_mode; | ||
1202 | } else if (connector->funcs->atomic_get_property) { | 1275 | } else if (connector->funcs->atomic_get_property) { |
1203 | return connector->funcs->atomic_get_property(connector, | 1276 | return connector->funcs->atomic_get_property(connector, |
1204 | state, property, val); | 1277 | state, property, val); |
@@ -1618,7 +1691,7 @@ int drm_atomic_commit(struct drm_atomic_state *state) | |||
1618 | if (ret) | 1691 | if (ret) |
1619 | return ret; | 1692 | return ret; |
1620 | 1693 | ||
1621 | DRM_DEBUG_ATOMIC("commiting %p\n", state); | 1694 | DRM_DEBUG_ATOMIC("committing %p\n", state); |
1622 | 1695 | ||
1623 | return config->funcs->atomic_commit(state->dev, state, false); | 1696 | return config->funcs->atomic_commit(state->dev, state, false); |
1624 | } | 1697 | } |
@@ -1647,7 +1720,7 @@ int drm_atomic_nonblocking_commit(struct drm_atomic_state *state) | |||
1647 | if (ret) | 1720 | if (ret) |
1648 | return ret; | 1721 | return ret; |
1649 | 1722 | ||
1650 | DRM_DEBUG_ATOMIC("commiting %p nonblocking\n", state); | 1723 | DRM_DEBUG_ATOMIC("committing %p nonblocking\n", state); |
1651 | 1724 | ||
1652 | return config->funcs->atomic_commit(state->dev, state, true); | 1725 | return config->funcs->atomic_commit(state->dev, state, true); |
1653 | } | 1726 | } |