Merge remote branch 'intel/drm-intel-fixes' of /ssd/git/drm-next into drm-fixes
[linux-2.6.git] / include / drm / drmP.h
index 774e1d4..fe29aad 100644 (file)
@@ -612,7 +612,7 @@ struct drm_gem_object {
        struct kref refcount;
 
        /** Handle count of this object. Each handle also holds a reference */
-       struct kref handlecount;
+       atomic_t handle_count; /* number of handles on this object */
 
        /** Related drm device */
        struct drm_device *dev;
@@ -683,6 +683,21 @@ struct drm_master {
        void *driver_priv; /**< Private structure for driver to use */
 };
 
+/* Size of ringbuffer for vblank timestamps. Just double-buffer
+ * in initial implementation.
+ */
+#define DRM_VBLANKTIME_RBSIZE 2
+
+/* Flags and return codes for get_vblank_timestamp() driver function. */
+#define DRM_CALLED_FROM_VBLIRQ 1
+#define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0)
+#define DRM_VBLANKTIME_INVBL             (1 << 1)
+
+/* get_scanout_position() return flags */
+#define DRM_SCANOUTPOS_VALID        (1 << 0)
+#define DRM_SCANOUTPOS_INVBL        (1 << 1)
+#define DRM_SCANOUTPOS_ACCURATE     (1 << 2)
+
 /**
  * DRM driver structure. This structure represent the common code for
  * a family of cards. There will one drm_device for each card present
@@ -699,13 +714,8 @@ struct drm_driver {
        int (*suspend) (struct drm_device *, pm_message_t state);
        int (*resume) (struct drm_device *);
        int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
-       void (*dma_ready) (struct drm_device *);
        int (*dma_quiescent) (struct drm_device *);
-       int (*context_ctor) (struct drm_device *dev, int context);
        int (*context_dtor) (struct drm_device *dev, int context);
-       int (*kernel_context_switch) (struct drm_device *dev, int old,
-                                     int new);
-       void (*kernel_context_switch_unlock) (struct drm_device *dev);
 
        /**
         * get_vblank_counter - get raw hardware vblank counter
@@ -765,6 +775,68 @@ struct drm_driver {
         */
        int (*device_is_agp) (struct drm_device *dev);
 
+       /**
+        * Called by vblank timestamping code.
+        *
+        * Return the current display scanout position from a crtc.
+        *
+        * \param dev  DRM device.
+        * \param crtc Id of the crtc to query.
+        * \param *vpos Target location for current vertical scanout position.
+        * \param *hpos Target location for current horizontal scanout position.
+        *
+        * Returns vpos as a positive number while in active scanout area.
+        * Returns vpos as a negative number inside vblank, counting the number
+        * of scanlines to go until end of vblank, e.g., -1 means "one scanline
+        * until start of active scanout / end of vblank."
+        *
+        * \return Flags, or'ed together as follows:
+        *
+        * DRM_SCANOUTPOS_VALID = Query successfull.
+        * DRM_SCANOUTPOS_INVBL = Inside vblank.
+        * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of
+        * this flag means that returned position may be offset by a constant
+        * but unknown small number of scanlines wrt. real scanout position.
+        *
+        */
+       int (*get_scanout_position) (struct drm_device *dev, int crtc,
+                                    int *vpos, int *hpos);
+
+       /**
+        * Called by \c drm_get_last_vbltimestamp. Should return a precise
+        * timestamp when the most recent VBLANK interval ended or will end.
+        *
+        * Specifically, the timestamp in @vblank_time should correspond as
+        * closely as possible to the time when the first video scanline of
+        * the video frame after the end of VBLANK will start scanning out,
+        * the time immmediately after end of the VBLANK interval. If the
+        * @crtc is currently inside VBLANK, this will be a time in the future.
+        * If the @crtc is currently scanning out a frame, this will be the
+        * past start time of the current scanout. This is meant to adhere
+        * to the OpenML OML_sync_control extension specification.
+        *
+        * \param dev dev DRM device handle.
+        * \param crtc crtc for which timestamp should be returned.
+        * \param *max_error Maximum allowable timestamp error in nanoseconds.
+        *                   Implementation should strive to provide timestamp
+        *                   with an error of at most *max_error nanoseconds.
+        *                   Returns true upper bound on error for timestamp.
+        * \param *vblank_time Target location for returned vblank timestamp.
+        * \param flags 0 = Defaults, no special treatment needed.
+        * \param       DRM_CALLED_FROM_VBLIRQ = Function is called from vblank
+        *              irq handler. Some drivers need to apply some workarounds
+        *              for gpu-specific vblank irq quirks if flag is set.
+        *
+        * \returns
+        * Zero if timestamping isn't supported in current display mode or a
+        * negative number on failure. A positive status code on success,
+        * which describes how the vblank_time timestamp was computed.
+        */
+       int (*get_vblank_timestamp) (struct drm_device *dev, int crtc,
+                                    int *max_error,
+                                    struct timeval *vblank_time,
+                                    unsigned flags);
+
        /* these have to be filled in */
 
        irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
@@ -777,8 +849,6 @@ struct drm_driver {
                                        struct drm_file *file_priv);
        void (*reclaim_buffers_idlelocked) (struct drm_device *dev,
                                            struct drm_file *file_priv);
-       resource_size_t (*get_map_ofs) (struct drm_local_map * map);
-       resource_size_t (*get_reg_ofs) (struct drm_device *dev);
        void (*set_version) (struct drm_device *dev,
                             struct drm_set_version *sv);
 
@@ -795,8 +865,6 @@ struct drm_driver {
        void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv,
                            bool from_release);
 
-       int (*proc_init)(struct drm_minor *minor);
-       void (*proc_cleanup)(struct drm_minor *minor);
        int (*debugfs_init)(struct drm_minor *minor);
        void (*debugfs_cleanup)(struct drm_minor *minor);
 
@@ -808,7 +876,6 @@ struct drm_driver {
         */
        int (*gem_init_object) (struct drm_gem_object *obj);
        void (*gem_free_object) (struct drm_gem_object *obj);
-       void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
 
        /* vga arb irq handler */
        void (*vgaarb_irq)(struct drm_device *dev, bool state);
@@ -973,7 +1040,6 @@ struct drm_device {
        __volatile__ long context_flag; /**< Context swapping flag */
        __volatile__ long interrupt_flag; /**< Interruption handler flag */
        __volatile__ long dma_flag;     /**< DMA dispatch flag */
-       struct timer_list timer;        /**< Timer for delaying ctx switch */
        wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
        int last_checked;               /**< Last context checked for DMA */
        int last_context;               /**< Last current context */
@@ -994,6 +1060,8 @@ struct drm_device {
 
        wait_queue_head_t *vbl_queue;   /**< VBLANK wait queue */
        atomic_t *_vblank_count;        /**< number of VBLANK interrupts (driver must alloc the right number of counters) */
+       struct timeval *_vblank_time;   /**< timestamp of current vblank_count (drivers must alloc right number of fields) */
+       spinlock_t vblank_time_lock;    /**< Protects vblank count and time updates during vblank enable/disable */
        spinlock_t vbl_lock;
        atomic_t *vblank_refcount;      /* number of users of vblank interruptsper crtc */
        u32 *last_vblank;               /* protected by dev->vbl_lock, used */
@@ -1046,31 +1114,20 @@ struct drm_device {
        struct drm_minor *control;              /**< Control node for card */
        struct drm_minor *primary;              /**< render type primary screen head */
 
-       /** \name Drawable information */
-       /*@{ */
-       spinlock_t drw_lock;
-       struct idr drw_idr;
-       /*@} */
-
         struct drm_mode_config mode_config;    /**< Current mode config */
 
        /** \name GEM information */
        /*@{ */
        spinlock_t object_name_lock;
        struct idr object_name_idr;
-       atomic_t object_count;
-       atomic_t object_memory;
-       atomic_t pin_count;
-       atomic_t pin_memory;
-       atomic_t gtt_count;
-       atomic_t gtt_memory;
-       uint32_t gtt_total;
-       uint32_t invalidate_domains;    /* domains pending invalidation */
-       uint32_t flush_domains;         /* domains pending flush */
        /*@} */
-
+       int switch_power_state;
 };
 
+#define DRM_SWITCH_POWER_ON 0
+#define DRM_SWITCH_POWER_OFF 1
+#define DRM_SWITCH_POWER_CHANGING 2
+
 static __inline__ int drm_core_check_feature(struct drm_device *dev,
                                             int feature)
 {
@@ -1176,8 +1233,6 @@ extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
 extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);
 extern void drm_vm_open_locked(struct vm_area_struct *vma);
 extern void drm_vm_close_locked(struct vm_area_struct *vma);
-extern resource_size_t drm_core_get_map_ofs(struct drm_local_map * map);
-extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev);
 extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
 
                                /* Memory management support (drm_memory.h) */
@@ -1187,8 +1242,7 @@ extern int drm_mem_info(char *buf, char **start, off_t offset,
                        int request, int *eof, void *data);
 extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
 
-extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type);
-extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
+extern void drm_free_agp(DRM_AGP_MEM * handle, int pages);
 extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
 extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
                                       struct page **pages,
@@ -1240,17 +1294,6 @@ extern int drm_setsareactx(struct drm_device *dev, void *data,
 extern int drm_getsareactx(struct drm_device *dev, void *data,
                           struct drm_file *file_priv);
 
-                               /* Drawable IOCTL support (drm_drawable.h) */
-extern int drm_adddraw(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv);
-extern int drm_rmdraw(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
-extern int drm_update_drawable_info(struct drm_device *dev, void *data,
-                                   struct drm_file *file_priv);
-extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev,
-                                                 drm_drawable_t id);
-extern void drm_drawable_free_all(struct drm_device *dev);
-
                                /* Authentication IOCTL support (drm_auth.h) */
 extern int drm_getmagic(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
@@ -1265,7 +1308,6 @@ extern int drm_lock(struct drm_device *dev, void *data,
                    struct drm_file *file_priv);
 extern int drm_unlock(struct drm_device *dev, void *data,
                      struct drm_file *file_priv);
-extern int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
 extern int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context);
 extern void drm_idlelock_take(struct drm_lock_data *lock_data);
 extern void drm_idlelock_release(struct drm_lock_data *lock_data);
@@ -1323,11 +1365,22 @@ extern int drm_wait_vblank(struct drm_device *dev, void *data,
                           struct drm_file *filp);
 extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
 extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
-extern void drm_handle_vblank(struct drm_device *dev, int crtc);
+extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
+                                    struct timeval *vblanktime);
+extern bool drm_handle_vblank(struct drm_device *dev, int crtc);
 extern int drm_vblank_get(struct drm_device *dev, int crtc);
 extern void drm_vblank_put(struct drm_device *dev, int crtc);
 extern void drm_vblank_off(struct drm_device *dev, int crtc);
 extern void drm_vblank_cleanup(struct drm_device *dev);
+extern u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
+                                    struct timeval *tvblank, unsigned flags);
+extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
+                                                int crtc, int *max_error,
+                                                struct timeval *vblank_time,
+                                                unsigned flags,
+                                                struct drm_crtc *refcrtc);
+extern void drm_calc_timestamping_constants(struct drm_crtc *crtc);
+
 /* Modesetting support */
 extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
 extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
