1450N/A * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. 1450N/A * \author Rickard E. (Rik) Faith <faith@valinux.com> 1450N/A * \author Gareth Hughes <gareth@valinux.com> 1450N/A * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com 1450N/A * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. 1450N/A * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 1450N/A * Copyright (c) 2009, 2013, Intel Corporation. 1450N/A * Permission is hereby granted, free of charge, to any person obtaining a 1450N/A * copy of this software and associated documentation files (the "Software"), 1450N/A * to deal in the Software without restriction, including without limitation 1450N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1450N/A * and/or sell copies of the Software, and to permit persons to whom the 1450N/A * Software is furnished to do so, subject to the following conditions: 1450N/A * The above copyright notice and this permission notice (including the next 1450N/A * paragraph) shall be included in all copies or substantial portions of the 1450N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1450N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1450N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1450N/A * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 1450N/A * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1450N/A * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 1450N/A * OTHER DEALINGS IN THE SOFTWARE. 1450N/A /* Call ddi_intr_add_handler() */ 1450N/A /* Call ddi_intr_block_enable() for MSI */ 1450N/A /* Call ddi_intr_enable() for MSI non block enable */ 1450N/A /* setup the interrupt handler */ 1450N/A /* Disable all interrupts */ 1450N/A /* Call ddi_intr_block_disable() */ 1450N/A /* Call ddi_intr_remove_handler() */ 1450N/A /* Get supported interrupt types */ 1450N/A /* Get number of interrupts */ 1450N/A /* Get number of available interrupts */ 1450N/A /* Allocate memory for MSI interrupts */ 1450N/A * Get priority for first msi, assume remaining are all the same 1450N/A/* Access macro for slots in vblank timestamp ringbuffer. */ 1450N/A/* Retry timestamp calculation up to 3 times to satisfy 1450N/A * drm_timestamp_precision before giving up. 1450N/A/* Threshold in nanoseconds for detection of redundant 1450N/A * vblank irq in drm_handle_vblank(). 1 msec should be ok. 1450N/A * Get interrupt from bus id. 1450N/A * \param inode device inode. 1450N/A * \param file_priv DRM file private. 1450N/A * \param arg user argument, pointing to a drm_irq_busid structure. 1450N/A * \return zero on success or a negative number on failure. 1450N/A * Finds the PCI device with the specified bus id and gets its IRQ number. 1450N/A * This IOCTL is deprecated, and will now return EINVAL for any busid not equal 1450N/A * to that of the device that this DRM instance attached to. 1450N/A * Clear vblank timestamp buffer for a crtc. 1450N/A * Disable vblank irq's on crtc, make sure that last vblank count 1450N/A * of hardware and corresponding consistent software vblank counter 1450N/A * are preserved, even if there are any spurious vblank irq's after 1450N/A /* Prevent vblank irq processing while disabling vblank irqs, 1450N/A * so no updates of timestamps or count can happen after we've 1450N/A * disabled. Needed to prevent races in case of delayed irq's. 1450N/A /* No further vblank irq's will be processed after 1450N/A * this point. Get current hardware vblank count and 1450N/A * vblank timestamp, repeat until they are consistent. 1450N/A * FIXME: There is still a race condition here and in 1450N/A * drm_update_vblank_count() which can cause off-by-one 1450N/A * reinitialization of software vblank counter. If gpu 1450N/A * vblank counter doesn't increment exactly at the leading 1450N/A * edge of a vblank interval, then we can lose 1 count if 1450N/A * we happen to execute between start of vblank and the 1450N/A * delayed gpu counter increment. 1450N/A /* Compute time difference to stored timestamp of last vblank 1450N/A * as updated by last invocation of drm_handle_vblank() in vblank irq. 1450N/A /* If there is at least 1 msec difference between the last stored 1450N/A * timestamp and tvblank, then we are currently executing our 1450N/A * disable inside a new vblank interval, the tvblank timestamp 1450N/A * corresponds to this new vblank interval and the irq handler 1450N/A * for this vblank didn't run yet and won't run due to our disable. 1450N/A * Therefore we need to do the job of drm_handle_vblank() and 1450N/A * increment the vblank counter by one to account for this vblank. 1450N/A * Skip this step if there isn't any high precision timestamp 1450N/A * available. In that case we can't account for this and just 1450N/A /* Invalidate all timestamps while vblank irq's are off. */ 1450N/A /* Bail if the driver didn't call drm_vblank_init() */ 1450N/A DRM_INFO(
"Supports vblank timestamp caching Rev 1 (10.10.2010).\n");
1450N/A /* Driver specific high-precision vblank timestamping supported? */ 1450N/A /* Zero per-crtc vblank stuff */ 1450N/A * Initializes the IRQ related data. Installs the handler, calling the driver 1450N/A * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions 1450N/A * before and after the installation. 1450N/A /* Driver must have been initialized */ 1450N/A /* Before installing handler */ 1450N/A /* After installing handler */ 1450N/A * Uninstall the IRQ handler. 1450N/A * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq. 1450N/A * Wake up any waiters so they don't hang. 1450N/A * \param inode device inode. 1450N/A * \param file_priv DRM file private. 1450N/A * \param arg user argument, pointing to a drm_control structure. 1450N/A * \return zero on success or a negative number on failure. 1450N/A * Calls irq_install() or irq_uninstall() according to \p arg. 1450N/A /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */ 1450N/A * drm_calc_timestamping_constants - Calculate and 1450N/A * store various constants which are later needed by 1450N/A * vblank and swap-completion timestamping, e.g, by 1450N/A * drm_calc_vbltimestamp_from_scanoutpos(). 1450N/A * They are derived from crtc's true scanout timing, 1450N/A * so they take things like panel scaling or other 1450N/A * adjustments into account. 1450N/A * @crtc drm_crtc whose timestamp constants should be updated. 1450N/A /* Fields of interlaced scanout modes are only halve a frame duration. 1450N/A /* Convert scanline length in pixels and video dot clock to 1450N/A * line duration, frame duration and pixel duration in 1450N/A DRM_DEBUG(
"crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
1450N/A * drm_calc_vbltimestamp_from_scanoutpos - helper routine for kms 1450N/A * drivers. Implements calculation of exact vblank timestamps from 1450N/A * given drm_display_mode timings and current video scanout position 1450N/A * of a crtc. This can be called from within get_vblank_timestamp() 1450N/A * implementation of a kms driver to implement the actual timestamping. 1450N/A * Should return timestamps conforming to the OML_sync_control OpenML 1450N/A * extension specification. The timestamp corresponds to the end of 1450N/A * the vblank interval, aka start of scanout of topmost-leftmost display 1450N/A * pixel in the following video frame. 1450N/A * Requires support for optional dev->driver->get_scanout_position() 1450N/A * in kms driver, plus a bit of setup code to provide a drm_display_mode 1450N/A * that corresponds to the true scanout timing. 1450N/A * The current implementation only handles standard video modes. It 1450N/A * returns as no operation if a doublescan or interlaced video mode is 1450N/A * active. Higher level code is expected to handle this. 1450N/A * @crtc: Which crtc's vblank timestamp to retrieve. 1450N/A * @max_error: Desired maximum allowable error in timestamps (nanosecs). 1450N/A * On return contains true maximum error of timestamp. 1450N/A * @vblank_time: Pointer to struct timeval which should receive the timestamp. 1450N/A * @flags: Flags to pass to driver: 1450N/A * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. 1450N/A * @refcrtc: drm_crtc* of crtc which defines scanout timing. 1450N/A * Returns negative value on error, failure or if not supported in current 1450N/A * -EAGAIN - Temporary unavailable, e.g., called before initial modeset. 1450N/A * -ENOTSUPP - Function not supported in current display mode. 1450N/A * -EIO - Failed, e.g., due to failed scanout position query. 1450N/A * Returns or'ed positive status flags on success: 1450N/A * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping. 1450N/A * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval. 1450N/A /* Scanout position query not supported? Should not happen. */ 1450N/A /* Durations of frames, lines, pixels in nanoseconds. */ 1450N/A /* If mode timing undefined, just return as no-op: 1450N/A * Happens during initial modesetting of a crtc. 1450N/A /* Get current scanout position with system timestamp. 1450N/A * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times 1450N/A * if single query takes longer than max_error nanoseconds. 1450N/A * This guarantees a tight bound on maximum error if 1450N/A * code gets preempted or delayed for some reason. 1450N/A /* Disable preemption to make it very likely to 1450N/A * succeed in the first iteration even on PREEMPT_RT kernel. 1450N/A /* Get system timestamp before query. */ 1450N/A /* Get vertical and horizontal scanout pos. vpos, hpos. */ 1450N/A /* Get system timestamp after query. */ 1450N/A /* Return as no-op if scanout query unsupported or failed. */ 1450N/A /* Accept result with < max_error nsecs timing uncertainty. */ 1450N/A /* Return upper bound of timestamp precision error. */ 1450N/A /* Check if in vblank area: 1450N/A * vpos is >=0 in video scanout area, but negative 1450N/A * within vblank area, counting down the number of lines until 1450N/A /* Convert scanout position into elapsed time at raw_time query 1450N/A * since start of scanout at first display scanline. delta_ns 1450N/A * can be negative if start of scanout hasn't happened yet. 1450N/A /* Is vpos outside nominal vblank area, but less than 1450N/A * 1/100 of a frame height away from start of vblank? 1450N/A * If so, assume this isn't a massively delayed vblank 1450N/A * interrupt, but a vblank interrupt that fired a few 1450N/A * microseconds before true start of vblank. Compensate 1450N/A * by adding a full frame duration to the final timestamp. 1450N/A * Happens, e.g., on ATI R500, R600. 1450N/A * We only do this if DRM_CALLED_FROM_VBLIRQ. 1450N/A /* Signal this correction as "applied". */ 1450N/A /* Subtract time delta from raw timestamp to get final 1450N/A * vblank_time timestamp for end of vblank. 1450N/A DRM_DEBUG(
"crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
1450N/A * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent 1450N/A * @crtc: which crtc's vblank timestamp to retrieve 1450N/A * @tvblank: Pointer to target struct timeval which should receive the timestamp 1450N/A * @flags: Flags to pass to driver: 1450N/A * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. 1450N/A * Fetches the system timestamp corresponding to the time of the most recent 1450N/A * vblank interval on specified crtc. May call into kms-driver to 1450N/A * compute the timestamp with a high-precision GPU specific method. 1450N/A * Returns zero if timestamp originates from uncorrected do_gettimeofday() 1450N/A * call, i.e., it isn't very precisely locked to the true vblank. 1450N/A * Returns non-zero if timestamp is considered to be very precise. 1450N/A /* Define requested maximum error on timestamps (nanoseconds). */ 1450N/A /* Query driver if possible and precision timestamping enabled. */ 1450N/A /* GPU high precision timestamp query unsupported or failed. 1450N/A * Return gettimeofday timestamp as best estimate. 1450N/A * drm_vblank_count - retrieve "cooked" vblank counter value 1450N/A * @crtc: which counter to retrieve 1450N/A * Fetches the "cooked" vblank count value that represents the number of 1450N/A * vblank events since the system was booted, including lost events due to 1450N/A * drm_vblank_count_and_time - retrieve "cooked" vblank counter value 1450N/A * and the system timestamp corresponding to that vblank counter value. 1450N/A * @crtc: which counter to retrieve 1450N/A * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. 1450N/A * Fetches the "cooked" vblank count value that represents the number of 1450N/A * vblank events since the system was booted, including lost events due to 1450N/A * modesetting activity. Returns corresponding system timestamp of the time 1450N/A * of the vblank interval that corresponds to the current value vblank counter 1450N/A /* Read timestamp from slot of _vblank_time ringbuffer 1450N/A * that corresponds to current vblank count. Retry if 1450N/A * count has incremented during readout. This works like 1450N/A * drm_send_vblank_event - helper to send vblank event after pageflip 1450N/A * Updates sequence # and timestamp on event, and sends it to userspace. 1450N/A * Caller must hold event lock. 1450N/A * drm_update_vblank_count - update the master vblank counter 1450N/A * Call back into the driver to update the appropriate vblank counter 1450N/A * (specified by @crtc). Deal with wraparound, if it occurred, and 1450N/A * update the last read value so we can deal with wraparound on the next 1450N/A * Only necessary when going from off->on, to account for frames we 1450N/A * didn't get an interrupt for. 1450N/A * Note: caller must hold dev->vbl_lock since this reads & writes 1450N/A * Interrupts were disabled prior to this call, so deal with counter 1450N/A * NOTE! It's possible we lost a full dev->max_vblank_count events 1450N/A * here if the register is small or we had vblank interrupts off for 1450N/A * We repeat the hardware vblank counter & timestamp query until 1450N/A * we get consistent results. This to prevent races between gpu 1450N/A * updating its hardware counter while we are retrieving the 1450N/A * corresponding vblank timestamp. 1450N/A /* Deal with counter wrap */ 1450N/A /* Reinitialize corresponding vblank timestamp if high-precision query 1450N/A * available. Skip this step if query unsupported or failed. Will 1450N/A * reinitialize delayed at next vblank interrupt in that case. 1450N/A * drm_vblank_get - get a reference count on vblank events 1450N/A * Acquire a reference count on vblank events to avoid having them disabled 1450N/A * Zero on success, nonzero on failure. 1450N/A /* Going from 0->1 means we have to enable interrupts again */ 1450N/A * drm_vblank_put - give up ownership of vblank events 1450N/A * @crtc: which counter to give up 1450N/A * Release ownership of a given vblank counter, turning off interrupts 1450N/A /* Last user schedules interrupt disable */ 1450N/A * drm_vblank_off - disable vblank events on a CRTC 1450N/A * Caller must hold event lock. 1450N/A /* Send any queued vblank events, lest the natives grow disquiet */ 1450N/A * drm_vblank_pre_modeset - account for vblanks across mode sets 1450N/A * @post: post or pre mode set? 1450N/A * Account for vblank events across mode setting events, which will likely 1450N/A * reset the hardware frame counter. 1450N/A /* vblank is not initialized (IRQ not installed ?) */ 1450N/A * To avoid all the problems that might happen if interrupts 1450N/A * have the kernel take a reference on the CRTC (just once though 1450N/A * to avoid corrupting the count if multiple, mismatch calls occur), 1450N/A * so that interrupts remain enabled in the interim. 1450N/A /* vblank is not initialized (IRQ not installed ?), or has been freed */ 1450N/A * drm_modeset_ctl - handle vblank event counter changes across mode switch 1450N/A * @DRM_IOCTL_ARGS: standard ioctl arguments 1450N/A * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET 1450N/A * ioctls around modesetting so that any lost vblank events are accounted for. 1450N/A * Generally the counter will reset across mode sets. If interrupts are 1450N/A * enabled around this call, we don't have to do anything since the counter 1450N/A * will have already been incremented. 1450N/A /* If drm_vblank_init() hasn't been called yet, just no-op */ 1450N/A /* KMS drivers handle this internally */ 1450N/A /* drm_handle_vblank_events will call drm_vblank_put */ 1450N/A * \param inode device inode. 1450N/A * \param file_priv DRM file private. 1450N/A * \param data user argument, pointing to a drm_wait_vblank structure. 1450N/A * \return zero on success or a negative number on failure. 1450N/A * This function enables the vblank interrupt on the pipe requested, then 1450N/A * sleeps waiting for the requested sequence number to occur, and drops 1450N/A * the vblank interrupt refcount afterwards. (vblank irq disable follows that 1450N/A * after a timeout with no further vblank waits scheduled). 1450N/A /* must hold on to the vblank ref until the event fires 1450N/A * drm_vblank_put will be called asynchronously 1450N/A * drm_handle_vblank - handle a vblank event 1450N/A * @crtc: where this event occurred 1450N/A * Drivers should call this routine in their vblank interrupt handlers to 1450N/A * update the vblank counter and send any signals that may be pending. 1450N/A /* Need timestamp lock to prevent concurrent execution with 1450N/A * or corrupted timestamps and vblank counts. 1450N/A /* Vblank irq handling disabled. Nothing to do. */ 1450N/A /* Fetch corresponding timestamp for this vblank interval from 1450N/A * driver and store it in proper slot of timestamp ringbuffer. 1450N/A /* Get current timestamp and count. */ 1450N/A /* Compute time difference to timestamp of last vblank */ 1450N/A /* Update vblank timestamp and count if at least 1450N/A * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds 1450N/A * difference between last stored timestamp and current 1450N/A * timestamp. A smaller difference means basically 1450N/A * identical timestamps. Happens if this vblank has 1450N/A * been already processed and this is a redundant call, 1450N/A * e.g., due to spurious vblank interrupts. We need to 1450N/A * ignore those for accounting. 1450N/A /* Store new timestamp in ringbuffer. */ 1450N/A /* Increment cooked vblank count. This also atomically commits 1450N/A * the timestamp computed above.