@@ -26,6 +26,8 @@
**************************************************************************/
#include "vmwgfx_kms.h"
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
/* Might need a hrtimer here? */
@@ -388,6 +390,84 @@ void vmw_du_primary_plane_destroy(struct drm_plane *plane)
}
+/**
+ * vmw_du_crtc_duplicate_state - duplicate crtc state
+ * @crtc: DRM crtc
+ *
+ * Allocates and returns a copy of the crtc state (both common and
+ * vmw-specific) for the specified crtc.
+ *
+ * Returns: The newly allocated crtc state, or NULL on failure.
+ */
+struct drm_crtc_state *
+vmw_du_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+ struct drm_crtc_state *state;
+ struct vmw_crtc_state *vcs;
+
+ if (WARN_ON(!crtc->state))
+ return NULL;
+
+ vcs = kmemdup(crtc->state, sizeof(*vcs), GFP_KERNEL);
+
+ if (!vcs)
+ return NULL;
+
+ state = &vcs->base;
+
+ __drm_atomic_helper_crtc_duplicate_state(crtc, state);
+
+ return state;
+}
+
+
+/**
+ * vmw_du_crtc_reset - creates a blank vmw crtc state
+ * @crtc: DRM crtc
+ *
+ * Resets the atomic state for @crtc by freeing the state pointer (which
+ * might be NULL, e.g. at driver load time) and allocating a new empty state
+ * object.
+ */
+void vmw_du_crtc_reset(struct drm_crtc *crtc)
+{
+ struct vmw_crtc_state *vcs;
+
+
+ if (crtc->state) {
+ __drm_atomic_helper_crtc_destroy_state(crtc->state);
+
+ kfree(vmw_crtc_state_to_vcs(crtc->state));
+ }
+
+ vcs = kzalloc(sizeof(*vcs), GFP_KERNEL);
+
+ if (!vcs) {
+ DRM_ERROR("Cannot allocate vmw_crtc_state\n");
+ return;
+ }
+
+ crtc->state = &vcs->base;
+ crtc->state->crtc = crtc;
+}
+
+
+/**
+ * vmw_du_crtc_destroy_state - destroy crtc state
+ * @crtc: DRM crtc
+ * @state: state object to destroy
+ *
+ * Destroys the crtc state (both common and vmw-specific) for the
+ * specified plane.
+ */
+void
+vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ drm_atomic_helper_crtc_destroy_state(crtc, state);
+}
+
+
/*
* Generic framebuffer code
*/
@@ -1600,6 +1680,7 @@ int vmw_du_connector_set_property(struct drm_connector *connector,
}
+
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
@@ -139,6 +139,19 @@ static const uint32_t vmw_cursor_plane_formats[] = {
DRM_FORMAT_ARGB8888,
};
+
+#define vmw_crtc_state_to_vcs(x) container_of(x, struct vmw_crtc_state, base)
+
+
+/**
+ * Derived class for crtc state object
+ *
+ * @base DRM crtc object
+ */
+struct vmw_crtc_state {
+ struct drm_crtc_state base;
+};
+
/**
* Base class display unit.
*
@@ -205,6 +218,9 @@ int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
uint32_t handle, uint32_t width, uint32_t height,
int32_t hot_x, int32_t hot_y);
int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
+int vmw_du_connector_set_property(struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t val);
int vmw_du_connector_dpms(struct drm_connector *connector, int mode);
void vmw_du_connector_save(struct drm_connector *connector);
void vmw_du_connector_restore(struct drm_connector *connector);
@@ -212,9 +228,6 @@ enum drm_connector_status
vmw_du_connector_detect(struct drm_connector *connector, bool force);
int vmw_du_connector_fill_modes(struct drm_connector *connector,
uint32_t max_width, uint32_t max_height);
-int vmw_du_connector_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t val);
int vmw_kms_helper_dirty(struct vmw_private *dev_priv,
struct vmw_framebuffer *framebuffer,
const struct drm_clip_rect *clips,
@@ -285,6 +298,10 @@ int vmw_du_cursor_plane_update(struct drm_plane *plane,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
+void vmw_du_crtc_reset(struct drm_crtc *crtc);
+struct drm_crtc_state *vmw_du_crtc_duplicate_state(struct drm_crtc *crtc);
+void vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
+ struct drm_crtc_state *state);
/*
* Legacy display unit functions - vmwgfx_ldu.c
@@ -280,6 +280,9 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
.gamma_set = vmw_du_crtc_gamma_set,
.destroy = vmw_ldu_crtc_destroy,
+ .reset = vmw_du_crtc_reset,
+ .atomic_duplicate_state = vmw_du_crtc_duplicate_state,
+ .atomic_destroy_state = vmw_du_crtc_destroy_state,
.set_config = vmw_ldu_crtc_set_config,
};
@@ -355,6 +358,11 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
ldu->base.pref_width = dev_priv->initial_width;
ldu->base.pref_height = dev_priv->initial_height;
ldu->base.pref_mode = NULL;
+
+ /*
+ * Remove this after enabling atomic because property values can
+ * only exist in a state object
+ */
ldu->base.is_implicit = true;
/* Initialize primary plane */
@@ -405,6 +413,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
goto err_free_encoder;
}
+ /* FIXME: Turn on after plane/connector states are implemented. */
+ /* vmw_du_crtc_reset(crtc); */
ret = drm_crtc_init_with_planes(dev, crtc, &ldu->base.primary,
&ldu->base.cursor,
&vmw_legacy_crtc_funcs, NULL);
@@ -461,6 +461,9 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
.gamma_set = vmw_du_crtc_gamma_set,
.destroy = vmw_sou_crtc_destroy,
+ .reset = vmw_du_crtc_reset,
+ .atomic_duplicate_state = vmw_du_crtc_duplicate_state,
+ .atomic_destroy_state = vmw_du_crtc_destroy_state,
.set_config = vmw_sou_crtc_set_config,
.page_flip = vmw_sou_crtc_page_flip,
};
@@ -535,6 +538,11 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
sou->base.pref_width = dev_priv->initial_width;
sou->base.pref_height = dev_priv->initial_height;
sou->base.pref_mode = NULL;
+
+ /*
+ * Remove this after enabling atomic because property values can
+ * only exist in a state object
+ */
sou->base.is_implicit = false;
/* Initialize primary plane */
@@ -586,6 +594,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
goto err_free_encoder;
}
+ /* FIXME: Turn on after plane/connector states are implemented. */
+ /* vmw_du_crtc_reset(crtc); */
ret = drm_crtc_init_with_planes(dev, crtc, &sou->base.primary,
&sou->base.cursor,
&vmw_screen_object_crtc_funcs, NULL);
@@ -1017,6 +1017,9 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
.gamma_set = vmw_du_crtc_gamma_set,
.destroy = vmw_stdu_crtc_destroy,
+ .reset = vmw_du_crtc_reset,
+ .atomic_duplicate_state = vmw_du_crtc_duplicate_state,
+ .atomic_destroy_state = vmw_du_crtc_destroy_state,
.set_config = vmw_stdu_crtc_set_config,
.page_flip = vmw_stdu_crtc_page_flip,
};
@@ -1131,6 +1134,11 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
stdu->base.pref_active = (unit == 0);
stdu->base.pref_width = dev_priv->initial_width;
stdu->base.pref_height = dev_priv->initial_height;
+
+ /*
+ * Remove this after enabling atomic because property values can
+ * only exist in a state object
+ */
stdu->base.is_implicit = false;
/* Initialize primary plane */
@@ -1181,6 +1189,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
goto err_free_encoder;
}
+ /* FIXME: Turn on after plane/connector states are implemented. */
+ /* vmw_du_crtc_reset(crtc); */
ret = drm_crtc_init_with_planes(dev, crtc, &stdu->base.primary,
&stdu->base.cursor,
&vmw_stdu_crtc_funcs, NULL);