Subversion Repositories Kolibri OS

Rev

Rev 5060 | Rev 6084 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * drm_irq.c IRQ and vblank support
  3.  *
  4.  * \author Rickard E. (Rik) Faith <faith@valinux.com>
  5.  * \author Gareth Hughes <gareth@valinux.com>
  6.  */
  7.  
  8. /*
  9.  * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
  10.  *
  11.  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
  12.  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  13.  * All Rights Reserved.
  14.  *
  15.  * Permission is hereby granted, free of charge, to any person obtaining a
  16.  * copy of this software and associated documentation files (the "Software"),
  17.  * to deal in the Software without restriction, including without limitation
  18.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  19.  * and/or sell copies of the Software, and to permit persons to whom the
  20.  * Software is furnished to do so, subject to the following conditions:
  21.  *
  22.  * The above copyright notice and this permission notice (including the next
  23.  * paragraph) shall be included in all copies or substantial portions of the
  24.  * Software.
  25.  *
  26.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  27.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  28.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  29.  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  30.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  31.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  32.  * OTHER DEALINGS IN THE SOFTWARE.
  33.  */
  34.  
  35. #include <drm/drmP.h>
  36. //#include "drm_trace.h"
  37. #include "drm_internal.h"
  38.  
  39. //#include <linux/interrupt.h>   /* For task queue support */
  40. #include <linux/slab.h>
  41.  
  42. #include <linux/vgaarb.h>
  43. #include <linux/export.h>
  44.  
  45. /* Access macro for slots in vblank timestamp ringbuffer. */
  46. #define vblanktimestamp(dev, crtc, count) \
  47.         ((dev)->vblank[crtc].time[(count) % DRM_VBLANKTIME_RBSIZE])
  48.  
  49. /* Retry timestamp calculation up to 3 times to satisfy
  50.  * drm_timestamp_precision before giving up.
  51.  */
  52. #define DRM_TIMESTAMP_MAXRETRIES 3
  53.  
  54. /* Threshold in nanoseconds for detection of redundant
  55.  * vblank irq in drm_handle_vblank(). 1 msec should be ok.
  56.  */
  57. #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000
  58.  
  59. static bool
  60. drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
  61.                           struct timeval *tvblank, unsigned flags);
  62.  
  63. static unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
  64.  
  65. /*
  66.  * Clear vblank timestamp buffer for a crtc.
  67.  */
  68.  
  69.  
  70. #if 0
  71. /**
  72.  * drm_vblank_init - initialize vblank support
  73.  * @dev: drm_device
  74.  * @num_crtcs: number of crtcs supported by @dev
  75.  *
  76.  * This function initializes vblank support for @num_crtcs display pipelines.
  77.  *
  78.  * Returns:
  79.  * Zero on success or a negative error code on failure.
  80.  */
  81. int drm_vblank_init(struct drm_device *dev, int num_crtcs)
  82. {
  83.         int i, ret = -ENOMEM;
  84.  
  85.         spin_lock_init(&dev->vbl_lock);
  86.         spin_lock_init(&dev->vblank_time_lock);
  87.  
  88.         dev->num_crtcs = num_crtcs;
  89.  
  90.         dev->vblank = kcalloc(num_crtcs, sizeof(*dev->vblank), GFP_KERNEL);
  91.         if (!dev->vblank)
  92.                 goto err;
  93.  
  94.         for (i = 0; i < num_crtcs; i++) {
  95.                 struct drm_vblank_crtc *vblank = &dev->vblank[i];
  96.  
  97.                 vblank->dev = dev;
  98.                 vblank->crtc = i;
  99.                 init_waitqueue_head(&vblank->queue);
  100.                 setup_timer(&vblank->disable_timer, vblank_disable_fn,
  101.                             (unsigned long)vblank);
  102.         }
  103.  
  104.         DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n");
  105.  
  106.         /* Driver specific high-precision vblank timestamping supported? */
  107.         if (dev->driver->get_vblank_timestamp)
  108.                 DRM_INFO("Driver supports precise vblank timestamp query.\n");
  109.         else
  110.                 DRM_INFO("No driver support for vblank timestamp query.\n");
  111.  
  112.         dev->vblank_disable_allowed = false;
  113.  
  114.         return 0;
  115.  
  116. err:
  117.         dev->num_crtcs = 0;
  118.         return ret;
  119. }
  120. EXPORT_SYMBOL(drm_vblank_init);
  121.  
  122. #endif
  123.  
  124. irqreturn_t device_irq_handler(struct drm_device *dev)
  125. {
  126.  
  127. //    printf("video irq\n");
  128.  
  129. //    printf("device %p driver %p handler %p\n", dev, dev->driver, dev->driver->irq_handler) ;
  130.  
  131.     return dev->driver->irq_handler(0, dev);
  132. }
  133.  
  134. /**
  135.  * drm_irq_install - install IRQ handler
  136.  * @dev: DRM device
  137.  * @irq: IRQ number to install the handler for
  138.  *
  139.  * Initializes the IRQ related data. Installs the handler, calling the driver
  140.  * irq_preinstall() and irq_postinstall() functions before and after the
  141.  * installation.
  142.  *
  143.  * This is the simplified helper interface provided for drivers with no special
  144.  * needs. Drivers which need to install interrupt handlers for multiple
  145.  * interrupts must instead set drm_device->irq_enabled to signal the DRM core
  146.  * that vblank interrupts are available.
  147.  *
  148.  * Returns:
  149.  * Zero on success or a negative error code on failure.
  150.  */
  151. int drm_irq_install(struct drm_device *dev, int irq)
  152. {
  153.         int ret;
  154.     unsigned long sh_flags = 0;
  155.  
  156.         if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
  157.                 return -EINVAL;
  158.  
  159.         if (irq == 0)
  160.                 return -EINVAL;
  161.  
  162.     /* Driver must have been initialized */
  163.         if (!dev->dev_private)
  164.             return -EINVAL;
  165.  
  166.         if (dev->irq_enabled)
  167.             return -EBUSY;
  168.         dev->irq_enabled = true;
  169.  
  170.         DRM_DEBUG("irq=%d\n", irq);
  171.  
  172.     /* Before installing handler */
  173.     if (dev->driver->irq_preinstall)
  174.             dev->driver->irq_preinstall(dev);
  175.  
  176.     ret = !AttachIntHandler(irq, device_irq_handler, (u32)dev);
  177.  
  178.     /* After installing handler */
  179.     if (dev->driver->irq_postinstall)
  180.             ret = dev->driver->irq_postinstall(dev);
  181.  
  182.     if (ret < 0) {
  183.                 dev->irq_enabled = false;
  184.         DRM_ERROR(__FUNCTION__);
  185.         } else {
  186.                 dev->irq = irq;
  187.     }
  188.  
  189.     u16 cmd = PciRead16(dev->pdev->busnr, dev->pdev->devfn, 4);
  190.     cmd&= ~(1<<10);
  191.     PciWrite16(dev->pdev->busnr, dev->pdev->devfn, 4, cmd);
  192.  
  193.     return ret;
  194. }
  195. EXPORT_SYMBOL(drm_irq_install);
  196.  
  197.  
  198.  
  199.  
  200. u64 div64_u64(u64 dividend, u64 divisor)
  201. {
  202.         u32 high, d;
  203.  
  204.         high = divisor >> 32;
  205.         if (high) {
  206.                 unsigned int shift = fls(high);
  207.  
  208.                 d = divisor >> shift;
  209.                 dividend >>= shift;
  210.         } else
  211.                 d = divisor;
  212.  
  213.         return div_u64(dividend, d);
  214. }
  215.  
  216. /**
  217.  * drm_calc_timestamping_constants - calculate vblank timestamp constants
  218.  * @crtc: drm_crtc whose timestamp constants should be updated.
  219.  * @mode: display mode containing the scanout timings
  220.  *
  221.  * Calculate and store various constants which are later
  222.  * needed by vblank and swap-completion timestamping, e.g,
  223.  * by drm_calc_vbltimestamp_from_scanoutpos(). They are
  224.  * derived from CRTC's true scanout timing, so they take
  225.  * things like panel scaling or other adjustments into account.
  226.  */
  227. void drm_calc_timestamping_constants(struct drm_crtc *crtc,
  228.                                      const struct drm_display_mode *mode)
  229. {
  230.         int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0;
  231.         int dotclock = mode->crtc_clock;
  232.  
  233.         /* Valid dotclock? */
  234.         if (dotclock > 0) {
  235.                 int frame_size = mode->crtc_htotal * mode->crtc_vtotal;
  236.  
  237.                 /*
  238.                  * Convert scanline length in pixels and video
  239.                  * dot clock to line duration, frame duration
  240.                  * and pixel duration in nanoseconds:
  241.          */
  242.                 pixeldur_ns = 1000000 / dotclock;
  243.                 linedur_ns  = div_u64((u64) mode->crtc_htotal * 1000000, dotclock);
  244.                 framedur_ns = div_u64((u64) frame_size * 1000000, dotclock);
  245.  
  246.                 /*
  247.                  * Fields of interlaced scanout modes are only half a frame duration.
  248.                  */
  249.                 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
  250.                         framedur_ns /= 2;
  251.         } else
  252.                 DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n",
  253.                           crtc->base.id);
  254.  
  255.         crtc->pixeldur_ns = pixeldur_ns;
  256.         crtc->linedur_ns  = linedur_ns;
  257.         crtc->framedur_ns = framedur_ns;
  258.  
  259.         DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
  260.                   crtc->base.id, mode->crtc_htotal,
  261.                   mode->crtc_vtotal, mode->crtc_vdisplay);
  262.         DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
  263.                   crtc->base.id, dotclock, framedur_ns,
  264.                   linedur_ns, pixeldur_ns);
  265. }
  266. EXPORT_SYMBOL(drm_calc_timestamping_constants);
  267.  
  268. /**
  269.  * drm_calc_vbltimestamp_from_scanoutpos - precise vblank timestamp helper
  270.  * @dev: DRM device
  271.  * @crtc: Which CRTC's vblank timestamp to retrieve
  272.  * @max_error: Desired maximum allowable error in timestamps (nanosecs)
  273.  *             On return contains true maximum error of timestamp
  274.  * @vblank_time: Pointer to struct timeval which should receive the timestamp
  275.  * @flags: Flags to pass to driver:
  276.  *         0 = Default,
  277.  *         DRM_CALLED_FROM_VBLIRQ = If function is called from vbl IRQ handler
  278.  * @refcrtc: CRTC which defines scanout timing
  279.  * @mode: mode which defines the scanout timings
  280.  *
  281.  * Implements calculation of exact vblank timestamps from given drm_display_mode
  282.  * timings and current video scanout position of a CRTC. This can be called from
  283.  * within get_vblank_timestamp() implementation of a kms driver to implement the
  284.  * actual timestamping.
  285.  *
  286.  * Should return timestamps conforming to the OML_sync_control OpenML
  287.  * extension specification. The timestamp corresponds to the end of
  288.  * the vblank interval, aka start of scanout of topmost-leftmost display
  289.  * pixel in the following video frame.
  290.  *
  291.  * Requires support for optional dev->driver->get_scanout_position()
  292.  * in kms driver, plus a bit of setup code to provide a drm_display_mode
  293.  * that corresponds to the true scanout timing.
  294.  *
  295.  * The current implementation only handles standard video modes. It
  296.  * returns as no operation if a doublescan or interlaced video mode is
  297.  * active. Higher level code is expected to handle this.
  298.  *
  299.  * Returns:
  300.  * Negative value on error, failure or if not supported in current
  301.  * video mode:
  302.  *
  303.  * -EINVAL   - Invalid CRTC.
  304.  * -EAGAIN   - Temporary unavailable, e.g., called before initial modeset.
  305.  * -ENOTSUPP - Function not supported in current display mode.
  306.  * -EIO      - Failed, e.g., due to failed scanout position query.
  307.  *
  308.  * Returns or'ed positive status flags on success:
  309.  *
  310.  * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping.
  311.  * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval.
  312.  *
  313.  */
  314. int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
  315.                                           int *max_error,
  316.                                           struct timeval *vblank_time,
  317.                                           unsigned flags,
  318.                                           const struct drm_crtc *refcrtc,
  319.                                           const struct drm_display_mode *mode)
  320. {
  321.         struct timeval tv_etime;
  322.         int vbl_status;
  323.         int vpos, hpos, i;
  324.         int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
  325.         bool invbl;
  326.  
  327.         if (crtc < 0 || crtc >= dev->num_crtcs) {
  328.                 DRM_ERROR("Invalid crtc %d\n", crtc);
  329.                 return -EINVAL;
  330.         }
  331.  
  332.         /* Scanout position query not supported? Should not happen. */
  333.         if (!dev->driver->get_scanout_position) {
  334.                 DRM_ERROR("Called from driver w/o get_scanout_position()!?\n");
  335.                 return -EIO;
  336.         }
  337.  
  338.         /* Durations of frames, lines, pixels in nanoseconds. */
  339.         framedur_ns = refcrtc->framedur_ns;
  340.         linedur_ns  = refcrtc->linedur_ns;
  341.         pixeldur_ns = refcrtc->pixeldur_ns;
  342.  
  343.         /* If mode timing undefined, just return as no-op:
  344.          * Happens during initial modesetting of a crtc.
  345.          */
  346.         if (framedur_ns == 0) {
  347.                 DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc);
  348.                 return -EAGAIN;
  349.         }
  350.  
  351.         return -EIO;
  352. }
  353. EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos);
  354.  
  355. /**
  356.  * drm_vblank_get - get a reference count on vblank events
  357.  * @dev: DRM device
  358.  * @crtc: which CRTC to own
  359.  *
  360.  * Acquire a reference count on vblank events to avoid having them disabled
  361.  * while in use.
  362.  *
  363.  * This is the legacy version of drm_crtc_vblank_get().
  364.  *
  365.  * Returns:
  366.  * Zero on success, nonzero on failure.
  367.  */
  368. int drm_vblank_get(struct drm_device *dev, int crtc)
  369. {
  370.         struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
  371.         unsigned long irqflags;
  372.         int ret = 0;
  373. #if 0
  374.  
  375.         if (WARN_ON(crtc >= dev->num_crtcs))
  376.                 return -EINVAL;
  377.  
  378.         spin_lock_irqsave(&dev->vbl_lock, irqflags);
  379.         /* Going from 0->1 means we have to enable interrupts again */
  380.         if (atomic_add_return(1, &vblank->refcount) == 1) {
  381.                 ret = drm_vblank_enable(dev, crtc);
  382.         } else {
  383.                 if (!vblank->enabled) {
  384.                         atomic_dec(&vblank->refcount);
  385.                         ret = -EINVAL;
  386.                 }
  387.         }
  388.         spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
  389. #endif
  390.         return ret;
  391. }
  392. EXPORT_SYMBOL(drm_vblank_get);
  393.  
  394. /**
  395.  * drm_crtc_vblank_get - get a reference count on vblank events
  396.  * @crtc: which CRTC to own
  397.  *
  398.  * Acquire a reference count on vblank events to avoid having them disabled
  399.  * while in use.
  400.  *
  401.  * This is the native kms version of drm_vblank_off().
  402.  *
  403.  * Returns:
  404.  * Zero on success, nonzero on failure.
  405.  */
  406. int drm_crtc_vblank_get(struct drm_crtc *crtc)
  407. {
  408.         return drm_vblank_get(crtc->dev, drm_crtc_index(crtc));
  409. }
  410. EXPORT_SYMBOL(drm_crtc_vblank_get);
  411.  
  412. /**
  413.  * drm_vblank_put - give up ownership of vblank events
  414.  * @dev: DRM device
  415.  * @crtc: which counter to give up
  416.  *
  417.  * Release ownership of a given vblank counter, turning off interrupts
  418.  * if possible. Disable interrupts after drm_vblank_offdelay milliseconds.
  419.  *
  420.  * This is the legacy version of drm_crtc_vblank_put().
  421.  */
  422. void drm_vblank_put(struct drm_device *dev, int crtc)
  423. {
  424. #if 0
  425.         struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
  426.  
  427.         if (WARN_ON(atomic_read(&vblank->refcount) == 0))
  428.                 return;
  429.  
  430.         if (WARN_ON(crtc >= dev->num_crtcs))
  431.                 return;
  432.  
  433.         /* Last user schedules interrupt disable */
  434.         if (atomic_dec_and_test(&vblank->refcount)) {
  435.                 if (drm_vblank_offdelay == 0)
  436.                         return;
  437.                 else if (dev->vblank_disable_immediate || drm_vblank_offdelay < 0)
  438.                         vblank_disable_fn((unsigned long)vblank);
  439.                 else
  440.                         mod_timer(&vblank->disable_timer,
  441.                                   jiffies + ((drm_vblank_offdelay * HZ)/1000));
  442.         }
  443. #endif
  444. }
  445. EXPORT_SYMBOL(drm_vblank_put);
  446.  
  447. /**
  448.  * drm_crtc_vblank_put - give up ownership of vblank events
  449.  * @crtc: which counter to give up
  450.  *
  451.  * Release ownership of a given vblank counter, turning off interrupts
  452.  * if possible. Disable interrupts after drm_vblank_offdelay milliseconds.
  453.  *
  454.  * This is the native kms version of drm_vblank_put().
  455.  */
  456. void drm_crtc_vblank_put(struct drm_crtc *crtc)
  457. {
  458.         drm_vblank_put(crtc->dev, drm_crtc_index(crtc));
  459. }
  460. EXPORT_SYMBOL(drm_crtc_vblank_put);
  461.  
  462. /**
  463.  * drm_wait_one_vblank - wait for one vblank
  464.  * @dev: DRM device
  465.  * @crtc: crtc index
  466.  *
  467.  * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
  468.  * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
  469.  * due to lack of driver support or because the crtc is off.
  470.  */
  471. void drm_wait_one_vblank(struct drm_device *dev, int crtc)
  472. {
  473. #if 0
  474.         int ret;
  475.         u32 last;
  476.  
  477.         ret = drm_vblank_get(dev, crtc);
  478.         if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", crtc, ret))
  479.                 return;
  480.  
  481.         last = drm_vblank_count(dev, crtc);
  482.  
  483.         ret = wait_event_timeout(dev->vblank[crtc].queue,
  484.                                  last != drm_vblank_count(dev, crtc),
  485.                                  msecs_to_jiffies(100));
  486.  
  487.         WARN(ret == 0, "vblank wait timed out on crtc %i\n", crtc);
  488.  
  489.         drm_vblank_put(dev, crtc);
  490. #endif
  491. }
  492. EXPORT_SYMBOL(drm_wait_one_vblank);
  493.  
  494. /**
  495.  * drm_crtc_wait_one_vblank - wait for one vblank
  496.  * @crtc: DRM crtc
  497.  *
  498.  * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
  499.  * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
  500.  * due to lack of driver support or because the crtc is off.
  501.  */
  502. void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
  503. {
  504.         drm_wait_one_vblank(crtc->dev, drm_crtc_index(crtc));
  505. }
  506. EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
  507.  
  508. /**
  509.  * drm_vblank_off - disable vblank events on a CRTC
  510.  * @dev: DRM device
  511.  * @crtc: CRTC in question
  512.  *
  513.  * Drivers can use this function to shut down the vblank interrupt handling when
  514.  * disabling a crtc. This function ensures that the latest vblank frame count is
  515.  * stored so that drm_vblank_on() can restore it again.
  516.  *
  517.  * Drivers must use this function when the hardware vblank counter can get
  518.  * reset, e.g. when suspending.
  519.  *
  520.  * This is the legacy version of drm_crtc_vblank_off().
  521.  */
  522. void drm_vblank_off(struct drm_device *dev, int crtc)
  523. {
  524.         struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
  525.         struct drm_pending_vblank_event *e, *t;
  526.         struct timeval now;
  527.         unsigned long irqflags;
  528.         unsigned int seq;
  529.  
  530.  
  531. }
  532. EXPORT_SYMBOL(drm_vblank_off);
  533.  
  534. /**
  535.  * drm_crtc_vblank_off - disable vblank events on a CRTC
  536.  * @crtc: CRTC in question
  537.  *
  538.  * Drivers can use this function to shut down the vblank interrupt handling when
  539.  * disabling a crtc. This function ensures that the latest vblank frame count is
  540.  * stored so that drm_vblank_on can restore it again.
  541.  *
  542.  * Drivers must use this function when the hardware vblank counter can get
  543.  * reset, e.g. when suspending.
  544.  *
  545.  * This is the native kms version of drm_vblank_off().
  546.  */
  547. void drm_crtc_vblank_off(struct drm_crtc *crtc)
  548. {
  549.         drm_vblank_off(crtc->dev, drm_crtc_index(crtc));
  550. }
  551. EXPORT_SYMBOL(drm_crtc_vblank_off);
  552.  
  553. /**
  554.  * drm_vblank_on - enable vblank events on a CRTC
  555.  * @dev: DRM device
  556.  * @crtc: CRTC in question
  557.  *
  558.  * This functions restores the vblank interrupt state captured with
  559.  * drm_vblank_off() again. Note that calls to drm_vblank_on() and
  560.  * drm_vblank_off() can be unbalanced and so can also be unconditionally called
  561.  * in driver load code to reflect the current hardware state of the crtc.
  562.  *
  563.  * This is the legacy version of drm_crtc_vblank_on().
  564.  */
  565. void drm_vblank_on(struct drm_device *dev, int crtc)
  566. {
  567.         struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
  568.         unsigned long irqflags;
  569.  
  570. }
  571. EXPORT_SYMBOL(drm_vblank_on);
  572.  
  573. /**
  574.  * drm_crtc_vblank_on - enable vblank events on a CRTC
  575.  * @crtc: CRTC in question
  576.  *
  577.  * This functions restores the vblank interrupt state captured with
  578.  * drm_vblank_off() again. Note that calls to drm_vblank_on() and
  579.  * drm_vblank_off() can be unbalanced and so can also be unconditionally called
  580.  * in driver load code to reflect the current hardware state of the crtc.
  581.  *
  582.  * This is the native kms version of drm_vblank_on().
  583.  */
  584. void drm_crtc_vblank_on(struct drm_crtc *crtc)
  585. {
  586.         drm_vblank_on(crtc->dev, drm_crtc_index(crtc));
  587. }
  588. EXPORT_SYMBOL(drm_crtc_vblank_on);
  589.  
  590. /**
  591.  * drm_vblank_pre_modeset - account for vblanks across mode sets
  592.  * @dev: DRM device
  593.  * @crtc: CRTC in question
  594.  *
  595.  * Account for vblank events across mode setting events, which will likely
  596.  * reset the hardware frame counter.
  597.  *
  598.  * This is done by grabbing a temporary vblank reference to ensure that the
  599.  * vblank interrupt keeps running across the modeset sequence. With this the
  600.  * software-side vblank frame counting will ensure that there are no jumps or
  601.  * discontinuities.
  602.  *
  603.  * Unfortunately this approach is racy and also doesn't work when the vblank
  604.  * interrupt stops running, e.g. across system suspend resume. It is therefore
  605.  * highly recommended that drivers use the newer drm_vblank_off() and
  606.  * drm_vblank_on() instead. drm_vblank_pre_modeset() only works correctly when
  607.  * using "cooked" software vblank frame counters and not relying on any hardware
  608.  * counters.
  609.  *
  610.  * Drivers must call drm_vblank_post_modeset() when re-enabling the same crtc
  611.  * again.
  612.  */
  613. void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
  614. {
  615. #if 0
  616.     /* vblank is not initialized (IRQ not installed ?) */
  617.     if (!dev->num_crtcs)
  618.         return;
  619.  
  620.         if (WARN_ON(crtc >= dev->num_crtcs))
  621.                 return;
  622.  
  623.     /*
  624.      * To avoid all the problems that might happen if interrupts
  625.      * were enabled/disabled around or between these calls, we just
  626.      * have the kernel take a reference on the CRTC (just once though
  627.      * to avoid corrupting the count if multiple, mismatch calls occur),
  628.      * so that interrupts remain enabled in the interim.
  629.      */
  630.         if (!vblank->inmodeset) {
  631.                 vblank->inmodeset = 0x1;
  632.         if (drm_vblank_get(dev, crtc) == 0)
  633.                         vblank->inmodeset |= 0x2;
  634.     }
  635. #endif
  636. }
  637. EXPORT_SYMBOL(drm_vblank_pre_modeset);
  638.  
  639. /**
  640.  * drm_vblank_post_modeset - undo drm_vblank_pre_modeset changes
  641.  * @dev: DRM device
  642.  * @crtc: CRTC in question
  643.  *
  644.  * This function again drops the temporary vblank reference acquired in
  645.  * drm_vblank_pre_modeset.
  646.  */
  647. void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
  648. {
  649. #if 0
  650.     unsigned long irqflags;
  651.  
  652.         /* vblank is not initialized (IRQ not installed ?), or has been freed */
  653.         if (!dev->num_crtcs)
  654.                 return;
  655.  
  656.         if (vblank->inmodeset) {
  657.         spin_lock_irqsave(&dev->vbl_lock, irqflags);
  658.                 dev->vblank_disable_allowed = true;
  659.         spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
  660.  
  661.                 if (vblank->inmodeset & 0x2)
  662.             drm_vblank_put(dev, crtc);
  663.  
  664.                 vblank->inmodeset = 0;
  665.     }
  666. #endif
  667. }
  668. EXPORT_SYMBOL(drm_vblank_post_modeset);
  669.  
  670.  
  671.