@@ -1360,11 +1413,6 @@ extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
 extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
 extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
-extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type);
-extern int drm_agp_free_memory(DRM_AGP_MEM * handle);
-extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
-extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
-extern void drm_agp_chipset_flush(struct drm_device *dev);
 
                                /* Stub support (drm_stub.h) */
 extern int drm_setmaster_ioctl(struct drm_device *dev, void *data,
@@ -1383,6 +1431,9 @@ extern void drm_put_dev(struct drm_device *dev);
 extern int drm_put_minor(struct drm_minor **minor);
 extern unsigned int drm_debug;
 
+extern unsigned int drm_vblank_offdelay;
+extern unsigned int drm_timestamp_precision;
+
 extern struct class *drm_class;
 extern struct proc_dir_entry *drm_proc_root;
 extern struct dentry *drm_debugfs_root;
@@ -1415,7 +1466,6 @@ extern int drm_bufs_info(struct seq_file *m, void *data);
 extern int drm_vblank_info(struct seq_file *m, void *data);
 extern int drm_clients_info(struct seq_file *m, void* data);
 extern int drm_gem_name_info(struct seq_file *m, void *data);
-extern int drm_gem_object_info(struct seq_file *m, void* data);
 
 #if DRM_DEBUG_CODE
 extern int drm_vma_info(struct seq_file *m, void *data);
@@ -1456,12 +1506,11 @@ int drm_gem_init(struct drm_device *dev);
 void drm_gem_destroy(struct drm_device *dev);
 void drm_gem_object_release(struct drm_gem_object *obj);
 void drm_gem_object_free(struct kref *kref);
-void drm_gem_object_free_unlocked(struct kref *kref);
 struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
                                            size_t size);
 int drm_gem_object_init(struct drm_device *dev,
                        struct drm_gem_object *obj, size_t size);
