[Openchrome-devel] drm-openchrome: drivers/gpu/drm
James Simmons
jsimmons at kemper.freedesktop.org
Sun Dec 30 06:23:39 PST 2012
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 <jsimmons at 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;
More information about the Openchrome-devel
mailing list