drivers/gpu/drm/via/via_drv.h | 4 drivers/gpu/drm/via/via_irq.c | 353 +++++++++++++++++++----------------------- 2 files changed, 165 insertions(+), 192 deletions(-)
New commits: commit fc7134fc0df9fdcf11058e68f6252e7bc78ab3b6 Author: James Simmons <jsimm...@infradead.org> Date: Sat Dec 29 18:55:59 2012 -0500 Add in support for vblank for the second IGA diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index 06a5af5..88ee4d2 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -118,10 +118,6 @@ struct drm_via_private { void __iomem *last_pause_ptr; void __iomem *hw_addr_ptr; - struct timeval last_vblank; - int last_vblank_valid; - unsigned usec_per_vblank; - char pci_buf[VIA_PCI_BUF_SIZE]; const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; uint32_t num_fire_offsets; diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c index 99c4fb3..089f89d 100644 --- a/drivers/gpu/drm/via/via_irq.c +++ b/drivers/gpu/drm/via/via_irq.c @@ -1,5 +1,4 @@ -/* via_irq.c - * +/* * Copyright 2004 BEAM Ltd. * Copyright 2002 Tungsten Graphics, Inc. * Copyright 2005 Thomas Hellstrom. @@ -18,9 +17,8 @@ * * 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 - * BEAM LTD, TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) OR COPYRIGHT HOLDER(S) 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. @@ -35,25 +33,57 @@ * The refresh rate is also calculated for video playback sync purposes. */ -#include <drm/drmP.h> +#include "drmP.h" #include "via_drv.h" -/* VIA_REG_INTERRUPT */ -#define VIA_IRQ_GLOBAL (1 << 31) -#define VIA_IRQ_VBLANK_ENABLE (1 << 19) -#define VIA_IRQ_VBLANK_PENDING (1 << 3) -#define VIA_IRQ_HQV0_ENABLE (1 << 11) -#define VIA_IRQ_HQV1_ENABLE (1 << 25) -#define VIA_IRQ_HQV0_PENDING (1 << 9) -#define VIA_IRQ_HQV1_PENDING (1 << 10) -#define VIA_IRQ_DMA0_DD_ENABLE (1 << 20) -#define VIA_IRQ_DMA0_TD_ENABLE (1 << 21) -#define VIA_IRQ_DMA1_DD_ENABLE (1 << 22) -#define VIA_IRQ_DMA1_TD_ENABLE (1 << 23) -#define VIA_IRQ_DMA0_DD_PENDING (1 << 4) -#define VIA_IRQ_DMA0_TD_PENDING (1 << 5) -#define VIA_IRQ_DMA1_DD_PENDING (1 << 6) -#define VIA_IRQ_DMA1_TD_PENDING (1 << 7) +/* HW Interrupt Register Setting */ +#define INTERRUPT_CTRL_REG1 0x200 + +/* mmio 0x200 IRQ enable and status bits. */ +#define VIA_IRQ_ALL_ENABLE BIT(31) + +#define VIA_IRQ_IGA1_VBLANK_STATUS BIT(1) + +#define VIA_IRQ_IGA1_VSYNC_ENABLE BIT(19) +#define VIA_IRQ_IGA2_VSYNC_ENABLE BIT(17) +#define VIA_IRQ_IGA1_VSYNC_STATUS BIT(3) +#define VIA_IRQ_IGA2_VSYNC_STATUS BIT(15) + +#define VIA_IRQ_CAPTURE0_ACTIVE_ENABLE BIT(28) +#define VIA_IRQ_CAPTURE1_ACTIVE_ENABLE BIT(24) +#define VIA_IRQ_CAPTURE0_ACTIVE_STATUS BIT(12) +#define VIA_IRQ_CAPTURE1_ACTIVE_STATUS BIT(8) + +#define VIA_IRQ_HQV0_ENABLE BIT(25) +#define VIA_IRQ_HQV1_ENABLE BIT(9) +#define VIA_IRQ_HQV0_STATUS BIT(12) +#define VIA_IRQ_HQV1_STATUS BIT(10) + +#define VIA_IRQ_DMA0_DD_ENABLE BIT(20) +#define VIA_IRQ_DMA0_TD_ENABLE BIT(21) +#define VIA_IRQ_DMA1_DD_ENABLE BIT(22) +#define VIA_IRQ_DMA1_TD_ENABLE BIT(23) + +#define VIA_IRQ_DMA0_DD_STATUS BIT(4) +#define VIA_IRQ_DMA0_TD_STATUS BIT(5) +#define VIA_IRQ_DMA1_DD_STATUS BIT(6) +#define VIA_IRQ_DMA1_TD_STATUS BIT(7) + +#define INTR_ENABLE_MASK (VIA_IRQ_DMA0_TD_ENABLE | VIA_IRQ_DMA1_TD_ENABLE | \ + VIA_IRQ_DMA0_DD_ENABLE | VIA_IRQ_DMA1_DD_ENABLE | \ + VIA_IRQ_IGA1_VSYNC_ENABLE | VIA_IRQ_IGA2_VSYNC_ENABLE) + +#define INTERRUPT_ENABLE_MASK (VIA_IRQ_CAPTURE0_ACTIVE_ENABLE | VIA_IRQ_CAPTURE1_ACTIVE_ENABLE | \ + VIA_IRQ_HQV0_ENABLE | VIA_IRQ_HQV1_ENABLE | \ + INTR_ENABLE_MASK) + +#define INTR_STATUS_MASK (VIA_IRQ_DMA0_TD_STATUS | VIA_IRQ_DMA1_TD_STATUS | \ + VIA_IRQ_DMA0_DD_STATUS | VIA_IRQ_DMA1_DD_STATUS | \ + VIA_IRQ_IGA1_VSYNC_STATUS | VIA_IRQ_IGA2_VSYNC_STATUS) + +#define INTERRUPT_STATUS_MASK (VIA_IRQ_CAPTURE0_ACTIVE_STATUS | VIA_IRQ_CAPTURE1_ACTIVE_STATUS | \ + VIA_IRQ_HQV0_STATUS | VIA_IRQ_HQV1_STATUS | \ + INTR_STATUS_MASK) /* * Device-specific IRQs go here. This type might need to be extended with @@ -61,72 +91,48 @@ * Currently we activate the HQV interrupts of Unichrome Pro group A. */ -static maskarray_t via_pro_group_a_irqs[] = { - {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, - 0x00000000 }, - {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, - 0x00000000 }, - {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, - VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, - {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, - VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, -}; -static int via_num_pro_group_a = ARRAY_SIZE(via_pro_group_a_irqs); -static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3}; - static maskarray_t via_unichrome_irqs[] = { - {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, - VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, - {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, - VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008} + { VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_STATUS, VIA_PCI_DMA_CSR0, + VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, + { VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_STATUS, VIA_PCI_DMA_CSR1, + VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008} }; static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs); static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; - -static unsigned time_diff(struct timeval *now, struct timeval *then) -{ - return (now->tv_usec >= then->tv_usec) ? - now->tv_usec - then->tv_usec : - 1000000 - (then->tv_usec - now->tv_usec); -} +static maskarray_t via_pro_group_a_irqs[] = { + { VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_STATUS, 0x000003D0, 0x00008010, + 0x00000000 }, + { VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_STATUS, 0x000013D0, 0x00008010, + 0x00000000 }, + { VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_STATUS, VIA_PCI_DMA_CSR0, + VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008 }, + { VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_STATUS, VIA_PCI_DMA_CSR1, + VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008 }, +}; +static int via_num_pro_group_a = ARRAY_SIZE(via_pro_group_a_irqs); +static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3}; irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; struct drm_via_private *dev_priv = dev->dev_private; - u32 status; - int handled = 0; - struct timeval cur_vblank; drm_via_irq_t *cur_irq = dev_priv->via_irqs; + u32 status = VIA_READ(INTERRUPT_CTRL_REG1); + irqreturn_t ret = IRQ_NONE; int i; - status = VIA_READ(VIA_REG_INTERRUPT); - if (status & VIA_IRQ_VBLANK_PENDING) { - atomic_inc(&dev->_vblank_count[0]); - if (!(atomic_read(&dev->_vblank_count[0]) & 0x0F)) { - do_gettimeofday(&cur_vblank); - if (dev_priv->last_vblank_valid) { - dev_priv->usec_per_vblank = - time_diff(&cur_vblank, - &dev_priv->last_vblank) >> 4; - } - dev_priv->last_vblank = cur_vblank; - dev_priv->last_vblank_valid = 1; - } - /*if (!(atomic_read(&dev->_vblank_count[0]) & 0xFF)) { - DRM_DEBUG("US per vblank is: %u\n", - dev_priv->usec_per_vblank); - }*/ + if (status & VIA_IRQ_IGA1_VSYNC_STATUS) { drm_handle_vblank(dev, 0); - handled = 1; + ret = IRQ_HANDLED; } for (i = 0; i < dev_priv->num_irqs; ++i) { if (status & cur_irq->pending_mask) { atomic_inc(&cur_irq->irq_received); DRM_WAKEUP(&cur_irq->irq_queue); - handled = 1; + ret = IRQ_HANDLED; + if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) via_dmablit_handler(dev, 0, 1); else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) @@ -136,59 +142,123 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) } /* Acknowledge interrupts */ - VIA_WRITE(VIA_REG_INTERRUPT, status); + VIA_WRITE(INTERRUPT_CTRL_REG1, status); + return ret; +} +int +via_enable_vblank(struct drm_device *dev, int crtc) +{ + struct drm_via_private *dev_priv = dev->dev_private; + u32 status; - if (handled) - return IRQ_HANDLED; - else - return IRQ_NONE; + if (crtc < 0 || crtc >= dev->num_crtcs) { + DRM_ERROR("%s: Invalid crtc %d\n", __func__, crtc); + return -EINVAL; + } + + status = VIA_READ(INTERRUPT_CTRL_REG1); + if (crtc == 1) + status |= VIA_IRQ_IGA2_VSYNC_ENABLE | VIA_IRQ_IGA2_VSYNC_STATUS; + else if (!crtc) + status |= VIA_IRQ_IGA1_VSYNC_ENABLE | VIA_IRQ_IGA1_VSYNC_STATUS; + + svga_wcrt_mask(VGABASE, 0xF3, 0, BIT(1)); + svga_wcrt_mask(VGABASE, 0x11, BIT(4), BIT(4)); + + VIA_WRITE(INTERRUPT_CTRL_REG1, status); + return 0; } -static __inline__ void viadrv_acknowledge_irqs(struct drm_via_private *dev_priv) +void +via_disable_vblank(struct drm_device *dev, int crtc) { + struct drm_via_private *dev_priv = dev->dev_private; u32 status; - if (dev_priv) { - /* Acknowledge interrupts */ - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status | - dev_priv->irq_pending_mask); + if (crtc < 0 || crtc >= dev->num_crtcs) { + DRM_ERROR("%s: Invalid crtc %d\n", __func__, crtc); + return; } + + status = VIA_READ(INTERRUPT_CTRL_REG1); + if (crtc == 1) + status &= ~VIA_IRQ_IGA2_VSYNC_ENABLE; + else if (!crtc) + status &= ~VIA_IRQ_IGA1_VSYNC_ENABLE; + + VIA_WRITE(INTERRUPT_CTRL_REG1, status); } -int via_enable_vblank(struct drm_device *dev, int crtc) +void +via_driver_irq_preinstall(struct drm_device *dev) { struct drm_via_private *dev_priv = dev->dev_private; + drm_via_irq_t *cur_irq; u32 status; + int i; - if (crtc > dev->num_crtcs) { - DRM_ERROR("%s: bad crtc %d\n", __func__, crtc); - return -EINVAL; + cur_irq = dev_priv->via_irqs; + + if (dev_priv->engine_type != VIA_ENG_H1) { + dev_priv->irq_masks = via_pro_group_a_irqs; + dev_priv->num_irqs = via_num_pro_group_a; + dev_priv->irq_map = via_irqmap_pro_group_a; + + dev_priv->irq_pending_mask = INTR_STATUS_MASK; + dev_priv->irq_enable_mask = INTR_ENABLE_MASK; + } else { + dev_priv->irq_masks = via_unichrome_irqs; + dev_priv->num_irqs = via_num_unichrome; + dev_priv->irq_map = via_irqmap_unichrome; + + dev_priv->irq_pending_mask = INTERRUPT_STATUS_MASK; + dev_priv->irq_enable_mask = INTERRUPT_ENABLE_MASK; } - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE); + for (i = 0; i < dev_priv->num_irqs; ++i) { + atomic_set(&cur_irq->irq_received, 0); + cur_irq->enable_mask = dev_priv->irq_masks[i][0]; + cur_irq->pending_mask = dev_priv->irq_masks[i][1]; + DRM_INIT_WAITQUEUE(&cur_irq->irq_queue); + cur_irq++; - VIA_WRITE8(0x83d4, 0x11); - VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); + DRM_DEBUG("Initializing IRQ %d\n", i); + } + + /* Clear VSync interrupt regs */ + status = VIA_READ(INTERRUPT_CTRL_REG1); + VIA_WRITE(INTERRUPT_CTRL_REG1, status & ~(dev_priv->irq_enable_mask)); + /* Acknowledge interrupts */ + status = VIA_READ(INTERRUPT_CTRL_REG1); + VIA_WRITE(INTERRUPT_CTRL_REG1, status | dev_priv->irq_pending_mask); +} + +int +via_driver_irq_postinstall(struct drm_device *dev) +{ + struct drm_via_private *dev_priv = dev->dev_private; + u32 status = VIA_READ(INTERRUPT_CTRL_REG1); + + VIA_WRITE(INTERRUPT_CTRL_REG1, status | VIA_IRQ_ALL_ENABLE | + dev_priv->irq_enable_mask); return 0; } -void via_disable_vblank(struct drm_device *dev, int crtc) +void +via_driver_irq_uninstall(struct drm_device *dev) { struct drm_via_private *dev_priv = dev->dev_private; u32 status; - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE); - + /* Some more magic, oh for some data sheets ! */ VIA_WRITE8(0x83d4, 0x11); VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); - if (crtc > dev->num_crtcs) - DRM_ERROR("%s: bad crtc %d\n", __func__, crtc); + status = VIA_READ(INTERRUPT_CTRL_REG1); + VIA_WRITE(INTERRUPT_CTRL_REG1, status & + ~(VIA_IRQ_IGA1_VSYNC_ENABLE | dev_priv->irq_enable_mask)); } static int @@ -202,8 +272,6 @@ via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence maskarray_t *masks; int real_irq; - DRM_DEBUG("\n"); - if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; @@ -240,99 +308,8 @@ via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence return ret; } - -/* - * drm_dma.h hooks - */ - -void via_driver_irq_preinstall(struct drm_device *dev) -{ - struct drm_via_private *dev_priv = dev->dev_private; - u32 status; - drm_via_irq_t *cur_irq; - int i; - - DRM_DEBUG("dev_priv: %p\n", dev_priv); - if (dev_priv) { - cur_irq = dev_priv->via_irqs; - - dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; - dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; - - if (dev_priv->engine_type != VIA_ENG_H1) { - dev_priv->irq_masks = via_pro_group_a_irqs; - dev_priv->num_irqs = via_num_pro_group_a; - dev_priv->irq_map = via_irqmap_pro_group_a; - } else { - dev_priv->irq_masks = via_unichrome_irqs; - dev_priv->num_irqs = via_num_unichrome; - dev_priv->irq_map = via_irqmap_unichrome; - } - - for (i = 0; i < dev_priv->num_irqs; ++i) { - atomic_set(&cur_irq->irq_received, 0); - cur_irq->enable_mask = dev_priv->irq_masks[i][0]; - cur_irq->pending_mask = dev_priv->irq_masks[i][1]; - DRM_INIT_WAITQUEUE(&cur_irq->irq_queue); - dev_priv->irq_enable_mask |= cur_irq->enable_mask; - dev_priv->irq_pending_mask |= cur_irq->pending_mask; - cur_irq++; - - DRM_DEBUG("Initializing IRQ %d\n", i); - } - - dev_priv->last_vblank_valid = 0; - - /* Clear VSync interrupt regs */ - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status & - ~(dev_priv->irq_enable_mask)); - - /* Clear bits if they're already high */ - viadrv_acknowledge_irqs(dev_priv); - } -} - -int via_driver_irq_postinstall(struct drm_device *dev) -{ - struct drm_via_private *dev_priv = dev->dev_private; - u32 status; - - DRM_DEBUG("via_driver_irq_postinstall\n"); - if (!dev_priv) - return -EINVAL; - - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL - | dev_priv->irq_enable_mask); - - /* Some magic, oh for some data sheets ! */ - VIA_WRITE8(0x83d4, 0x11); - VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); - - return 0; -} - -void via_driver_irq_uninstall(struct drm_device *dev) -{ - struct drm_via_private *dev_priv = dev->dev_private; - u32 status; - - DRM_DEBUG("\n"); - if (dev_priv) { - - /* Some more magic, oh for some data sheets ! */ - - VIA_WRITE8(0x83d4, 0x11); - VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); - - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status & - ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask)); - } -} - -int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) +int +via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_via_irqwait_t *irqwait = data; struct timeval now; _______________________________________________ Openchrome-devel mailing list Openchrome-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/openchrome-devel