aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_atomic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_atomic.c')
-rw-r--r--drivers/gpu/drm/i915/intel_atomic.c137
1 files changed, 107 insertions, 30 deletions
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 50fb1f76cc5f..36d4e635e4ce 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -36,44 +36,121 @@
#include "intel_drv.h"
/**
- * intel_connector_atomic_get_property - fetch connector property value
- * @connector: connector to fetch property for
- * @state: state containing the property value
- * @property: property to look up
- * @val: pointer to write property value into
+ * intel_digital_connector_atomic_get_property - hook for connector->atomic_get_property.
+ * @connector: Connector to get the property for.
+ * @state: Connector state to retrieve the property from.
+ * @property: Property to retrieve.
+ * @val: Return value for the property.
*
- * The DRM core does not store shadow copies of properties for
- * atomic-capable drivers. This entrypoint is used to fetch
- * the current value of a driver-specific connector property.
+ * Returns the atomic property value for a digital connector.
*/
-int
-intel_connector_atomic_get_property(struct drm_connector *connector,
- const struct drm_connector_state *state,
- struct drm_property *property,
- uint64_t *val)
+int intel_digital_connector_atomic_get_property(struct drm_connector *connector,
+ const struct drm_connector_state *state,
+ struct drm_property *property,
+ uint64_t *val)
{
- int i;
+ struct drm_device *dev = connector->dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_digital_connector_state *intel_conn_state =
+ to_intel_digital_connector_state(state);
+
+ if (property == dev_priv->force_audio_property)
+ *val = intel_conn_state->force_audio;
+ else if (property == dev_priv->broadcast_rgb_property)
+ *val = intel_conn_state->broadcast_rgb;
+ else {
+ DRM_DEBUG_ATOMIC("Unknown property %s\n", property->name);
+ return -EINVAL;
+ }
- /*
- * TODO: We only have atomic modeset for planes at the moment, so the
- * crtc/connector code isn't quite ready yet. Until it's ready,
- * continue to look up all property values in the DRM's shadow copy
- * in obj->properties->values[].
- *
- * When the crtc/connector state work matures, this function should
- * be updated to read the values out of the state structure instead.
- */
- for (i = 0; i < connector->base.properties->count; i++) {
- if (connector->base.properties->properties[i] == property) {
- *val = connector->base.properties->values[i];
- return 0;
- }
+ return 0;
+}
+
+/**
+ * intel_digital_connector_atomic_set_property - hook for connector->atomic_set_property.
+ * @connector: Connector to set the property for.
+ * @state: Connector state to set the property on.
+ * @property: Property to set.
+ * @val: New value for the property.
+ *
+ * Sets the atomic property value for a digital connector.
+ */
+int intel_digital_connector_atomic_set_property(struct drm_connector *connector,
+ struct drm_connector_state *state,
+ struct drm_property *property,
+ uint64_t val)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_digital_connector_state *intel_conn_state =
+ to_intel_digital_connector_state(state);
+
+ if (property == dev_priv->force_audio_property) {
+ intel_conn_state->force_audio = val;
+ return 0;
}
+ if (property == dev_priv->broadcast_rgb_property) {
+ intel_conn_state->broadcast_rgb = val;
+ return 0;
+ }
+
+ DRM_DEBUG_ATOMIC("Unknown property %s\n", property->name);
return -EINVAL;
}
-/*
+int intel_digital_connector_atomic_check(struct drm_connector *conn,
+ struct drm_connector_state *new_state)
+{
+ struct intel_digital_connector_state *new_conn_state =
+ to_intel_digital_connector_state(new_state);
+ struct drm_connector_state *old_state =
+ drm_atomic_get_old_connector_state(new_state->state, conn);
+ struct intel_digital_connector_state *old_conn_state =
+ to_intel_digital_connector_state(old_state);
+ struct drm_crtc_state *crtc_state;
+
+ if (!new_state->crtc)
+ return 0;
+
+ crtc_state = drm_atomic_get_new_crtc_state(new_state->state, new_state->crtc);
+
+ /*
+ * These properties are handled by fastset, and might not end
+ * up in a modeset.
+ */
+ if (new_conn_state->force_audio != old_conn_state->force_audio ||
+ new_conn_state->broadcast_rgb != old_conn_state->broadcast_rgb ||
+ new_conn_state->base.picture_aspect_ratio != old_conn_state->base.picture_aspect_ratio ||
+ new_conn_state->base.scaling_mode != old_conn_state->base.scaling_mode)
+ crtc_state->mode_changed = true;
+
+ return 0;
+}
+
+/**
+ * intel_digital_connector_duplicate_state - duplicate connector state
+ * @connector: digital connector
+ *
+ * Allocates and returns a copy of the connector state (both common and
+ * digital connector specific) for the specified connector.
+ *
+ * Returns: The newly allocated connector state, or NULL on failure.
+ */
+struct drm_connector_state *
+intel_digital_connector_duplicate_state(struct drm_connector *connector)
+{
+ struct intel_digital_connector_state *state;
+
+ state = kmemdup(connector->state, sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return NULL;
+
+ __drm_atomic_helper_connector_duplicate_state(connector, &state->base);
+ return &state->base;
+}
+
+/**
* intel_crtc_duplicate_state - duplicate crtc state
* @crtc: drm crtc
*
@@ -248,7 +325,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
}
/* set scaler mode */
- if (IS_GEMINILAKE(dev_priv)) {
+ if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) {
scaler_state->scalers[*scaler_id].mode = 0;
} else if (num_scalers_need == 1 && intel_crtc->pipe != PIPE_C) {
/*