diff options
author | Dave Airlie <airlied@redhat.com> | 2008-01-25 15:27:53 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2008-01-25 15:27:53 +1000 |
commit | e7a41d7f5be49241480a20eb733262712e0f8dcb (patch) | |
tree | 801c7eadf769db981dfb8a900a24ef48542958a6 /shared-core | |
parent | fb9ea12438de95a6ac085879e079055eaea3daf8 (diff) | |
parent | bfdddd218ec3e7ce3f8e765b93af35661a7bf0fd (diff) |
Merge remote branch 'origin/master' into modesetting-101
Conflicts:
linux-core/drm_bo.c
linux-core/drm_drv.c
shared-core/drm.h
shared-core/i915_dma.c
shared-core/i915_drv.h
shared-core/i915_irq.c
shared-core/radeon_irq.c
Diffstat (limited to 'shared-core')
45 files changed, 1417 insertions, 954 deletions
diff --git a/shared-core/drm.h b/shared-core/drm.h index f8d44048..7aea3033 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -555,6 +555,21 @@ union drm_wait_vblank { struct drm_wait_vblank_reply reply; }; +enum drm_modeset_ctl_cmd { + _DRM_PRE_MODESET = 1, + _DRM_POST_MODESET = 2, +}; + +/** + * DRM_IOCTL_MODESET_CTL ioctl argument type + * + * \sa drmModesetCtl(). + */ +struct drm_modeset_ctl { + unsigned long arg; + enum drm_modeset_ctl_cmd cmd; +}; + /** * DRM_IOCTL_AGP_ENABLE ioctl argument type. * @@ -662,6 +677,10 @@ struct drm_fence_arg { #define DRM_BO_FLAG_EXE (1ULL << 2) /* + * All of the bits related to access mode + */ +#define DRM_BO_MASK_ACCESS (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE) +/* * Status flags. Can be read to determine the actual state of a buffer. * Can also be set in the buffer mask before validation. */ @@ -701,7 +720,14 @@ struct drm_fence_arg { */ #define DRM_BO_FLAG_NO_MOVE (1ULL << 8) -/* Mask: Make sure the buffer is in cached memory when mapped +/* Mask: Make sure the buffer is in cached memory when mapped. In conjunction + * with DRM_BO_FLAG_CACHED it also allows the buffer to be bound into the GART + * with unsnooped PTEs instead of snooped, by using chipset-specific cache + * flushing at bind time. A better name might be DRM_BO_FLAG_TT_UNSNOOPED, + * as the eviction to local memory (TTM unbind) on map is just a side effect + * to prevent aggressive cache prefetch from the GPU disturbing the cache + * management that the DRM is doing. + * * Flags: Acknowledge. * Buffers allocated with this flag should not be used for suballocators * This type may have issues on CPUs with over-aggressive caching @@ -741,18 +767,49 @@ struct drm_fence_arg { #define DRM_BO_FLAG_MEM_PRIV4 (1ULL << 31) /* We can add more of these now with a 64-bit flag type */ -/* Memory flag mask */ +/* + * This is a mask covering all of the memory type flags; easier to just + * use a single constant than a bunch of | values. It covers + * DRM_BO_FLAG_MEM_LOCAL through DRM_BO_FLAG_MEM_PRIV4 + */ #define DRM_BO_MASK_MEM 0x00000000FF000000ULL -#define DRM_BO_MASK_MEMTYPE 0x00000000FF0800A0ULL - +/* + * This adds all of the CPU-mapping options in with the memory + * type to label all bits which change how the page gets mapped + */ +#define DRM_BO_MASK_MEMTYPE (DRM_BO_MASK_MEM | \ + DRM_BO_FLAG_CACHED_MAPPED | \ + DRM_BO_FLAG_CACHED | \ + DRM_BO_FLAG_MAPPABLE) + /* Driver-private flags */ #define DRM_BO_MASK_DRIVER 0xFFFF000000000000ULL -/* Don't block on validate and map */ +/* + * Don't block on validate and map. Instead, return EBUSY. + */ #define DRM_BO_HINT_DONT_BLOCK 0x00000002 -/* Don't place this buffer on the unfenced list.*/ +/* + * Don't place this buffer on the unfenced list. This means + * that the buffer will not end up having a fence associated + * with it as a result of this operation + */ #define DRM_BO_HINT_DONT_FENCE 0x00000004 +/* + * Sleep while waiting for the operation to complete. + * Without this flag, the kernel will, instead, spin + * until this operation has completed. I'm not sure + * why you would ever want this, so please always + * provide DRM_BO_HINT_WAIT_LAZY to any operation + * which may block + */ #define DRM_BO_HINT_WAIT_LAZY 0x00000008 +/* + * The client has compute relocations refering to this buffer using the + * offset in the presumed_offset field. If that offset ends up matching + * where this buffer lands, the kernel is free to skip executing those + * relocations + */ #define DRM_BO_HINT_PRESUMED_OFFSET 0x00000010 #define DRM_BO_INIT_MAGIC 0xfe769812 @@ -774,7 +831,7 @@ struct drm_bo_info_req { }; struct drm_bo_create_req { - uint64_t mask; + uint64_t flags; uint64_t size; uint64_t buffer_start; unsigned int hint; @@ -790,7 +847,7 @@ struct drm_bo_create_req { struct drm_bo_info_rep { uint64_t flags; - uint64_t mask; + uint64_t proposed_flags; uint64_t size; uint64_t offset; uint64_t arg_handle; @@ -1046,6 +1103,7 @@ struct drm_mode_mode_cmd { #define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) +#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) @@ -1118,7 +1176,6 @@ struct drm_mode_mode_cmd { #define DRM_IOCTL_BO_WAIT_IDLE DRM_IOWR(0xd5, struct drm_bo_map_wait_idle_arg) #define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg) - #define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) #define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) #define DRM_IOCTL_MODE_GETOUTPUT DRM_IOWR(0xA2, struct drm_mode_get_output) @@ -1133,6 +1190,7 @@ struct drm_mode_mode_cmd { #define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xAA, struct drm_mode_mode_cmd) #define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAB, struct drm_mode_get_property) + /*@}*/ /** diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt index a76413d4..7ef34dfd 100644 --- a/shared-core/drm_pciids.txt +++ b/shared-core/drm_pciids.txt @@ -139,6 +139,101 @@ 0x1002 0x5e4c CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 SE" 0x1002 0x5e4d CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700" 0x1002 0x5e4f CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 SE" +0x1002 0x7100 CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800" +0x1002 0x7101 CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1800 XT" +0x1002 0x7102 CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1800" +0x1002 0x7103 CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V7200" +0x1002 0x7104 CHIP_R520|RADEON_NEW_MEMMAP "ATI FireGL V7200" +0x1002 0x7105 CHIP_R520|RADEON_NEW_MEMMAP "ATI FireGL V5300" +0x1002 0x7106 CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V7100" +0x1002 0x7108 CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800" +0x1002 0x7109 CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800" +0x1002 0x710A CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800" +0x1002 0x710B CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800" +0x1002 0x710C CHIP_R520|RADEON_NEW_MEMMAP "ATI Radeon X1800" +0x1002 0x710E CHIP_R520|RADEON_NEW_MEMMAP "ATI FireGL V7300" +0x1002 0x710F CHIP_R520|RADEON_NEW_MEMMAP "ATI FireGL V7350" +0x1002 0x7140 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1600" +0x1002 0x7141 CHIP_RV515|RADEON_NEW_MEMMAP "ATI RV505" +0x1002 0x7142 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300/X1550" +0x1002 0x7143 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1550" +0x1002 0x7144 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI M54-GL" +0x1002 0x7145 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1400" +0x1002 0x7146 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300/X1550" +0x1002 0x7147 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1550 64-bit" +0x1002 0x7149 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1300" +0x1002 0x714A CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1300" +0x1002 0x714B CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1300" +0x1002 0x714C CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1300" +0x1002 0x714D CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300" +0x1002 0x714E CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300" +0x1002 0x714F CHIP_RV515|RADEON_NEW_MEMMAP "ATI RV505" +0x1002 0x7151 CHIP_RV515|RADEON_NEW_MEMMAP "ATI RV505" +0x1002 0x7152 CHIP_RV515|RADEON_NEW_MEMMAP "ATI FireGL V3300" +0x1002 0x7153 CHIP_RV515|RADEON_NEW_MEMMAP "ATI FireGL V3350" +0x1002 0x715E CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300" +0x1002 0x715F CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1550 64-bit" +0x1002 0x7180 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300/X1550" +0x1002 0x7181 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1600" +0x1002 0x7183 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300/X1550" +0x1002 0x7186 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1450" +0x1002 0x7187 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300/X1550" +0x1002 0x7188 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X2300" +0x1002 0x718A CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X2300" +0x1002 0x718B CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1350" +0x1002 0x718C CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1350" +0x1002 0x718D CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1450" +0x1002 0x718F CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1300" +0x1002 0x7193 CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1550" +0x1002 0x7196 CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1350" +0x1002 0x719B CHIP_RV515|RADEON_NEW_MEMMAP "ATI FireMV 2250" +0x1002 0x719F CHIP_RV515|RADEON_NEW_MEMMAP "ATI Radeon X1550 64-bit" +0x1002 0x71C0 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1600" +0x1002 0x71C1 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1650" +0x1002 0x71C2 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1600" +0x1002 0x71C3 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1600" +0x1002 0x71C4 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V5200" +0x1002 0x71C5 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1600" +0x1002 0x71C6 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1650" +0x1002 0x71C7 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1650" +0x1002 0x71CD CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1600" +0x1002 0x71CE CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X1300 XT/X1600 Pro" +0x1002 0x71D2 CHIP_RV530|RADEON_NEW_MEMMAP "ATI FireGL V3400" +0x1002 0x71D4 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V5250" +0x1002 0x71D5 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1700" +0x1002 0x71D6 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1700 XT" +0x1002 0x71DA CHIP_RV530|RADEON_NEW_MEMMAP "ATI FireGL V5200" +0x1002 0x71DE CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1700" +0x1002 0x7200 CHIP_RV530|RADEON_NEW_MEMMAP "ATI Radeon X2300HD" +0x1002 0x7210 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon HD 2300" +0x1002 0x7211 CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon HD 2300" +0x1002 0x7240 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1950" +0x1002 0x7243 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900" +0x1002 0x7244 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1950" +0x1002 0x7245 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900" +0x1002 0x7246 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900" +0x1002 0x7247 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900" +0x1002 0x7248 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900" +0x1002 0x7249 CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900" +0x1002 0x724A CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900" +0x1002 0x724B CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900" +0x1002 0x724C CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900" +0x1002 0x724D CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900" +0x1002 0x724E CHIP_R580|RADEON_NEW_MEMMAP "ATI AMD Stream Processor" +0x1002 0x724F CHIP_R580|RADEON_NEW_MEMMAP "ATI Radeon X1900" +0x1002 0x7280 CHIP_RV570|RADEON_NEW_MEMMAP "ATI Radeon X1950" +0x1002 0x7281 CHIP_RV560|RADEON_NEW_MEMMAP "ATI RV560" +0x1002 0x7283 CHIP_RV560|RADEON_NEW_MEMMAP "ATI RV560" +0x1002 0x7284 CHIP_R580|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X1900" +0x1002 0x7287 CHIP_RV560|RADEON_NEW_MEMMAP "ATI RV560" +0x1002 0x7288 CHIP_RV570|RADEON_NEW_MEMMAP "ATI Radeon X1950 GT" +0x1002 0x7289 CHIP_RV570|RADEON_NEW_MEMMAP "ATI RV570" +0x1002 0x728B CHIP_RV570|RADEON_NEW_MEMMAP "ATI RV570" +0x1002 0x728C CHIP_RV570|RADEON_NEW_MEMMAP "ATI ATI FireGL V7400" +0x1002 0x7290 CHIP_RV560|RADEON_NEW_MEMMAP "ATI RV560" +0x1002 0x7291 CHIP_RV560|RADEON_NEW_MEMMAP "ATI Radeon X1650" +0x1002 0x7293 CHIP_RV560|RADEON_NEW_MEMMAP "ATI Radeon X1650" +0x1002 0x7297 CHIP_RV560|RADEON_NEW_MEMMAP "ATI RV560" 0x1002 0x7834 CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP "ATI Radeon RS350 9000/9100 IGP" 0x1002 0x7835 CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon RS350 Mobility IGP" @@ -236,6 +331,7 @@ 0x1106 0x3343 0 "VIA P4M890" 0x1106 0x3230 VIA_DX9_0 "VIA K8M890" 0x1106 0x3157 VIA_PRO_GROUP_A "VIA CX700" +0x1106 0x3371 VIA_DX9_0 "VIA P4M900 / VN896" [i810] 0x8086 0x7121 0 "Intel i810 GMCH" @@ -285,6 +381,7 @@ 0x8086 0x3582 CHIP_I8XX "Intel i852GM/i855GM GMCH" 0x8086 0x2572 CHIP_I8XX "Intel i865G GMCH" 0x8086 0x2582 CHIP_I9XX|CHIP_I915 "Intel i915G" +0x8086 0x258a CHIP_I9XX|CHIP_I915 "Intel E7221 (i915)" 0x8086 0x2592 CHIP_I9XX|CHIP_I915 "Intel i915GM" 0x8086 0x2772 CHIP_I9XX|CHIP_I915 "Intel i945G" 0x8086 0x27A2 CHIP_I9XX|CHIP_I915 "Intel i945GM" @@ -298,6 +395,7 @@ 0x8086 0x29C2 CHIP_I9XX|CHIP_I915 "Intel G33" 0x8086 0x29B2 CHIP_I9XX|CHIP_I915 "Intel Q35" 0x8086 0x29D2 CHIP_I9XX|CHIP_I915 "Intel Q33" +0x8086 0x2A42 CHIP_I9XX|CHIP_I965 "Intel Integrated Graphics Device" [imagine] 0x105d 0x2309 IMAGINE_128 "Imagine 128" diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 4c1a07ac..66d1b13d 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -718,9 +718,15 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, unsigned index; unsigned long new_cmd_offset; u32 val; - int ret; + int ret, i; + int buf_index = -1; + + for (i = 0; i <= num_buffers; i++) + if (buffers[i].buffer) + if (reloc[2] == buffers[i].buffer->base.hash.key) + buf_index = i; - if (reloc[2] >= num_buffers) { + if (buf_index == -1) { DRM_ERROR("Illegal relocation buffer %08X\n", reloc[2]); return -EINVAL; } @@ -729,7 +735,7 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, * Short-circuit relocations that were correctly * guessed by the client */ - if (buffers[reloc[2]].presumed_offset_correct && !DRM_DEBUG_RELOCATION) + if (buffers[buf_index].presumed_offset_correct && !DRM_DEBUG_RELOCATION) return 0; new_cmd_offset = reloc[0]; @@ -756,17 +762,17 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, relocatee->page_offset = (relocatee->offset & PAGE_MASK); } - val = buffers[reloc[2]].buffer->offset; + val = buffers[buf_index].buffer->offset; index = (reloc[0] - relocatee->page_offset) >> 2; /* add in validate */ val = val + reloc[1]; if (DRM_DEBUG_RELOCATION) { - if (buffers[reloc[2]].presumed_offset_correct && + if (buffers[buf_index].presumed_offset_correct && relocatee->data_page[index] != val) { DRM_DEBUG ("Relocation mismatch source %d target %d buffer %d user %08x kernel %08x\n", - reloc[0], reloc[1], reloc[2], relocatee->data_page[index], val); + reloc[0], reloc[1], buf_index, relocatee->data_page[index], val); } } relocatee->data_page[index] = val; @@ -775,94 +781,79 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, int i915_process_relocs(struct drm_file *file_priv, uint32_t buf_handle, - uint32_t *reloc_buf_handle, + uint32_t __user **reloc_user_ptr, struct i915_relocatee_info *relocatee, struct drm_i915_validate_buffer *buffers, uint32_t num_buffers) { - struct drm_device *dev = file_priv->minor->dev; - struct drm_buffer_object *reloc_list_object; - uint32_t cur_handle = *reloc_buf_handle; - uint32_t *reloc_page; - int ret, reloc_is_iomem, reloc_stride; - uint32_t num_relocs, reloc_offset, reloc_end, reloc_page_offset, next_offset, cur_offset; - struct drm_bo_kmap_obj reloc_kmap; - - memset(&reloc_kmap, 0, sizeof(reloc_kmap)); - - mutex_lock(&dev->struct_mutex); - reloc_list_object = drm_lookup_buffer_object(file_priv, cur_handle, 1); - mutex_unlock(&dev->struct_mutex); - if (!reloc_list_object) - return -EINVAL; + int ret, reloc_stride; + uint32_t cur_offset; + uint32_t reloc_count; + uint32_t reloc_type; + uint32_t reloc_buf_size; + uint32_t *reloc_buf = NULL; + int i; - ret = drm_bo_kmap(reloc_list_object, 0, 1, &reloc_kmap); + /* do a copy from user from the user ptr */ + ret = get_user(reloc_count, *reloc_user_ptr); if (ret) { DRM_ERROR("Could not map relocation buffer.\n"); goto out; } - reloc_page = drm_bmo_virtual(&reloc_kmap, &reloc_is_iomem); - num_relocs = reloc_page[0] & 0xffff; + ret = get_user(reloc_type, (*reloc_user_ptr)+1); + if (ret) { + DRM_ERROR("Could not map relocation buffer.\n"); + goto out; + } - if ((reloc_page[0] >> 16) & 0xffff) { + if (reloc_type != 0) { DRM_ERROR("Unsupported relocation type requested\n"); + ret = -EINVAL; goto out; } - /* get next relocate buffer handle */ - *reloc_buf_handle = reloc_page[1]; - reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */ - - DRM_DEBUG("num relocs is %d, next is %08X\n", num_relocs, reloc_page[1]); - - reloc_page_offset = 0; - reloc_offset = I915_RELOC_HEADER * sizeof(uint32_t); - reloc_end = reloc_offset + (num_relocs * reloc_stride); - - do { - next_offset = drm_bo_offset_end(reloc_offset, reloc_end); + reloc_buf_size = (I915_RELOC_HEADER + (reloc_count * I915_RELOC0_STRIDE)) * sizeof(uint32_t); + reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); + if (!reloc_buf) { + DRM_ERROR("Out of memory for reloc buffer\n"); + ret = -ENOMEM; + goto out; + } - do { - cur_offset = ((reloc_offset + reloc_page_offset) & ~PAGE_MASK) / sizeof(uint32_t); - ret = i915_apply_reloc(file_priv, num_buffers, - buffers, relocatee, &reloc_page[cur_offset]); - if (ret) - goto out; + if (copy_from_user(reloc_buf, *reloc_user_ptr, reloc_buf_size)) { + ret = -EFAULT; + goto out; + } - reloc_offset += reloc_stride; - } while (reloc_offset < next_offset); + /* get next relocate buffer handle */ + *reloc_user_ptr = (uint32_t *)*(unsigned long *)&reloc_buf[2]; - drm_bo_kunmap(&reloc_kmap); + reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */ - reloc_offset = next_offset; - if (reloc_offset != reloc_end) { - ret = drm_bo_kmap(reloc_list_object, reloc_offset >> PAGE_SHIFT, 1, &reloc_kmap); - if (ret) { - DRM_ERROR("Could not map relocation buffer.\n"); - goto out; - } + DRM_DEBUG("num relocs is %d, next is %p\n", reloc_count, *reloc_user_ptr); - reloc_page = drm_bmo_virtual(&reloc_kmap, &reloc_is_iomem); - reloc_page_offset = reloc_offset & ~PAGE_MASK; - } + for (i = 0; i < reloc_count; i++) { + cur_offset = I915_RELOC_HEADER + (i * I915_RELOC0_STRIDE); + + ret = i915_apply_reloc(file_priv, num_buffers, buffers, + relocatee, reloc_buf + cur_offset); + if (ret) + goto out; + } - } while (reloc_offset != reloc_end); out: + + if (reloc_buf) + kfree(reloc_buf); drm_bo_kunmap(&relocatee->kmap); relocatee->data_page = NULL; - drm_bo_kunmap(&reloc_kmap); - - mutex_lock(&dev->struct_mutex); - drm_bo_usage_deref_locked(&reloc_list_object); - mutex_unlock(&dev->struct_mutex); - return ret; } static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, - drm_handle_t buf_reloc_handle, + uint32_t __user *reloc_user_ptr, struct drm_i915_validate_buffer *buffers, uint32_t buf_count) { @@ -896,8 +887,8 @@ static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, goto out_err; } - while (buf_reloc_handle) { - ret = i915_process_relocs(file_priv, buf_handle, &buf_reloc_handle, &relocatee, buffers, buf_count); + while (reloc_user_ptr) { + ret = i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, &relocatee, buffers, buf_count); if (ret) { DRM_ERROR("process relocs failed\n"); break; @@ -927,8 +918,8 @@ int i915_validate_buffer_list(struct drm_file *file_priv, int ret = 0; unsigned buf_count = 0; struct drm_device *dev = file_priv->minor->dev; - uint32_t buf_reloc_handle, buf_handle; - + uint32_t buf_handle; + uint32_t __user *reloc_user_ptr; do { if (buf_count >= *num_buffers) { @@ -963,21 +954,19 @@ int i915_validate_buffer_list(struct drm_file *file_priv, } buf_handle = req->bo_req.handle; - buf_reloc_handle = arg.reloc_handle; + reloc_user_ptr = (uint32_t *)(unsigned long)arg.reloc_ptr; - if (buf_reloc_handle) { - ret = i915_exec_reloc(file_priv, buf_handle, buf_reloc_handle, buffers, buf_count); + if (reloc_user_ptr) { + ret = i915_exec_reloc(file_priv, buf_handle, reloc_user_ptr, buffers, buf_count); if (ret) goto out_err; DRM_MEMORYBARRIER(); } rep.ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, - req->bo_req.fence_class, - req->bo_req.flags, - req->bo_req.mask, + req->bo_req.flags, req->bo_req.mask, req->bo_req.hint, - 0, + req->bo_req.fence_class, 0, &rep.bo_info, &buffers[buf_count].buffer); @@ -1092,7 +1081,8 @@ static int i915_execbuffer(struct drm_device *dev, void *data, sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); /* fence */ - ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence); + ret = drm_fence_buffer_objects(dev, NULL, fence_arg->flags, + NULL, &fence); if (ret) goto out_err0; @@ -1174,7 +1164,7 @@ static int i915_getparam(struct drm_device *dev, void *data, int value; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -1208,7 +1198,7 @@ static int i915_setparam(struct drm_device *dev, void *data, drm_i915_setparam_t *param = data; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -1252,7 +1242,7 @@ static int i915_mmio(struct drm_device *dev, void *data, int i; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -1295,7 +1285,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data, drm_i915_hws_addr_t *hws = data; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index c5819953..d48d7665 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -329,9 +329,9 @@ typedef struct drm_i915_hws_addr { /* * Relocation header is 4 uint32_ts - * 0 - (16-bit relocation type << 16)| 16 bit reloc count - * 1 - buffer handle for another list of relocs - * 2-3 - spare. + * 0 - 32 bit reloc count + * 1 - 32-bit relocation type + * 2-3 - 64-bit user buffer handle ptr for another list of relocs. */ #define I915_RELOC_HEADER 4 @@ -339,7 +339,7 @@ typedef struct drm_i915_hws_addr { * type 0 relocation has 4-uint32_t stride * 0 - offset into buffer * 1 - delta to add in - * 2 - index into buffer list + * 2 - buffer handle * 3 - reserved (for optimisations later). */ #define I915_RELOC_TYPE_0 0 @@ -347,7 +347,7 @@ typedef struct drm_i915_hws_addr { struct drm_i915_op_arg { uint64_t next; - uint32_t reloc_handle; + uint64_t reloc_ptr; int handled; union { struct drm_bo_op_req req; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 45b7786a..49e23ac3 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -271,23 +271,23 @@ extern int i915_irq_emit(struct drm_device *dev, void *data, extern int i915_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern void i915_driver_wait_next_vblank(struct drm_device *dev, int pipe); -extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence); -extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence); extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); extern void i915_driver_irq_preinstall(struct drm_device * dev); -extern void i915_driver_irq_postinstall(struct drm_device * dev); +extern int i915_driver_irq_postinstall(struct drm_device * dev); extern void i915_driver_irq_uninstall(struct drm_device * dev); extern int i915_vblank_pipe_set(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int i915_vblank_pipe_get(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int i915_emit_irq(struct drm_device * dev); -extern void i915_user_irq_on(struct drm_i915_private *dev_priv); -extern void i915_user_irq_off(struct drm_i915_private *dev_priv); extern void i915_enable_interrupt (struct drm_device *dev); +extern int i915_enable_vblank(struct drm_device *dev, int crtc); +extern void i915_disable_vblank(struct drm_device *dev, int crtc); +extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc); extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern void i915_user_irq_on(struct drm_i915_private *dev_priv); +extern void i915_user_irq_off(struct drm_i915_private *dev_priv); /* i915_mem.c */ extern int i915_mem_alloc(struct drm_device *dev, void *data, @@ -318,12 +318,12 @@ extern int i915_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t f #ifdef I915_HAVE_BUFFER /* i915_buffer.c */ extern struct drm_ttm_backend *i915_create_ttm_backend_entry(struct drm_device *dev); -extern int i915_fence_types(struct drm_buffer_object *bo, uint32_t *fclass, - uint32_t *type); +extern int i915_fence_type(struct drm_buffer_object *bo, uint32_t *fclass, + uint32_t *type); extern int i915_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags); extern int i915_init_mem_type(struct drm_device *dev, uint32_t type, struct drm_mem_type_manager *man); -extern uint32_t i915_evict_mask(struct drm_buffer_object *bo); +extern uint64_t i915_evict_flags(struct drm_buffer_object *bo); extern int i915_move(struct drm_buffer_object *bo, int evict, int no_wait, struct drm_bo_mem_reg *new_mem); void i915_flush_ttm(struct drm_ttm *ttm); @@ -354,8 +354,8 @@ extern void intel_modeset_cleanup(struct drm_device *dev); #define BEGIN_LP_RING(n) do { \ if (I915_VERBOSE) \ - DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ - (n), __FUNCTION__); \ + DRM_DEBUG("BEGIN_LP_RING(%d)\n", \ + (n)); \ if (dev_priv->ring.space < (n)*4) \ i915_wait_ring(dev, (n)*4, __FUNCTION__); \ outcount = 0; \ @@ -516,8 +516,41 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define I915REG_INT_ENABLE_R 0x020a0 #define I915REG_INSTPM 0x020c0 +#define PIPEADSL 0x70000 +#define PIPEBDSL 0x71000 + #define I915REG_PIPEASTAT 0x70024 #define I915REG_PIPEBSTAT 0x71024 +/* + * The two pipe frame counter registers are not synchronized, so + * reading a stable value is somewhat tricky. The following code + * should work: + * + * do { + * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> + * PIPE_FRAME_HIGH_SHIFT; + * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >> + * PIPE_FRAME_LOW_SHIFT); + * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> + * PIPE_FRAME_HIGH_SHIFT); + * } while (high1 != high2); + * frame = (high1 << 8) | low1; + */ +#define PIPEAFRAMEHIGH 0x70040 +#define PIPEBFRAMEHIGH 0x71040 +#define PIPE_FRAME_HIGH_MASK 0x0000ffff +#define PIPE_FRAME_HIGH_SHIFT 0 +#define PIPEAFRAMEPIXEL 0x70044 +#define PIPEBFRAMEPIXEL 0x71044 + +#define PIPE_FRAME_LOW_MASK 0xff000000 +#define PIPE_FRAME_LOW_SHIFT 24 +/* + * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register + * and is 24 bits wide. + */ +#define PIPE_PIXEL_MASK 0x00ffffff +#define PIPE_PIXEL_SHIFT 0 #define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) #define I915_VBLANK_CLEAR (1UL<<1) @@ -871,6 +904,14 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define BCLRPAT_B 0x61020 #define VSYNCSHIFT_B 0x61028 +#define HACTIVE_MASK 0x00000fff +#define VTOTAL_MASK 0x00001fff +#define VTOTAL_SHIFT 16 +#define VACTIVE_MASK 0x00000fff +#define VBLANK_END_MASK 0x00001fff +#define VBLANK_END_SHIFT 16 +#define VBLANK_START_MASK 0x00001fff + #define PP_STATUS 0x61200 # define PP_ON (1 << 31) /** @@ -1274,7 +1315,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define IS_I855(dev) ((dev)->pci_device == 0x3582) #define IS_I865G(dev) ((dev)->pci_device == 0x2572) -#define IS_I915G(dev) (dev->pci_device == 0x2582)/* || dev->pci_device == PCI_DEVICE_ID_INTELPCI_CHIP_E7221_G)*/ +#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a) #define IS_I915GM(dev) ((dev)->pci_device == 0x2592) #define IS_I945G(dev) ((dev)->pci_device == 0x2772) #define IS_I945GM(dev) ((dev)->pci_device == 0x27A2) @@ -1284,10 +1325,13 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); (dev)->pci_device == 0x2992 || \ (dev)->pci_device == 0x29A2 || \ (dev)->pci_device == 0x2A02 || \ - (dev)->pci_device == 0x2A12) + (dev)->pci_device == 0x2A12 || \ + (dev)->pci_device == 0x2A42) #define IS_I965GM(dev) ((dev)->pci_device == 0x2A02) +#define IS_IGD_GM(dev) ((dev)->pci_device == 0x2A42) + #define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \ (dev)->pci_device == 0x29B2 || \ (dev)->pci_device == 0x29D2) @@ -1296,7 +1340,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev)) #define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \ - IS_I945GM(dev) || IS_I965GM(dev)) + IS_I945GM(dev) || IS_I965GM(dev) || IS_IGD_GM(dev)) #define PRIMARY_RINGBUFFER_SIZE (128*1024) diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index ac5361f2..9b391b75 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -45,9 +45,9 @@ * @dev: DRM device * @plane: plane to look for * - * We need to get the pipe associated with a given plane to correctly perform - * vblank driven swapping, and they may not always be equal. So look up the - * pipe associated with @plane here. + * The Intel Mesa & 2D drivers call the vblank routines with a plane number + * rather than a pipe number, since they may not always be equal. This routine + * maps the given @plane back to a pipe number. */ static int i915_get_pipe(struct drm_device *dev, int plane) @@ -61,6 +61,44 @@ i915_get_pipe(struct drm_device *dev, int plane) } /** + * i915_get_plane - return the the plane associated with a given pipe + * @dev: DRM device + * @pipe: pipe to look for + * + * The Intel Mesa & 2D drivers call the vblank routines with a plane number + * rather than a plane number, since they may not always be equal. This routine + * maps the given @pipe back to a plane number. + */ +static int +i915_get_plane(struct drm_device *dev, int pipe) +{ + if (i915_get_pipe(dev, 0) == pipe) + return 0; + return 1; +} + +/** + * i915_pipe_enabled - check if a pipe is enabled + * @dev: DRM device + * @pipe: pipe to check + * + * Reading certain registers when the pipe is disabled can hang the chip. + * Use this routine to make sure the PLL is running and the pipe is active + * before reading such registers if unsure. + */ +static int +i915_pipe_enabled(struct drm_device *dev, int pipe) +{ + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF; + + if (I915_READ(pipeconf) & PIPEACONF_ENABLE) + return 1; + + return 0; +} + +/** * Emit a synchronous flip. * * This function must be called with the drawable spinlock held. @@ -117,8 +155,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; struct list_head *list, *tmp, hits, *hit; int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages; - unsigned counter[2] = { atomic_read(&dev->vbl_received), - atomic_read(&dev->vbl_received2) }; + unsigned counter[2]; struct drm_drawable_info *drw; struct drm_i915_sarea *sarea_priv = dev_priv->sarea_priv; u32 cpp = dev_priv->cpp, offsets[3]; @@ -130,6 +167,9 @@ static void i915_vblank_tasklet(struct drm_device *dev) (cpp << 23) | (1 << 24); RING_LOCALS; + counter[0] = drm_vblank_count(dev, 0); + counter[1] = drm_vblank_count(dev, 1); + DRM_DEBUG("\n"); INIT_LIST_HEAD(&hits); @@ -154,6 +194,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) list_del(list); dev_priv->swaps_pending--; + drm_vblank_put(dev, pipe); DRM_SPINUNLOCK(&dev_priv->swaps_lock); DRM_SPINLOCK(&dev->drw_lock); @@ -303,6 +344,73 @@ static void i915_vblank_tasklet(struct drm_device *dev) drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER); } } +#if 0 +static int i915_in_vblank(struct drm_device *dev, int pipe) +{ + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + unsigned long pipedsl, vblank, vtotal; + unsigned long vbl_start, vbl_end, cur_line; + + pipedsl = pipe ? PIPEBDSL : PIPEADSL; + vblank = pipe ? VBLANK_B : VBLANK_A; + vtotal = pipe ? VTOTAL_B : VTOTAL_A; + + vbl_start = I915_READ(vblank) & VBLANK_START_MASK; + vbl_end = (I915_READ(vblank) >> VBLANK_END_SHIFT) & VBLANK_END_MASK; + + cur_line = I915_READ(pipedsl); + + if (cur_line >= vbl_start) + return 1; + + return 0; +} +#endif +u32 i915_get_vblank_counter(struct drm_device *dev, int plane) +{ + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + unsigned long high_frame; + unsigned long low_frame; + u32 high1, high2, low, count; + int pipe; + + pipe = i915_get_pipe(dev, plane); + high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; + low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; + + if (!i915_pipe_enabled(dev, pipe)) { + printk(KERN_ERR "trying to get vblank count for disabled " + "pipe %d\n", pipe); + return 0; + } + + /* + * High & low register fields aren't synchronized, so make sure + * we get a low value that's stable across two reads of the high + * register. + */ + do { + high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> + PIPE_FRAME_HIGH_SHIFT); + low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >> + PIPE_FRAME_LOW_SHIFT); + high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> + PIPE_FRAME_HIGH_SHIFT); + } while (high1 != high2); + + count = (high1 << 8) | low; + + /* + * If we're in the middle of the vblank period, the + * above regs won't have been updated yet, so return + * an incremented count to stay accurate + */ +#if 0 + if (i915_in_vblank(dev, pipe)) + count++; +#endif + return count; +} #define HOTPLUG_CMD_CRT 1 #define HOTPLUG_CMD_SDVOB 4 @@ -445,11 +553,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) pipeb_stats = I915_READ(I915REG_PIPEBSTAT); /* On i8xx hw the IIR and IER are 16bit on i9xx its 32bit */ - if (IS_I9XX(dev)) { + if (IS_I9XX(dev)) temp = I915_READ(I915REG_INT_IDENTITY_R); - } else { + else temp = I915_READ16(I915REG_INT_IDENTITY_R); - } temp2 = temp; temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG); @@ -464,7 +571,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) } #else #if 0 - DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); + DRM_DEBUG("flag=%08x\n", temp); #endif #endif @@ -479,8 +586,32 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) (void) I915_READ16(I915REG_INT_IDENTITY_R); } + /* + * Clear the PIPE(A|B)STAT regs before the IIR otherwise + * we may get extra interrupts. + */ + if (temp & VSYNC_PIPEA_FLAG) { + drm_handle_vblank(dev, i915_get_plane(dev, 0)); + I915_WRITE(I915REG_PIPEASTAT, + pipea_stats | I915_VBLANK_INTERRUPT_ENABLE | + I915_VBLANK_CLEAR); + } + + if (temp & VSYNC_PIPEB_FLAG) { + drm_handle_vblank(dev, i915_get_plane(dev, 1)); + I915_WRITE(I915REG_PIPEBSTAT, + pipeb_stats | I915_VBLANK_INTERRUPT_ENABLE | + I915_VBLANK_CLEAR); + } + + I915_WRITE16(I915REG_INT_IDENTITY_R, temp); + (void) I915_READ16(I915REG_INT_IDENTITY_R); /* Flush posted write */ + DRM_READMEMORYBARRIER(); + temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG | VSYNC_PIPEA_FLAG | + VSYNC_PIPEB_FLAG); + dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); if (temp & USER_INT_FLAG) { @@ -491,32 +622,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) } if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { - int vblank_pipe = dev_priv->vblank_pipe; - - if ((vblank_pipe & - (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) - == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) { - if (temp & VSYNC_PIPEA_FLAG) - atomic_inc(&dev->vbl_received); - if (temp & VSYNC_PIPEB_FLAG) - atomic_inc(&dev->vbl_received2); - } else if (((temp & VSYNC_PIPEA_FLAG) && - (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) || - ((temp & VSYNC_PIPEB_FLAG) && - (vblank_pipe & DRM_I915_VBLANK_PIPE_B))) - atomic_inc(&dev->vbl_received); - - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); - if (dev_priv->swaps_pending > 0) drm_locked_tasklet(dev, i915_vblank_tasklet); - I915_WRITE(I915REG_PIPEASTAT, - pipea_stats|I915_VBLANK_INTERRUPT_ENABLE| - I915_VBLANK_CLEAR); - I915_WRITE(I915REG_PIPEBSTAT, - pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE| - I915_VBLANK_CLEAR); } /* for now lest just ack it */ @@ -535,13 +642,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) int i915_emit_irq(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; RING_LOCALS; i915_kernel_lost_context(dev); - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); i915_emit_breadcrumb(dev); @@ -580,7 +686,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; int ret = 0; - DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr, + DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr, READ_BREADCRUMB(dev_priv)); if (READ_BREADCRUMB(dev_priv) >= irq_nr) @@ -592,8 +698,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) i915_user_irq_off(dev_priv); if (ret == -EBUSY) { - DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n", - __FUNCTION__, + DRM_ERROR("EBUSY -- rec: %d emitted: %d\n", READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); } @@ -601,64 +706,6 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) return ret; } -static int i915_driver_vblank_do_wait(struct drm_device *dev, - unsigned int *sequence, - atomic_t *counter) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned int cur_vblank; - int ret = 0; - - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; - } - - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(counter)) - - *sequence) <= (1<<23))); - - *sequence = cur_vblank; - - return ret; -} - -void i915_driver_wait_next_vblank(struct drm_device *dev, int pipe) -{ - unsigned int seq; - - seq = pipe ? atomic_read(&dev->vbl_received2) + 1 : - atomic_read(&dev->vbl_received) + 1; - - if (!pipe) - i915_driver_vblank_do_wait(dev, &seq, &dev->vbl_received); - else - i915_driver_vblank_do_wait(dev, &seq, &dev->vbl_received2); -} - -int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence) -{ - atomic_t *counter; - - if (i915_get_pipe(dev, 0) == 0) - counter = &dev->vbl_received; - else - counter = &dev->vbl_received2; - return i915_driver_vblank_do_wait(dev, sequence, counter); -} - -int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) -{ - atomic_t *counter; - - if (i915_get_pipe(dev, 1) == 0) - counter = &dev->vbl_received; - else - counter = &dev->vbl_received2; - - return i915_driver_vblank_do_wait(dev, sequence, counter); -} - /* Needs the lock as it touches the ring. */ int i915_irq_emit(struct drm_device *dev, void *data, @@ -671,7 +718,7 @@ int i915_irq_emit(struct drm_device *dev, void *data, LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -694,24 +741,63 @@ int i915_irq_wait(struct drm_device *dev, void *data, struct drm_i915_irq_wait *irqwait = data; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } return i915_wait_irq(dev, irqwait->irq_seq); } -void i915_enable_interrupt (struct drm_device *dev) +int i915_enable_vblank(struct drm_device *dev, int plane) { struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; - struct drm_output *o; + int pipe = i915_get_pipe(dev, plane); - dev_priv->irq_enable_reg = USER_INT_FLAG; - - if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) + switch (pipe) { + case 0: dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG; - if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) + break; + case 1: dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG; + break; + default: + DRM_ERROR("tried to enable vblank on non-existent pipe %d\n", + pipe); + break; + } + + I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + + return 0; +} + +void i915_disable_vblank(struct drm_device *dev, int plane) +{ + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + int pipe = i915_get_pipe(dev, plane); + + switch (pipe) { + case 0: + dev_priv->irq_enable_reg &= ~VSYNC_PIPEA_FLAG; + break; + case 1: + dev_priv->irq_enable_reg &= ~VSYNC_PIPEB_FLAG; + break; + default: + DRM_ERROR("tried to disable vblank on non-existent pipe %d\n", + pipe); + break; + } + + I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); +} + +void i915_enable_interrupt (struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + struct drm_output *o; + + dev_priv->irq_enable_reg |= USER_INT_FLAG; if (IS_I9XX(dev) && dev->mode_config.num_output) { dev_priv->irq_enable_reg |= HOTPLUG_FLAG; @@ -760,20 +846,17 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data, struct drm_i915_vblank_pipe *pipe = data; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { - DRM_ERROR("%s called with invalid pipe 0x%x\n", - __FUNCTION__, pipe->pipe); + DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe); return -EINVAL; } dev_priv->vblank_pipe = pipe->pipe; - i915_enable_interrupt (dev); - return 0; } @@ -785,7 +868,7 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data, u16 flag; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -811,6 +894,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, unsigned int pipe, seqtype, curseq, plane; unsigned long irqflags; struct list_head *list; + int ret; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __func__); @@ -854,7 +938,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data, DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags); - curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received); + drm_update_vblank_count(dev, pipe); + curseq = drm_vblank_count(dev, pipe); if (seqtype == _DRM_VBLANK_RELATIVE) swap->sequence += curseq; @@ -927,6 +1012,12 @@ int i915_vblank_swap(struct drm_device *dev, void *data, DRM_DEBUG("\n"); + ret = drm_vblank_get(dev, pipe); + if (ret) { + drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); + return ret; + } + vbl_swap->drw_id = swap->drawable; vbl_swap->plane = plane; vbl_swap->sequence = swap->sequence; @@ -937,7 +1028,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, DRM_SPINLOCK_IRQSAVE(&dev_priv->swaps_lock, irqflags); - list_add_tail((struct list_head *)vbl_swap, &dev_priv->vbl_swaps.head); + list_add_tail(&vbl_swap->head, &dev_priv->vbl_swaps.head); dev_priv->swaps_pending++; DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->swaps_lock, irqflags); @@ -962,9 +1053,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev) } -void i915_driver_irq_postinstall(struct drm_device * dev) +int i915_driver_irq_postinstall(struct drm_device * dev) { struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + int ret, num_pipes = 2; DRM_SPININIT(&dev_priv->swaps_lock, "swap"); INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); @@ -972,6 +1064,13 @@ void i915_driver_irq_postinstall(struct drm_device * dev) DRM_SPININIT(&dev_priv->user_irq_lock, "userirq"); dev_priv->user_irq_refcount = 0; + dev_priv->irq_enable_reg = 0; + + ret = drm_vblank_init(dev, num_pipes); + if (ret) + return ret; + + dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ i915_enable_interrupt(dev); DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); @@ -981,6 +1080,7 @@ void i915_driver_irq_postinstall(struct drm_device * dev) */ I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21)); + return 0; } void i915_driver_irq_uninstall(struct drm_device * dev) diff --git a/shared-core/i915_mem.c b/shared-core/i915_mem.c index 4c7ced24..f24547c7 100644 --- a/shared-core/i915_mem.c +++ b/shared-core/i915_mem.c @@ -276,7 +276,7 @@ int i915_mem_alloc(struct drm_device *dev, void *data, struct mem_block *block, **heap; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -314,7 +314,7 @@ int i915_mem_free(struct drm_device *dev, void *data, struct mem_block *block, **heap; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -342,7 +342,7 @@ int i915_mem_init_heap(struct drm_device *dev, void *data, struct mem_block **heap; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -366,7 +366,7 @@ int i915_mem_destroy_heap( struct drm_device *dev, void *data, struct mem_block **heap; if ( !dev_priv ) { - DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + DRM_ERROR( "called with no initialization\n" ); return -EINVAL; } diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c index 411b98d5..339234fa 100644 --- a/shared-core/mach64_dma.c +++ b/shared-core/mach64_dma.c @@ -57,7 +57,7 @@ * \returns zero on success, or -EBUSY if the timeout (specificed by * drm_mach64_private::usec_timeout) occurs. */ -int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, int entries) +int mach64_do_wait_for_fifo(drm_mach64_private_t *dev_priv, int entries) { int slots = 0, i; @@ -68,15 +68,14 @@ int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, int entries) DRM_UDELAY(1); } - DRM_INFO("%s failed! slots=%d entries=%d\n", __FUNCTION__, slots, - entries); + DRM_INFO("failed! slots=%d entries=%d\n", slots, entries); return -EBUSY; } /** * Wait for the draw engine to be idle. */ -int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv) +int mach64_do_wait_for_idle(drm_mach64_private_t *dev_priv) { int i, ret; @@ -85,14 +84,12 @@ int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv) return ret; for (i = 0; i < dev_priv->usec_timeout; i++) { - if (!(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE)) { + if (!(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE)) return 0; - } DRM_UDELAY(1); } - DRM_INFO("%s failed! GUI_STAT=0x%08x\n", __FUNCTION__, - MACH64_READ(MACH64_GUI_STAT)); + DRM_INFO("failed! GUI_STAT=0x%08x\n", MACH64_READ(MACH64_GUI_STAT)); mach64_dump_ring_info(dev_priv); return -EBUSY; } @@ -116,7 +113,7 @@ int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv) * * \sa mach64_dump_ring_info() */ -int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n) +int mach64_wait_ring(drm_mach64_private_t *dev_priv, int n) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; int i; @@ -124,9 +121,8 @@ int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n) for (i = 0; i < dev_priv->usec_timeout; i++) { mach64_update_ring_snapshot(dev_priv); if (ring->space >= n) { - if (i > 0) { - DRM_DEBUG("%s: %d usecs\n", __FUNCTION__, i); - } + if (i > 0) + DRM_DEBUG("%d usecs\n", i); return 0; } DRM_UDELAY(1); @@ -143,7 +139,7 @@ int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n) * * \sa mach64_wait_ring() */ -static int mach64_ring_idle(drm_mach64_private_t * dev_priv) +static int mach64_ring_idle(drm_mach64_private_t *dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; u32 head; @@ -155,9 +151,8 @@ static int mach64_ring_idle(drm_mach64_private_t * dev_priv) mach64_update_ring_snapshot(dev_priv); if (ring->head == ring->tail && !(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE)) { - if (i > 0) { - DRM_DEBUG("%s: %d usecs\n", __FUNCTION__, i); - } + if (i > 0) + DRM_DEBUG("%d usecs\n", i); return 0; } if (ring->head == head) { @@ -169,8 +164,7 @@ static int mach64_ring_idle(drm_mach64_private_t * dev_priv) DRM_UDELAY(1); } - DRM_INFO("%s failed! GUI_STAT=0x%08x\n", __FUNCTION__, - MACH64_READ(MACH64_GUI_STAT)); + DRM_INFO("failed! GUI_STAT=0x%08x\n", MACH64_READ(MACH64_GUI_STAT)); mach64_dump_ring_info(dev_priv); return -EBUSY; } @@ -180,7 +174,7 @@ static int mach64_ring_idle(drm_mach64_private_t * dev_priv) * * \sa mach64_do_engine_reset() */ -static void mach64_ring_reset(drm_mach64_private_t * dev_priv) +static void mach64_ring_reset(drm_mach64_private_t *dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; @@ -198,7 +192,7 @@ static void mach64_ring_reset(drm_mach64_private_t * dev_priv) /** * Ensure the all the queued commands will be processed. */ -int mach64_do_dma_flush(drm_mach64_private_t * dev_priv) +int mach64_do_dma_flush(drm_mach64_private_t *dev_priv) { /* FIXME: It's not necessary to wait for idle when flushing * we just need to ensure the ring will be completely processed @@ -210,14 +204,14 @@ int mach64_do_dma_flush(drm_mach64_private_t * dev_priv) /** * Stop all DMA activity. */ -int mach64_do_dma_idle(drm_mach64_private_t * dev_priv) +int mach64_do_dma_idle(drm_mach64_private_t *dev_priv) { int ret; /* wait for completion */ if ((ret = mach64_ring_idle(dev_priv)) < 0) { - DRM_ERROR("%s failed BM_GUI_TABLE=0x%08x tail: %u\n", - __FUNCTION__, MACH64_READ(MACH64_BM_GUI_TABLE), + DRM_ERROR("failed BM_GUI_TABLE=0x%08x tail: %u\n", + MACH64_READ(MACH64_BM_GUI_TABLE), dev_priv->ring.tail); return ret; } @@ -232,11 +226,11 @@ int mach64_do_dma_idle(drm_mach64_private_t * dev_priv) /** * Reset the engine. This will stop the DMA if it is running. */ -int mach64_do_engine_reset(drm_mach64_private_t * dev_priv) +int mach64_do_engine_reset(drm_mach64_private_t *dev_priv) { u32 tmp; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); /* Kill off any outstanding DMA transfers. */ @@ -276,7 +270,7 @@ int mach64_do_engine_reset(drm_mach64_private_t * dev_priv) /** * Dump engine registers values. */ -void mach64_dump_engine_info(drm_mach64_private_t * dev_priv) +void mach64_dump_engine_info(drm_mach64_private_t *dev_priv) { DRM_INFO("\n"); if (!dev_priv->is_pci) { @@ -417,8 +411,8 @@ void mach64_dump_engine_info(drm_mach64_private_t * dev_priv) * Used by mach64_dump_ring_info() to dump the contents of the current buffer * pointed by the ring head. */ -static void mach64_dump_buf_info(drm_mach64_private_t * dev_priv, - struct drm_buf * buf) +static void mach64_dump_buf_info(drm_mach64_private_t *dev_priv, + struct drm_buf *buf) { u32 addr = GETBUFADDR(buf); u32 used = buf->used >> 2; @@ -477,7 +471,7 @@ static void mach64_dump_buf_info(drm_mach64_private_t * dev_priv, * Dump the ring state and contents, including the contents of the buffer being * processed by the graphics engine. */ -void mach64_dump_ring_info(drm_mach64_private_t * dev_priv) +void mach64_dump_ring_info(drm_mach64_private_t *dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; int i, skipped; @@ -526,9 +520,8 @@ void mach64_dump_ring_info(drm_mach64_private_t * dev_priv) u32 buf_addr = GETBUFADDR(buf); - if (buf_addr <= addr && addr < buf_addr + buf->used) { + if (buf_addr <= addr && addr < buf_addr + buf->used) mach64_dump_buf_info(dev_priv, buf); - } } } @@ -564,13 +557,13 @@ void mach64_dump_ring_info(drm_mach64_private_t * dev_priv) /** * Add the end mark to the ring's new tail position. - * + * * The bus master engine will keep processing the DMA buffers listed in the ring * until it finds this mark, making it stop. - * + * * \sa mach64_clear_dma_eol */ -static __inline__ void mach64_set_dma_eol(volatile u32 * addr) +static __inline__ void mach64_set_dma_eol(volatile u32 *addr) { #if defined(__i386__) int nr = 31; @@ -611,17 +604,17 @@ static __inline__ void mach64_set_dma_eol(volatile u32 * addr) } /** - * Remove the end mark from the ring's old tail position. - * + * Remove the end mark from the ring's old tail position. + * * It should be called after calling mach64_set_dma_eol to mark the ring's new * tail position. - * - * We update the end marks while the bus master engine is in operation. Since + * + * We update the end marks while the bus master engine is in operation. Since * the bus master engine may potentially be reading from the same position - * that we write, we must change atomically to avoid having intermediary bad + * that we write, we must change atomically to avoid having intermediary bad * data. */ -static __inline__ void mach64_clear_dma_eol(volatile u32 * addr) +static __inline__ void mach64_clear_dma_eol(volatile u32 *addr) { #if defined(__i386__) int nr = 31; @@ -661,35 +654,35 @@ static __inline__ void mach64_clear_dma_eol(volatile u32 * addr) #endif } -#define RING_LOCALS \ +#define RING_LOCALS \ int _ring_tail, _ring_write; unsigned int _ring_mask; volatile u32 *_ring #define RING_WRITE_OFS _ring_write -#define BEGIN_RING( n ) \ -do { \ - if ( MACH64_VERBOSE ) { \ - DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ - (n), __FUNCTION__ ); \ - } \ - if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ - int ret; \ - if ((ret=mach64_wait_ring( dev_priv, (n) * sizeof(u32))) < 0 ) { \ - DRM_ERROR( "wait_ring failed, resetting engine\n"); \ - mach64_dump_engine_info( dev_priv ); \ - mach64_do_engine_reset( dev_priv ); \ - return ret; \ - } \ - } \ - dev_priv->ring.space -= (n) * sizeof(u32); \ - _ring = (u32 *) dev_priv->ring.start; \ - _ring_tail = _ring_write = dev_priv->ring.tail; \ - _ring_mask = dev_priv->ring.tail_mask; \ -} while (0) +#define BEGIN_RING(n) \ + do { \ + if (MACH64_VERBOSE) { \ + DRM_INFO( "BEGIN_RING( %d ) \n", \ + (n) ); \ + } \ + if (dev_priv->ring.space <= (n) * sizeof(u32)) { \ + int ret; \ + if ((ret = mach64_wait_ring( dev_priv, (n) * sizeof(u32))) < 0 ) { \ + DRM_ERROR( "wait_ring failed, resetting engine\n"); \ + mach64_dump_engine_info( dev_priv ); \ + mach64_do_engine_reset( dev_priv ); \ + return ret; \ + } \ + } \ + dev_priv->ring.space -= (n) * sizeof(u32); \ + _ring = (u32 *) dev_priv->ring.start; \ + _ring_tail = _ring_write = dev_priv->ring.tail; \ + _ring_mask = dev_priv->ring.tail_mask; \ + } while (0) #define OUT_RING( x ) \ do { \ - if ( MACH64_VERBOSE ) { \ + if (MACH64_VERBOSE) { \ DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ (unsigned int)(x), _ring_write ); \ } \ @@ -699,7 +692,7 @@ do { \ #define ADVANCE_RING() \ do { \ - if ( MACH64_VERBOSE ) { \ + if (MACH64_VERBOSE) { \ DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ _ring_write, _ring_tail ); \ } \ @@ -835,7 +828,7 @@ static int mach64_bm_dma_test(struct drm_device * dev) u32 src_cntl, pat_reg0, pat_reg1; int i, count, failed; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); table = (u32 *) dev_priv->ring.start; @@ -1011,7 +1004,7 @@ static int mach64_do_dma_init(struct drm_device * dev, drm_mach64_init_t * init) u32 tmp; int i, ret; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); dev_priv = drm_alloc(sizeof(drm_mach64_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) @@ -1221,7 +1214,7 @@ static int mach64_do_dma_init(struct drm_device * dev, drm_mach64_init_t * init) /** MMIO Pseudo-DMA (intended primarily for debugging, not performance) */ -int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv) +int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t *dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; volatile u32 *ring_read; @@ -1236,9 +1229,7 @@ int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv) target = MACH64_BM_ADDR; if ((ret = mach64_do_wait_for_idle(dev_priv)) < 0) { - DRM_INFO - ("%s: idle failed before pseudo-dma dispatch, resetting engine\n", - __FUNCTION__); + DRM_INFO("idle failed before pseudo-dma dispatch, resetting engine\n"); mach64_dump_engine_info(dev_priv); mach64_do_engine_reset(dev_priv); return ret; @@ -1359,7 +1350,7 @@ int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv) MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD, ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB); - DRM_DEBUG("%s completed\n", __FUNCTION__); + DRM_DEBUG("completed\n"); return 0; } @@ -1372,7 +1363,7 @@ int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv) int mach64_do_cleanup_dma(struct drm_device * dev) { - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private @@ -1416,7 +1407,7 @@ int mach64_dma_init(struct drm_device *dev, void *data, { drm_mach64_init_t *init = data; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -1435,7 +1426,7 @@ int mach64_dma_idle(struct drm_device *dev, void *data, { drm_mach64_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -1447,7 +1438,7 @@ int mach64_dma_flush(struct drm_device *dev, void *data, { drm_mach64_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -1459,7 +1450,7 @@ int mach64_engine_reset(struct drm_device *dev, void *data, { drm_mach64_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -1481,8 +1472,7 @@ int mach64_init_freelist(struct drm_device * dev) struct list_head *ptr; int i; - DRM_DEBUG("%s: adding %d buffers to freelist\n", __FUNCTION__, - dma->buf_count); + DRM_DEBUG("adding %d buffers to freelist\n", dma->buf_count); for (i = 0; i < dma->buf_count; i++) { if ((entry = @@ -1506,7 +1496,7 @@ void mach64_destroy_freelist(struct drm_device * dev) struct list_head *ptr; struct list_head *tmp; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); list_for_each_safe(ptr, tmp, &dev_priv->pending) { list_del(ptr); @@ -1529,7 +1519,7 @@ void mach64_destroy_freelist(struct drm_device * dev) /* IMPORTANT: This function should only be called when the engine is idle or locked up, * as it assumes all buffers in the pending list have been completed by the hardware. */ -int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv) +int mach64_do_release_used_buffers(drm_mach64_private_t *dev_priv) { struct list_head *ptr; struct list_head *tmp; @@ -1551,13 +1541,12 @@ int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv) } } - DRM_DEBUG("%s: released %d buffers from pending list\n", __FUNCTION__, - i); + DRM_DEBUG("released %d buffers from pending list\n", i); return 0; } -static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv) +static int mach64_do_reclaim_completed(drm_mach64_private_t *dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; struct list_head *ptr; @@ -1579,8 +1568,7 @@ static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv) #endif /* last pass is complete, so release everything */ mach64_do_release_used_buffers(dev_priv); - DRM_DEBUG("%s: idle engine, freed all buffers.\n", - __FUNCTION__); + DRM_DEBUG("idle engine, freed all buffers.\n"); if (list_empty(&dev_priv->free_list)) { DRM_ERROR("Freelist empty with idle engine\n"); return -1; @@ -1621,9 +1609,9 @@ static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv) list_del(ptr); list_add_tail(ptr, &dev_priv->free_list); DRM_DEBUG - ("%s: freed processed buffer (head=%d tail=%d " + ("freed processed buffer (head=%d tail=%d " "buf ring ofs=%d).\n", - __FUNCTION__, head, tail, ofs); + head, tail, ofs); return 0; } } @@ -1631,7 +1619,7 @@ static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv) return 1; } -struct drm_buf *mach64_freelist_get(drm_mach64_private_t * dev_priv) +struct drm_buf *mach64_freelist_get(drm_mach64_private_t *dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; drm_mach64_freelist_t *entry; @@ -1677,7 +1665,7 @@ struct drm_buf *mach64_freelist_get(drm_mach64_private_t * dev_priv) return entry->buf; } -int mach64_freelist_put(drm_mach64_private_t * dev_priv, struct drm_buf * copy_buf) +int mach64_freelist_put(drm_mach64_private_t *dev_priv, struct drm_buf *copy_buf) { struct list_head *ptr; drm_mach64_freelist_t *entry; @@ -1686,8 +1674,7 @@ int mach64_freelist_put(drm_mach64_private_t * dev_priv, struct drm_buf * copy_b list_for_each(ptr, &dev_priv->pending) { entry = list_entry(ptr, drm_mach64_freelist_t, list); if (copy_buf == entry->buf) { - DRM_ERROR("%s: Trying to release a pending buf\n", - __FUNCTION__); + DRM_ERROR("Trying to release a pending buf\n"); return -EFAULT; } } diff --git a/shared-core/mach64_drv.h b/shared-core/mach64_drv.h index 1768a2a4..fb8a7724 100644 --- a/shared-core/mach64_drv.h +++ b/shared-core/mach64_drv.h @@ -96,6 +96,8 @@ typedef struct drm_mach64_private { unsigned int depth_bpp; unsigned int depth_offset, depth_pitch; + atomic_t vbl_received; /**< Number of vblanks received. */ + u32 front_offset_pitch; u32 back_offset_pitch; u32 depth_offset_pitch; @@ -160,13 +162,14 @@ extern int mach64_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int mach64_get_param(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int mach64_driver_vblank_wait(struct drm_device * dev, - unsigned int *sequence); +extern u32 mach64_get_vblank_counter(struct drm_device *dev, int crtc); +extern int mach64_enable_vblank(struct drm_device *dev, int crtc); +extern void mach64_disable_vblank(struct drm_device *dev, int crtc); extern irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS); -extern void mach64_driver_irq_preinstall(struct drm_device * dev); -extern void mach64_driver_irq_postinstall(struct drm_device * dev); -extern void mach64_driver_irq_uninstall(struct drm_device * dev); +extern void mach64_driver_irq_preinstall(struct drm_device *dev); +extern int mach64_driver_irq_postinstall(struct drm_device *dev); +extern void mach64_driver_irq_uninstall(struct drm_device *dev); /* ================================================================ * Registers @@ -536,8 +539,7 @@ static __inline__ void mach64_ring_start(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; - DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", - __FUNCTION__, + DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n", ring->head_addr, ring->head, ring->tail, ring->space); if (mach64_do_wait_for_idle(dev_priv) < 0) { @@ -563,8 +565,7 @@ static __inline__ void mach64_ring_start(drm_mach64_private_t * dev_priv) static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv, drm_mach64_descriptor_ring_t * ring) { - DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", - __FUNCTION__, + DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n", ring->head_addr, ring->head, ring->tail, ring->space); /* reset descriptor table ring head */ @@ -583,8 +584,7 @@ static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv, MACH64_WRITE(MACH64_DST_HEIGHT_WIDTH, 0); if (dev_priv->driver_mode == MACH64_MODE_DMA_SYNC) { if ((mach64_do_wait_for_idle(dev_priv)) < 0) { - DRM_ERROR("%s: idle failed, resetting engine\n", - __FUNCTION__); + DRM_ERROR("idle failed, resetting engine\n"); mach64_dump_engine_info(dev_priv); mach64_do_engine_reset(dev_priv); return; @@ -609,8 +609,7 @@ static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv, static __inline__ void mach64_ring_tick(drm_mach64_private_t * dev_priv, drm_mach64_descriptor_ring_t * ring) { - DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", - __FUNCTION__, + DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n", ring->head_addr, ring->head, ring->tail, ring->space); if (!dev_priv->ring_running) { @@ -657,8 +656,7 @@ static __inline__ void mach64_ring_tick(drm_mach64_private_t * dev_priv, static __inline__ void mach64_ring_stop(drm_mach64_private_t * dev_priv) { - DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n", - __FUNCTION__, + DRM_DEBUG("head_addr: 0x%08x head: %d tail: %d space: %d\n", dev_priv->ring.head_addr, dev_priv->ring.head, dev_priv->ring.tail, dev_priv->ring.space); @@ -679,7 +677,7 @@ mach64_update_ring_snapshot(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); mach64_ring_tick(dev_priv, ring); @@ -720,7 +718,7 @@ static __inline__ int mach64_find_pending_buf_entry(drm_mach64_private_t * struct list_head *ptr; #if MACH64_EXTRA_CHECKING if (list_empty(&dev_priv->pending)) { - DRM_ERROR("Empty pending list in %s\n", __FUNCTION__); + DRM_ERROR("Empty pending list in \n"); return -EINVAL; } #endif @@ -747,18 +745,15 @@ do { \ #define DMAGETPTR( file_priv, dev_priv, n ) \ do { \ if ( MACH64_VERBOSE ) { \ - DRM_INFO( "DMAGETPTR( %d ) in %s\n", \ - n, __FUNCTION__ ); \ + DRM_INFO( "DMAGETPTR( %d )\n", (n) ); \ } \ _buf = mach64_freelist_get( dev_priv ); \ if (_buf == NULL) { \ - DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n", \ - __FUNCTION__ ); \ + DRM_ERROR("couldn't get buffer in DMAGETPTR\n"); \ return -EAGAIN; \ } \ if (_buf->pending) { \ - DRM_ERROR("%s: pending buf in DMAGETPTR\n", \ - __FUNCTION__ ); \ + DRM_ERROR("pending buf in DMAGETPTR\n"); \ return -EFAULT; \ } \ _buf->file_priv = file_priv; \ @@ -778,92 +773,87 @@ do { \ _buf->used += 8; \ } while (0) -#define DMAADVANCE( dev_priv, _discard ) \ -do { \ - struct list_head *ptr; \ - int ret; \ - \ - if ( MACH64_VERBOSE ) { \ - DRM_INFO( "DMAADVANCE() in %s\n", __FUNCTION__ ); \ - } \ - \ - if (_buf->used <= 0) { \ - DRM_ERROR( "DMAADVANCE() in %s: sending empty buf %d\n", \ - __FUNCTION__, _buf->idx ); \ - return -EFAULT; \ - } \ - if (_buf->pending) { \ - /* This is a resued buffer, so we need to find it in the pending list */ \ - if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) { \ - DRM_ERROR( "DMAADVANCE() in %s: couldn't find pending buf %d\n", \ - __FUNCTION__, _buf->idx ); \ - return ret; \ - } \ - if (_entry->discard) { \ - DRM_ERROR( "DMAADVANCE() in %s: sending discarded pending buf %d\n", \ - __FUNCTION__, _buf->idx ); \ - return -EFAULT; \ - } \ - } else { \ - if (list_empty(&dev_priv->placeholders)) { \ - DRM_ERROR( "DMAADVANCE() in %s: empty placeholder list\n", \ - __FUNCTION__ ); \ - return -EFAULT; \ - } \ - ptr = dev_priv->placeholders.next; \ - list_del(ptr); \ - _entry = list_entry(ptr, drm_mach64_freelist_t, list); \ - _buf->pending = 1; \ - _entry->buf = _buf; \ - list_add_tail(ptr, &dev_priv->pending); \ - } \ - _entry->discard = (_discard); \ - if ( (ret = mach64_add_buf_to_ring( dev_priv, _entry )) ) \ - return ret; \ -} while (0) - -#define DMADISCARDBUF() \ -do { \ - if (_entry == NULL) { \ - int ret; \ - if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) { \ - DRM_ERROR( "%s: couldn't find pending buf %d\n", \ - __FUNCTION__, _buf->idx ); \ - return ret; \ - } \ - } \ - _entry->discard = 1; \ -} while(0) - -#define DMAADVANCEHOSTDATA( dev_priv ) \ -do { \ - struct list_head *ptr; \ - int ret; \ - \ - if ( MACH64_VERBOSE ) { \ - DRM_INFO( "DMAADVANCEHOSTDATA() in %s\n", __FUNCTION__ ); \ - } \ - \ - if (_buf->used <= 0) { \ - DRM_ERROR( "DMAADVANCEHOSTDATA() in %s: sending empty buf %d\n", \ - __FUNCTION__, _buf->idx ); \ - return -EFAULT; \ - } \ - if (list_empty(&dev_priv->placeholders)) { \ - DRM_ERROR( "%s: empty placeholder list in DMAADVANCEHOSTDATA()\n", \ - __FUNCTION__ ); \ - return -EFAULT; \ - } \ - \ - ptr = dev_priv->placeholders.next; \ - list_del(ptr); \ - _entry = list_entry(ptr, drm_mach64_freelist_t, list); \ - _entry->buf = _buf; \ - _entry->buf->pending = 1; \ - list_add_tail(ptr, &dev_priv->pending); \ - _entry->discard = 1; \ - if ( (ret = mach64_add_hostdata_buf_to_ring( dev_priv, _entry )) ) \ - return ret; \ -} while (0) +#define DMAADVANCE( dev_priv, _discard ) \ + do { \ + struct list_head *ptr; \ + int ret; \ + \ + if ( MACH64_VERBOSE ) { \ + DRM_INFO( "DMAADVANCE() in \n" ); \ + } \ + \ + if (_buf->used <= 0) { \ + DRM_ERROR( "DMAADVANCE(): sending empty buf %d\n", \ + _buf->idx ); \ + return -EFAULT; \ + } \ + if (_buf->pending) { \ + /* This is a resued buffer, so we need to find it in the pending list */ \ + if ((ret = mach64_find_pending_buf_entry(dev_priv, &_entry, _buf))) { \ + DRM_ERROR( "DMAADVANCE(): couldn't find pending buf %d\n", _buf->idx ); \ + return ret; \ + } \ + if (_entry->discard) { \ + DRM_ERROR( "DMAADVANCE(): sending discarded pending buf %d\n", _buf->idx ); \ + return -EFAULT; \ + } \ + } else { \ + if (list_empty(&dev_priv->placeholders)) { \ + DRM_ERROR( "DMAADVANCE(): empty placeholder list\n"); \ + return -EFAULT; \ + } \ + ptr = dev_priv->placeholders.next; \ + list_del(ptr); \ + _entry = list_entry(ptr, drm_mach64_freelist_t, list); \ + _buf->pending = 1; \ + _entry->buf = _buf; \ + list_add_tail(ptr, &dev_priv->pending); \ + } \ + _entry->discard = (_discard); \ + if ((ret = mach64_add_buf_to_ring( dev_priv, _entry ))) \ + return ret; \ + } while (0) + +#define DMADISCARDBUF() \ + do { \ + if (_entry == NULL) { \ + int ret; \ + if ((ret = mach64_find_pending_buf_entry(dev_priv, &_entry, _buf))) { \ + DRM_ERROR( "couldn't find pending buf %d\n", \ + _buf->idx ); \ + return ret; \ + } \ + } \ + _entry->discard = 1; \ + } while(0) + +#define DMAADVANCEHOSTDATA( dev_priv ) \ + do { \ + struct list_head *ptr; \ + int ret; \ + \ + if ( MACH64_VERBOSE ) { \ + DRM_INFO( "DMAADVANCEHOSTDATA() in \n" ); \ + } \ + \ + if (_buf->used <= 0) { \ + DRM_ERROR( "DMAADVANCEHOSTDATA(): sending empty buf %d\n", _buf->idx ); \ + return -EFAULT; \ + } \ + if (list_empty(&dev_priv->placeholders)) { \ + DRM_ERROR( "empty placeholder list in DMAADVANCEHOSTDATA()\n" ); \ + return -EFAULT; \ + } \ + \ + ptr = dev_priv->placeholders.next; \ + list_del(ptr); \ + _entry = list_entry(ptr, drm_mach64_freelist_t, list); \ + _entry->buf = _buf; \ + _entry->buf->pending = 1; \ + list_add_tail(ptr, &dev_priv->pending); \ + _entry->discard = 1; \ + if ((ret = mach64_add_hostdata_buf_to_ring( dev_priv, _entry ))) \ + return ret; \ + } while (0) #endif /* __MACH64_DRV_H__ */ diff --git a/shared-core/mach64_irq.c b/shared-core/mach64_irq.c index 4122dd91..2d522a6c 100644 --- a/shared-core/mach64_irq.c +++ b/shared-core/mach64_irq.c @@ -42,9 +42,8 @@ irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS) { - struct drm_device *dev = (struct drm_device *) arg; - drm_mach64_private_t *dev_priv = - (drm_mach64_private_t *) dev->dev_private; + struct drm_device *dev = arg; + drm_mach64_private_t *dev_priv = dev->dev_private; int status; status = MACH64_READ(MACH64_CRTC_INT_CNTL); @@ -62,74 +61,81 @@ irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS) (status & ~MACH64_CRTC_INT_ACKS) | MACH64_CRTC_VBLANK_INT); - atomic_inc(&dev->vbl_received); - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); + atomic_inc(&dev_priv->vbl_received); + drm_handle_vblank(dev, 0); return IRQ_HANDLED; } return IRQ_NONE; } -int mach64_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) +u32 mach64_get_vblank_counter(struct drm_device * dev, int crtc) { - unsigned int cur_vblank; - int ret = 0; - - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(&dev->vbl_received)) - - *sequence) <= (1 << 23))); + const drm_mach64_private_t *const dev_priv = dev->dev_private; + + if (crtc != 0) { + return 0; + } + + return atomic_read(&dev_priv->vbl_received); +} - *sequence = cur_vblank; +int mach64_enable_vblank(struct drm_device * dev, int crtc) +{ + drm_mach64_private_t *dev_priv = dev->dev_private; + u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL); + + if (crtc != 0) { + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", crtc); + return 0; + } + + DRM_DEBUG("before enable vblank CRTC_INT_CTNL: 0x%08x\n", status); + + /* Turn on VBLANK interrupt */ + MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL) + | MACH64_CRTC_VBLANK_INT_EN); - return ret; + return 0; } -/* drm_dma.h hooks -*/ -void mach64_driver_irq_preinstall(struct drm_device * dev) -{ - drm_mach64_private_t *dev_priv = - (drm_mach64_private_t *) dev->dev_private; +void mach64_disable_vblank(struct drm_device * dev, int crtc) +{ + drm_mach64_private_t *dev_priv = dev->dev_private; u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL); - DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status); + DRM_DEBUG("before disable vblank CRTC_INT_CTNL: 0x%08x\n", status); /* Disable and clear VBLANK interrupt */ MACH64_WRITE(MACH64_CRTC_INT_CNTL, (status & ~MACH64_CRTC_VBLANK_INT_EN) | MACH64_CRTC_VBLANK_INT); } -void mach64_driver_irq_postinstall(struct drm_device * dev) +/* drm_dma.h hooks +*/ +void mach64_driver_irq_preinstall(struct drm_device * dev) { - drm_mach64_private_t *dev_priv = - (drm_mach64_private_t *) dev->dev_private; + drm_mach64_private_t *dev_priv = dev->dev_private; - /* Turn on VBLANK interrupt */ - MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL) - | MACH64_CRTC_VBLANK_INT_EN); + u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL); - DRM_DEBUG("after install CRTC_INT_CTNL: 0x%08x\n", - MACH64_READ(MACH64_CRTC_INT_CNTL)); + DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status); + mach64_disable_vblank(dev,0); +} + +int mach64_driver_irq_postinstall(struct drm_device * dev) +{ + return drm_vblank_init(dev, 1); } void mach64_driver_irq_uninstall(struct drm_device * dev) { - drm_mach64_private_t *dev_priv = - (drm_mach64_private_t *) dev->dev_private; + drm_mach64_private_t *dev_priv = dev->dev_private; if (!dev_priv) return; - /* Disable and clear VBLANK interrupt */ - MACH64_WRITE(MACH64_CRTC_INT_CNTL, - (MACH64_READ(MACH64_CRTC_INT_CNTL) & - ~MACH64_CRTC_VBLANK_INT_EN) - | MACH64_CRTC_VBLANK_INT); + mach64_disable_vblank(dev, 0); DRM_DEBUG("after uninstall CRTC_INT_CTNL: 0x%08x\n", MACH64_READ(MACH64_CRTC_INT_CNTL)); diff --git a/shared-core/mach64_state.c b/shared-core/mach64_state.c index 88ff4843..c82f38bb 100644 --- a/shared-core/mach64_state.c +++ b/shared-core/mach64_state.c @@ -95,7 +95,7 @@ static int mach64_emit_cliprect(struct drm_file *file_priv, drm_mach64_context_regs_t *regs = &sarea_priv->context_state; DMALOCALS; - DRM_DEBUG("%s: box=%p\n", __FUNCTION__, box); + DRM_DEBUG("box=%p\n", box); /* Get GL scissor */ /* FIXME: store scissor in SAREA as a cliprect instead of in @@ -146,7 +146,7 @@ static __inline__ int mach64_emit_state(struct drm_file *file_priv, if (MACH64_VERBOSE) { mach64_print_dirty(__FUNCTION__, dirty); } else { - DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty); + DRM_DEBUG("dirty=0x%08x\n", dirty); } DMAGETPTR(file_priv, dev_priv, 17); /* returns on failure to get buffer */ @@ -229,7 +229,7 @@ static int mach64_dma_dispatch_clear(struct drm_device * dev, int i; DMALOCALS; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); switch (dev_priv->fb_bpp) { case 16: @@ -368,7 +368,7 @@ static int mach64_dma_dispatch_swap(struct drm_device * dev, int i; DMALOCALS; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); switch (dev_priv->fb_bpp) { case 16: @@ -445,7 +445,7 @@ static int mach64_do_get_frames_queued(drm_mach64_private_t * dev_priv) int i, start; u32 head, tail, ofs; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); if (sarea_priv->frames_queued == 0) return 0; @@ -525,15 +525,14 @@ static __inline__ int copy_from_user_vertex(u32 *to, from += count; to += count; } else { - DRM_ERROR("%s: Got bad command: 0x%04x\n", - __FUNCTION__, reg); + DRM_ERROR("Got bad command: 0x%04x\n", reg); drm_free(orig_from, bytes, DRM_MEM_DRIVER); return -EACCES; } } else { DRM_ERROR - ("%s: Got bad command count(=%u) dwords remaining=%lu\n", - __FUNCTION__, count, n); + ("Got bad command count(=%u) dwords remaining=%lu\n", + count, n); drm_free(orig_from, bytes, DRM_MEM_DRIVER); return -EINVAL; } @@ -543,7 +542,7 @@ static __inline__ int copy_from_user_vertex(u32 *to, if (n == 0) return 0; else { - DRM_ERROR("%s: Bad buf->used(=%lu)\n", __FUNCTION__, bytes); + DRM_ERROR("Bad buf->used(=%lu)\n", bytes); return -EINVAL; } } @@ -563,15 +562,15 @@ static int mach64_dma_dispatch_vertex(struct drm_device * dev, int verify_ret = 0; DMALOCALS; - DRM_DEBUG("%s: buf=%p used=%lu nbox=%d\n", - __FUNCTION__, buf, used, sarea_priv->nbox); + DRM_DEBUG("buf=%p used=%lu nbox=%d\n", + buf, used, sarea_priv->nbox); if (!used) goto _vertex_done; copy_buf = mach64_freelist_get(dev_priv); if (copy_buf == NULL) { - DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__); + DRM_ERROR("couldn't get buffer\n"); return -EAGAIN; } @@ -698,7 +697,7 @@ static int mach64_dma_dispatch_blit(struct drm_device * dev, copy_buf = mach64_freelist_get(dev_priv); if (copy_buf == NULL) { - DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__); + DRM_ERROR("couldn't get buffer\n"); return -EAGAIN; } @@ -759,7 +758,7 @@ static int mach64_dma_dispatch_blit(struct drm_device * dev, DMAOUTREG(MACH64_DST_X_Y, (blit->y << 16) | blit->x); DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (blit->height << 16) | blit->width); - DRM_DEBUG("%s: %lu bytes\n", __FUNCTION__, used); + DRM_DEBUG("%lu bytes\n", used); /* Add the buffer to the queue */ DMAADVANCEHOSTDATA(dev_priv); @@ -780,7 +779,7 @@ int mach64_dma_clear(struct drm_device *dev, void *data, drm_mach64_clear_t *clear = data; int ret; - DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID); + DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -805,7 +804,7 @@ int mach64_dma_swap(struct drm_device *dev, void *data, drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; int ret; - DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID); + DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -830,12 +829,12 @@ int mach64_dma_vertex(struct drm_device *dev, void *data, LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } - DRM_DEBUG("%s: pid=%d buf=%p used=%lu discard=%d\n", - __FUNCTION__, DRM_CURRENTPID, + DRM_DEBUG("pid=%d buf=%p used=%lu discard=%d\n", + DRM_CURRENTPID, vertex->buf, vertex->used, vertex->discard); if (vertex->prim < 0 || vertex->prim > MACH64_PRIM_POLYGON) { @@ -882,10 +881,10 @@ int mach64_get_param(struct drm_device *dev, void *data, drm_mach64_getparam_t *param = data; int value; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } diff --git a/shared-core/mga_dma.c b/shared-core/mga_dma.c index 67236b2d..d56f4d7a 100644 --- a/shared-core/mga_dma.c +++ b/shared-core/mga_dma.c @@ -997,7 +997,7 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup) } } - return 0; + return err; } int mga_dma_init(struct drm_device *dev, void *data, @@ -1049,7 +1049,7 @@ int mga_dma_flush(struct drm_device *dev, void *data, #if MGA_DMA_DEBUG int ret = mga_do_wait_for_idle(dev_priv); if (ret < 0) - DRM_INFO("%s: -EBUSY\n", __FUNCTION__); + DRM_INFO("-EBUSY\n"); return ret; #else return mga_do_wait_for_idle(dev_priv); diff --git a/shared-core/mga_drv.h b/shared-core/mga_drv.h index 0c7fab5b..bf3be808 100644 --- a/shared-core/mga_drv.h +++ b/shared-core/mga_drv.h @@ -113,13 +113,14 @@ typedef struct drm_mga_private { * \sa drm_mga_private_t::mmio */ /*@{*/ - u32 mmio_base; /**< Bus address of base of MMIO. */ - u32 mmio_size; /**< Size of the MMIO region. */ + u32 mmio_base; /**< Bus address of base of MMIO. */ + u32 mmio_size; /**< Size of the MMIO region. */ /*@}*/ u32 clear_cmd; u32 maccess; + atomic_t vbl_received; /**< Number of vblanks received. */ wait_queue_head_t fence_queue; atomic_t last_fence_retired; u32 next_fence_to_post; @@ -181,11 +182,14 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv); extern int mga_warp_init(drm_mga_private_t * dev_priv); /* mga_irq.c */ +extern int mga_enable_vblank(struct drm_device *dev, int crtc); +extern void mga_disable_vblank(struct drm_device *dev, int crtc); +extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc); extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence); extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence); extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS); extern void mga_driver_irq_preinstall(struct drm_device * dev); -extern void mga_driver_irq_postinstall(struct drm_device * dev); +extern int mga_driver_irq_postinstall(struct drm_device * dev); extern void mga_driver_irq_uninstall(struct drm_device * dev); extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); @@ -249,7 +253,7 @@ do { \ } else if ( dev_priv->prim.space < \ dev_priv->prim.high_mark ) { \ if ( MGA_DMA_DEBUG ) \ - DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ + DRM_INFO( "wrap...\n"); \ return -EBUSY; \ } \ } \ @@ -260,7 +264,7 @@ do { \ if ( test_bit( 0, &dev_priv->prim.wrapped ) ) { \ if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { \ if ( MGA_DMA_DEBUG ) \ - DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ + DRM_INFO( "wrap...\n"); \ return -EBUSY; \ } \ mga_do_dma_wrap_end( dev_priv ); \ @@ -280,8 +284,7 @@ do { \ #define BEGIN_DMA( n ) \ do { \ if ( MGA_VERBOSE ) { \ - DRM_INFO( "BEGIN_DMA( %d ) in %s\n", \ - (n), __FUNCTION__ ); \ + DRM_INFO( "BEGIN_DMA( %d )\n", (n) ); \ DRM_INFO( " space=0x%x req=0x%Zx\n", \ dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \ } \ @@ -292,7 +295,7 @@ do { \ #define BEGIN_DMA_WRAP() \ do { \ if ( MGA_VERBOSE ) { \ - DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ ); \ + DRM_INFO( "BEGIN_DMA()\n" ); \ DRM_INFO( " space=0x%x\n", dev_priv->prim.space ); \ } \ prim = dev_priv->prim.start; \ @@ -311,7 +314,7 @@ do { \ #define FLUSH_DMA() \ do { \ if ( 0 ) { \ - DRM_INFO( "%s:\n", __FUNCTION__ ); \ + DRM_INFO( "\n" ); \ DRM_INFO( " tail=0x%06x head=0x%06lx\n", \ dev_priv->prim.tail, \ MGA_READ( MGA_PRIMADDRESS ) - \ diff --git a/shared-core/mga_irq.c b/shared-core/mga_irq.c index 0f83577f..4fe86322 100644 --- a/shared-core/mga_irq.c +++ b/shared-core/mga_irq.c @@ -36,6 +36,20 @@ #include "mga_drm.h" #include "mga_drv.h" +u32 mga_get_vblank_counter(struct drm_device *dev, int crtc) +{ + const drm_mga_private_t *const dev_priv = + (drm_mga_private_t *) dev->dev_private; + + if (crtc != 0) { + return 0; + } + + + return atomic_read(&dev_priv->vbl_received); +} + + irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -48,9 +62,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) /* VBLANK interrupt */ if (status & MGA_VLINEPEN) { MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); - atomic_inc(&dev->vbl_received); - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); + atomic_inc(&dev_priv->vbl_received); + drm_handle_vblank(dev, 0); handled = 1; } @@ -79,22 +92,34 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) return IRQ_NONE; } -int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) +int mga_enable_vblank(struct drm_device *dev, int crtc) { - unsigned int cur_vblank; - int ret = 0; + drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(&dev->vbl_received)) - - *sequence) <= (1 << 23))); + if (crtc != 0) { + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + return 0; + } - *sequence = cur_vblank; + MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); + return 0; +} - return ret; + +void mga_disable_vblank(struct drm_device *dev, int crtc) +{ + if (crtc != 0) { + DRM_ERROR("tried to disable vblank on non-existent crtc %d\n", + crtc); + } + + /* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have + * a nice hardware counter that tracks the number of refreshes when + * the interrupt is disabled, and the kernel doesn't know the refresh + * rate to calculate an estimate. + */ + /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */ } int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence) @@ -126,14 +151,22 @@ void mga_driver_irq_preinstall(struct drm_device * dev) MGA_WRITE(MGA_ICLEAR, ~0); } -void mga_driver_irq_postinstall(struct drm_device * dev) +int mga_driver_irq_postinstall(struct drm_device * dev) { drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; + int ret; + + ret = drm_vblank_init(dev, 1); + if (ret) + return ret; DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); - /* Turn on vertical blank interrupt and soft trap interrupt. */ - MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); + /* Turn on soft trap interrupt. Vertical blank interrupts are enabled + * in mga_enable_vblank. + */ + MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN); + return 0; } void mga_driver_irq_uninstall(struct drm_device * dev) diff --git a/shared-core/mga_state.c b/shared-core/mga_state.c index d9cc9d7e..2da108be 100644 --- a/shared-core/mga_state.c +++ b/shared-core/mga_state.c @@ -644,7 +644,7 @@ static void mga_dma_dispatch_swap(struct drm_device * dev) FLUSH_DMA(); - DRM_DEBUG("%s... done.\n", __FUNCTION__); + DRM_DEBUG("... done.\n"); } static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf) @@ -656,7 +656,7 @@ static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * bu u32 length = (u32) buf->used; int i = 0; DMA_LOCALS; - DRM_DEBUG("vertex: buf=%d used=%d\n", buf->idx, buf->used); + DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used); if (buf->used) { buf_priv->dispatched = 1; @@ -703,7 +703,7 @@ static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * b u32 address = (u32) buf->bus_address; int i = 0; DMA_LOCALS; - DRM_DEBUG("indices: buf=%d start=%d end=%d\n", buf->idx, start, end); + DRM_DEBUG("buf=%d start=%d end=%d\n", buf->idx, start, end); if (start != end) { buf_priv->dispatched = 1; @@ -988,7 +988,7 @@ static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *fi #if 0 if (mga_do_wait_for_idle(dev_priv) < 0) { if (MGA_DMA_DEBUG) - DRM_INFO("%s: -EBUSY\n", __FUNCTION__); + DRM_INFO("-EBUSY\n"); return -EBUSY; } #endif @@ -1047,7 +1047,7 @@ static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *fil int value; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -1079,7 +1079,7 @@ static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *fi DMA_LOCALS; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -1108,7 +1108,7 @@ static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file *f u32 *fence = data; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 85a0d0b5..4184aa5b 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -432,7 +432,7 @@ extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, /* nouveau_irq.c */ extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); extern void nouveau_irq_preinstall(struct drm_device *); -extern void nouveau_irq_postinstall(struct drm_device *); +extern int nouveau_irq_postinstall(struct drm_device *); extern void nouveau_irq_uninstall(struct drm_device *); /* nouveau_sgdma.c */ diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index 500fda2f..bceb81ab 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -46,13 +46,15 @@ nouveau_irq_preinstall(struct drm_device *dev) NV_WRITE(NV03_PMC_INTR_EN_0, 0); } -void +int nouveau_irq_postinstall(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; /* Master enable */ NV_WRITE(NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE); + + return 0; } void diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index 5259ea27..f4e641b9 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -619,7 +619,7 @@ alloc_ok: block->map_handle = entry->user_token; } - DRM_DEBUG("allocated 0x%llx type=0x%08x\n", block->start, block->flags); + DRM_DEBUG("allocated %lld bytes at 0x%llx type=0x%08x\n", block->size, block->start, block->flags); return block; } diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 7ac02f4a..a2506146 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -112,6 +112,9 @@ #define NV50_PUNK_BAR3_CTXDMA_VALID (1<<31) #define NV50_PUNK_UNK1710 0x00001710 +#define NV04_PBUS_PCI_NV_1 0x00001804 +#define NV04_PBUS_PCI_NV_19 0x0000184C + #define NV04_PTIMER_INTR_0 0x00009100 #define NV04_PTIMER_INTR_EN_0 0x00009140 #define NV04_PTIMER_NUMERATOR 0x00009200 diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 16c86494..7086a0ab 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -88,7 +88,6 @@ static int nouveau_init_card_mappings(struct drm_device *dev) static int nouveau_stub_init(struct drm_device *dev) { return 0; } static void nouveau_stub_takedown(struct drm_device *dev) {} -static uint64_t nouveau_stub_timer_read(struct drm_device *dev) { return 0; } static int nouveau_init_engine_ptrs(struct drm_device *dev) { @@ -251,9 +250,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->instmem.unbind = nv50_instmem_unbind; engine->mc.init = nv50_mc_init; engine->mc.takedown = nv50_mc_takedown; - engine->timer.init = nouveau_stub_init; - engine->timer.read = nouveau_stub_timer_read; - engine->timer.takedown = nouveau_stub_takedown; + engine->timer.init = nv04_timer_init; + engine->timer.read = nv04_timer_read; + engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nouveau_stub_init; engine->fb.takedown = nouveau_stub_takedown; engine->graph.init = nv50_graph_init; @@ -285,9 +284,6 @@ nouveau_card_init(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine; int ret; -#if defined(__powerpc__) - struct device_node *dn; -#endif DRM_DEBUG("prev state = %d\n", dev_priv->init_state); @@ -295,43 +291,6 @@ nouveau_card_init(struct drm_device *dev) return 0; dev_priv->ttm = 0; - /* Map any PCI resources we need on the card */ - ret = nouveau_init_card_mappings(dev); - if (ret) return ret; - -#if defined(__powerpc__) - /* Put the card in BE mode if it's not */ - if (NV_READ(NV03_PMC_BOOT_1)) - NV_WRITE(NV03_PMC_BOOT_1,0x00000001); - - DRM_MEMORYBARRIER(); -#endif - -#if defined(__linux__) && defined(__powerpc__) - /* if we have an OF card, copy vbios to RAMIN */ - dn = pci_device_to_OF_node(dev->pdev); - if (dn) - { - int size; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) - const uint32_t *bios = of_get_property(dn, "NVDA,BMP", &size); -#else - const uint32_t *bios = get_property(dn, "NVDA,BMP", &size); -#endif - if (bios) - { - int i; - for(i=0;i<size;i+=4) - NV_WI32(i, bios[i/4]); - DRM_INFO("OF bios successfully copied (%d bytes)\n",size); - } - else - DRM_INFO("Unable to get the OF bios\n"); - } - else - DRM_INFO("Unable to get the OF node\n"); -#endif - /* Determine exact chipset we're running on */ if (dev_priv->card_type < NV_10) dev_priv->chipset = dev_priv->card_type; @@ -451,6 +410,47 @@ void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv) /* first module load, setup the mmio/fb mapping */ int nouveau_firstopen(struct drm_device *dev) { +#if defined(__powerpc__) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct device_node *dn; +#endif + int ret; + /* Map any PCI resources we need on the card */ + ret = nouveau_init_card_mappings(dev); + if (ret) return ret; + +#if defined(__powerpc__) + /* Put the card in BE mode if it's not */ + if (NV_READ(NV03_PMC_BOOT_1)) + NV_WRITE(NV03_PMC_BOOT_1,0x00000001); + + DRM_MEMORYBARRIER(); +#endif + +#if defined(__linux__) && defined(__powerpc__) + /* if we have an OF card, copy vbios to RAMIN */ + dn = pci_device_to_OF_node(dev->pdev); + if (dn) + { + int size; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) + const uint32_t *bios = of_get_property(dn, "NVDA,BMP", &size); +#else + const uint32_t *bios = get_property(dn, "NVDA,BMP", &size); +#endif + if (bios) + { + int i; + for(i=0;i<size;i+=4) + NV_WI32(i, bios[i/4]); + DRM_INFO("OF bios successfully copied (%d bytes)\n",size); + } + else + DRM_INFO("Unable to get the OF bios\n"); + } + else + DRM_INFO("Unable to get the OF node\n"); +#endif return 0; } @@ -498,7 +498,12 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) iounmap(regs); - if (architecture >= 0x50) { + if (architecture >= 0x80) { + dev_priv->card_type = NV_50; + } else if (architecture >= 0x60) { + /* FIXME we need to figure out who's who for NV6x */ + dev_priv->card_type = NV_44; + } else if (architecture >= 0x50) { dev_priv->card_type = NV_50; } else if (architecture >= 0x40) { uint8_t subarch = architecture & 0xf; diff --git a/shared-core/nv04_graph.c b/shared-core/nv04_graph.c index 81a6d5c8..6caae257 100644 --- a/shared-core/nv04_graph.c +++ b/shared-core/nv04_graph.c @@ -497,7 +497,7 @@ int nv04_graph_init(struct drm_device *dev) { /*haiku same*/ /*NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/ - NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x10d4ff31); + NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xf0d4ff31); /*haiku and blob 10d4*/ NV_WRITE(NV04_PGRAPH_STATE , 0xFFFFFFFF); diff --git a/shared-core/nv04_mc.c b/shared-core/nv04_mc.c index 24c1f7b3..766f3a33 100644 --- a/shared-core/nv04_mc.c +++ b/shared-core/nv04_mc.c @@ -7,12 +7,25 @@ int nv04_mc_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t saved_pci_nv_1, saved_pci_nv_19; + + saved_pci_nv_1 = NV_READ(NV04_PBUS_PCI_NV_1); + saved_pci_nv_19 = NV_READ(NV04_PBUS_PCI_NV_19); + + /* clear busmaster bit */ + NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~(0x00000001 << 2)); + /* clear SBA and AGP bits */ + NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff); /* Power up everything, resetting each individual unit will * be done later if needed. */ NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF); + /* and restore (gives effect of resetting AGP) */ + NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19); + NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1); + return 0; } diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c index 81501ed7..37a147b5 100644 --- a/shared-core/nv20_graph.c +++ b/shared-core/nv20_graph.c @@ -432,19 +432,6 @@ static void nv30_31_graph_context_init(struct drm_device *dev, INSTANCE_WR(ctx, 0x385c/4, 0x3f800000); INSTANCE_WR(ctx, 0x3864/4, 0xbf800000); INSTANCE_WR(ctx, 0x386c/4, 0xbf800000); - - /* nv30gl stuff */ - for (i=0; i<8; i++) { - INSTANCE_WR(ctx, (0x4dfc/4)+i, 0x001c527d); - } - INSTANCE_WR(ctx, 0x4e3c/4, 0x001c527c); -/* these ones make dma fifo hang - INSTANCE_WR(ctx, 0x567c/4, 0x000a0000); - INSTANCE_WR(ctx, 0x0878/4, 0x01000000); - INSTANCE_WR(ctx, 0x02f4/4, 0x0001ffff); - - INSTANCE_WR(ctx, 0x0028/4, INSTANCE_RD(ctx, 0x0028/4) | 1); -*/ } static void nv34_graph_context_init(struct drm_device *dev, @@ -655,6 +642,7 @@ int nv20_graph_load_context(struct nouveau_channel *chan) NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_XFER, NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD); + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100); nouveau_wait_for_idle(dev); return 0; @@ -772,7 +760,7 @@ int nv20_graph_init(struct drm_device *dev) { NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x00EA000C); NV_WRITE(NV10_PGRAPH_RDI_DATA, NV_READ(0x100324)); - NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100); + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000100); NV_WRITE(NV10_PGRAPH_STATE , 0xFFFFFFFF); NV_WRITE(NV04_PGRAPH_FIFO , 0x00000001); @@ -867,7 +855,7 @@ int nv30_graph_init(struct drm_device *dev) NV_WRITE(NV10_PGRAPH_TSTATUS(i), NV_READ(NV10_PFB_TSTATUS(i))); } - NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100); + NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000100); NV_WRITE(NV10_PGRAPH_STATE , 0xFFFFFFFF); NV_WRITE(NV04_PGRAPH_FIFO , 0x00000001); diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c index c5cde913..edf4edbf 100644 --- a/shared-core/nv50_fifo.c +++ b/shared-core/nv50_fifo.c @@ -28,9 +28,10 @@ #include "drm.h" #include "nouveau_drv.h" -typedef struct { - struct nouveau_gpuobj_ref *thingo; -} nv50_fifo_priv; +struct nv50_fifo_priv { + struct nouveau_gpuobj_ref *thingo[2]; + int cur_thingo; +}; #define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50) @@ -38,23 +39,23 @@ static void nv50_fifo_init_thingo(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv; - struct nouveau_gpuobj_ref *thingo = priv->thingo; - int i, fi=2; + struct nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv; + struct nouveau_gpuobj_ref *cur; + int i, nr; DRM_DEBUG("\n"); - INSTANCE_WR(thingo->gpuobj, 0, 0x7e); - INSTANCE_WR(thingo->gpuobj, 1, 0x7e); - for (i = 1; i < 127; i++, fi) { + cur = priv->thingo[priv->cur_thingo]; + priv->cur_thingo = !priv->cur_thingo; + + /* We never schedule channel 0 or 127 */ + for (i = 1, nr = 0; i < 127; i++) { if (dev_priv->fifos[i]) { - INSTANCE_WR(thingo->gpuobj, fi, i); - fi++; + INSTANCE_WR(cur->gpuobj, nr++, i); } } - - NV_WRITE(0x32f4, thingo->instance >> 12); - NV_WRITE(0x32ec, fi); + NV_WRITE(0x32f4, cur->instance >> 12); + NV_WRITE(0x32ec, nr); NV_WRITE(0x2500, 0x101); } @@ -98,14 +99,12 @@ static void nv50_fifo_init_reset(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t pmc_e; + uint32_t pmc_e = NV_PMC_ENABLE_PFIFO; DRM_DEBUG("\n"); - pmc_e = NV_READ(NV03_PMC_ENABLE); - NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PFIFO); - pmc_e = NV_READ(NV03_PMC_ENABLE); - NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PFIFO); + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & ~pmc_e); + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | pmc_e); } static void @@ -141,7 +140,7 @@ nv50_fifo_init_regs__nv(struct drm_device *dev) NV_WRITE(0x250c, 0x6f3cfc34); } -static int +static void nv50_fifo_init_regs(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -158,15 +157,13 @@ nv50_fifo_init_regs(struct drm_device *dev) /* Enable dummy channels setup by nv50_instmem.c */ nv50_fifo_channel_enable(dev, 0, 1); nv50_fifo_channel_enable(dev, 127, 1); - - return 0; } int nv50_fifo_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - nv50_fifo_priv *priv; + struct nv50_fifo_priv *priv; int ret; DRM_DEBUG("\n"); @@ -179,18 +176,23 @@ nv50_fifo_init(struct drm_device *dev) nv50_fifo_init_reset(dev); nv50_fifo_init_intr(dev); - if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, (128+2)*4, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, - &priv->thingo))) { - DRM_ERROR("error creating thingo: %d\n", ret); + ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[0]); + if (ret) { + DRM_ERROR("error creating thingo0: %d\n", ret); return ret; } - nv50_fifo_init_context_table(dev); + ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[1]); + if (ret) { + DRM_ERROR("error creating thingo1: %d\n", ret); + return ret; + } + nv50_fifo_init_context_table(dev); nv50_fifo_init_regs__nv(dev); - if ((ret = nv50_fifo_init_regs(dev))) - return ret; + nv50_fifo_init_regs(dev); return 0; } @@ -199,14 +201,15 @@ void nv50_fifo_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv; + struct nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv; DRM_DEBUG("\n"); if (!priv) return; - nouveau_gpuobj_ref_del(dev, &priv->thingo); + nouveau_gpuobj_ref_del(dev, &priv->thingo[0]); + nouveau_gpuobj_ref_del(dev, &priv->thingo[1]); dev_priv->Engine.fifo.priv = NULL; drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER); @@ -234,18 +237,18 @@ nv50_fifo_create_context(struct nouveau_channel *chan) if (IS_G80) { uint32_t ramfc_offset = chan->ramin->gpuobj->im_pramin->start; uint32_t vram_offset = chan->ramin->gpuobj->im_backing->start; - if ((ret = nouveau_gpuobj_new_fake(dev, ramfc_offset, - vram_offset, 0x100, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, - &ramfc, &chan->ramfc))) - return ret; + ret = nouveau_gpuobj_new_fake(dev, ramfc_offset, vram_offset, + 0x100, NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &ramfc, + &chan->ramfc); + if (ret) + return ret; } else { - if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100, - 256, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, - &chan->ramfc))) + ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100, 256, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, + &chan->ramfc); + if (ret) return ret; ramfc = chan->ramfc->gpuobj; } @@ -272,7 +275,8 @@ nv50_fifo_create_context(struct nouveau_channel *chan) INSTANCE_WR(ramfc, 0x98/4, chan->ramin->instance >> 12); } - if ((ret = nv50_fifo_channel_enable(dev, chan->id, 0))) { + ret = nv50_fifo_channel_enable(dev, chan->id, 0); + if (ret) { DRM_ERROR("error enabling ch%d: %d\n", chan->id, ret); nouveau_gpuobj_ref_del(dev, &chan->ramfc); return ret; diff --git a/shared-core/nv50_graph.c b/shared-core/nv50_graph.c index 5814abd4..503f45dd 100644 --- a/shared-core/nv50_graph.c +++ b/shared-core/nv50_graph.c @@ -34,14 +34,12 @@ static void nv50_graph_init_reset(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t pmc_e; + uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21); DRM_DEBUG("\n"); - pmc_e = NV_READ(NV03_PMC_ENABLE); - NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PGRAPH); - pmc_e = NV_READ(NV03_PMC_ENABLE); - NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PGRAPH); + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & ~pmc_e); + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | pmc_e); } static void @@ -51,6 +49,7 @@ nv50_graph_init_intr(struct drm_device *dev) DRM_DEBUG("\n"); NV_WRITE(NV03_PGRAPH_INTR, 0xffffffff); + NV_WRITE(0x400138, 0xffffffff); NV_WRITE(NV40_PGRAPH_INTR_EN, 0xffffffff); } @@ -146,12 +145,53 @@ static uint32_t nv84_ctx_voodoo[] = { 0x00415e06, 0x00415f05, 0x0060000d, 0x00700005, 0x0070000d, 0x00700006, 0x0070000b, 0x0070000e, 0x0070001c, 0x0060000c, ~0 }; + +static uint32_t nv86_ctx_voodoo[] = { + 0x0070008e, 0x0070009c, 0x00200020, 0x00600008, 0x0050004c, 0x00400e89, + 0x00200000, 0x00600007, 0x00300000, 0x00c000ff, 0x00200000, 0x008000ff, + 0x00700009, 0x0040dd4d, 0x00402944, 0x00402905, 0x0040290d, 0x0040b906, + 0x00600005, 0x004015c5, 0x00600011, 0x0040270b, 0x004021c5, 0x00700000, + 0x00700081, 0x00600004, 0x0050004a, 0x00216d80, 0x00600007, 0x00c02801, + 0x0020002e, 0x00800001, 0x005000cb, 0x0090ffff, 0x0091ffff, 0x00200020, + 0x00600008, 0x0050004c, 0x00600009, 0x0040b945, 0x0040d44d, 0x0070009d, + 0x00402dcf, 0x0070009f, 0x0050009f, 0x00402ac0, 0x00200200, 0x00600008, + 0x00402a4f, 0x00402ac0, 0x004030cc, 0x00700081, 0x00200000, 0x00600006, + 0x00700000, 0x00111bfc, 0x00700083, 0x00300000, 0x00216d80, 0x00600007, + 0x00c00b01, 0x0020001e, 0x00800001, 0x005000cb, 0x00c000ff, 0x00700080, + 0x00700083, 0x00200047, 0x00600006, 0x0011020a, 0x00200280, 0x00600007, + 0x00300000, 0x00c000ff, 0x00c800ff, 0x0040c407, 0x00202916, 0x008000ff, + 0x0040508c, 0x005000cb, 0x00a0023f, 0x00200040, 0x00600006, 0x0070000f, + 0x00170202, 0x0011020a, 0x00200032, 0x0010020d, 0x001c0242, 0x00120302, + 0x00140402, 0x00180500, 0x00130509, 0x00150550, 0x00110605, 0x0020000f, + 0x00100607, 0x00110700, 0x00110900, 0x00120902, 0x00110a00, 0x00160b02, + 0x00120b28, 0x00140b2b, 0x00110c01, 0x00111400, 0x00111405, 0x00111407, + 0x00111409, 0x0011140b, 0x002000cb, 0x00101500, 0x0040790f, 0x0040794b, + 0x00214b40, 0x00600007, 0x00200442, 0x008800ff, 0x0070008f, 0x0040798c, + 0x005000cb, 0x00000000, 0x0020002b, 0x00101a05, 0x00131c00, 0x00121c04, + 0x00141c20, 0x00111c25, 0x00131c40, 0x00121c44, 0x00141c60, 0x00111c65, + 0x00131f00, 0x00191f40, 0x004099e0, 0x002001d9, 0x00600006, 0x00200044, + 0x00102080, 0x001120c6, 0x001520c9, 0x001920d0, 0x00122100, 0x00122103, + 0x00162200, 0x00122207, 0x00112280, 0x00112300, 0x00112302, 0x00122380, + 0x0011238b, 0x00112394, 0x0011239c, 0x00000000, 0x0040a00f, 0x005000cb, + 0x00214b40, 0x00600007, 0x00200442, 0x008800ff, 0x005000cb, 0x0040a387, + 0x0060000a, 0x00000000, 0x0040b200, 0x007000a0, 0x00700080, 0x00200280, + 0x00600007, 0x00200004, 0x00c000ff, 0x008000ff, 0x005000cb, 0x00700000, + 0x00200000, 0x00600006, 0x00111bfe, 0x0040d44d, 0x00700000, 0x00200000, + 0x00600006, 0x00111bfe, 0x00700080, 0x0070001d, 0x0040114d, 0x00700081, + 0x00600004, 0x0050004a, 0x0040be88, 0x0060000b, 0x00200000, 0x00600006, + 0x00700000, 0x0040d40b, 0x00111bfd, 0x0040424d, 0x00202916, 0x008000fd, + 0x005000cb, 0x00c00002, 0x00200280, 0x00600007, 0x00200160, 0x00800002, + 0x005000cb, 0x00c01802, 0x002027b6, 0x00800002, 0x005000cb, 0x00404e4d, + 0x0060000b, 0x0040d24d, 0x00700001, 0x00700003, 0x0040d806, 0x0040d905, + 0x0060000d, 0x00700005, 0x0070000d, 0x00700006, 0x0070000b, 0x0070000e, + 0x0070001c, 0x0060000c, ~0 +}; -static void +static int nv50_graph_init_ctxctl(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t *voodoo; + uint32_t *voodoo = NULL; DRM_DEBUG("\n"); @@ -159,34 +199,42 @@ nv50_graph_init_ctxctl(struct drm_device *dev) case 0x84: voodoo = nv84_ctx_voodoo; break; + case 0x86: + voodoo = nv86_ctx_voodoo; + break; default: DRM_ERROR("no voodoo for chipset NV%02x\n", dev_priv->chipset); - break; + return -EINVAL; } - if (voodoo) { - NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); - while (*voodoo != ~0) { - NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA, *voodoo); - voodoo++; - } + NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); + while (*voodoo != ~0) { + NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA, *voodoo); + voodoo++; } NV_WRITE(0x400320, 4); NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, 0); NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, 0); + + return 0; } int nv50_graph_init(struct drm_device *dev) { + int ret; + DRM_DEBUG("\n"); nv50_graph_init_reset(dev); nv50_graph_init_intr(dev); nv50_graph_init_regs__nv(dev); nv50_graph_init_regs(dev); - nv50_graph_init_ctxctl(dev); + + ret = nv50_graph_init_ctxctl(dev); + if (ret) + return ret; return 0; } @@ -209,11 +257,10 @@ nv50_graph_create_context(struct nouveau_channel *chan) DRM_DEBUG("ch%d\n", chan->id); - if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, - grctx_size, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, - &chan->ramin_grctx))) + ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, grctx_size, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); + if (ret) return ret; hdr = IS_G80 ? 0x200 : 0x20; @@ -225,11 +272,16 @@ nv50_graph_create_context(struct nouveau_channel *chan) INSTANCE_WR(ramin, (hdr + 0x10)/4, 0); INSTANCE_WR(ramin, (hdr + 0x14)/4, 0x00010000); - if ((ret = engine->graph.load_context(chan))) { + ret = engine->graph.load_context(chan); + if (ret) { DRM_ERROR("Error hacking up initial context: %d\n", ret); return ret; } + INSTANCE_WR(chan->ramin_grctx->gpuobj, 0x00000/4, + chan->ramin->instance >> 12); + INSTANCE_WR(chan->ramin_grctx->gpuobj, 0x0011c/4, 0x00000002); + return 0; } @@ -259,7 +311,7 @@ nv50_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) DRM_DEBUG("inst=0x%08x, save=%d\n", inst, save); old_cp = NV_READ(NV20_PGRAPH_CHANNEL_CTX_POINTER); - NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst | (1<<31)); + NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); NV_WRITE(0x400824, NV_READ(0x400824) | (save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE : NV40_PGRAPH_CTXCTL_0310_XFER_LOAD)); @@ -286,7 +338,7 @@ nv50_graph_load_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31)); + uint32_t inst = chan->ramin->instance >> 12; int ret; (void)ret; DRM_DEBUG("ch%d\n", chan->id); @@ -298,7 +350,7 @@ nv50_graph_load_context(struct nouveau_channel *chan) NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); NV_WRITE(0x400320, 4); - NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, inst); + NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, inst | (1<<31)); return 0; } @@ -307,7 +359,7 @@ int nv50_graph_save_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; - uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31)); + uint32_t inst = chan->ramin->instance >> 12; DRM_DEBUG("ch%d\n", chan->id); diff --git a/shared-core/nv50_instmem.c b/shared-core/nv50_instmem.c index c80574a9..9687ecbb 100644 --- a/shared-core/nv50_instmem.c +++ b/shared-core/nv50_instmem.c @@ -69,6 +69,10 @@ nv50_instmem_init(struct drm_device *dev) return -ENOMEM; dev_priv->Engine.instmem.priv = priv; + /* Save state, will restore at takedown. */ + for (i = 0x1700; i <= 0x1710; i+=4) + priv->save1700[(i-0x1700)/4] = NV_READ(i); + /* Reserve the last MiB of VRAM, we should probably try to avoid * setting up the below tables over the top of the VBIOS image at * some point. diff --git a/shared-core/r128_cce.c b/shared-core/r128_cce.c index 8ce128bd..204ea37d 100644 --- a/shared-core/r128_cce.c +++ b/shared-core/r128_cce.c @@ -649,7 +649,7 @@ int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_pri LOCK_TEST_WITH_RETURN(dev, file_priv); if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) { - DRM_DEBUG("%s while CCE running\n", __FUNCTION__); + DRM_DEBUG("while CCE running\n"); return 0; } @@ -708,7 +708,7 @@ int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_pri LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_DEBUG("%s called before init done\n", __FUNCTION__); + DRM_DEBUG("called before init done\n"); return -EINVAL; } diff --git a/shared-core/r128_drv.h b/shared-core/r128_drv.h index b0558389..ab8b6297 100644 --- a/shared-core/r128_drv.h +++ b/shared-core/r128_drv.h @@ -97,6 +97,8 @@ typedef struct drm_r128_private { u32 crtc_offset; u32 crtc_offset_cntl; + atomic_t vbl_received; + u32 color_fmt; unsigned int front_offset; unsigned int front_pitch; @@ -149,11 +151,12 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n); extern int r128_do_cce_idle(drm_r128_private_t * dev_priv); extern int r128_do_cleanup_cce(struct drm_device * dev); -extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence); - +extern int r128_enable_vblank(struct drm_device *dev, int crtc); +extern void r128_disable_vblank(struct drm_device *dev, int crtc); +extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc); extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS); extern void r128_driver_irq_preinstall(struct drm_device * dev); -extern void r128_driver_irq_postinstall(struct drm_device * dev); +extern int r128_driver_irq_postinstall(struct drm_device * dev); extern void r128_driver_irq_uninstall(struct drm_device * dev); extern void r128_driver_lastclose(struct drm_device * dev); extern void r128_driver_preclose(struct drm_device * dev, @@ -462,8 +465,7 @@ do { \ #define BEGIN_RING( n ) do { \ if ( R128_VERBOSE ) { \ - DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ - (n), __FUNCTION__ ); \ + DRM_INFO( "BEGIN_RING( %d )\n", (n)); \ } \ if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ COMMIT_RING(); \ diff --git a/shared-core/r128_irq.c b/shared-core/r128_irq.c index c76fdca7..5b95bd89 100644 --- a/shared-core/r128_irq.c +++ b/shared-core/r128_irq.c @@ -35,6 +35,16 @@ #include "r128_drm.h" #include "r128_drv.h" +u32 r128_get_vblank_counter(struct drm_device *dev, int crtc) +{ + const drm_r128_private_t *dev_priv = dev->dev_private; + + if (crtc != 0) + return 0; + + return atomic_read(&dev_priv->vbl_received); +} + irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -46,30 +56,38 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS) /* VBLANK interrupt */ if (status & R128_CRTC_VBLANK_INT) { R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); - atomic_inc(&dev->vbl_received); - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); + atomic_inc(&dev_priv->vbl_received); + drm_handle_vblank(dev, 0); return IRQ_HANDLED; } return IRQ_NONE; } -int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) +int r128_enable_vblank(struct drm_device *dev, int crtc) { - unsigned int cur_vblank; - int ret = 0; + drm_r128_private_t *dev_priv = dev->dev_private; - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(&dev->vbl_received)) - - *sequence) <= (1 << 23))); + if (crtc != 0) { + DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); + return -EINVAL; + } - *sequence = cur_vblank; + R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN); + return 0; +} + +void r128_disable_vblank(struct drm_device *dev, int crtc) +{ + if (crtc != 0) + DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); - return ret; + /* + * FIXME: implement proper interrupt disable by using the vblank + * counter register (if available) + * + * R128_WRITE(R128_GEN_INT_CNTL, + * R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN); + */ } void r128_driver_irq_preinstall(struct drm_device * dev) @@ -82,12 +100,9 @@ void r128_driver_irq_preinstall(struct drm_device * dev) R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); } -void r128_driver_irq_postinstall(struct drm_device * dev) +int r128_driver_irq_postinstall(struct drm_device * dev) { - drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; - - /* Turn on VBL interrupt */ - R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN); + return drm_vblank_init(dev, 1); } void r128_driver_irq_uninstall(struct drm_device * dev) diff --git a/shared-core/r128_state.c b/shared-core/r128_state.c index b7f483ca..51a9afce 100644 --- a/shared-core/r128_state.c +++ b/shared-core/r128_state.c @@ -42,7 +42,7 @@ static void r128_emit_clip_rects(drm_r128_private_t * dev_priv, { u32 aux_sc_cntl = 0x00000000; RING_LOCALS; - DRM_DEBUG(" %s\n", __FUNCTION__); + DRM_DEBUG("\n"); BEGIN_RING((count < 3 ? count : 3) * 5 + 2); @@ -85,7 +85,7 @@ static __inline__ void r128_emit_core(drm_r128_private_t * dev_priv) drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_context_regs_t *ctx = &sarea_priv->context_state; RING_LOCALS; - DRM_DEBUG(" %s\n", __FUNCTION__); + DRM_DEBUG("\n"); BEGIN_RING(2); @@ -100,7 +100,7 @@ static __inline__ void r128_emit_context(drm_r128_private_t * dev_priv) drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_context_regs_t *ctx = &sarea_priv->context_state; RING_LOCALS; - DRM_DEBUG(" %s\n", __FUNCTION__); + DRM_DEBUG("\n"); BEGIN_RING(13); @@ -126,7 +126,7 @@ static __inline__ void r128_emit_setup(drm_r128_private_t * dev_priv) drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_context_regs_t *ctx = &sarea_priv->context_state; RING_LOCALS; - DRM_DEBUG(" %s\n", __FUNCTION__); + DRM_DEBUG("\n"); BEGIN_RING(3); @@ -142,7 +142,7 @@ static __inline__ void r128_emit_masks(drm_r128_private_t * dev_priv) drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_context_regs_t *ctx = &sarea_priv->context_state; RING_LOCALS; - DRM_DEBUG(" %s\n", __FUNCTION__); + DRM_DEBUG("\n"); BEGIN_RING(5); @@ -161,7 +161,7 @@ static __inline__ void r128_emit_window(drm_r128_private_t * dev_priv) drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_r128_context_regs_t *ctx = &sarea_priv->context_state; RING_LOCALS; - DRM_DEBUG(" %s\n", __FUNCTION__); + DRM_DEBUG("\n"); BEGIN_RING(2); @@ -178,7 +178,7 @@ static __inline__ void r128_emit_tex0(drm_r128_private_t * dev_priv) drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0]; int i; RING_LOCALS; - DRM_DEBUG(" %s\n", __FUNCTION__); + DRM_DEBUG("\n"); BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS); @@ -204,7 +204,7 @@ static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv) drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1]; int i; RING_LOCALS; - DRM_DEBUG(" %s\n", __FUNCTION__); + DRM_DEBUG("\n"); BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS); @@ -226,7 +226,7 @@ static void r128_emit_state(drm_r128_private_t * dev_priv) drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; - DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty); + DRM_DEBUG("dirty=0x%08x\n", dirty); if (dirty & R128_UPLOAD_CORE) { r128_emit_core(dev_priv); @@ -362,7 +362,7 @@ static void r128_cce_dispatch_clear(struct drm_device * dev, unsigned int flags = clear->flags; int i; RING_LOCALS; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); if (dev_priv->page_flipping && dev_priv->current_page == 1) { unsigned int tmp = flags; @@ -466,7 +466,7 @@ static void r128_cce_dispatch_swap(struct drm_device * dev) struct drm_clip_rect *pbox = sarea_priv->boxes; int i; RING_LOCALS; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); #if R128_PERFORMANCE_BOXES /* Do some trivial performance monitoring... @@ -528,8 +528,7 @@ static void r128_cce_dispatch_flip(struct drm_device * dev) { drm_r128_private_t *dev_priv = dev->dev_private; RING_LOCALS; - DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", - __FUNCTION__, + DRM_DEBUG("page=%d pfCurrentPage=%d\n", dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage); #if R128_PERFORMANCE_BOXES @@ -1156,7 +1155,7 @@ static int r128_cce_dispatch_read_pixels(struct drm_device * dev, int count, *x, *y; int i, xbuf_size, ybuf_size; RING_LOCALS; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); count = depth->n; if (count > 4096 || count <= 0) @@ -1226,7 +1225,7 @@ static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple) drm_r128_private_t *dev_priv = dev->dev_private; int i; RING_LOCALS; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); BEGIN_RING(33); @@ -1309,7 +1308,7 @@ static int r128_do_cleanup_pageflip(struct drm_device * dev) static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -1328,7 +1327,7 @@ static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *fi { drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -1356,7 +1355,7 @@ static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file * LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -1412,7 +1411,7 @@ static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -1557,11 +1556,11 @@ static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } - DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n", + DRM_DEBUG("idx=%d s=%d e=%d d=%d\n", indirect->idx, indirect->start, indirect->end, indirect->discard); @@ -1622,7 +1621,7 @@ static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *fi int value; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index 6ab907c6..a26a71d5 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -77,23 +77,31 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, return -EFAULT; } - box.x1 = - (box.x1 + - R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK; - box.y1 = - (box.y1 + - R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK; - box.x2 = - (box.x2 + - R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK; - box.y2 = - (box.y2 + - R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK; + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { + box.x1 = (box.x1) & + R300_CLIPRECT_MASK; + box.y1 = (box.y1) & + R300_CLIPRECT_MASK; + box.x2 = (box.x2) & + R300_CLIPRECT_MASK; + box.y2 = (box.y2) & + R300_CLIPRECT_MASK; + } else { + box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) & + R300_CLIPRECT_MASK; + box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) & + R300_CLIPRECT_MASK; + box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) & + R300_CLIPRECT_MASK; + box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & + R300_CLIPRECT_MASK; + } OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) | (box.y1 << R300_CLIPRECT_Y_SHIFT)); OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) | (box.y2 << R300_CLIPRECT_Y_SHIFT)); + } OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]); @@ -133,9 +141,11 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, static u8 r300_reg_flags[0x10000 >> 2]; -void r300_init_reg_flags(void) +void r300_init_reg_flags(struct drm_device *dev) { int i; + drm_radeon_private_t *dev_priv = dev->dev_private; + memset(r300_reg_flags, 0, 0x10000 >> 2); #define ADD_RANGE_MARK(reg, count,mark) \ for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\ @@ -230,6 +240,9 @@ void r300_init_reg_flags(void) ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8); ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8); + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { + ADD_RANGE(0x4074, 16); + } } static __inline__ int r300_check_range(unsigned reg, int count) diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index c2863346..f0e55105 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -816,19 +816,44 @@ static const u32 R300_cp_microcode[][2] = { { 0000000000, 0000000000 }, }; +static u32 RADEON_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) +{ + u32 ret; + RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff)); + ret = RADEON_READ(R520_MC_IND_DATA); + RADEON_WRITE(R520_MC_IND_INDEX, 0); + return ret; +} + u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv) { - return RADEON_READ(RADEON_MC_FB_LOCATION); + + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) + return RADEON_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) + return RADEON_READ_MCIND(dev_priv, R520_MC_FB_LOCATION); + else + return RADEON_READ(RADEON_MC_FB_LOCATION); } static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc) { - RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc); + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) + RADEON_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) + RADEON_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc); + else + RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc); } static void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc) { - RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc); + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) + RADEON_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) + RADEON_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc); + else + RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc); } static int RADEON_READ_PLL(struct drm_device * dev, int addr) @@ -1089,41 +1114,43 @@ static int radeon_do_engine_reset(struct drm_device * dev) radeon_do_pixcache_flush(dev_priv); - clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX); - mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL); - - RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl | - RADEON_FORCEON_MCLKA | - RADEON_FORCEON_MCLKB | - RADEON_FORCEON_YCLKA | - RADEON_FORCEON_YCLKB | - RADEON_FORCEON_MC | - RADEON_FORCEON_AIC)); - - rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET); - - RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | - RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | - RADEON_SOFT_RESET_SE | - RADEON_SOFT_RESET_RE | - RADEON_SOFT_RESET_PP | - RADEON_SOFT_RESET_E2 | - RADEON_SOFT_RESET_RB)); - RADEON_READ(RADEON_RBBM_SOFT_RESET); - RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & - ~(RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | - RADEON_SOFT_RESET_SE | - RADEON_SOFT_RESET_RE | - RADEON_SOFT_RESET_PP | - RADEON_SOFT_RESET_E2 | - RADEON_SOFT_RESET_RB))); - RADEON_READ(RADEON_RBBM_SOFT_RESET); - - RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl); - RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); - RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); + if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) { + clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX); + mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL); + + RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl | + RADEON_FORCEON_MCLKA | + RADEON_FORCEON_MCLKB | + RADEON_FORCEON_YCLKA | + RADEON_FORCEON_YCLKB | + RADEON_FORCEON_MC | + RADEON_FORCEON_AIC)); + + rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET); + + RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | + RADEON_SOFT_RESET_CP | + RADEON_SOFT_RESET_HI | + RADEON_SOFT_RESET_SE | + RADEON_SOFT_RESET_RE | + RADEON_SOFT_RESET_PP | + RADEON_SOFT_RESET_E2 | + RADEON_SOFT_RESET_RB)); + RADEON_READ(RADEON_RBBM_SOFT_RESET); + RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & + ~(RADEON_SOFT_RESET_CP | + RADEON_SOFT_RESET_HI | + RADEON_SOFT_RESET_SE | + RADEON_SOFT_RESET_RE | + RADEON_SOFT_RESET_PP | + RADEON_SOFT_RESET_E2 | + RADEON_SOFT_RESET_RB))); + RADEON_READ(RADEON_RBBM_SOFT_RESET); + + RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl); + RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); + RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); + } /* Reset the CP ring */ radeon_do_cp_reset(dev_priv); @@ -1881,7 +1908,7 @@ int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_pri LOCK_TEST_WITH_RETURN(dev, file_priv); if (init->func == RADEON_INIT_R300_CP) - r300_init_reg_flags(); + r300_init_reg_flags(dev); switch (init->func) { case RADEON_INIT_CP: @@ -1903,12 +1930,12 @@ int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_pr LOCK_TEST_WITH_RETURN(dev, file_priv); if (dev_priv->cp_running) { - DRM_DEBUG("%s while CP running\n", __FUNCTION__); + DRM_DEBUG("while CP running\n"); return 0; } if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) { - DRM_DEBUG("%s called with bogus CP mode (%d)\n", - __FUNCTION__, dev_priv->cp_mode); + DRM_DEBUG("called with bogus CP mode (%d)\n", + dev_priv->cp_mode); return 0; } @@ -2018,7 +2045,7 @@ int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_pr LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_DEBUG("%s called before init done\n", __FUNCTION__); + DRM_DEBUG("called before init done\n"); return -EINVAL; } @@ -2295,6 +2322,10 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) case CHIP_R350: case CHIP_R420: case CHIP_RV410: + case CHIP_RV515: + case CHIP_R520: + case CHIP_RV570: + case CHIP_R580: dev_priv->flags |= RADEON_HAS_HIERZ; break; default: diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 37b9c43f..63877008 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -129,6 +129,12 @@ enum radeon_family { CHIP_R420, CHIP_RV410, CHIP_RS400, + CHIP_RV515, + CHIP_R520, + CHIP_RV530, + CHIP_RV560, + CHIP_RV570, + CHIP_R580, CHIP_LAST, }; @@ -305,6 +311,9 @@ typedef struct drm_radeon_private { u32 scratch_ages[5]; + unsigned int crtc_last_cnt; + unsigned int crtc2_last_cnt; + /* starting from here on, data is preserved accross an open */ uint32_t flags; /* see radeon_chip_flags */ unsigned long fb_aper_offset; @@ -374,13 +383,13 @@ extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file * extern int radeon_emit_irq(struct drm_device * dev); extern void radeon_do_release(struct drm_device * dev); -extern int radeon_driver_vblank_wait(struct drm_device * dev, - unsigned int *sequence); -extern int radeon_driver_vblank_wait2(struct drm_device * dev, - unsigned int *sequence); +extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc); +extern int radeon_enable_vblank(struct drm_device *dev, int crtc); +extern void radeon_disable_vblank(struct drm_device *dev, int crtc); +extern void radeon_do_release(struct drm_device * dev); extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); extern void radeon_driver_irq_preinstall(struct drm_device * dev); -extern void radeon_driver_irq_postinstall(struct drm_device * dev); +extern int radeon_driver_irq_postinstall(struct drm_device * dev); extern void radeon_driver_irq_uninstall(struct drm_device * dev); extern int radeon_vblank_crtc_get(struct drm_device *dev); extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value); @@ -399,7 +408,7 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); /* r300_cmdbuf.c */ -extern void r300_init_reg_flags(void); +extern void r300_init_reg_flags(struct drm_device *dev); extern int r300_do_cp_cmdbuf(struct drm_device *dev, struct drm_file *file_priv, @@ -423,7 +432,7 @@ extern int radeon_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t extern struct drm_ttm_backend *radeon_create_ttm_backend_entry(struct drm_device *dev); extern int radeon_fence_types(struct drm_buffer_object *bo, uint32_t *class, uint32_t *type); extern int radeon_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags); -extern uint32_t radeon_evict_mask(struct drm_buffer_object *bo); +extern uint64_t radeon_evict_flags(struct drm_buffer_object *bo); extern int radeon_init_mem_type(struct drm_device * dev, uint32_t type, struct drm_mem_type_manager * man); extern int radeon_move(struct drm_buffer_object * bo, @@ -494,6 +503,15 @@ extern int radeon_move(struct drm_buffer_object * bo, #define RADEON_IGPGART_ENABLE 0x38 #define RADEON_IGPGART_UNK_39 0x39 +#define R520_MC_IND_INDEX 0x70 +#define R520_MC_IND_WR_EN (1<<24) +#define R520_MC_IND_DATA 0x74 + +#define RV515_MC_FB_LOCATION 0x01 +#define RV515_MC_AGP_LOCATION 0x02 + +#define R520_MC_FB_LOCATION 0x04 +#define R520_MC_AGP_LOCATION 0x05 #define RADEON_MPP_TB_CONFIG 0x01c0 #define RADEON_MEM_CNTL 0x0140 @@ -545,6 +563,12 @@ extern int radeon_move(struct drm_buffer_object * bo, ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \ : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) ) +#define RADEON_CRTC_CRNT_FRAME 0x0214 +#define RADEON_CRTC2_CRNT_FRAME 0x0314 + +#define RADEON_CRTC_STATUS 0x005c +#define RADEON_CRTC2_STATUS 0x03fc + #define RADEON_GEN_INT_CNTL 0x0040 # define RADEON_CRTC_VBLANK_MASK (1 << 0) # define RADEON_CRTC2_VBLANK_MASK (1 << 9) @@ -1117,6 +1141,13 @@ do { \ RADEON_WRITE( RADEON_PCIE_DATA, (val) ); \ } while (0) +#define RADEON_WRITE_MCIND( addr, val ) \ + do { \ + RADEON_WRITE(R520_MC_IND_INDEX, 0xff0000 | ((addr) & 0xff)); \ + RADEON_WRITE(R520_MC_IND_DATA, (val)); \ + RADEON_WRITE(R520_MC_IND_INDEX, 0); \ + } while (0) + #define CP_PACKET0( reg, n ) \ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) #define CP_PACKET0_TABLE( reg, n ) \ @@ -1227,8 +1258,7 @@ do { \ #define BEGIN_RING( n ) do { \ if ( RADEON_VERBOSE ) { \ - DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ - n, __FUNCTION__ ); \ + DRM_INFO( "BEGIN_RING( %d )\n", (n)); \ } \ if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \ COMMIT_RING(); \ diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c index 544e3a0f..3f6ace88 100644 --- a/shared-core/radeon_irq.c +++ b/shared-core/radeon_irq.c @@ -35,12 +35,61 @@ #include "radeon_drm.h" #include "radeon_drv.h" -static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv, - u32 mask) +static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state) { - u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask; + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (state) + dev_priv->irq_enable_reg |= mask; + else + dev_priv->irq_enable_reg &= ~mask; + + RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); +} + +int radeon_enable_vblank(struct drm_device *dev, int crtc) +{ + switch (crtc) { + case 0: + radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1); + break; + case 1: + radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1); + break; + default: + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + return EINVAL; + } + + return 0; +} + +void radeon_disable_vblank(struct drm_device *dev, int crtc) +{ + switch (crtc) { + case 0: + radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0); + break; + case 1: + radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0); + break; + default: + DRM_ERROR("tried to enable vblank on non-existent crtc %d\n", + crtc); + break; + } +} + +static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv) +{ + u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & + (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | + RADEON_CRTC2_VBLANK_STAT); + if (irqs) RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); + return irqs; } @@ -72,9 +121,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) /* Only consider the bits we're interested in - others could be used * outside the DRM */ - stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | - RADEON_CRTC_VBLANK_STAT | - RADEON_CRTC2_VBLANK_STAT)); + stat = radeon_acknowledge_irqs(dev_priv); if (!stat) return IRQ_NONE; @@ -87,27 +134,11 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) radeon_fence_handler(dev); #endif } - /* VBLANK interrupt */ - if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) { - int vblank_crtc = dev_priv->vblank_crtc; - - if ((vblank_crtc & - (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) == - (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { - if (stat & RADEON_CRTC_VBLANK_STAT) - atomic_inc(&dev->vbl_received); - if (stat & RADEON_CRTC2_VBLANK_STAT) - atomic_inc(&dev->vbl_received2); - } else if (((stat & RADEON_CRTC_VBLANK_STAT) && - (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) || - ((stat & RADEON_CRTC2_VBLANK_STAT) && - (vblank_crtc & DRM_RADEON_VBLANK_CRTC2))) - atomic_inc(&dev->vbl_received); - - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); - } + if (stat & RADEON_CRTC_VBLANK_STAT) + drm_handle_vblank(dev, 0); + if (stat & RADEON_CRTC2_VBLANK_STAT) + drm_handle_vblank(dev, 1); return IRQ_HANDLED; } @@ -146,54 +177,27 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr) return ret; } -static int radeon_driver_vblank_do_wait(struct drm_device * dev, - unsigned int *sequence, int crtc) +u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc) { - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - unsigned int cur_vblank; - int ret = 0; - int ack = 0; - atomic_t *counter; + drm_radeon_private_t *dev_priv = dev->dev_private; + u32 crtc_cnt_reg, crtc_status_reg; + if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } - if (crtc == DRM_RADEON_VBLANK_CRTC1) { - counter = &dev->vbl_received; - ack |= RADEON_CRTC_VBLANK_STAT; - } else if (crtc == DRM_RADEON_VBLANK_CRTC2) { - counter = &dev->vbl_received2; - ack |= RADEON_CRTC2_VBLANK_STAT; - } else + if (crtc == 0) { + crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME; + crtc_status_reg = RADEON_CRTC_STATUS; + } else if (crtc == 1) { + crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME; + crtc_status_reg = RADEON_CRTC2_STATUS; + } else { return -EINVAL; + } - radeon_acknowledge_irqs(dev_priv, ack); - - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(counter)) - - *sequence) <= (1 << 23))); - - *sequence = cur_vblank; - - return ret; -} - -int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence) -{ - return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1); -} - -int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) -{ - return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2); + return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1); } /* Needs the lock as it touches the ring. @@ -207,7 +211,7 @@ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_pr LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -229,28 +233,13 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr drm_radeon_irq_wait_t *irqwait = data; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } return radeon_wait_irq(dev, irqwait->irq_seq); } -static void radeon_enable_interrupt(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; - - dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE; - if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1) - dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK; - - if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2) - dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK; - - RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); - dev_priv->irq_enabled = 1; -} - /* drm_dma.h hooks */ void radeon_driver_irq_preinstall(struct drm_device * dev) @@ -262,20 +251,27 @@ void radeon_driver_irq_preinstall(struct drm_device * dev) RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); /* Clear bits if they're already high */ - radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | - RADEON_CRTC_VBLANK_STAT | - RADEON_CRTC2_VBLANK_STAT)); + radeon_acknowledge_irqs(dev_priv); } -void radeon_driver_irq_postinstall(struct drm_device * dev) +int radeon_driver_irq_postinstall(struct drm_device * dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; + int ret; dev_priv->counter = 0; DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); - radeon_enable_interrupt(dev); + ret = drm_vblank_init(dev, 2); + if (ret) + return ret; + + dev->max_vblank_count = 0x001fffff; + + radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); + + return 0; } void radeon_driver_irq_uninstall(struct drm_device * dev) @@ -317,6 +313,5 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value) return -EINVAL; } dev_priv->vblank_crtc = (unsigned int)value; - radeon_enable_interrupt(dev); return 0; } diff --git a/shared-core/radeon_mem.c b/shared-core/radeon_mem.c index 9947e940..1e582ee0 100644 --- a/shared-core/radeon_mem.c +++ b/shared-core/radeon_mem.c @@ -224,7 +224,7 @@ int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_p struct mem_block *block, **heap; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -259,7 +259,7 @@ int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_pr struct mem_block *block, **heap; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -285,7 +285,7 @@ int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *fi struct mem_block **heap; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } diff --git a/shared-core/radeon_ms.h b/shared-core/radeon_ms.h index a784882b..66533837 100644 --- a/shared-core/radeon_ms.h +++ b/shared-core/radeon_ms.h @@ -338,7 +338,7 @@ int radeon_ms_bo_get_gpu_addr(struct drm_device *dev, int radeon_ms_bo_move(struct drm_buffer_object * bo, int evict, int no_wait, struct drm_bo_mem_reg * new_mem); struct drm_ttm_backend *radeon_ms_create_ttm_backend(struct drm_device * dev); -uint32_t radeon_ms_evict_mask(struct drm_buffer_object *bo); +uint64_t radeon_ms_evict_flags(struct drm_buffer_object *bo); int radeon_ms_init_mem_type(struct drm_device * dev, uint32_t type, struct drm_mem_type_manager * man); int radeon_ms_invalidate_caches(struct drm_device * dev, uint64_t flags); diff --git a/shared-core/radeon_ms_bo.c b/shared-core/radeon_ms_bo.c index cedad689..6d9a97c1 100644 --- a/shared-core/radeon_ms_bo.c +++ b/shared-core/radeon_ms_bo.c @@ -141,7 +141,7 @@ static int radeon_ms_bo_move_flip(struct drm_buffer_object *bo, tmp_mem = *new_mem; tmp_mem.mm_node = NULL; - tmp_mem.mask = DRM_BO_FLAG_MEM_TT | + tmp_mem.flags = DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING; ret = drm_bo_mem_space(bo, &tmp_mem, no_wait); @@ -149,7 +149,7 @@ static int radeon_ms_bo_move_flip(struct drm_buffer_object *bo, return ret; } - ret = drm_bind_ttm(bo->ttm, &tmp_mem); + ret = drm_ttm_bind(bo->ttm, &tmp_mem); if (ret) { goto out_cleanup; } @@ -217,7 +217,7 @@ struct drm_ttm_backend *radeon_ms_create_ttm_backend(struct drm_device * dev) return NULL; } -uint32_t radeon_ms_evict_mask(struct drm_buffer_object *bo) +uint64_t radeon_ms_evict_flags(struct drm_buffer_object *bo) { switch (bo->mem.mem_type) { case DRM_BO_MEM_LOCAL: diff --git a/shared-core/radeon_ms_drm.c b/shared-core/radeon_ms_drm.c index 91ca4a32..bf76b45d 100644 --- a/shared-core/radeon_ms_drm.c +++ b/shared-core/radeon_ms_drm.c @@ -63,7 +63,7 @@ struct drm_bo_driver radeon_ms_bo_driver = { .fence_type = radeon_ms_fence_types, .invalidate_caches = radeon_ms_invalidate_caches, .init_mem_type = radeon_ms_init_mem_type, - .evict_mask = radeon_ms_evict_mask, + .evict_flags = radeon_ms_evict_flags, .move = radeon_ms_bo_move, .ttm_cache_flush = radeon_ms_ttm_flush, }; diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 623576ad..6f2e05b3 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -898,7 +898,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, int w = pbox[i].x2 - x; int h = pbox[i].y2 - y; - DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n", + DRM_DEBUG("%d,%d-%d,%d flags 0x%x\n", x, y, w, h, flags); if (flags & RADEON_FRONT) { @@ -1368,7 +1368,7 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev) int w = pbox[i].x2 - x; int h = pbox[i].y2 - y; - DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h); + DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h); BEGIN_RING(9); @@ -1422,8 +1422,7 @@ static void radeon_cp_dispatch_flip(struct drm_device * dev) int offset = (dev_priv->sarea_priv->pfCurrentPage == 1) ? dev_priv->front_offset : dev_priv->back_offset; RING_LOCALS; - DRM_DEBUG("%s: pfCurrentPage=%d\n", - __FUNCTION__, + DRM_DEBUG("pfCurrentPage=%d\n", dev_priv->sarea_priv->pfCurrentPage); /* Do some trivial performance monitoring... @@ -1562,7 +1561,7 @@ static void radeon_cp_dispatch_indirect(struct drm_device * dev, { drm_radeon_private_t *dev_priv = dev->dev_private; RING_LOCALS; - DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end); + DRM_DEBUG("buf=%d s=0x%x e=0x%x\n", buf->idx, start, end); if (start != end) { int offset = (dev_priv->gart_buffers_offset @@ -1758,7 +1757,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, buf = radeon_freelist_get(dev); } if (!buf) { - DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n"); + DRM_DEBUG("EAGAIN\n"); if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) return -EFAULT; return -EAGAIN; @@ -2084,7 +2083,7 @@ static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_f drm_radeon_surface_alloc_t *alloc = data; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -2100,7 +2099,7 @@ static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_fi drm_radeon_surface_free_t *memfree = data; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -2215,7 +2214,7 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -2299,7 +2298,7 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } sarea_priv = dev_priv->sarea_priv; @@ -2437,11 +2436,11 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } - DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n", + DRM_DEBUG("idx=%d s=%d e=%d d=%d\n", indirect->idx, indirect->start, indirect->end, indirect->discard); @@ -2509,7 +2508,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -2814,7 +2813,7 @@ static int radeon_emit_wait(struct drm_device * dev, int flags) drm_radeon_private_t *dev_priv = dev->dev_private; RING_LOCALS; - DRM_DEBUG("%s: %x\n", __FUNCTION__, flags); + DRM_DEBUG("%x\n", flags); switch (flags) { case RADEON_WAIT_2D: BEGIN_RING(2); @@ -2852,7 +2851,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -3013,7 +3012,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil int value; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -3104,7 +3103,7 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil struct drm_radeon_driver_file_fields *radeon_priv; if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c index ab39f53c..431738a9 100644 --- a/shared-core/via_dma.c +++ b/shared-core/via_dma.c @@ -167,14 +167,12 @@ static int via_initialize(struct drm_device * dev, } if (dev_priv->ring.virtual_start != NULL) { - DRM_ERROR("%s called again without calling cleanup\n", - __FUNCTION__); + DRM_ERROR("called again without calling cleanup\n"); return -EFAULT; } if (!dev->agp || !dev->agp->base) { - DRM_ERROR("%s called with no agp memory available\n", - __FUNCTION__); + DRM_ERROR("called with no agp memory available\n"); return -EFAULT; } @@ -257,8 +255,7 @@ static int via_dispatch_cmdbuffer(struct drm_device * dev, drm_via_cmdbuffer_t * dev_priv = (drm_via_private_t *) dev->dev_private; if (dev_priv->ring.virtual_start == NULL) { - DRM_ERROR("%s called without initializing AGP ring buffer.\n", - __FUNCTION__); + DRM_ERROR("called without initializing AGP ring buffer.\n"); return -EFAULT; } @@ -327,8 +324,7 @@ static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *fi LOCK_TEST_WITH_RETURN(dev, file_priv); - DRM_DEBUG("via cmdbuffer, buf %p size %lu\n", cmdbuf->buf, - cmdbuf->size); + DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); ret = via_dispatch_cmdbuffer(dev, cmdbuf); if (ret) { @@ -369,8 +365,7 @@ static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file LOCK_TEST_WITH_RETURN(dev, file_priv); - DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf->buf, - cmdbuf->size); + DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf); if (ret) { @@ -640,14 +635,13 @@ static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file * uint32_t tmp_size, count; drm_via_private_t *dev_priv; - DRM_DEBUG("via cmdbuf_size\n"); + DRM_DEBUG("\n"); LOCK_TEST_WITH_RETURN(dev, file_priv); dev_priv = (drm_via_private_t *) dev->dev_private; if (dev_priv->ring.virtual_start == NULL) { - DRM_ERROR("%s called without initializing AGP ring buffer.\n", - __FUNCTION__); + DRM_ERROR("called without initializing AGP ring buffer.\n"); return -EFAULT; } diff --git a/shared-core/via_drv.c b/shared-core/via_drv.c index 9f099555..a802e4ae 100644 --- a/shared-core/via_drv.c +++ b/shared-core/via_drv.c @@ -74,7 +74,7 @@ static struct drm_bo_driver via_bo_driver = { .fence_type = via_fence_types, .invalidate_caches = via_invalidate_caches, .init_mem_type = via_init_mem_type, - .evict_mask = via_evict_mask, + .evict_flags = via_evict_flags, .move = NULL, }; #endif @@ -83,14 +83,16 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *ent); static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | - DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, + DRIVER_IRQ_SHARED, .load = via_driver_load, .unload = via_driver_unload, #ifndef VIA_HAVE_CORE_MM .context_ctor = via_init_context, #endif .context_dtor = via_final_context, - .vblank_wait = via_driver_vblank_wait, + .get_vblank_counter = via_get_vblank_counter, + .enable_vblank = via_enable_vblank, + .disable_vblank = via_disable_vblank, .irq_preinstall = via_driver_irq_preinstall, .irq_postinstall = via_driver_irq_postinstall, .irq_uninstall = via_driver_irq_uninstall, diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h index d6da8bd9..8dd4a727 100644 --- a/shared-core/via_drv.h +++ b/shared-core/via_drv.h @@ -102,6 +102,7 @@ typedef struct drm_via_private { struct timeval last_vblank; int last_vblank_valid; unsigned usec_per_vblank; + atomic_t vbl_received; drm_via_state_t hc_state; char pci_buf[VIA_PCI_BUF_SIZE]; const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; @@ -166,11 +167,13 @@ extern int via_driver_unload(struct drm_device *dev); extern int via_final_context(struct drm_device * dev, int context); extern int via_do_cleanup_map(struct drm_device * dev); -extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence); +extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc); +extern int via_enable_vblank(struct drm_device *dev, int crtc); +extern void via_disable_vblank(struct drm_device *dev, int crtc); extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS); extern void via_driver_irq_preinstall(struct drm_device * dev); -extern void via_driver_irq_postinstall(struct drm_device * dev); +extern int via_driver_irq_postinstall(struct drm_device * dev); extern void via_driver_irq_uninstall(struct drm_device * dev); extern int via_dma_cleanup(struct drm_device * dev); @@ -211,7 +214,7 @@ extern int via_fence_types(struct drm_buffer_object *bo, uint32_t *fclass, extern int via_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags); extern int via_init_mem_type(struct drm_device *dev, uint32_t type, struct drm_mem_type_manager *man); -extern uint32_t via_evict_mask(struct drm_buffer_object *bo); +extern uint64_t via_evict_flags(struct drm_buffer_object *bo); extern int via_move(struct drm_buffer_object *bo, int evict, int no_wait, struct drm_bo_mem_reg *new_mem); #endif diff --git a/shared-core/via_irq.c b/shared-core/via_irq.c index ec3f50bd..b8e652e6 100644 --- a/shared-core/via_irq.c +++ b/shared-core/via_irq.c @@ -96,6 +96,15 @@ static unsigned time_diff(struct timeval *now,struct timeval *then) 1000000 - (then->tv_usec - now->tv_usec); } +u32 via_get_vblank_counter(struct drm_device *dev, int crtc) +{ + drm_via_private_t *dev_priv = dev->dev_private; + if (crtc != 0) + return 0; + + return atomic_read(&dev_priv->vbl_received); +} + irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -108,8 +117,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) status = VIA_READ(VIA_REG_INTERRUPT); if (status & VIA_IRQ_VBLANK_PENDING) { - atomic_inc(&dev->vbl_received); - if (!(atomic_read(&dev->vbl_received) & 0x0F)) { + atomic_inc(&dev_priv->vbl_received); + if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) { #ifdef __linux__ do_gettimeofday(&cur_vblank); #else @@ -123,12 +132,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) dev_priv->last_vblank = cur_vblank; dev_priv->last_vblank_valid = 1; } - if (!(atomic_read(&dev->vbl_received) & 0xFF)) { + if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) { DRM_DEBUG("US per vblank is: %u\n", dev_priv->usec_per_vblank); } - DRM_WAKEUP(&dev->vbl_queue); - drm_vbl_send_signals(dev); + drm_handle_vblank(dev, 0); handled = 1; } @@ -170,31 +178,25 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv) } } -int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) +int via_enable_vblank(struct drm_device *dev, int crtc) { - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - unsigned int cur_vblank; - int ret = 0; + drm_via_private_t *dev_priv = dev->dev_private; + u32 status; - DRM_DEBUG("viadrv_vblank_wait\n"); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + if (crtc != 0) { + DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); return -EINVAL; } - viadrv_acknowledge_irqs(dev_priv); - - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using vertical blanks... - */ - - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(&dev->vbl_received)) - - *sequence) <= (1 << 23))); + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE); + return 0; +} - *sequence = cur_vblank; - return ret; +void via_disable_vblank(struct drm_device *dev, int crtc) +{ + if (crtc != 0) + DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc); } static int @@ -208,24 +210,23 @@ via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequenc maskarray_t *masks; int real_irq; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + DRM_ERROR("called with no initialization\n"); return -EINVAL; } if (irq >= drm_via_irq_num) { - DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, - irq); + DRM_ERROR("Trying to wait on unknown irq %d\n", irq); return -EINVAL; } real_irq = dev_priv->irq_map[irq]; if (real_irq < 0) { - DRM_ERROR("%s Video IRQ %d not available on this hardware.\n", - __FUNCTION__, irq); + DRM_ERROR("Video IRQ %d not available on this hardware.\n", + irq); return -EINVAL; } @@ -259,7 +260,7 @@ void via_driver_irq_preinstall(struct drm_device * dev) drm_via_irq_t *cur_irq; int i; - DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv); + DRM_DEBUG("dev_priv: %p\n", dev_priv); if (dev_priv) { cur_irq = dev_priv->via_irqs; @@ -301,23 +302,24 @@ void via_driver_irq_preinstall(struct drm_device * dev) } } -void via_driver_irq_postinstall(struct drm_device * dev) +int via_driver_irq_postinstall(struct drm_device * dev) { drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; u32 status; DRM_DEBUG("via_driver_irq_postinstall\n"); - if (dev_priv) { - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL - | dev_priv->irq_enable_mask); + if (!dev_priv) + return -EINVAL; - /* Some magic, oh for some data sheets ! */ + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL + | dev_priv->irq_enable_mask); - VIA_WRITE8(0x83d4, 0x11); - VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); + /* 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) @@ -325,7 +327,7 @@ void via_driver_irq_uninstall(struct drm_device * dev) drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; u32 status; - DRM_DEBUG("driver_irq_uninstall)\n"); + DRM_DEBUG("\n"); if (dev_priv) { /* Some more magic, oh for some data sheets ! */ @@ -352,7 +354,7 @@ int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; if (irqwait->request.irq >= dev_priv->num_irqs) { - DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, + DRM_ERROR("Trying to wait on unknown irq %d\n", irqwait->request.irq); return -EINVAL; } @@ -371,8 +373,7 @@ int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) } if (irqwait->request.type & VIA_IRQ_SIGNAL) { - DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n", - __FUNCTION__); + DRM_ERROR("Signals on Via IRQs not implemented yet.\n"); return -EINVAL; } diff --git a/shared-core/via_map.c b/shared-core/via_map.c index b8f61673..11bfa551 100644 --- a/shared-core/via_map.c +++ b/shared-core/via_map.c @@ -30,7 +30,7 @@ static int via_do_init_map(struct drm_device * dev, drm_via_init_t * init) drm_via_private_t *dev_priv = dev->dev_private; int ret = 0; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); dev_priv->sarea = drm_getsarea(dev); if (!dev_priv->sarea) { @@ -95,7 +95,7 @@ int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_via_init_t *init = data; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); switch (init->func) { case VIA_INIT_MAP: diff --git a/shared-core/via_video.c b/shared-core/via_video.c index c15e75b5..6ec04ac1 100644 --- a/shared-core/via_video.c +++ b/shared-core/via_video.c @@ -33,7 +33,7 @@ void via_init_futex(drm_via_private_t * dev_priv) { unsigned int i; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) { DRM_INIT_WAITQUEUE(&(dev_priv->decoder_queue[i])); @@ -73,7 +73,7 @@ int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_ drm_via_sarea_t *sAPriv = dev_priv->sarea_priv; int ret = 0; - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("\n"); if (fx->lock > VIA_NR_XVMC_LOCKS) return -EFAULT; |