Commit c93546a5 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'topic/atomic-core-2015-01-05' of git://anongit.freedesktop.org/drm-intel into drm-next

Next batch of atomic work. Most important is the propertification from Rob
and the nth iteration of the actual atomic ioctl originally from Ville.
Big differences compared to earlier revisions:
- Core properties are now fully handled by the core, drivers can only
  handle driver-specific properties.
- Atomic props&ioctl are opt-in per file_priv, userspace needs to
  explicitly ask for it (like universal plane support).
- For now all hidden behind the atomic module option until this has
  settled a bit.
- Atomic modesets are currently not possible since the exact abi for how
  to handle the mode property is still under discussion.

Besides this some cleanup patches from me and the addition of per-object
state to global state backpointers to simplify drivers.

* tag 'topic/atomic-core-2015-01-05' of git://anongit.freedesktop.org/drm-intel:
  drm: Ensure universal_planes is set for atomic
  drm/atomic: Hide drm.ko internal interfaces
  drm: Atomic modeset ioctl
  drm/atomic: atomic connector properties
  drm/atomic: atomic plane properties
  drm: small property creation cleanup
  drm/atomic: atomic_check functions
  drm: add atomic properties
  drm: refactor getproperties/getconnector
  drm: tweak getconnector locking
  drm: add atomic_get_property
  drm: add atomic_set_property wrappers
  drm: get rid of direct property value access
  drm: store property instead of id in obj attachment
  drm: allow property validation for refcnted props
  drm/atomic: Introduce state->obj backpointers
  drm/atomic-helper: Again check modeset *before* plane states
  drm/atomic-helper: Export both plane and modeset check helpers