-void drm_gem_object_handle_free(struct kref *kref);
+void drm_gem_object_handle_free(struct drm_gem_object *obj);
 void drm_gem_vm_open(struct vm_area_struct *vma);
 void drm_gem_vm_close(struct vm_area_struct *vma);
 int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
@@ -1484,8 +1533,12 @@ drm_gem_object_unreference(struct drm_gem_object *obj)
 static inline void
 drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
 {
-       if (obj != NULL)
-               kref_put(&obj->refcount, drm_gem_object_free_unlocked);
+       if (obj != NULL) {
+               struct drm_device *dev = obj->dev;
+               mutex_lock(&dev->struct_mutex);
+               kref_put(&obj->refcount, drm_gem_object_free);
+               mutex_unlock(&dev->struct_mutex);
+       }
 }
 
 int drm_gem_handle_create(struct drm_file *file_priv,
@@ -1496,7 +1549,7 @@ static inline void
 drm_gem_object_handle_reference(struct drm_gem_object *obj)
 {
        drm_gem_object_reference(obj);
-       kref_get(&obj->handlecount);
+       atomic_inc(&obj->handle_count);
 }
 
 static inline void
@@ -1505,12 +1558,15 @@ drm_gem_object_handle_unreference(struct drm_gem_object *obj)
        if (obj == NULL)
                return;
 
+       if (atomic_read(&obj->handle_count) == 0)
+               return;
        /*
         * Must bump handle count first as this may be the last
         * ref, in which case the object would disappear before we
         * checked for a name
         */
-       kref_put(&obj->handlecount, drm_gem_object_handle_free);
+       if (atomic_dec_and_test(&obj->handle_count))
+               drm_gem_object_handle_free(obj);
        drm_gem_object_unreference(obj);
 }
 
@@ -1520,12 +1576,17 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
        if (obj == NULL)
                return;
 
+       if (atomic_read(&obj->handle_count) == 0)
+               return;
+
        /*
        * Must bump handle count first as this may be the last
        * ref, in which case the object would disappear before we
        * checked for a name
        */
-       kref_put(&obj->handlecount, drm_gem_object_handle_free);
+
+       if (atomic_dec_and_test(&obj->handle_count))
+               drm_gem_object_handle_free(obj);
        drm_gem_object_unreference_unlocked(obj);
 }