Exemple #1
0
static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
{
	struct drm_psb_private *dev_priv =
	    (struct drm_psb_private *)dev->dev_private;
	uint32_t pipestat;
	int wake = 0;
	int vsync_a = 0;
	int vsync_b = 0;
	static int pipe_a_on = 0;
	static int pipe_b_on = 0;
	int trigger_2d_blit = 0;

	pipestat = PSB_RVDC32(PSB_PIPEASTAT);
	if (pipestat & (1<<31)) {
		printk("buffer underrun 0x%x\n",underrun++);
		PSB_WVDC32(1<<31 | 1<<15, PSB_PIPEASTAT);
	}

	if ((!drm_psb_disable_vsync) && 
	    (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)) {
		atomic_inc(&dev->vbl_received);
		wake = 1;
		PSB_WVDC32(_PSB_VBLANK_INTERRUPT_ENABLE |
			   _PSB_VBLANK_CLEAR, PSB_PIPEASTAT);
	}

	if ((!drm_psb_disable_vsync) &&
	    (vdc_stat & _PSB_VSYNC_PIPEB_FLAG)) {
		atomic_inc(&dev->vbl_received2);
		wake = 1;
		PSB_WVDC32(_PSB_VBLANK_INTERRUPT_ENABLE |
			   _PSB_VBLANK_CLEAR, PSB_PIPEBSTAT);
	}

	if (vdc_stat & _PSB_HOTPLUG_INTERRUPT_FLAG) {
		// Clear 2nd status register
		spin_lock(&dev_priv->irqmask_lock);
		uint32_t hotplugstat = PSB_RVDC32(PORT_HOTPLUG_STATUS_REG);
		PSB_WVDC32(hotplugstat, PORT_HOTPLUG_STATUS_REG);
		spin_unlock(&dev_priv->irqmask_lock);
		
		hotplug_env = '1';
		wake_up_interruptible(&hotplug_queue);
	}

	PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
	(void)PSB_RVDC32(PSB_INT_IDENTITY_R);
	DRM_READMEMORYBARRIER();

	if (wake) {
		DRM_WAKEUP(&dev->vbl_queue);
		drm_vbl_send_signals(dev);
	}
}
Exemple #2
0
/*
 * MSVDX interrupt.
 */
static void psb_msvdx_interrupt(struct drm_device *dev, uint32_t msvdx_stat)
{
	struct drm_psb_private *dev_priv =
	    (struct drm_psb_private *)dev->dev_private;

	if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK) {
		/*Ideally we should we should never get to this */
		PSB_DEBUG_GENERAL
		    ("******MSVDX: msvdx_stat: 0x%x fence2_irq_on=%d ***** (MMU FAULT)\n",
		     msvdx_stat, dev_priv->fence2_irq_on);

		/* Pause MMU */
		PSB_WMSVDX32(MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_MASK,
			     MSVDX_MMU_CONTROL0);
		DRM_WRITEMEMORYBARRIER();

		/* Clear this interupt bit only */
		PSB_WMSVDX32(MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK,
			     MSVDX_INTERRUPT_CLEAR);
		PSB_RMSVDX32(MSVDX_INTERRUPT_CLEAR);
		DRM_READMEMORYBARRIER();

		dev_priv->msvdx_needs_reset = 1;
	} else if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_MASK) {
		PSB_DEBUG_GENERAL
		    ("******MSVDX: msvdx_stat: 0x%x fence2_irq_on=%d ***** (MTX)\n",
		     msvdx_stat, dev_priv->fence2_irq_on);

		/* Clear all interupt bits */
		PSB_WMSVDX32(0xffff, MSVDX_INTERRUPT_CLEAR);
		PSB_RMSVDX32(MSVDX_INTERRUPT_CLEAR);
		DRM_READMEMORYBARRIER();

		psb_msvdx_mtx_interrupt(dev);
	}
}
Exemple #3
0
/**
 * drm_vblank_count_and_time - retrieve "cooked" vblank counter value
 * and the system timestamp corresponding to that vblank counter value.
 *
 * @dev: DRM device
 * @crtc: which counter to retrieve
 * @vblanktime: Pointer to struct timeval to receive the vblank timestamp.
 *
 * Fetches the "cooked" vblank count value that represents the number of
 * vblank events since the system was booted, including lost events due to
 * modesetting activity. Returns corresponding system timestamp of the time
 * of the vblank interval that corresponds to the current value vblank counter
 * value.
 */
u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
			      struct timeval *vblanktime)
{
	u32 cur_vblank;

	/* Read timestamp from slot of _vblank_time ringbuffer
	 * that corresponds to current vblank count. Retry if
	 * count has incremented during readout. This works like
	 * a seqlock.
	 */
	do {
		cur_vblank = atomic_read(&dev->_vblank_count[crtc]);
		*vblanktime = vblanktimestamp(dev, crtc, cur_vblank);
		DRM_READMEMORYBARRIER();
	} while (cur_vblank != atomic_read(&dev->_vblank_count[crtc]));

	return cur_vblank;
}