parents e5202a22 179f158c
......@@ -239,6 +239,14 @@
Driver supports dedicated render nodes.
</para></listitem>
</varlistentry>
<varlistentry>
<term>DRIVER_ATOMIC</term>
<listitem><para>
Driver supports atomic properties. In this case the driver
must implement appropriate obj->atomic_get_property() vfuncs
for any modeset objects with driver specific properties.
</para></listitem>
</varlistentry>
</variablelist>
</sect3>
<sect3>
......@@ -2565,8 +2573,8 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >Description/Restrictions</td>
</tr>
<tr>
<td rowspan="25" valign="top" >DRM</td>
<td rowspan="4" valign="top" >Generic</td>
<td rowspan="36" valign="top" >DRM</td>
<td rowspan="5" valign="top" >Connector</td>
<td valign="top" >“EDID”</td>
<td valign="top" >BLOB | IMMUTABLE</td>
<td valign="top" >0</td>
......@@ -2595,7 +2603,14 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >Contains tiling information for a connector.</td>
</tr>
<tr>
<td rowspan="1" valign="top" >Plane</td>
<td valign="top" >“CRTC_ID”</td>
<td valign="top" >OBJECT</td>
<td valign="top" >DRM_MODE_OBJECT_CRTC</td>
<td valign="top" >Connector</td>
<td valign="top" >CRTC that connector is attached to (atomic)</td>
</tr>
<tr>
<td rowspan="11" valign="top" >Plane</td>
<td valign="top" >“type”</td>
<td valign="top" >ENUM | IMMUTABLE</td>
<td valign="top" >{ "Overlay", "Primary", "Cursor" }</td>
......@@ -2603,6 +2618,76 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >Plane type</td>
</tr>
<tr>
<td valign="top" >“SRC_X”</td>
<td valign="top" >RANGE</td>
<td valign="top" >Min=0, Max=UINT_MAX</td>
<td valign="top" >Plane</td>
<td valign="top" >Scanout source x coordinate in 16.16 fixed point (atomic)</td>
</tr>
<tr>
<td valign="top" >“SRC_Y”</td>
<td valign="top" >RANGE</td>
<td valign="top" >Min=0, Max=UINT_MAX</td>
<td valign="top" >Plane</td>
<td valign="top" >Scanout source y coordinate in 16.16 fixed point (atomic)</td>
</tr>
<tr>
<td valign="top" >“SRC_W”</td>
<td valign="top" >RANGE</td>
<td valign="top" >Min=0, Max=UINT_MAX</td>
<td valign="top" >Plane</td>
<td valign="top" >Scanout source width in 16.16 fixed point (atomic)</td>
</tr>
<tr>
<td valign="top" >“SRC_H”</td>
<td valign="top" >RANGE</td>
<td valign="top" >Min=0, Max=UINT_MAX</td>
<td valign="top" >Plane</td>
<td valign="top" >Scanout source height in 16.16 fixed point (atomic)</td>
</tr>
<tr>
<td valign="top" >“CRTC_X”</td>
<td valign="top" >SIGNED_RANGE</td>
<td valign="top" >Min=INT_MIN, Max=INT_MAX</td>
<td valign="top" >Plane</td>
<td valign="top" >Scanout CRTC (destination) x coordinate (atomic)</td>
</tr>
<tr>
<td valign="top" >“CRTC_Y”</td>
<td valign="top" >SIGNED_RANGE</td>
<td valign="top" >Min=INT_MIN, Max=INT_MAX</td>
<td valign="top" >Plane</td>
<td valign="top" >Scanout CRTC (destination) y coordinate (atomic)</td>
</tr>
<tr>
<td valign="top" >“CRTC_W”</td>
<td valign="top" >RANGE</td>
<td valign="top" >Min=0, Max=UINT_MAX</td>
<td valign="top" >Plane</td>
<td valign="top" >Scanout CRTC (destination) width (atomic)</td>
</tr>
<tr>
<td valign="top" >“CRTC_H”</td>
<td valign="top" >RANGE</td>
<td valign="top" >Min=0, Max=UINT_MAX</td>
<td valign="top" >Plane</td>
<td valign="top" >Scanout CRTC (destination) height (atomic)</td>
</tr>
<tr>
<td valign="top" >“FB_ID”</td>
<td valign="top" >OBJECT</td>
<td valign="top" >DRM_MODE_OBJECT_FB</td>
<td valign="top" >Plane</td>
<td valign="top" >Scanout framebuffer (atomic)</td>
</tr>
<tr>
<td valign="top" >“CRTC_ID”</td>
<td valign="top" >OBJECT</td>
<td valign="top" >DRM_MODE_OBJECT_CRTC</td>
<td valign="top" >Plane</td>
<td valign="top" >CRTC that plane is attached to (atomic)</td>
</tr>
<tr>
<td rowspan="2" valign="top" >DVI-I</td>
<td valign="top" >“subconnector”</td>
<td valign="top" >ENUM</td>
......
This diff is collapsed.
......@@ -330,7 +330,29 @@ mode_fixup(struct drm_atomic_state *state)
return 0;
}
static int
/**
* drm_atomic_helper_check - validate state object for modeset changes
* @dev: DRM device
* @state: the driver state object
*
* Check the state object to see if the requested state is physically possible.
* This does all the crtc and connector related computations for an atomic
* update. It computes and updates crtc_state->mode_changed, adds any additional
* connectors needed for full modesets and calls down into ->mode_fixup
* functions of the driver backend.
*
* IMPORTANT:
*
* Drivers which update ->mode_changed (e.g. in their ->atomic_check hooks if a
* plane update can't be done without a full modeset) _must_ call this function
* afterwards after that change. It is permitted to call this function multiple
* times for the same update, e.g. when the ->atomic_check functions depend upon
* the adjusted dotclock for fifo space allocation and watermark computation.
*
* RETURNS
* Zero for success or -errno
*/
int
drm_atomic_helper_check_modeset(struct drm_device *dev,
struct drm_atomic_state *state)
{
......@@ -406,23 +428,23 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
return mode_fixup(state);
}
EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
/**
* drm_atomic_helper_check - validate state object
* drm_atomic_helper_check - validate state object for modeset changes
* @dev: DRM device
* @state: the driver state object
*
* Check the state object to see if the requested state is physically possible.
* Only crtcs and planes have check callbacks, so for any additional (global)
* checking that a driver needs it can simply wrap that around this function.
* Drivers without such needs can directly use this as their ->atomic_check()
* callback.
* This does all the plane update related checks using by calling into the
* ->atomic_check hooks provided by the driver.
*
* RETURNS
* Zero for success or -errno
*/
int drm_atomic_helper_check(struct drm_device *dev,
struct drm_atomic_state *state)
int
drm_atomic_helper_check_planes(struct drm_device *dev,
struct drm_atomic_state *state)
{
int nplanes = dev->mode_config.num_total_plane;
int ncrtcs = dev->mode_config.num_crtc;
......@@ -445,7 +467,7 @@ int drm_atomic_helper_check(struct drm_device *dev,
ret = funcs->atomic_check(plane, plane_state);
if (ret) {
DRM_DEBUG_KMS("[PLANE:%d] atomic check failed\n",
DRM_DEBUG_KMS("[PLANE:%d] atomic driver check failed\n",
plane->base.id);
return ret;
}
......@@ -465,16 +487,49 @@ int drm_atomic_helper_check(struct drm_device *dev,
ret = funcs->atomic_check(crtc, state->crtc_states[i]);
if (ret) {
DRM_DEBUG_KMS("[CRTC:%d] atomic check failed\n",
DRM_DEBUG_KMS("[CRTC:%d] atomic driver check failed\n",
crtc->base.id);
return ret;
}
}
return ret;
}
EXPORT_SYMBOL(drm_atomic_helper_check_planes);
/**
* drm_atomic_helper_check - validate state object
* @dev: DRM device
* @state: the driver state object
*
* Check the state object to see if the requested state is physically possible.
* Only crtcs and planes have check callbacks, so for any additional (global)
* checking that a driver needs it can simply wrap that around this function.
* Drivers without such needs can directly use this as their ->atomic_check()
* callback.
*
* This just wraps the two parts of the state checking for planes and modeset
* state in the default order: First it calls drm_atomic_helper_check_modeset()
* and then drm_atomic_helper_check_planes(). The assumption is that the
* ->atomic_check functions depend upon an updated adjusted_mode.clock to
* e.g. properly compute watermarks.
*
* RETURNS
* Zero for success or -errno
*/
int drm_atomic_helper_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
int ret;
ret = drm_atomic_helper_check_modeset(dev, state);
if (ret)
return ret;
ret = drm_atomic_helper_check_planes(dev, state);
if (ret)
return ret;
return ret;
}
EXPORT_SYMBOL(drm_atomic_helper_check);
......@@ -1222,7 +1277,7 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane,
goto fail;
}
ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(plane_state, fb);
......@@ -1301,7 +1356,7 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane)
goto fail;
}
ret = drm_atomic_set_crtc_for_plane(state, plane, NULL);
ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(plane_state, NULL);
......@@ -1464,7 +1519,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
crtc_state->enable = false;
ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, NULL);
ret = drm_atomic_set_crtc_for_plane(primary_state, NULL);
if (ret != 0)
goto fail;
......@@ -1479,7 +1534,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
crtc_state->enable = true;
drm_mode_copy(&crtc_state->mode, set->mode);
ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, crtc);
ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(primary_state, set->fb);
......@@ -1558,8 +1613,8 @@ drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc,
goto fail;
}
ret = crtc->funcs->atomic_set_property(crtc, crtc_state,
property, val);
ret = drm_atomic_crtc_set_property(crtc, crtc_state,
property, val);
if (ret)
goto fail;
......@@ -1617,8 +1672,8 @@ drm_atomic_helper_plane_set_property(struct drm_plane *plane,
goto fail;
}
ret = plane->funcs->atomic_set_property(plane, plane_state,
property, val);
ret = drm_atomic_plane_set_property(plane, plane_state,
property, val);
if (ret)
goto fail;
......@@ -1676,8 +1731,8 @@ drm_atomic_helper_connector_set_property(struct drm_connector *connector,
goto fail;
}
ret = connector->funcs->atomic_set_property(connector, connector_state,
property, val);
ret = drm_atomic_connector_set_property(connector, connector_state,
property, val);
if (ret)
goto fail;
......@@ -1751,7 +1806,7 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
goto fail;
}
ret = drm_atomic_set_crtc_for_plane(state, plane, crtc);
ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(plane_state, fb);
......@@ -1814,6 +1869,9 @@ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
{
kfree(crtc->state);
crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
if (crtc->state)
crtc->state->crtc = crtc;
}
EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
......@@ -1873,6 +1931,9 @@ void drm_atomic_helper_plane_reset(struct drm_plane *plane)
kfree(plane->state);
plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
if (plane->state)
plane->state->plane = plane;
}
EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
......@@ -1930,6 +1991,9 @@ void drm_atomic_helper_connector_reset(struct drm_connector *connector)
{
kfree(connector->state);
connector->state = kzalloc(sizeof(*connector->state), GFP_KERNEL);
if (connector->state)
connector->state->connector = connector;
}
EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
......
This diff is collapsed.
......@@ -946,6 +946,7 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mod
crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
if (!crtc_state)
return -ENOMEM;
crtc_state->crtc = crtc;
crtc_state->enable = true;
crtc_state->planes_changed = true;
......@@ -1005,6 +1006,7 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
if (!plane_state)
return -ENOMEM;
plane_state->plane = plane;
plane_state->crtc = crtc;
drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb);
......
......@@ -36,3 +36,9 @@ int drm_mode_object_get(struct drm_device *dev,
void drm_mode_object_put(struct drm_device *dev,
struct drm_mode_object *object);
/* drm_atomic.c */
int drm_atomic_get_property(struct drm_mode_object *obj,
struct drm_property *property, uint64_t *val);
int drm_mode_atomic_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
......@@ -40,15 +40,19 @@
unsigned int drm_debug = 0; /* 1 to enable debug output */
EXPORT_SYMBOL(drm_debug);
bool drm_atomic = 0;
MODULE_AUTHOR(CORE_AUTHOR);
MODULE_DESCRIPTION(CORE_DESC);
MODULE_LICENSE("GPL and additional rights");
MODULE_PARM_DESC(debug, "Enable debug output");
MODULE_PARM_DESC(atomic, "Enable experimental atomic KMS API");
MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)");
MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
module_param_named(debug, drm_debug, int, 0600);
module_param_named_unsafe(atomic, drm_atomic, bool, 0600);
static DEFINE_SPINLOCK(drm_minor_lock);
static struct idr drm_minors_idr;
......
......@@ -32,6 +32,7 @@
#include <drm/drm_core.h>
#include "drm_legacy.h"
#include "drm_internal.h"
#include "drm_crtc_internal.h"
#include <linux/pci.h>
#include <linux/export.h>
......@@ -345,6 +346,17 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
return -EINVAL;
file_priv->universal_planes = req->value;
break;
case DRM_CLIENT_CAP_ATOMIC:
/* for now, hide behind experimental drm.atomic moduleparam */
if (!drm_atomic)
return -EINVAL;
if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
return -EINVAL;
if (req->value > 1)
return -EINVAL;
file_priv->atomic = req->value;
file_priv->universal_planes = req->value;
break;
default:
return -EINVAL;
}
......@@ -620,6 +632,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
};
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
......
......@@ -523,6 +523,7 @@ int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
if (!plane_state)
return -ENOMEM;
plane_state->plane = plane;
plane_state->crtc = crtc;
drm_atomic_set_fb_for_plane(plane_state, fb);
......@@ -569,6 +570,7 @@ int drm_plane_helper_disable(struct drm_plane *plane)
plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
if (!plane_state)
return -ENOMEM;
plane_state->plane = plane;
plane_state->crtc = NULL;
drm_atomic_set_fb_for_plane(plane_state, NULL);
......
......@@ -113,6 +113,7 @@ static void mdp5_plane_reset(struct drm_plane *plane)
} else {
mdp5_state->zpos = 1 + drm_plane_index(plane);
}
mdp5_state->base.plane = plane;
plane->state = &mdp5_state->base;
}
......
......@@ -127,6 +127,26 @@ static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb)
}
int msm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
int ret;
/*
* msm ->atomic_check can update ->mode_changed for pixel format
* changes, hence must be run before we check the modeset changes.
*/
ret = drm_atomic_helper_check_planes(dev, state);
if (ret)
return ret;
ret = drm_atomic_helper_check_modeset(dev, state);
if (ret)
return ret;
return ret;
}
/**
* drm_atomic_helper_commit - commit validated state object
* @dev: DRM device
......
......@@ -29,7 +29,7 @@ static void msm_fb_output_poll_changed(struct drm_device *dev)
static const struct drm_mode_config_funcs mode_config_funcs = {
.fb_create = msm_framebuffer_create,
.output_poll_changed = msm_fb_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_check = msm_atomic_check,
.atomic_commit = msm_atomic_commit,
};
......
......@@ -148,6 +148,8 @@ void __msm_fence_worker(struct work_struct *work);
(_cb)->func = _func; \
} while (0)
int msm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state);
int msm_atomic_commit(struct drm_device *dev,
struct drm_atomic_state *state, bool async);
......
......@@ -143,6 +143,7 @@ void drm_err(const char *format, ...);
#define DRIVER_MODESET 0x2000
#define DRIVER_PRIME 0x4000
#define DRIVER_RENDER 0x8000
#define DRIVER_ATOMIC 0x10000
/***********************************************************************/
/** \name Macros to make printk easier */
......@@ -283,6 +284,8 @@ struct drm_file {
* in the plane list
*/
unsigned universal_planes:1;
/* true if client understands atomic properties */
unsigned atomic:1;
struct pid *pid;
kuid_t uid;
......@@ -954,6 +957,7 @@ extern void drm_master_put(struct drm_master **master);
extern void drm_put_dev(struct drm_device *dev);
extern void drm_unplug_dev(struct drm_device *dev);
extern unsigned int drm_debug;
extern bool drm_atomic;
/* Debugfs support */
#if defined(CONFIG_DEBUG_FS)
......
......@@ -38,16 +38,25 @@ void drm_atomic_state_free(struct drm_atomic_state *state);
struct drm_crtc_state * __must_check
drm_atomic_get_crtc_state(struct drm_atomic_state *state,
struct drm_crtc *crtc);
int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
struct drm_crtc_state *state, struct drm_property *property,
uint64_t val);
struct drm_plane_state * __must_check
drm_atomic_get_plane_state(struct drm_atomic_state *state,
struct drm_plane *plane);
int drm_atomic_plane_set_property(struct drm_plane *plane,
struct drm_plane_state *state, struct drm_property *property,
uint64_t val);
struct drm_connector_state * __must_check
drm_atomic_get_connector_state(struct drm_atomic_state *state,
struct drm_connector *connector);
int drm_atomic_connector_set_property(struct drm_connector *connector,
struct drm_connector_state *state, struct drm_property *property,
uint64_t val);
int __must_check
drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state,
struct drm_plane *plane, struct drm_crtc *crtc);
drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
struct drm_crtc *crtc);
void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
struct drm_framebuffer *fb);
int __must_check
......
......@@ -30,6 +30,10 @@
#include <drm/drm_crtc.h>
int drm_atomic_helper_check_modeset(struct drm_device *dev,
struct drm_atomic_state *state);
int drm_atomic_helper_check_planes(struct drm_device *dev,
struct drm_atomic_state *state);
int drm_atomic_helper_check(struct drm_device *dev,
struct drm_atomic_state *state);
int drm_atomic_helper_commit(struct drm_device *dev,
......
......@@ -63,8 +63,16 @@ struct drm_mode_object {
#define DRM_OBJECT_MAX_PROPERTY 24
struct drm_object_properties {
int count;
uint32_t ids[DRM_OBJECT_MAX_PROPERTY];
int count, atomic_count;
/* NOTE: if we ever start dynamically destroying properties (ie.
* not at drm_mode_config_cleanup() time), then we'd have to do
* a better job of detaching property from mode objects to avoid
* dangling property pointers:
*/
struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY];
/* do not read/write values directly, but use drm_object_property_get_value()
* and drm_object_property_set_value():
*/
uint64_t values[DRM_OBJECT_MAX_PROPERTY];
};
......@@ -237,7 +245,9 @@ struct drm_atomic_state;
/**
* struct drm_crtc_state - mutable CRTC state
* @crtc: backpointer to the CRTC
* @enable: whether the CRTC should be enabled, gates all other state
* @active: whether the CRTC is actively displaying (used for DPMS)
* @mode_changed: for use by helpers and drivers when computing state updates
* @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
* @last_vblank_count: for helpers and drivers to capture the vblank of the
......@@ -248,9 +258,18 @@ struct drm_atomic_state;
* @event: optional pointer to a DRM event to signal upon completion of the
* state update
* @state: backpointer to global drm_atomic_state
*
* Note that the distinction between @enable and @active is rather subtile:
* Flipping @active while @enable is set without changing anything else may
* never return in a failure from the ->atomic_check callback. Userspace assumes
* that a DPMS On will always succeed. In other words: @enable controls resource
* assignment, @active controls the actual hardware state.
*/
struct drm_crtc_state {
struct drm_crtc *crtc;
bool enable;
bool active;
/* computed state bits used by helpers and drivers */
bool planes_changed : 1;
......@@ -292,6 +311,9 @@ struct drm_crtc_state {
* @atomic_duplicate_state: duplicate the atomic state for this CRTC
* @atomic_destroy_state: destroy an atomic state for this CRTC
* @atomic_set_property: set a property on an atomic state for this CRTC
* (do not call directly, use drm_atomic_crtc_set_property())
* @atomic_get_property: get a property on an atomic state for this CRTC
* (do not call directly, use drm_atomic_crtc_get_property())
*
* The drm_crtc_funcs structure is the central CRTC management structure
* in the DRM. Each CRTC controls one or more connectors (note that the name
......@@ -351,6 +373,10 @@ struct drm_crtc_funcs {
struct drm_crtc_state *state,
struct drm_property *property,
uint64_t val);
int (*atomic_get_property)(struct drm_crtc *crtc,
const struct drm_crtc_state *state,
struct drm_property *property,
uint64_t *val);
};
/**
......@@ -449,11 +475,14 @@ struct drm_crtc {
/**
* struct drm_connector_state - mutable connector state
* @connector: backpointer to the connector
* @crtc: CRTC to connect connector to, NULL if disabled
* @best_encoder: can be used by helpers and drivers to select the encoder
* @state: backpointer to global drm_atomic_state
*/
struct drm_connector_state {
struct drm_connector *connector;
struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */
struct drm_encoder *best_encoder;
......@@ -475,6 +504,9 @@ struct drm_connector_state {
* @atomic_duplicate_state: duplicate the atomic state for this connector
* @atomic_destroy_state: destroy an atomic state for this connector
* @atomic_set_property: set a property on an atomic state for this connector
* (do not call directly, use drm_atomic_connector_set_property())
* @atomic_get_property: get a property on an atomic state for this connector
* (do not call directly, use drm_atomic_connector_get_property())
*
* Each CRTC may have one or more connectors attached to it. The functions
* below allow the core DRM code to control connectors, enumerate available modes,
......@@ -508,6 +540,10 @@ struct drm_connector_funcs {
struct drm_connector_state *state,
struct drm_property *property,
uint64_t val);
int (*atomic_get_property)(struct drm_connector *connector,
const struct drm_connector_state *state,
struct drm_property *property,
uint64_t *val);
};
/**
......@@ -693,6 +729,7 @@ struct drm_connector {
/**
* struct drm_plane_state - mutable plane state
* @plane: backpointer to the plane
* @crtc: currently bound CRTC, NULL if disabled
* @fb: currently bound framebuffer
* @fence: optional fence to wait for before scanning out @fb
......@@ -709,6 +746,8 @@ struct drm_connector {
* @state: backpointer to global drm_atomic_state
*/
struct drm_plane_state {
struct drm_plane *plane;
struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */
struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */
struct fence *fence;
......@@ -735,6 +774,9 @@ struct drm_plane_state {
* @atomic_duplicate_state: duplicate the atomic state for this plane
* @atomic_destroy_state: destroy an atomic state for this plane
* @atomic_set_property: set a property on an atomic state for this plane
* (do not call directly, use drm_atomic_plane_set_property())
* @atomic_get_property: get a property on an atomic state for this plane
* (do not call directly, use drm_atomic_plane_get_property())
*/
struct drm_plane_funcs {
int (*update_plane)(struct drm_plane *plane,
......@@ -758,6 +800,10 @@ struct drm_plane_funcs {
struct drm_plane_state *state,
struct drm_property *property,
uint64_t val);
int (*atomic_get_property)(struct drm_plane *plane,
const struct drm_plane_state *state,
struct drm_property *property,
uint64_t *val);
};
enum drm_plane_type {
......@@ -856,7 +902,7 @@ struct drm_bridge {
/**
* struct struct drm_atomic_state - the global state object for atomic updates
* @dev: parent DRM device
* @flags: state flags like async update
* @allow_modeset: allow full modeset
* @planes: pointer to array of plane pointers
* @plane_states: pointer to array of plane states pointers
* @crtcs: pointer to array of CRTC pointers
......@@ -868,7 +914,7 @@ struct drm_bridge {
*/
struct drm_atomic_state {
struct drm_device *dev;
uint32_t flags;
bool allow_modeset : 1;
struct drm_plane **planes;
struct drm_plane_state **plane_states;
struct drm_crtc **crtcs;
......@@ -1053,6 +1099,16 @@ struct drm_mode_config {
struct drm_property *tile_property;
struct drm_property *plane_type_property;
struct drm_property *rotation_property;
struct drm_property *prop_src_x;
struct drm_property *prop_src_y;
struct drm_property *prop_src_w;
struct drm_property *prop_src_h;
struct drm_property *prop_crtc_x;
struct drm_property *prop_crtc_y;
struct drm_property *prop_crtc_w;
struct drm_property *prop_crtc_h;
struct drm_property *prop_fb_id;
struct drm_property *prop_crtc_id;
/* DVI-I properties */
struct drm_property *dvi_i_subconnector_property;
......@@ -1290,6 +1346,10 @@ extern int drm_mode_create_scaling_mode_property(struct drm_device *dev);
extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
extern int drm_mode_create_dirty_info_property(struct drm_device *dev);
extern int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
extern bool drm_property_change_valid_get(struct drm_property *property,
uint64_t value, struct drm_mode_object **ref);
extern void drm_property_change_valid_put(struct drm_property *property,
struct drm_mode_object *ref);
extern int drm_mode_connector_attach_encoder(struct drm_connector *connector,
struct drm_encoder *encoder);
......@@ -1381,6 +1441,8 @@ extern int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
extern int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
struct drm_property *property,
uint64_t value);
extern int drm_mode_atomic_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
int *bpp);
......
......@@ -654,6 +654,13 @@ struct drm_get_cap {
*/
#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
/**
* DRM_CLIENT_CAP_ATOMIC
*
* If set to 1, the DRM core will expose atomic properties to userspace
*/
#define DRM_CLIENT_CAP_ATOMIC 3
/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
struct drm_set_client_cap {
__u64 capability;
......@@ -777,6 +784,7 @@ struct drm_prime_handle {
#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property)
#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2)
#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic)
/**
* Device specific ioctls should only be in their respective headers
......
......@@ -272,6 +272,13 @@ struct drm_mode_get_connector {
#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1)
#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2)
/* the PROP_ATOMIC flag is used to hide properties from userspace that
* is not aware of atomic properties. This is mostly to work around
* older userspace (DDX drivers) that read/write each prop they find,
* witout being aware that this could be triggering a lengthy modeset.
*/
#define DRM_MODE_PROP_ATOMIC 0x80000000
struct drm_mode_property_enum {
__u64 value;
char name[DRM_PROP_NAME_LEN];
......@@ -519,4 +526,27 @@ struct drm_mode_destroy_dumb {
uint32_t handle;
};
/* page-flip flags are valid, plus: */
#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100
#define DRM_MODE_ATOMIC_NONBLOCK 0x0200
#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400
#define DRM_MODE_ATOMIC_FLAGS (\
DRM_MODE_PAGE_FLIP_EVENT |\
DRM_MODE_PAGE_FLIP_ASYNC |\
DRM_MODE_ATOMIC_TEST_ONLY |\
DRM_MODE_ATOMIC_NONBLOCK |\
DRM_MODE_ATOMIC_ALLOW_MODESET)
struct drm_mode_atomic {
__u32 flags;
__u32 count_objs;
__u64 objs_ptr;
__u64 count_props_ptr;
__u64 props_ptr;
__u64 prop_values_ptr;
__u64 reserved;
__u64 user_data;
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment