drm: add atomic properties
[deliverable/linux.git] / include / drm / drm_crtc.h
index 125bb7f290a18bfc402cf874e48a300d10973b7c..b5ab673add29b797d9d3a3076a455211eb784a94 100644 (file)
@@ -42,6 +42,7 @@ struct drm_object_properties;
 struct drm_file;
 struct drm_clip_rect;
 struct device_node;
+struct fence;
 
 #define DRM_MODE_OBJECT_CRTC 0xcccccccc
 #define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0
@@ -62,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];
 };
 
@@ -136,6 +145,14 @@ struct drm_display_info {
        u8 cea_rev;
 };
 
+/* data corresponds to displayid vend/prod/serial */
+struct drm_tile_group {
+       struct kref refcount;
+       struct drm_device *dev;
+       int id;
+       u8 group_data[8];
+};
+
 struct drm_framebuffer_funcs {
        /* note: use drm_framebuffer_remove() */
        void (*destroy)(struct drm_framebuffer *framebuffer);
@@ -196,7 +213,7 @@ struct drm_framebuffer {
 struct drm_property_blob {
        struct drm_mode_object base;
        struct list_head head;
-       unsigned int length;
+       size_t length;
        unsigned char data[];
 };
 
@@ -215,7 +232,7 @@ struct drm_property {
        uint64_t *values;
        struct drm_device *dev;
 
-       struct list_head enum_blob_list;
+       struct list_head enum_list;
 };
 
 struct drm_crtc;
@@ -224,6 +241,59 @@ struct drm_encoder;
 struct drm_pending_vblank_event;
 struct drm_plane;
 struct drm_bridge;
+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
+ *     update to ensure framebuffer cleanup isn't done too early
+ * @planes_changed: for use by helpers and drivers when computing state updates
+ * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings
+ * @mode: current mode timings
+ * @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;
+       bool mode_changed : 1;
+
+       /* attached planes bitmask:
+        * WARNING: transitional helpers do not maintain plane_mask so
+        * drivers not converted over to atomic helpers should not rely
+        * on plane_mask being accurate!
+        */
+       u32 plane_mask;
+
+       /* last_vblank_count: for vblank waits before cleanup */
+       u32 last_vblank_count;
+
+       /* adjusted_mode: for use by helpers and drivers */
+       struct drm_display_mode adjusted_mode;
+
+       struct drm_display_mode mode;
+
+       struct drm_pending_vblank_event *event;
+
+       struct drm_atomic_state *state;
+};
 
 /**
  * struct drm_crtc_funcs - control CRTCs for a given device
@@ -238,6 +308,12 @@ struct drm_bridge;
  * @set_property: called when a property is changed
  * @set_config: apply a new CRTC configuration
  * @page_flip: initiate a page flip
+ * @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
@@ -288,6 +364,19 @@ struct drm_crtc_funcs {
 
        int (*set_property)(struct drm_crtc *crtc,
                            struct drm_property *property, uint64_t val);
+
+       /* atomic update handling */
+       struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc);
+       void (*atomic_destroy_state)(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *state);
+       int (*atomic_set_property)(struct drm_crtc *crtc,
+                                  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);
 };
 
 /**
@@ -317,6 +406,7 @@ struct drm_crtc_funcs {
  * @pixeldur_ns: precise pixel timing
  * @helper_private: mid-layer private data
  * @properties: property tracking for this CRTC
+ * @state: current atomic state for this CRTC
  * @acquire_ctx: per-CRTC implicit acquire context used by atomic drivers for
  *     legacy ioctls
  *
@@ -374,6 +464,8 @@ struct drm_crtc {
 
        struct drm_object_properties properties;
 
+       struct drm_crtc_state *state;
+
        /*
         * For legacy crtc ioctls so that atomic drivers can get at the locking
         * acquire context.
@@ -381,6 +473,22 @@ struct drm_crtc {
        struct drm_modeset_acquire_ctx *acquire_ctx;
 };
 
+/**
+ * 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;
+
+       struct drm_atomic_state *state;
+};
 
 /**
  * struct drm_connector_funcs - control connectors on a given device
@@ -393,6 +501,12 @@ struct drm_crtc {
  * @set_property: property for this connector may need an update
  * @destroy: make object go away
  * @force: notify the driver that the connector is forced on
+ * @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,
@@ -417,6 +531,19 @@ struct drm_connector_funcs {
                             uint64_t val);
        void (*destroy)(struct drm_connector *connector);
        void (*force)(struct drm_connector *connector);
+
+       /* atomic update handling */
+       struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector);
+       void (*atomic_destroy_state)(struct drm_connector *connector,
+                                    struct drm_connector_state *state);
+       int (*atomic_set_property)(struct drm_connector *connector,
+                                  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);
 };
 
 /**
@@ -515,6 +642,16 @@ struct drm_encoder {
  * @null_edid_counter: track sinks that give us all zeros for the EDID
  * @bad_edid_counter: track sinks that give us an EDID with invalid checksum
  * @debugfs_entry: debugfs directory for this connector
+ * @state: current atomic state for this connector
+ * @has_tile: is this connector connected to a tiled monitor
+ * @tile_group: tile group for the connected monitor
+ * @tile_is_single_monitor: whether the tile is one monitor housing
+ * @num_h_tile: number of horizontal tiles in the tile group
+ * @num_v_tile: number of vertical tiles in the tile group
+ * @tile_h_loc: horizontal location of this tile
+ * @tile_v_loc: vertical location of this tile
+ * @tile_h_size: horizontal size of this tile.
+ * @tile_v_size: vertical size of this tile.
  *
  * Each connector may be connected to one or more CRTCs, or may be clonable by
  * another connector if they can share a CRTC.  Each connector also has a specific
@@ -550,6 +687,8 @@ struct drm_connector {
 
        struct drm_property_blob *path_blob_ptr;
 
+       struct drm_property_blob *tile_blob_ptr;
+
        uint8_t polled; /* DRM_CONNECTOR_POLL_* */
 
        /* requested DPMS state */
