/* * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sub license, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * 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 NON-INFRINGEMENT. IN NO EVENT SHALL * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS 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. */ #ifndef _VIA_DRV_H_ #define _VIA_DRV_H_ #include "drm_sman.h" #define DRIVER_AUTHOR "Various" #define DRIVER_NAME "via" #define DRIVER_DESC "VIA Unichrome / Pro" #include "via_verifier.h" /* * Registers go here. */ #define CMDBUF_ALIGNMENT_SIZE (0x100) #define CMDBUF_ALIGNMENT_MASK (0x0ff) /* defines for VIA 3D registers */ #define VIA_REG_STATUS 0x400 #define VIA_REG_TRANSET 0x43C #define VIA_REG_TRANSPACE 0x440 /* VIA_REG_STATUS(0x400): Engine Status */ #define VIA_CMD_RGTR_BUSY 0x00000080 /* Command Regulator is busy */ #define VIA_2D_ENG_BUSY 0x00000001 /* 2D Engine is busy */ #define VIA_3D_ENG_BUSY 0x00000002 /* 3D Engine is busy */ #define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */ #if defined(__linux__) #include "via_dmablit.h" /* * This define and all its references can be removed when * the DMA blit code has been implemented for FreeBSD. */ #define VIA_HAVE_DMABLIT 1 #define VIA_HAVE_CORE_MM 1 #define VIA_HAVE_FENCE 1 #define VIA_HAVE_BUFFER 1 #endif #define VIA_PCI_BUF_SIZE 60000 #define VIA_FIRE_BUF_SIZE 1024 #define VIA_NUM_IRQS 4 typedef struct drm_via_ring_buffer { drm_local_map_t map; char *virtual_start; } drm_via_ring_buffer_t; typedef uint32_t maskarray_t[5]; typedef struct drm_via_irq { atomic_t irq_received; uint32_t pending_mask; uint32_t enable_mask; wait_queue_head_t irq_queue; } drm_via_irq_t; typedef struct drm_via_private { drm_via_sarea_t *sarea_priv; drm_local_map_t *sarea; drm_local_map_t *fb; drm_local_map_t *mmio; unsigned long agpAddr; wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS]; char *dma_ptr; unsigned int dma_low; unsigned int dma_high; unsigned int dma_offset; uint32_t dma_wrap; volatile uint32_t *last_pause_ptr; volatile uint32_t *hw_addr_ptr; drm_via_ring_buffer_t ring; struct timeval last_vblank; int last_vblank_valid; unsigned usec_per_vblank; drm_via_state_t hc_state; char pci_buf[VIA_PCI_BUF_SIZE]; const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; uint32_t num_fire_offsets; int chipset; drm_via_irq_t via_irqs[VIA_NUM_IRQS]; unsigned num_irqs; maskarray_t *irq_masks; uint32_t irq_enable_mask; uint32_t irq_pending_mask; int *irq_map; /* Memory manager stuff */ #ifdef VIA_HAVE_CORE_MM unsigned int idle_fault; drm_sman_t sman; int vram_initialized; int agp_initialized; unsigned long vram_offset; unsigned long agp_offset; #endif #ifdef VIA_HAVE_DMABLIT drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; #endif uint32_t dma_diff; #ifdef VIA_HAVE_FENCE spinlock_t fence_lock; uint32_t emit_0_sequence; int have_idlelock; struct timer_list fence_timer; #endif } drm_via_private_t; enum via_family { VIA_OTHER = 0, /* Baseline */ VIA_PRO_GROUP_A, /* Another video engine and DMA commands */ VIA_DX9_0 /* Same video as pro_group_a, but 3D is unsupported */ }; /* VIA MMIO register access */ #define VIA_BASE ((dev_priv->mmio)) #define VIA_READ(reg) DRM_READ32(VIA_BASE, reg) #define VIA_WRITE(reg,val) DRM_WRITE32(VIA_BASE, reg, val) #define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg) #define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val) extern drm_ioctl_desc_t via_ioctls[]; extern int via_max_ioctl; extern int via_fb_init(DRM_IOCTL_ARGS); extern int via_mem_alloc(DRM_IOCTL_ARGS); extern int via_mem_free(DRM_IOCTL_ARGS); extern int via_agp_init(DRM_IOCTL_ARGS); extern int via_map_init(DRM_IOCTL_ARGS); extern int via_decoder_futex(DRM_IOCTL_ARGS); extern int via_wait_irq(DRM_IOCTL_ARGS); extern int via_dma_blit_sync( DRM_IOCTL_ARGS ); extern int via_dma_blit( DRM_IOCTL_ARGS ); extern int via_driver_load(drm_device_t *dev, unsigned long chipset); extern int via_driver_unload(drm_device_t *dev); extern int via_final_context(drm_device_t * dev, int context); extern int via_do_cleanup_map(drm_device_t * dev); extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence); extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS); extern void via_driver_irq_preinstall(drm_device_t * dev); extern void via_driver_irq_postinstall(drm_device_t * dev); extern void via_driver_irq_uninstall(drm_device_t * dev); extern int via_dma_cleanup(drm_device_t * dev); extern void via_init_command_verifier(void); extern int via_driver_dma_quiescent(drm_device_t * dev); extern void via_init_futex(drm_via_private_t *dev_priv); extern void via_cleanup_futex(drm_via_private_t *dev_priv); extern void via_release_futex(drm_via_private_t *dev_priv, int context); #ifdef VIA_HAVE_CORE_MM extern void via_reclaim_buffers_locked(drm_device_t *dev, struct file *filp); extern void via_lastclose(drm_device_t *dev); #else extern int via_init_context(drm_device_t * dev, int context); #endif #ifdef VIA_HAVE_DMABLIT extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq); extern void via_init_dmablit(drm_device_t *dev); #endif #ifdef VIA_HAVE_FENCE extern void via_fence_timer(unsigned long data); extern void via_poke_flush(drm_device_t * dev, uint32_t class); extern int via_fence_emit_sequence(drm_device_t * dev, uint32_t class, uint32_t flags, uint32_t * sequence, uint32_t * native_type); extern int via_fence_has_irq(struct drm_device * dev, uint32_t class, uint32_t flags); #endif #ifdef VIA_HAVE_BUFFER extern drm_ttm_backend_t *via_create_ttm_backend_entry(drm_device_t *dev); extern int via_fence_types(drm_buffer_object_t *bo, uint32_t *class, uint32_t *type); extern int via_invalidate_caches(drm_device_t *dev, uint32_t buffer_flags); extern int via_init_mem_type(drm_device_t *dev, uint32_t type, drm_mem_type_manager_t *man); extern uint32_t via_evict_mask(drm_buffer_object_t *bo); extern int via_move(drm_buffer_object_t *bo, int evict, int no_wait, drm_bo_mem_reg_t *new_mem); #endif #endif ' href='#n130'>130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
**************************************************************************/
/*
* Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#include "drmP.h"
#include "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"
/*
* Implements an intel sync flush operation.
*/
static void i915_perform_flush(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_class_manager *fc = &fm->class[0];
struct drm_fence_driver *driver = dev->driver->fence_driver;
uint32_t flush_flags = 0;
uint32_t flush_sequence = 0;
uint32_t i_status;
uint32_t diff;
uint32_t sequence;
int rwflush;
if (!dev_priv)
return;
if (fc->pending_exe_flush) {
sequence = READ_BREADCRUMB(dev_priv);
/*
* First update fences with the current breadcrumb.
*/
diff = (sequence - fc->last_exe_flush) & BREADCRUMB_MASK;
if (diff < driver->wrap_diff && diff != 0) {
drm_fence_handler(dev, 0, sequence, DRM_FENCE_TYPE_EXE);
}
if (dev_priv->fence_irq_on && !fc->pending_exe_flush) {
i915_user_irq_off(dev_priv);
dev_priv->fence_irq_on = 0;
} else if (!dev_priv->fence_irq_on && fc->pending_exe_flush) {
i915_user_irq_on(dev_priv);
dev_priv->fence_irq_on = 1;
}
}
if (dev_priv->flush_pending) {
i_status = READ_HWSP(dev_priv, 0);
if ((i_status & (1 << 12)) !=
(dev_priv->saved_flush_status & (1 << 12))) {
flush_flags = dev_priv->flush_flags;
flush_sequence = dev_priv->flush_sequence;
dev_priv->flush_pending = 0;
drm_fence_handler(dev, 0, flush_sequence, flush_flags);
}
}
rwflush = fc->pending_flush & DRM_I915_FENCE_TYPE_RW;
if (rwflush && !dev_priv->flush_pending) {
dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv);
dev_priv->flush_flags = fc->pending_flush;
dev_priv->saved_flush_status = READ_HWSP(dev_priv, 0);
I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
dev_priv->flush_pending = 1;
fc->pending_flush &= ~DRM_I915_FENCE_TYPE_RW;
}
if (dev_priv->flush_pending) {
i_status = READ_HWSP(dev_priv, 0);
if ((i_status & (1 << 12)) !=
(dev_priv->saved_flush_status & (1 << 12))) {
flush_flags = dev_priv->flush_flags;
flush_sequence = dev_priv->flush_sequence;
dev_priv->flush_pending = 0;
drm_fence_handler(dev, 0, flush_sequence, flush_flags);
}
}
}
void i915_poke_flush(struct drm_device * dev, uint32_t class)
{
struct drm_fence_manager *fm = &dev->fm;
unsigned long flags;
write_lock_irqsave(&fm->lock, flags);
i915_perform_flush(dev);
write_unlock_irqrestore(&fm->lock, flags);
}
int i915_fence_emit_sequence(struct drm_device * dev, uint32_t class, uint32_t flags,
uint32_t * sequence, uint32_t * native_type)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
if (!dev_priv)
return -EINVAL;
i915_emit_irq(dev);
*sequence = (uint32_t) dev_priv->counter;
*native_type = DRM_FENCE_TYPE_EXE;
if (flags & DRM_I915_FENCE_FLAG_FLUSHED)
*native_type |= DRM_I915_FENCE_TYPE_RW;
return 0;
}
void i915_fence_handler(struct drm_device * dev)
{
struct drm_fence_manager *fm = &dev->fm;
write_lock(&fm->lock);
i915_perform_flush(dev);
write_unlock(&fm->lock);
}
int i915_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags)
{
/*
* We have an irq that tells us when we have a new breadcrumb.
*/
if (class == 0 && flags == DRM_FENCE_TYPE_EXE)
return 1;
return 0;
}