|
@@ -338,6 +338,51 @@ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
|
|
|
|
|
|
+/**
|
|
|
+ * drm_atomic_set_mode_prop_for_crtc - set mode for CRTC
|
|
|
+ * @state: the CRTC whose incoming state to update
|
|
|
+ * @blob: pointer to blob property to use for mode
|
|
|
+ *
|
|
|
+ * Set a mode (originating from a blob property) on the desired CRTC state.
|
|
|
+ * This function will take a reference on the blob property for the CRTC state,
|
|
|
+ * and release the reference held on the state's existing mode property, if any
|
|
|
+ * was set.
|
|
|
+ *
|
|
|
+ * RETURNS:
|
|
|
+ * Zero on success, error code on failure. Cannot return -EDEADLK.
|
|
|
+ */
|
|
|
+int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
|
|
|
+ struct drm_property_blob *blob)
|
|
|
+{
|
|
|
+ if (blob == state->mode_blob)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (state->mode_blob)
|
|
|
+ drm_property_unreference_blob(state->mode_blob);
|
|
|
+ state->mode_blob = NULL;
|
|
|
+
|
|
|
+ if (blob) {
|
|
|
+ if (blob->length != sizeof(struct drm_mode_modeinfo) ||
|
|
|
+ drm_mode_convert_umode(&state->mode,
|
|
|
+ (const struct drm_mode_modeinfo *)
|
|
|
+ blob->data))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ state->mode_blob = drm_property_reference_blob(blob);
|
|
|
+ state->enable = true;
|
|
|
+ DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
|
|
|
+ state->mode.name, state);
|
|
|
+ } else {
|
|
|
+ memset(&state->mode, 0, sizeof(state->mode));
|
|
|
+ state->enable = false;
|
|
|
+ DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
|
|
|
+ state);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
|
|
|
+
|
|
|
/**
|
|
|
* drm_atomic_crtc_set_property - set property on CRTC
|
|
|
* @crtc: the drm CRTC to set a property on
|
|
@@ -360,10 +405,18 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_mode_config *config = &dev->mode_config;
|
|
|
+ int ret;
|
|
|
|
|
|
- /* FIXME: Mode prop is missing, which also controls ->enable. */
|
|
|
if (property == config->prop_active)
|
|
|
state->active = val;
|
|
|
+ else if (property == config->prop_mode_id) {
|
|
|
+ struct drm_property_blob *mode =
|
|
|
+ drm_property_lookup_blob(dev, val);
|
|
|
+ ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
|
|
|
+ if (mode)
|
|
|
+ drm_property_unreference_blob(mode);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
else if (crtc->funcs->atomic_set_property)
|
|
|
return crtc->funcs->atomic_set_property(crtc, state, property, val);
|
|
|
else
|
|
@@ -388,6 +441,8 @@ int drm_atomic_crtc_get_property(struct drm_crtc *crtc,
|
|
|
|
|
|
if (property == config->prop_active)
|
|
|
*val = state->active;
|
|
|
+ else if (property == config->prop_mode_id)
|
|
|
+ *val = (state->mode_blob) ? state->mode_blob->base.id : 0;
|
|
|
else if (crtc->funcs->atomic_get_property)
|
|
|
return crtc->funcs->atomic_get_property(crtc, state, property, val);
|
|
|
else
|