@@ -575,8 +714,56 @@ struct drm_connector {
        unsigned bad_edid_counter;
 
        struct dentry *debugfs_entry;
+
+       struct drm_connector_state *state;
+
+       /* DisplayID bits */
+       bool has_tile;
+       struct drm_tile_group *tile_group;
+       bool tile_is_single_monitor;
+
+       uint8_t num_h_tile, num_v_tile;
+       uint8_t tile_h_loc, tile_v_loc;
+       uint16_t tile_h_size, tile_v_size;
 };
 
+/**
+ * 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
+ * @crtc_x: left position of visible portion of plane on crtc
+ * @crtc_y: upper position of visible portion of plane on crtc
+ * @crtc_w: width of visible portion of plane on crtc
+ * @crtc_h: height of visible portion of plane on crtc
+ * @src_x: left position of visible portion of plane within
+ *     plane (in 16.16)
+ * @src_y: upper position of visible portion of plane within
+ *     plane (in 16.16)
+ * @src_w: width of visible portion of plane (in 16.16)
+ * @src_h: height of visible portion of plane (in 16.16)
+ * @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;
+
+       /* Signed dest location allows it to be partially off screen */
+       int32_t crtc_x, crtc_y;
+       uint32_t crtc_w, crtc_h;
+
+       /* Source values are 16.16 fixed point */
+       uint32_t src_x, src_y;
+       uint32_t src_h, src_w;
+
+       struct drm_atomic_state *state;
+};
+
+
 /**
  * struct drm_plane_funcs - driver plane control functions
  * @update_plane: update the plane configuration
@@ -584,6 +771,12 @@ struct drm_connector {
  * @destroy: clean up plane resources
  * @reset: reset plane after state has been invalidated (e.g. resume)
  * @set_property: called when a property is changed
+ * @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,
@@ -598,6 +791,19 @@ struct drm_plane_funcs {
 
        int (*set_property)(struct drm_plane *plane,
                            struct drm_property *property, uint64_t val);
+
+       /* atomic update handling */
+       struct drm_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane);
+       void (*atomic_destroy_state)(struct drm_plane *plane,
+                                    struct drm_plane_state *state);
+       int (*atomic_set_property)(struct drm_plane *plane,
+                                  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 {
@@ -621,11 +827,14 @@ enum drm_plane_type {
  * @funcs: helper functions
  * @properties: property tracking for this plane
  * @type: type of plane (overlay, primary, cursor)
+ * @state: current atomic state for this plane
  */
 struct drm_plane {
        struct drm_device *dev;
        struct list_head head;
 
+       struct drm_modeset_lock mutex;
+
        struct drm_mode_object base;
 
        uint32_t possible_crtcs;
@@ -642,6 +851,10 @@ struct drm_plane {
        struct drm_object_properties properties;
 
        enum drm_plane_type type;
+
+       void *helper_private;
+
+       struct drm_plane_state *state;
 };
 
 /**
@@ -686,6 +899,34 @@ struct drm_bridge {
        void *driver_private;
 };
 
+/**
+ * struct struct drm_atomic_state - the global state object for atomic updates
+ * @dev: parent DRM device
+ * @flags: state flags like async update
+ * @planes: pointer to array of plane pointers
+ * @plane_states: pointer to array of plane states pointers
+ * @crtcs: pointer to array of CRTC pointers
+ * @crtc_states: pointer to array of CRTC states pointers
+ * @num_connector: size of the @connectors and @connector_states arrays
+ * @connectors: pointer to array of connector pointers
+ * @connector_states: pointer to array of connector states pointers
+ * @acquire_ctx: acquire context for this atomic modeset state update
+ */
+struct drm_atomic_state {
+       struct drm_device *dev;
+       uint32_t flags;
+       struct drm_plane **planes;
+       struct drm_plane_state **plane_states;
+       struct drm_crtc **crtcs;
+       struct drm_crtc_state **crtc_states;
+       int num_connector;
+       struct drm_connector **connectors;
+       struct drm_connector_state **connector_states;
+
+       struct drm_modeset_acquire_ctx *acquire_ctx;
+};
+
+
 /**
  * struct drm_mode_set - new values for a CRTC config change
  * @fb: framebuffer to use for new config
@@ -717,6 +958,9 @@ struct drm_mode_set {
  * struct drm_mode_config_funcs - basic driver provided mode setting functions
  * @fb_create: create a new framebuffer object
  * @output_poll_changed: function to handle output configuration changes
+ * @atomic_check: check whether a give atomic state update is possible
+ * @atomic_commit: commit an atomic state update previously verified with
+ *     atomic_check()
  *
  * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that
  * involve drivers.
@@ -726,6 +970,12 @@ struct drm_mode_config_funcs {
                                             struct drm_file *file_priv,
                                             struct drm_mode_fb_cmd2 *mode_cmd);
        void (*output_poll_changed)(struct drm_device *dev);
+
+       int (*atomic_check)(struct drm_device *dev,
+                           struct drm_atomic_state *a);
+       int (*atomic_commit)(struct drm_device *dev,
+                            struct drm_atomic_state *a,
+                            bool async);
 };
 
 /**
@@ -802,6 +1052,7 @@ struct drm_mode_config {
        struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */
        struct mutex idr_mutex; /* for IDR management */
        struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
+       struct idr tile_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
        /* this is limited to one for now */
 
        struct mutex fb_lock; /* proctects global and per-file fb lists */
@@ -845,6 +1096,7 @@ struct drm_mode_config {
        struct drm_property *edid_property;
        struct drm_property *dpms_property;
        struct drm_property *path_property;
+       struct drm_property *tile_property;
        struct drm_property *plane_type_property;
        struct drm_property *rotation_property;
 
@@ -872,6 +1124,10 @@ struct drm_mode_config {
        struct drm_property *aspect_ratio_property;
        struct drm_property *dirty_info_property;
 
+       /* properties for virtual machine layout */
+       struct drm_property *suggested_x_property;
+       struct drm_property *suggested_y_property;
+
        /* dumb ioctl parameters */
        uint32_t preferred_depth, prefer_shadow;
 
@@ -882,6 +1138,19 @@ struct drm_mode_config {
        uint32_t cursor_width, cursor_height;
 };
 
+/**
+ * drm_for_each_plane_mask - iterate over planes specified by bitmask
+ * @plane: the loop cursor
+ * @dev: the DRM device
+ * @plane_mask: bitmask of plane indices
+ *
+ * Iterate over all planes specified by bitmask.
+ */
+#define drm_for_each_plane_mask(plane, dev, plane_mask) \
+       list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \
+               if ((plane_mask) & (1 << drm_plane_index(plane)))
+
+
 #define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
 #define obj_to_connector(x) container_of(x, struct drm_connector, base)
 #define obj_to_encoder(x) container_of(x, struct drm_encoder, base)
@@ -996,9 +1265,10 @@ extern void drm_mode_config_reset(struct drm_device *dev);
 extern void drm_mode_config_cleanup(struct drm_device *dev);
 
 extern int drm_mode_connector_set_path_property(struct drm_connector *connector,
-                                               char *path);
+                                               const char *path);
+int drm_mode_connector_set_tile_property(struct drm_connector *connector);
 extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,
-                                               struct edid *edid);
+                                                  const struct edid *edid);
 
 static inline bool drm_property_type_is(struct drm_property *property,
                uint32_t type)
@@ -1059,11 +1329,13 @@ extern void drm_property_destroy(struct drm_device *dev, struct drm_property *pr
 extern int drm_property_add_enum(struct drm_property *property, int index,
                                 uint64_t value, const char *name);
 extern int drm_mode_create_dvi_i_properties(struct drm_device *dev);
-extern int drm_mode_create_tv_properties(struct drm_device *dev, int num_formats,
-                                    char *formats[]);
+extern int drm_mode_create_tv_properties(struct drm_device *dev,
+                                        unsigned int num_modes,
+                                        char *modes[]);
 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 int drm_mode_connector_attach_encoder(struct drm_connector *connector,
                                             struct drm_encoder *encoder);
@@ -1131,6 +1403,13 @@ extern void drm_set_preferred_mode(struct drm_connector *connector,
 extern int drm_edid_header_is_valid(const u8 *raw_edid);
 extern bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
+
+extern struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
+                                                        char topology[8]);
+extern struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
+                                              char topology[8]);
+extern void drm_mode_put_tile_group(struct drm_device *dev,
+                                  struct drm_tile_group *tg);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
                                           int hsize, int vsize, int fresh,
                                           bool rb);
This page took 0.0456 seconds and 5 git commands to generate.