diff options
author | Dave Airlie <airlied@redhat.com> | 2017-06-06 16:53:16 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-06-06 16:53:16 +1000 |
commit | 55f5b0bf51f86a32f9ef6cb81636358fc0f1bb8b (patch) | |
tree | bec0174ea1688206886724020c234333df93c62e /include/drm | |
parent | 562ff059bd5f8f04881256532c6d835af3db55bd (diff) | |
parent | 7f696942a7e52df2a99410bf23da513f9aad04fb (diff) |
Merge tag 'drm-misc-next-2017-06-02' of git://anongit.freedesktop.org/git/drm-misc into drm-next
Core Changes:
- Stop proliferation of drm_vblank_cleanup by adding to the docs and deleting
boilerplate (Daniel)
- Roll out and use mode_valid hooks across crtc/encoder/bridge (Jose)
- Add drm_vblank.[hc] to isolate vblank code from optional irq helpers (Daniel)
Driver Changes:
- Replace drm_for_each_connector with drm_for_each_connector_iter (Gustavo)
- A couple misc driver fixes
Cc: Gustavo Padovan <gustavo.padovan@collabora.com>
Cc: Jose Abreu <Jose.Abreu@synopsys.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
* tag 'drm-misc-next-2017-06-02' of git://anongit.freedesktop.org/git/drm-misc: (34 commits)
drm/vc4: Mark the device as active when enabling runtime PM.
drm: remove writeq/readq function definitions
drm/atmel-hlcdc: Use crtc->mode_valid() callback
drm/exynos: Drop drm_vblank_cleanup
drm/hdlcd|mali: Drop drm_vblank_cleanup
drm/doc: Polish irq helper documentation
drm: Extract drm_vblank.[hc]
drm/vc4: Fix comment in vc4_drv.h
drm/pl111: fix warnings without CONFIG_ARM_AMBA
drm/atomic: Consitfy mode parameter to drm_atomic_set_mode_for_crtc()
drm/arcgpu: Drop drm_vblank_cleanup
drm/atmel: Drop drm_vblank_cleanup
drm/imx: Drop drm_vblank_cleanup
drm/meson: Drop drm_vblank_cleanup
drm/stm: Drop drm_vblank_cleanup
drm/sun4i: Drop drm_vblank_cleanup
drm: better document how to send out the crtc disable event
drm: Use vsnprintf extension %ph
drm/doc: move printf helpers out of drmP.h
drm/pl111: select DRM_PANEL
...
Diffstat (limited to 'include/drm')
-rw-r--r-- | include/drm/drmP.h | 33 | ||||
-rw-r--r-- | include/drm/drm_atomic.h | 2 | ||||
-rw-r--r-- | include/drm/drm_bridge.h | 2 | ||||
-rw-r--r-- | include/drm/drm_connector.h | 15 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 4 | ||||
-rw-r--r-- | include/drm/drm_drv.h | 33 | ||||
-rw-r--r-- | include/drm/drm_file.h | 1 | ||||
-rw-r--r-- | include/drm/drm_irq.h | 158 | ||||
-rw-r--r-- | include/drm/drm_modes.h | 17 | ||||
-rw-r--r-- | include/drm/drm_os_linux.h | 14 | ||||
-rw-r--r-- | include/drm/drm_prime.h | 2 | ||||
-rw-r--r-- | include/drm/drm_rect.h | 27 | ||||
-rw-r--r-- | include/drm/drm_vblank.h | 181 |
13 files changed, 277 insertions, 212 deletions
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index b9b5566acfe6..39df16af7a4a 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -80,6 +80,9 @@ #include <drm/drm_debugfs.h> #include <drm/drm_ioctl.h> #include <drm/drm_sysfs.h> +#include <drm/drm_vblank.h> +#include <drm/drm_irq.h> + struct module; @@ -292,23 +295,6 @@ struct pci_controller; /* Format strings and argument splitters to simplify printing * various "complex" objects */ -#define DRM_MODE_FMT "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x" -#define DRM_MODE_ARG(m) \ - (m)->base.id, (m)->name, (m)->vrefresh, (m)->clock, \ - (m)->hdisplay, (m)->hsync_start, (m)->hsync_end, (m)->htotal, \ - (m)->vdisplay, (m)->vsync_start, (m)->vsync_end, (m)->vtotal, \ - (m)->type, (m)->flags - -#define DRM_RECT_FMT "%dx%d%+d%+d" -#define DRM_RECT_ARG(r) drm_rect_width(r), drm_rect_height(r), (r)->x1, (r)->y1 - -/* for rect's in fixed-point format: */ -#define DRM_RECT_FP_FMT "%d.%06ux%d.%06u%+d.%06u%+d.%06u" -#define DRM_RECT_FP_ARG(r) \ - drm_rect_width(r) >> 16, ((drm_rect_width(r) & 0xffff) * 15625) >> 10, \ - drm_rect_height(r) >> 16, ((drm_rect_height(r) & 0xffff) * 15625) >> 10, \ - (r)->x1 >> 16, (((r)->x1 & 0xffff) * 15625) >> 10, \ - (r)->y1 >> 16, (((r)->y1 & 0xffff) * 15625) >> 10 /*@}*/ @@ -391,8 +377,13 @@ struct drm_device { int last_context; /**< Last current context */ /*@} */ - /** \name VBLANK IRQ support */ - /*@{ */ + /** + * @irq_enabled: + * + * Indicates that interrupt handling is enabled, specifically vblank + * handling. Drivers which don't use drm_irq_install() need to set this + * to true manually. + */ bool irq_enabled; int irq; @@ -429,8 +420,6 @@ struct drm_device { struct pci_controller *hose; #endif - struct virtio_device *virtdev; - struct drm_sg_mem *sg; /**< Scatter gather memory */ unsigned int num_crtcs; /**< Number of CRTCs on this device */ @@ -466,8 +455,6 @@ static inline bool drm_drv_uses_atomic_modeset(struct drm_device *dev) return dev->mode_config.funcs->atomic_commit != NULL; } -#include <drm/drm_irq.h> - #define DRM_SWITCH_POWER_ON 0 #define DRM_SWITCH_POWER_OFF 1 #define DRM_SWITCH_POWER_CHANGING 2 diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 8645dcdef031..0196f264a418 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -520,7 +520,7 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state, int __must_check drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, - struct drm_display_mode *mode); + const struct drm_display_mode *mode); int __must_check drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, struct drm_property_blob *blob); diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 983054f2e86e..5b106eca6d57 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -253,6 +253,8 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, bool drm_bridge_mode_fixup(struct drm_bridge *bridge, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); +enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_mode *mode); void drm_bridge_disable(struct drm_bridge *bridge); void drm_bridge_post_disable(struct drm_bridge *bridge); void drm_bridge_mode_set(struct drm_bridge *bridge, diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 2fe09c1ddfb8..d8bb25f38eba 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1010,21 +1010,6 @@ void drm_mode_put_tile_group(struct drm_device *dev, struct drm_tile_group *tg); /** - * drm_for_each_connector - iterate over all connectors - * @connector: the loop cursor - * @dev: the DRM device - * - * Iterate over all connectors of @dev. - * - * WARNING: - * - * This iterator is not safe against hotadd/removal of connectors and is - * deprecated. Use drm_for_each_connector_iter() instead. - */ -#define drm_for_each_connector(connector, dev) \ - list_for_each_entry(connector, &(dev)->mode_config.connector_list, head) - -/** * struct drm_connector_list_iter - connector_list iterator * * This iterator tracks state needed to be able to walk the connector_list diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index b6e3713bd7a9..629a5fe075b3 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -214,7 +214,9 @@ struct drm_crtc_state { * atomic commit. In that case the event can be send out any time * after the hardware has stopped scanning out the current * framebuffers. It should contain the timestamp and counter for the - * last vblank before the display pipeline was shut off. + * last vblank before the display pipeline was shut off. The simplest + * way to achieve that is calling drm_crtc_send_vblank_event() + * somewhen after drm_crtc_vblank_off() has been called. * * - For a CRTC which is enabled at the end of the commit (even when it * undergoes an full modeset) the vblank timestamp and counter must diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index e64e33b9dd26..18f3181674e8 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -327,11 +327,40 @@ struct drm_driver { struct timeval *vblank_time, bool in_vblank_irq); - /* these have to be filled in */ - + /** + * @irq_handler: + * + * Interrupt handler called when using drm_irq_install(). Not used by + * drivers which implement their own interrupt handling. + */ irqreturn_t(*irq_handler) (int irq, void *arg); + + /** + * @irq_preinstall: + * + * Optional callback used by drm_irq_install() which is called before + * the interrupt handler is registered. This should be used to clear out + * any pending interrupts (from e.g. firmware based drives) and reset + * the interrupt handling registers. + */ void (*irq_preinstall) (struct drm_device *dev); + + /** + * @irq_postinstall: + * + * Optional callback used by drm_irq_install() which is called after + * the interrupt handler is registered. This should be used to enable + * interrupt generation in the hardware. + */ int (*irq_postinstall) (struct drm_device *dev); + + /** + * @irq_uninstall: + * + * Optional callback used by drm_irq_uninstall() which is called before + * the interrupt handler is unregistered. This should be used to disable + * interrupt generation in the hardware. + */ void (*irq_uninstall) (struct drm_device *dev); /** diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 5dd27ae5c47c..d66f7ee07fb5 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -40,6 +40,7 @@ struct dma_fence; struct drm_file; struct drm_device; +struct device; /* * FIXME: Not sure we want to have drm_minor here in the end, but to avoid diff --git a/include/drm/drm_irq.h b/include/drm/drm_irq.h index 569ca86d4e1f..d77f6e65b1c6 100644 --- a/include/drm/drm_irq.h +++ b/include/drm/drm_irq.h @@ -24,165 +24,9 @@ #ifndef _DRM_IRQ_H_ #define _DRM_IRQ_H_ -#include <linux/seqlock.h> - -/** - * struct drm_pending_vblank_event - pending vblank event tracking - */ -struct drm_pending_vblank_event { - /** - * @base: Base structure for tracking pending DRM events. - */ - struct drm_pending_event base; - /** - * @pipe: drm_crtc_index() of the &drm_crtc this event is for. - */ - unsigned int pipe; - /** - * @event: Actual event which will be sent to userspace. - */ - struct drm_event_vblank event; -}; - -/** - * struct drm_vblank_crtc - vblank tracking for a CRTC - * - * This structure tracks the vblank state for one CRTC. - * - * Note that for historical reasons - the vblank handling code is still shared - * with legacy/non-kms drivers - this is a free-standing structure not directly - * connected to &struct drm_crtc. But all public interface functions are taking - * a &struct drm_crtc to hide this implementation detail. - */ -struct drm_vblank_crtc { - /** - * @dev: Pointer to the &drm_device. - */ - struct drm_device *dev; - /** - * @queue: Wait queue for vblank waiters. - */ - wait_queue_head_t queue; /**< VBLANK wait queue */ - /** - * @disable_timer: Disable timer for the delayed vblank disabling - * hysteresis logic. Vblank disabling is controlled through the - * drm_vblank_offdelay module option and the setting of the - * &drm_device.max_vblank_count value. - */ - struct timer_list disable_timer; - - /** - * @seqlock: Protect vblank count and time. - */ - seqlock_t seqlock; /* protects vblank count and time */ - - /** - * @count: Current software vblank counter. - */ - u32 count; - /** - * @time: Vblank timestamp corresponding to @count. - */ - struct timeval time; - - /** - * @refcount: Number of users/waiters of the vblank interrupt. Only when - * this refcount reaches 0 can the hardware interrupt be disabled using - * @disable_timer. - */ - atomic_t refcount; /* number of users of vblank interruptsper crtc */ - /** - * @last: Protected by &drm_device.vbl_lock, used for wraparound handling. - */ - u32 last; - /** - * @inmodeset: Tracks whether the vblank is disabled due to a modeset. - * For legacy driver bit 2 additionally tracks whether an additional - * temporary vblank reference has been acquired to paper over the - * hardware counter resetting/jumping. KMS drivers should instead just - * call drm_crtc_vblank_off() and drm_crtc_vblank_on(), which explicitly - * save and restore the vblank count. - */ - unsigned int inmodeset; /* Display driver is setting mode */ - /** - * @pipe: drm_crtc_index() of the &drm_crtc corresponding to this - * structure. - */ - unsigned int pipe; - /** - * @framedur_ns: Frame/Field duration in ns, used by - * drm_calc_vbltimestamp_from_scanoutpos() and computed by - * drm_calc_timestamping_constants(). - */ - int framedur_ns; - /** - * @linedur_ns: Line duration in ns, used by - * drm_calc_vbltimestamp_from_scanoutpos() and computed by - * drm_calc_timestamping_constants(). - */ - int linedur_ns; - - /** - * @hwmode: - * - * Cache of the current hardware display mode. Only valid when @enabled - * is set. This is used by helpers like - * drm_calc_vbltimestamp_from_scanoutpos(). We can't just access the - * hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode, - * because that one is really hard to get from interrupt context. - */ - struct drm_display_mode hwmode; - - /** - * @enabled: Tracks the enabling state of the corresponding &drm_crtc to - * avoid double-disabling and hence corrupting saved state. Needed by - * drivers not using atomic KMS, since those might go through their CRTC - * disabling functions multiple times. - */ - bool enabled; -}; +struct drm_device; int drm_irq_install(struct drm_device *dev, int irq); int drm_irq_uninstall(struct drm_device *dev); -int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs); -u32 drm_crtc_vblank_count(struct drm_crtc *crtc); -u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, - struct timeval *vblanktime); -void drm_crtc_send_vblank_event(struct drm_crtc *crtc, - struct drm_pending_vblank_event *e); -void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, - struct drm_pending_vblank_event *e); -bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe); -bool drm_crtc_handle_vblank(struct drm_crtc *crtc); -int drm_crtc_vblank_get(struct drm_crtc *crtc); -void drm_crtc_vblank_put(struct drm_crtc *crtc); -void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe); -void drm_crtc_wait_one_vblank(struct drm_crtc *crtc); -void drm_crtc_vblank_off(struct drm_crtc *crtc); -void drm_crtc_vblank_reset(struct drm_crtc *crtc); -void drm_crtc_vblank_on(struct drm_crtc *crtc); -void drm_vblank_cleanup(struct drm_device *dev); -u32 drm_accurate_vblank_count(struct drm_crtc *crtc); - -bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, - unsigned int pipe, int *max_error, - struct timeval *vblank_time, - bool in_vblank_irq); -void drm_calc_timestamping_constants(struct drm_crtc *crtc, - const struct drm_display_mode *mode); - -/** - * drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC - * @crtc: which CRTC's vblank waitqueue to retrieve - * - * This function returns a pointer to the vblank waitqueue for the CRTC. - * Drivers can use this to implement vblank waits using wait_event() and related - * functions. - */ -static inline wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc) -{ - return &crtc->dev->vblank[drm_crtc_index(crtc)].queue; -} - #endif diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 6dd34280e892..94ac771fe460 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -197,6 +197,8 @@ enum drm_mode_status { * there's the hardware timings, which are corrected for interlacing, * double-clocking and similar things. They are provided as a convenience, and * can be appropriately computed using drm_mode_set_crtcinfo(). + * + * For printing you can use %DRM_MODE_FMT and DRM_MODE_ARG(). */ struct drm_display_mode { /** @@ -407,6 +409,21 @@ struct drm_display_mode { enum hdmi_picture_aspect picture_aspect_ratio; }; +/** + * DRM_MODE_FMT - printf string for &struct drm_display_mode + */ +#define DRM_MODE_FMT "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x" + +/** + * DRM_MODE_ARG - printf arguments for &struct drm_display_mode + * @m: display mode + */ +#define DRM_MODE_ARG(m) \ + (m)->base.id, (m)->name, (m)->vrefresh, (m)->clock, \ + (m)->hdisplay, (m)->hsync_start, (m)->hsync_end, (m)->htotal, \ + (m)->vdisplay, (m)->vsync_start, (m)->vsync_end, (m)->vtotal, \ + (m)->type, (m)->flags + #define obj_to_mode(x) container_of(x, struct drm_display_mode, base) /** diff --git a/include/drm/drm_os_linux.h b/include/drm/drm_os_linux.h index 35e1482ba8a1..10122353b744 100644 --- a/include/drm/drm_os_linux.h +++ b/include/drm/drm_os_linux.h @@ -6,19 +6,7 @@ #include <linux/interrupt.h> /* For task queue support */ #include <linux/sched/signal.h> #include <linux/delay.h> - -#ifndef readq -static inline u64 readq(void __iomem *reg) -{ - return ((u64) readl(reg)) | (((u64) readl(reg + 4UL)) << 32); -} - -static inline void writeq(u64 val, void __iomem *reg) -{ - writel(val & 0xffffffff, reg); - writel(val >> 32, reg + 0x4UL); -} -#endif +#include <linux/io-64-nonatomic-lo-hi.h> /** Current process ID */ #define DRM_CURRENTPID task_pid_nr(current) diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h index 59ccab402e85..9cd9e36f77b5 100644 --- a/include/drm/drm_prime.h +++ b/include/drm/drm_prime.h @@ -59,6 +59,8 @@ struct drm_device; struct drm_gem_object; struct drm_file; +struct device; + struct dma_buf *drm_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags); diff --git a/include/drm/drm_rect.h b/include/drm/drm_rect.h index 83bb156d4356..44bc122b9ee0 100644 --- a/include/drm/drm_rect.h +++ b/include/drm/drm_rect.h @@ -43,6 +43,33 @@ struct drm_rect { }; /** + * DRM_RECT_FMT - printf string for &struct drm_rect + */ +#define DRM_RECT_FMT "%dx%d%+d%+d" +/** + * DRM_RECT_ARG - printf arguments for &struct drm_rect + * @r: rectangle struct + */ +#define DRM_RECT_ARG(r) drm_rect_width(r), drm_rect_height(r), (r)->x1, (r)->y1 + +/** + * DRM_RECT_FP_FMT - printf string for &struct drm_rect in 16.16 fixed point + */ +#define DRM_RECT_FP_FMT "%d.%06ux%d.%06u%+d.%06u%+d.%06u" +/** + * DRM_RECT_FP_ARG - printf arguments for &struct drm_rect in 16.16 fixed point + * @r: rectangle struct + * + * This is useful for e.g. printing plane source rectangles, which are in 16.16 + * fixed point. + */ +#define DRM_RECT_FP_ARG(r) \ + drm_rect_width(r) >> 16, ((drm_rect_width(r) & 0xffff) * 15625) >> 10, \ + drm_rect_height(r) >> 16, ((drm_rect_height(r) & 0xffff) * 15625) >> 10, \ + (r)->x1 >> 16, (((r)->x1 & 0xffff) * 15625) >> 10, \ + (r)->y1 >> 16, (((r)->y1 & 0xffff) * 15625) >> 10 + +/** * drm_rect_adjust_size - adjust the size of the rectangle * @r: rectangle to be adjusted * @dw: horizontal adjustment diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h new file mode 100644 index 000000000000..4cde47332dfa --- /dev/null +++ b/include/drm/drm_vblank.h @@ -0,0 +1,181 @@ +/* + * Copyright 2016 Intel Corp. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DRM_VBLANK_H_ +#define _DRM_VBLANK_H_ + +#include <linux/seqlock.h> +#include <linux/idr.h> +#include <linux/poll.h> + +#include <drm/drm_file.h> +#include <drm/drm_modes.h> +#include <uapi/drm/drm.h> + +struct drm_device; +struct drm_crtc; + +/** + * struct drm_pending_vblank_event - pending vblank event tracking + */ +struct drm_pending_vblank_event { + /** + * @base: Base structure for tracking pending DRM events. + */ + struct drm_pending_event base; + /** + * @pipe: drm_crtc_index() of the &drm_crtc this event is for. + */ + unsigned int pipe; + /** + * @event: Actual event which will be sent to userspace. + */ + struct drm_event_vblank event; +}; + +/** + * struct drm_vblank_crtc - vblank tracking for a CRTC + * + * This structure tracks the vblank state for one CRTC. + * + * Note that for historical reasons - the vblank handling code is still shared + * with legacy/non-kms drivers - this is a free-standing structure not directly + * connected to &struct drm_crtc. But all public interface functions are taking + * a &struct drm_crtc to hide this implementation detail. + */ +struct drm_vblank_crtc { + /** + * @dev: Pointer to the &drm_device. + */ + struct drm_device *dev; + /** + * @queue: Wait queue for vblank waiters. + */ + wait_queue_head_t queue; /**< VBLANK wait queue */ + /** + * @disable_timer: Disable timer for the delayed vblank disabling + * hysteresis logic. Vblank disabling is controlled through the + * drm_vblank_offdelay module option and the setting of the + * &drm_device.max_vblank_count value. + */ + struct timer_list disable_timer; + + /** + * @seqlock: Protect vblank count and time. + */ + seqlock_t seqlock; /* protects vblank count and time */ + + /** + * @count: Current software vblank counter. + */ + u32 count; + /** + * @time: Vblank timestamp corresponding to @count. + */ + struct timeval time; + + /** + * @refcount: Number of users/waiters of the vblank interrupt. Only when + * this refcount reaches 0 can the hardware interrupt be disabled using + * @disable_timer. + */ + atomic_t refcount; /* number of users of vblank interruptsper crtc */ + /** + * @last: Protected by &drm_device.vbl_lock, used for wraparound handling. + */ + u32 last; + /** + * @inmodeset: Tracks whether the vblank is disabled due to a modeset. + * For legacy driver bit 2 additionally tracks whether an additional + * temporary vblank reference has been acquired to paper over the + * hardware counter resetting/jumping. KMS drivers should instead just + * call drm_crtc_vblank_off() and drm_crtc_vblank_on(), which explicitly + * save and restore the vblank count. + */ + unsigned int inmodeset; /* Display driver is setting mode */ + /** + * @pipe: drm_crtc_index() of the &drm_crtc corresponding to this + * structure. + */ + unsigned int pipe; + /** + * @framedur_ns: Frame/Field duration in ns, used by + * drm_calc_vbltimestamp_from_scanoutpos() and computed by + * drm_calc_timestamping_constants(). + */ + int framedur_ns; + /** + * @linedur_ns: Line duration in ns, used by + * drm_calc_vbltimestamp_from_scanoutpos() and computed by + * drm_calc_timestamping_constants(). + */ + int linedur_ns; + + /** + * @hwmode: + * + * Cache of the current hardware display mode. Only valid when @enabled + * is set. This is used by helpers like + * drm_calc_vbltimestamp_from_scanoutpos(). We can't just access the + * hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode, + * because that one is really hard to get from interrupt context. + */ + struct drm_display_mode hwmode; + + /** + * @enabled: Tracks the enabling state of the corresponding &drm_crtc to + * avoid double-disabling and hence corrupting saved state. Needed by + * drivers not using atomic KMS, since those might go through their CRTC + * disabling functions multiple times. + */ + bool enabled; +}; + +int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs); +u32 drm_crtc_vblank_count(struct drm_crtc *crtc); +u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, + struct timeval *vblanktime); +void drm_crtc_send_vblank_event(struct drm_crtc *crtc, + struct drm_pending_vblank_event *e); +void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, + struct drm_pending_vblank_event *e); +bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe); +bool drm_crtc_handle_vblank(struct drm_crtc *crtc); +int drm_crtc_vblank_get(struct drm_crtc *crtc); +void drm_crtc_vblank_put(struct drm_crtc *crtc); +void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe); +void drm_crtc_wait_one_vblank(struct drm_crtc *crtc); +void drm_crtc_vblank_off(struct drm_crtc *crtc); +void drm_crtc_vblank_reset(struct drm_crtc *crtc); +void drm_crtc_vblank_on(struct drm_crtc *crtc); +void drm_vblank_cleanup(struct drm_device *dev); +u32 drm_accurate_vblank_count(struct drm_crtc *crtc); + +bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, + unsigned int pipe, int *max_error, + struct timeval *vblank_time, + bool in_vblank_irq); +void drm_calc_timestamping_constants(struct drm_crtc *crtc, + const struct drm_display_mode *mode); +wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc); +#endif |