1771fe6b9SJerome Glisse /* 2771fe6b9SJerome Glisse * Copyright 2008 Advanced Micro Devices, Inc. 3771fe6b9SJerome Glisse * Copyright 2008 Red Hat Inc. 4771fe6b9SJerome Glisse * Copyright 2009 Jerome Glisse. 5771fe6b9SJerome Glisse * 6771fe6b9SJerome Glisse * Permission is hereby granted, free of charge, to any person obtaining a 7771fe6b9SJerome Glisse * copy of this software and associated documentation files (the "Software"), 8771fe6b9SJerome Glisse * to deal in the Software without restriction, including without limitation 9771fe6b9SJerome Glisse * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10771fe6b9SJerome Glisse * and/or sell copies of the Software, and to permit persons to whom the 11771fe6b9SJerome Glisse * Software is furnished to do so, subject to the following conditions: 12771fe6b9SJerome Glisse * 13771fe6b9SJerome Glisse * The above copyright notice and this permission notice shall be included in 14771fe6b9SJerome Glisse * all copies or substantial portions of the Software. 15771fe6b9SJerome Glisse * 16771fe6b9SJerome Glisse * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17771fe6b9SJerome Glisse * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18771fe6b9SJerome Glisse * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19771fe6b9SJerome Glisse * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20771fe6b9SJerome Glisse * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21771fe6b9SJerome Glisse * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22771fe6b9SJerome Glisse * OTHER DEALINGS IN THE SOFTWARE. 23771fe6b9SJerome Glisse * 24771fe6b9SJerome Glisse * Authors: Dave Airlie 25771fe6b9SJerome Glisse * Alex Deucher 26771fe6b9SJerome Glisse * Jerome Glisse 27771fe6b9SJerome Glisse */ 28771fe6b9SJerome Glisse #include <linux/seq_file.h> 29771fe6b9SJerome Glisse #include "drmP.h" 30771fe6b9SJerome Glisse #include "drm.h" 31771fe6b9SJerome Glisse #include "radeon_drm.h" 32771fe6b9SJerome Glisse #include "radeon_microcode.h" 33771fe6b9SJerome Glisse #include "radeon_reg.h" 34771fe6b9SJerome Glisse #include "radeon.h" 35771fe6b9SJerome Glisse 36771fe6b9SJerome Glisse /* This files gather functions specifics to: 37771fe6b9SJerome Glisse * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 38771fe6b9SJerome Glisse * 39771fe6b9SJerome Glisse * Some of these functions might be used by newer ASICs. 40771fe6b9SJerome Glisse */ 41771fe6b9SJerome Glisse void r100_hdp_reset(struct radeon_device *rdev); 42771fe6b9SJerome Glisse void r100_gpu_init(struct radeon_device *rdev); 43771fe6b9SJerome Glisse int r100_gui_wait_for_idle(struct radeon_device *rdev); 44771fe6b9SJerome Glisse int r100_mc_wait_for_idle(struct radeon_device *rdev); 45771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync(struct radeon_device *rdev); 46771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync2(struct radeon_device *rdev); 47771fe6b9SJerome Glisse int r100_debugfs_mc_info_init(struct radeon_device *rdev); 48771fe6b9SJerome Glisse 49771fe6b9SJerome Glisse 50771fe6b9SJerome Glisse /* 51771fe6b9SJerome Glisse * PCI GART 52771fe6b9SJerome Glisse */ 53771fe6b9SJerome Glisse void r100_pci_gart_tlb_flush(struct radeon_device *rdev) 54771fe6b9SJerome Glisse { 55771fe6b9SJerome Glisse /* TODO: can we do somethings here ? */ 56771fe6b9SJerome Glisse /* It seems hw only cache one entry so we should discard this 57771fe6b9SJerome Glisse * entry otherwise if first GPU GART read hit this entry it 58771fe6b9SJerome Glisse * could end up in wrong address. */ 59771fe6b9SJerome Glisse } 60771fe6b9SJerome Glisse 61771fe6b9SJerome Glisse int r100_pci_gart_enable(struct radeon_device *rdev) 62771fe6b9SJerome Glisse { 63771fe6b9SJerome Glisse uint32_t tmp; 64771fe6b9SJerome Glisse int r; 65771fe6b9SJerome Glisse 66771fe6b9SJerome Glisse /* Initialize common gart structure */ 67771fe6b9SJerome Glisse r = radeon_gart_init(rdev); 68771fe6b9SJerome Glisse if (r) { 69771fe6b9SJerome Glisse return r; 70771fe6b9SJerome Glisse } 71771fe6b9SJerome Glisse if (rdev->gart.table.ram.ptr == NULL) { 72771fe6b9SJerome Glisse rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; 73771fe6b9SJerome Glisse r = radeon_gart_table_ram_alloc(rdev); 74771fe6b9SJerome Glisse if (r) { 75771fe6b9SJerome Glisse return r; 76771fe6b9SJerome Glisse } 77771fe6b9SJerome Glisse } 78771fe6b9SJerome Glisse /* discard memory request outside of configured range */ 79771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; 80771fe6b9SJerome Glisse WREG32(RADEON_AIC_CNTL, tmp); 81771fe6b9SJerome Glisse /* set address range for PCI address translate */ 82771fe6b9SJerome Glisse WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location); 83771fe6b9SJerome Glisse tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; 84771fe6b9SJerome Glisse WREG32(RADEON_AIC_HI_ADDR, tmp); 85771fe6b9SJerome Glisse /* Enable bus mastering */ 86771fe6b9SJerome Glisse tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; 87771fe6b9SJerome Glisse WREG32(RADEON_BUS_CNTL, tmp); 88771fe6b9SJerome Glisse /* set PCI GART page-table base address */ 89771fe6b9SJerome Glisse WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr); 90771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN; 91771fe6b9SJerome Glisse WREG32(RADEON_AIC_CNTL, tmp); 92771fe6b9SJerome Glisse r100_pci_gart_tlb_flush(rdev); 93771fe6b9SJerome Glisse rdev->gart.ready = true; 94771fe6b9SJerome Glisse return 0; 95771fe6b9SJerome Glisse } 96771fe6b9SJerome Glisse 97771fe6b9SJerome Glisse void r100_pci_gart_disable(struct radeon_device *rdev) 98771fe6b9SJerome Glisse { 99771fe6b9SJerome Glisse uint32_t tmp; 100771fe6b9SJerome Glisse 101771fe6b9SJerome Glisse /* discard memory request outside of configured range */ 102771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; 103771fe6b9SJerome Glisse WREG32(RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN); 104771fe6b9SJerome Glisse WREG32(RADEON_AIC_LO_ADDR, 0); 105771fe6b9SJerome Glisse WREG32(RADEON_AIC_HI_ADDR, 0); 106771fe6b9SJerome Glisse } 107771fe6b9SJerome Glisse 108771fe6b9SJerome Glisse int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) 109771fe6b9SJerome Glisse { 110771fe6b9SJerome Glisse if (i < 0 || i > rdev->gart.num_gpu_pages) { 111771fe6b9SJerome Glisse return -EINVAL; 112771fe6b9SJerome Glisse } 113ed10f95dSDave Airlie rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr)); 114771fe6b9SJerome Glisse return 0; 115771fe6b9SJerome Glisse } 116771fe6b9SJerome Glisse 117771fe6b9SJerome Glisse int r100_gart_enable(struct radeon_device *rdev) 118771fe6b9SJerome Glisse { 119771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 120771fe6b9SJerome Glisse r100_pci_gart_disable(rdev); 121771fe6b9SJerome Glisse return 0; 122771fe6b9SJerome Glisse } 123771fe6b9SJerome Glisse return r100_pci_gart_enable(rdev); 124771fe6b9SJerome Glisse } 125771fe6b9SJerome Glisse 126771fe6b9SJerome Glisse 127771fe6b9SJerome Glisse /* 128771fe6b9SJerome Glisse * MC 129771fe6b9SJerome Glisse */ 130771fe6b9SJerome Glisse void r100_mc_disable_clients(struct radeon_device *rdev) 131771fe6b9SJerome Glisse { 132771fe6b9SJerome Glisse uint32_t ov0_scale_cntl, crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl; 133771fe6b9SJerome Glisse 134771fe6b9SJerome Glisse /* FIXME: is this function correct for rs100,rs200,rs300 ? */ 135771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 136771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 137771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 138771fe6b9SJerome Glisse } 139771fe6b9SJerome Glisse 140771fe6b9SJerome Glisse /* stop display and memory access */ 141771fe6b9SJerome Glisse ov0_scale_cntl = RREG32(RADEON_OV0_SCALE_CNTL); 142771fe6b9SJerome Glisse WREG32(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE); 143771fe6b9SJerome Glisse crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); 144771fe6b9SJerome Glisse WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS); 145771fe6b9SJerome Glisse crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); 146771fe6b9SJerome Glisse 147771fe6b9SJerome Glisse r100_gpu_wait_for_vsync(rdev); 148771fe6b9SJerome Glisse 149771fe6b9SJerome Glisse WREG32(RADEON_CRTC_GEN_CNTL, 150771fe6b9SJerome Glisse (crtc_gen_cntl & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) | 151771fe6b9SJerome Glisse RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN); 152771fe6b9SJerome Glisse 153771fe6b9SJerome Glisse if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 154771fe6b9SJerome Glisse crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 155771fe6b9SJerome Glisse 156771fe6b9SJerome Glisse r100_gpu_wait_for_vsync2(rdev); 157771fe6b9SJerome Glisse WREG32(RADEON_CRTC2_GEN_CNTL, 158771fe6b9SJerome Glisse (crtc2_gen_cntl & 159771fe6b9SJerome Glisse ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) | 160771fe6b9SJerome Glisse RADEON_CRTC2_DISP_REQ_EN_B); 161771fe6b9SJerome Glisse } 162771fe6b9SJerome Glisse 163771fe6b9SJerome Glisse udelay(500); 164771fe6b9SJerome Glisse } 165771fe6b9SJerome Glisse 166771fe6b9SJerome Glisse void r100_mc_setup(struct radeon_device *rdev) 167771fe6b9SJerome Glisse { 168771fe6b9SJerome Glisse uint32_t tmp; 169771fe6b9SJerome Glisse int r; 170771fe6b9SJerome Glisse 171771fe6b9SJerome Glisse r = r100_debugfs_mc_info_init(rdev); 172771fe6b9SJerome Glisse if (r) { 173771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for R100 MC !\n"); 174771fe6b9SJerome Glisse } 175771fe6b9SJerome Glisse /* Write VRAM size in case we are limiting it */ 176*7a50f01aSDave Airlie WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 177*7a50f01aSDave Airlie /* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM, 178*7a50f01aSDave Airlie * if the aperture is 64MB but we have 32MB VRAM 179*7a50f01aSDave Airlie * we report only 32MB VRAM but we have to set MC_FB_LOCATION 180*7a50f01aSDave Airlie * to 64MB, otherwise the gpu accidentially dies */ 181*7a50f01aSDave Airlie tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; 182771fe6b9SJerome Glisse tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); 183771fe6b9SJerome Glisse tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); 184771fe6b9SJerome Glisse WREG32(RADEON_MC_FB_LOCATION, tmp); 185771fe6b9SJerome Glisse 186771fe6b9SJerome Glisse /* Enable bus mastering */ 187771fe6b9SJerome Glisse tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; 188771fe6b9SJerome Glisse WREG32(RADEON_BUS_CNTL, tmp); 189771fe6b9SJerome Glisse 190771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 191771fe6b9SJerome Glisse tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; 192771fe6b9SJerome Glisse tmp = REG_SET(RADEON_MC_AGP_TOP, tmp >> 16); 193771fe6b9SJerome Glisse tmp |= REG_SET(RADEON_MC_AGP_START, rdev->mc.gtt_location >> 16); 194771fe6b9SJerome Glisse WREG32(RADEON_MC_AGP_LOCATION, tmp); 195771fe6b9SJerome Glisse WREG32(RADEON_AGP_BASE, rdev->mc.agp_base); 196771fe6b9SJerome Glisse } else { 197771fe6b9SJerome Glisse WREG32(RADEON_MC_AGP_LOCATION, 0x0FFFFFFF); 198771fe6b9SJerome Glisse WREG32(RADEON_AGP_BASE, 0); 199771fe6b9SJerome Glisse } 200771fe6b9SJerome Glisse 201771fe6b9SJerome Glisse tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; 202771fe6b9SJerome Glisse tmp |= (7 << 28); 203771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); 204771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 205771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp); 206771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 207771fe6b9SJerome Glisse } 208771fe6b9SJerome Glisse 209771fe6b9SJerome Glisse int r100_mc_init(struct radeon_device *rdev) 210771fe6b9SJerome Glisse { 211771fe6b9SJerome Glisse int r; 212771fe6b9SJerome Glisse 213771fe6b9SJerome Glisse if (r100_debugfs_rbbm_init(rdev)) { 214771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for RBBM !\n"); 215771fe6b9SJerome Glisse } 216771fe6b9SJerome Glisse 217771fe6b9SJerome Glisse r100_gpu_init(rdev); 218771fe6b9SJerome Glisse /* Disable gart which also disable out of gart access */ 219771fe6b9SJerome Glisse r100_pci_gart_disable(rdev); 220771fe6b9SJerome Glisse 221771fe6b9SJerome Glisse /* Setup GPU memory space */ 222771fe6b9SJerome Glisse rdev->mc.gtt_location = 0xFFFFFFFFUL; 223771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 224771fe6b9SJerome Glisse r = radeon_agp_init(rdev); 225771fe6b9SJerome Glisse if (r) { 226771fe6b9SJerome Glisse printk(KERN_WARNING "[drm] Disabling AGP\n"); 227771fe6b9SJerome Glisse rdev->flags &= ~RADEON_IS_AGP; 228771fe6b9SJerome Glisse rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; 229771fe6b9SJerome Glisse } else { 230771fe6b9SJerome Glisse rdev->mc.gtt_location = rdev->mc.agp_base; 231771fe6b9SJerome Glisse } 232771fe6b9SJerome Glisse } 233771fe6b9SJerome Glisse r = radeon_mc_setup(rdev); 234771fe6b9SJerome Glisse if (r) { 235771fe6b9SJerome Glisse return r; 236771fe6b9SJerome Glisse } 237771fe6b9SJerome Glisse 238771fe6b9SJerome Glisse r100_mc_disable_clients(rdev); 239771fe6b9SJerome Glisse if (r100_mc_wait_for_idle(rdev)) { 240771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait MC idle while " 241771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 242771fe6b9SJerome Glisse } 243771fe6b9SJerome Glisse 244771fe6b9SJerome Glisse r100_mc_setup(rdev); 245771fe6b9SJerome Glisse return 0; 246771fe6b9SJerome Glisse } 247771fe6b9SJerome Glisse 248771fe6b9SJerome Glisse void r100_mc_fini(struct radeon_device *rdev) 249771fe6b9SJerome Glisse { 250771fe6b9SJerome Glisse r100_pci_gart_disable(rdev); 251771fe6b9SJerome Glisse radeon_gart_table_ram_free(rdev); 252771fe6b9SJerome Glisse radeon_gart_fini(rdev); 253771fe6b9SJerome Glisse } 254771fe6b9SJerome Glisse 255771fe6b9SJerome Glisse 256771fe6b9SJerome Glisse /* 257771fe6b9SJerome Glisse * Fence emission 258771fe6b9SJerome Glisse */ 259771fe6b9SJerome Glisse void r100_fence_ring_emit(struct radeon_device *rdev, 260771fe6b9SJerome Glisse struct radeon_fence *fence) 261771fe6b9SJerome Glisse { 262771fe6b9SJerome Glisse /* Who ever call radeon_fence_emit should call ring_lock and ask 263771fe6b9SJerome Glisse * for enough space (today caller are ib schedule and buffer move) */ 264771fe6b9SJerome Glisse /* Wait until IDLE & CLEAN */ 265771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(0x1720, 0)); 266771fe6b9SJerome Glisse radeon_ring_write(rdev, (1 << 16) | (1 << 17)); 267771fe6b9SJerome Glisse /* Emit fence sequence & fire IRQ */ 268771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0)); 269771fe6b9SJerome Glisse radeon_ring_write(rdev, fence->seq); 270771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_GEN_INT_STATUS, 0)); 271771fe6b9SJerome Glisse radeon_ring_write(rdev, RADEON_SW_INT_FIRE); 272771fe6b9SJerome Glisse } 273771fe6b9SJerome Glisse 274771fe6b9SJerome Glisse 275771fe6b9SJerome Glisse /* 276771fe6b9SJerome Glisse * Writeback 277771fe6b9SJerome Glisse */ 278771fe6b9SJerome Glisse int r100_wb_init(struct radeon_device *rdev) 279771fe6b9SJerome Glisse { 280771fe6b9SJerome Glisse int r; 281771fe6b9SJerome Glisse 282771fe6b9SJerome Glisse if (rdev->wb.wb_obj == NULL) { 283771fe6b9SJerome Glisse r = radeon_object_create(rdev, NULL, 4096, 284771fe6b9SJerome Glisse true, 285771fe6b9SJerome Glisse RADEON_GEM_DOMAIN_GTT, 286771fe6b9SJerome Glisse false, &rdev->wb.wb_obj); 287771fe6b9SJerome Glisse if (r) { 288771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to create WB buffer (%d).\n", r); 289771fe6b9SJerome Glisse return r; 290771fe6b9SJerome Glisse } 291771fe6b9SJerome Glisse r = radeon_object_pin(rdev->wb.wb_obj, 292771fe6b9SJerome Glisse RADEON_GEM_DOMAIN_GTT, 293771fe6b9SJerome Glisse &rdev->wb.gpu_addr); 294771fe6b9SJerome Glisse if (r) { 295771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to pin WB buffer (%d).\n", r); 296771fe6b9SJerome Glisse return r; 297771fe6b9SJerome Glisse } 298771fe6b9SJerome Glisse r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); 299771fe6b9SJerome Glisse if (r) { 300771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to map WB buffer (%d).\n", r); 301771fe6b9SJerome Glisse return r; 302771fe6b9SJerome Glisse } 303771fe6b9SJerome Glisse } 304771fe6b9SJerome Glisse WREG32(0x774, rdev->wb.gpu_addr); 305771fe6b9SJerome Glisse WREG32(0x70C, rdev->wb.gpu_addr + 1024); 306771fe6b9SJerome Glisse WREG32(0x770, 0xff); 307771fe6b9SJerome Glisse return 0; 308771fe6b9SJerome Glisse } 309771fe6b9SJerome Glisse 310771fe6b9SJerome Glisse void r100_wb_fini(struct radeon_device *rdev) 311771fe6b9SJerome Glisse { 312771fe6b9SJerome Glisse if (rdev->wb.wb_obj) { 313771fe6b9SJerome Glisse radeon_object_kunmap(rdev->wb.wb_obj); 314771fe6b9SJerome Glisse radeon_object_unpin(rdev->wb.wb_obj); 315771fe6b9SJerome Glisse radeon_object_unref(&rdev->wb.wb_obj); 316771fe6b9SJerome Glisse rdev->wb.wb = NULL; 317771fe6b9SJerome Glisse rdev->wb.wb_obj = NULL; 318771fe6b9SJerome Glisse } 319771fe6b9SJerome Glisse } 320771fe6b9SJerome Glisse 321771fe6b9SJerome Glisse int r100_copy_blit(struct radeon_device *rdev, 322771fe6b9SJerome Glisse uint64_t src_offset, 323771fe6b9SJerome Glisse uint64_t dst_offset, 324771fe6b9SJerome Glisse unsigned num_pages, 325771fe6b9SJerome Glisse struct radeon_fence *fence) 326771fe6b9SJerome Glisse { 327771fe6b9SJerome Glisse uint32_t cur_pages; 328771fe6b9SJerome Glisse uint32_t stride_bytes = PAGE_SIZE; 329771fe6b9SJerome Glisse uint32_t pitch; 330771fe6b9SJerome Glisse uint32_t stride_pixels; 331771fe6b9SJerome Glisse unsigned ndw; 332771fe6b9SJerome Glisse int num_loops; 333771fe6b9SJerome Glisse int r = 0; 334771fe6b9SJerome Glisse 335771fe6b9SJerome Glisse /* radeon limited to 16k stride */ 336771fe6b9SJerome Glisse stride_bytes &= 0x3fff; 337771fe6b9SJerome Glisse /* radeon pitch is /64 */ 338771fe6b9SJerome Glisse pitch = stride_bytes / 64; 339771fe6b9SJerome Glisse stride_pixels = stride_bytes / 4; 340771fe6b9SJerome Glisse num_loops = DIV_ROUND_UP(num_pages, 8191); 341771fe6b9SJerome Glisse 342771fe6b9SJerome Glisse /* Ask for enough room for blit + flush + fence */ 343771fe6b9SJerome Glisse ndw = 64 + (10 * num_loops); 344771fe6b9SJerome Glisse r = radeon_ring_lock(rdev, ndw); 345771fe6b9SJerome Glisse if (r) { 346771fe6b9SJerome Glisse DRM_ERROR("radeon: moving bo (%d) asking for %u dw.\n", r, ndw); 347771fe6b9SJerome Glisse return -EINVAL; 348771fe6b9SJerome Glisse } 349771fe6b9SJerome Glisse while (num_pages > 0) { 350771fe6b9SJerome Glisse cur_pages = num_pages; 351771fe6b9SJerome Glisse if (cur_pages > 8191) { 352771fe6b9SJerome Glisse cur_pages = 8191; 353771fe6b9SJerome Glisse } 354771fe6b9SJerome Glisse num_pages -= cur_pages; 355771fe6b9SJerome Glisse 356771fe6b9SJerome Glisse /* pages are in Y direction - height 357771fe6b9SJerome Glisse page width in X direction - width */ 358771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET3(PACKET3_BITBLT_MULTI, 8)); 359771fe6b9SJerome Glisse radeon_ring_write(rdev, 360771fe6b9SJerome Glisse RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 361771fe6b9SJerome Glisse RADEON_GMC_DST_PITCH_OFFSET_CNTL | 362771fe6b9SJerome Glisse RADEON_GMC_SRC_CLIPPING | 363771fe6b9SJerome Glisse RADEON_GMC_DST_CLIPPING | 364771fe6b9SJerome Glisse RADEON_GMC_BRUSH_NONE | 365771fe6b9SJerome Glisse (RADEON_COLOR_FORMAT_ARGB8888 << 8) | 366771fe6b9SJerome Glisse RADEON_GMC_SRC_DATATYPE_COLOR | 367771fe6b9SJerome Glisse RADEON_ROP3_S | 368771fe6b9SJerome Glisse RADEON_DP_SRC_SOURCE_MEMORY | 369771fe6b9SJerome Glisse RADEON_GMC_CLR_CMP_CNTL_DIS | 370771fe6b9SJerome Glisse RADEON_GMC_WR_MSK_DIS); 371771fe6b9SJerome Glisse radeon_ring_write(rdev, (pitch << 22) | (src_offset >> 10)); 372771fe6b9SJerome Glisse radeon_ring_write(rdev, (pitch << 22) | (dst_offset >> 10)); 373771fe6b9SJerome Glisse radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); 374771fe6b9SJerome Glisse radeon_ring_write(rdev, 0); 375771fe6b9SJerome Glisse radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); 376771fe6b9SJerome Glisse radeon_ring_write(rdev, num_pages); 377771fe6b9SJerome Glisse radeon_ring_write(rdev, num_pages); 378771fe6b9SJerome Glisse radeon_ring_write(rdev, cur_pages | (stride_pixels << 16)); 379771fe6b9SJerome Glisse } 380771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0)); 381771fe6b9SJerome Glisse radeon_ring_write(rdev, RADEON_RB2D_DC_FLUSH_ALL); 382771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); 383771fe6b9SJerome Glisse radeon_ring_write(rdev, 384771fe6b9SJerome Glisse RADEON_WAIT_2D_IDLECLEAN | 385771fe6b9SJerome Glisse RADEON_WAIT_HOST_IDLECLEAN | 386771fe6b9SJerome Glisse RADEON_WAIT_DMA_GUI_IDLE); 387771fe6b9SJerome Glisse if (fence) { 388771fe6b9SJerome Glisse r = radeon_fence_emit(rdev, fence); 389771fe6b9SJerome Glisse } 390771fe6b9SJerome Glisse radeon_ring_unlock_commit(rdev); 391771fe6b9SJerome Glisse return r; 392771fe6b9SJerome Glisse } 393771fe6b9SJerome Glisse 394771fe6b9SJerome Glisse 395771fe6b9SJerome Glisse /* 396771fe6b9SJerome Glisse * CP 397771fe6b9SJerome Glisse */ 398771fe6b9SJerome Glisse void r100_ring_start(struct radeon_device *rdev) 399771fe6b9SJerome Glisse { 400771fe6b9SJerome Glisse int r; 401771fe6b9SJerome Glisse 402771fe6b9SJerome Glisse r = radeon_ring_lock(rdev, 2); 403771fe6b9SJerome Glisse if (r) { 404771fe6b9SJerome Glisse return; 405771fe6b9SJerome Glisse } 406771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0)); 407771fe6b9SJerome Glisse radeon_ring_write(rdev, 408771fe6b9SJerome Glisse RADEON_ISYNC_ANY2D_IDLE3D | 409771fe6b9SJerome Glisse RADEON_ISYNC_ANY3D_IDLE2D | 410771fe6b9SJerome Glisse RADEON_ISYNC_WAIT_IDLEGUI | 411771fe6b9SJerome Glisse RADEON_ISYNC_CPSCRATCH_IDLEGUI); 412771fe6b9SJerome Glisse radeon_ring_unlock_commit(rdev); 413771fe6b9SJerome Glisse } 414771fe6b9SJerome Glisse 415771fe6b9SJerome Glisse static void r100_cp_load_microcode(struct radeon_device *rdev) 416771fe6b9SJerome Glisse { 417771fe6b9SJerome Glisse int i; 418771fe6b9SJerome Glisse 419771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 420771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 421771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 422771fe6b9SJerome Glisse } 423771fe6b9SJerome Glisse 424771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_ADDR, 0); 425771fe6b9SJerome Glisse if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) || 426771fe6b9SJerome Glisse (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) || 427771fe6b9SJerome Glisse (rdev->family == CHIP_RS200)) { 428771fe6b9SJerome Glisse DRM_INFO("Loading R100 Microcode\n"); 429771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 430771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R100_cp_microcode[i][1]); 431771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R100_cp_microcode[i][0]); 432771fe6b9SJerome Glisse } 433771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R200) || 434771fe6b9SJerome Glisse (rdev->family == CHIP_RV250) || 435771fe6b9SJerome Glisse (rdev->family == CHIP_RV280) || 436771fe6b9SJerome Glisse (rdev->family == CHIP_RS300)) { 437771fe6b9SJerome Glisse DRM_INFO("Loading R200 Microcode\n"); 438771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 439771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R200_cp_microcode[i][1]); 440771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R200_cp_microcode[i][0]); 441771fe6b9SJerome Glisse } 442771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R300) || 443771fe6b9SJerome Glisse (rdev->family == CHIP_R350) || 444771fe6b9SJerome Glisse (rdev->family == CHIP_RV350) || 445771fe6b9SJerome Glisse (rdev->family == CHIP_RV380) || 446771fe6b9SJerome Glisse (rdev->family == CHIP_RS400) || 447771fe6b9SJerome Glisse (rdev->family == CHIP_RS480)) { 448771fe6b9SJerome Glisse DRM_INFO("Loading R300 Microcode\n"); 449771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 450771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R300_cp_microcode[i][1]); 451771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R300_cp_microcode[i][0]); 452771fe6b9SJerome Glisse } 453771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R420) || 454771fe6b9SJerome Glisse (rdev->family == CHIP_R423) || 455771fe6b9SJerome Glisse (rdev->family == CHIP_RV410)) { 456771fe6b9SJerome Glisse DRM_INFO("Loading R400 Microcode\n"); 457771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 458771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R420_cp_microcode[i][1]); 459771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R420_cp_microcode[i][0]); 460771fe6b9SJerome Glisse } 461771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_RS690) || 462771fe6b9SJerome Glisse (rdev->family == CHIP_RS740)) { 463771fe6b9SJerome Glisse DRM_INFO("Loading RS690/RS740 Microcode\n"); 464771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 465771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, RS690_cp_microcode[i][1]); 466771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, RS690_cp_microcode[i][0]); 467771fe6b9SJerome Glisse } 468771fe6b9SJerome Glisse } else if (rdev->family == CHIP_RS600) { 469771fe6b9SJerome Glisse DRM_INFO("Loading RS600 Microcode\n"); 470771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 471771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, RS600_cp_microcode[i][1]); 472771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, RS600_cp_microcode[i][0]); 473771fe6b9SJerome Glisse } 474771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_RV515) || 475771fe6b9SJerome Glisse (rdev->family == CHIP_R520) || 476771fe6b9SJerome Glisse (rdev->family == CHIP_RV530) || 477771fe6b9SJerome Glisse (rdev->family == CHIP_R580) || 478771fe6b9SJerome Glisse (rdev->family == CHIP_RV560) || 479771fe6b9SJerome Glisse (rdev->family == CHIP_RV570)) { 480771fe6b9SJerome Glisse DRM_INFO("Loading R500 Microcode\n"); 481771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 482771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R520_cp_microcode[i][1]); 483771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R520_cp_microcode[i][0]); 484771fe6b9SJerome Glisse } 485771fe6b9SJerome Glisse } 486771fe6b9SJerome Glisse } 487771fe6b9SJerome Glisse 488771fe6b9SJerome Glisse int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) 489771fe6b9SJerome Glisse { 490771fe6b9SJerome Glisse unsigned rb_bufsz; 491771fe6b9SJerome Glisse unsigned rb_blksz; 492771fe6b9SJerome Glisse unsigned max_fetch; 493771fe6b9SJerome Glisse unsigned pre_write_timer; 494771fe6b9SJerome Glisse unsigned pre_write_limit; 495771fe6b9SJerome Glisse unsigned indirect2_start; 496771fe6b9SJerome Glisse unsigned indirect1_start; 497771fe6b9SJerome Glisse uint32_t tmp; 498771fe6b9SJerome Glisse int r; 499771fe6b9SJerome Glisse 500771fe6b9SJerome Glisse if (r100_debugfs_cp_init(rdev)) { 501771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for CP !\n"); 502771fe6b9SJerome Glisse } 503771fe6b9SJerome Glisse /* Reset CP */ 504771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_STAT); 505771fe6b9SJerome Glisse if ((tmp & (1 << 31))) { 506771fe6b9SJerome Glisse DRM_INFO("radeon: cp busy (0x%08X) resetting\n", tmp); 507771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 508771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 509771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP); 510771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_SOFT_RESET); 511771fe6b9SJerome Glisse mdelay(2); 512771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 513771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_SOFT_RESET); 514771fe6b9SJerome Glisse mdelay(2); 515771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_STAT); 516771fe6b9SJerome Glisse if ((tmp & (1 << 31))) { 517771fe6b9SJerome Glisse DRM_INFO("radeon: cp reset failed (0x%08X)\n", tmp); 518771fe6b9SJerome Glisse } 519771fe6b9SJerome Glisse } else { 520771fe6b9SJerome Glisse DRM_INFO("radeon: cp idle (0x%08X)\n", tmp); 521771fe6b9SJerome Glisse } 522771fe6b9SJerome Glisse /* Align ring size */ 523771fe6b9SJerome Glisse rb_bufsz = drm_order(ring_size / 8); 524771fe6b9SJerome Glisse ring_size = (1 << (rb_bufsz + 1)) * 4; 525771fe6b9SJerome Glisse r100_cp_load_microcode(rdev); 526771fe6b9SJerome Glisse r = radeon_ring_init(rdev, ring_size); 527771fe6b9SJerome Glisse if (r) { 528771fe6b9SJerome Glisse return r; 529771fe6b9SJerome Glisse } 530771fe6b9SJerome Glisse /* Each time the cp read 1024 bytes (16 dword/quadword) update 531771fe6b9SJerome Glisse * the rptr copy in system ram */ 532771fe6b9SJerome Glisse rb_blksz = 9; 533771fe6b9SJerome Glisse /* cp will read 128bytes at a time (4 dwords) */ 534771fe6b9SJerome Glisse max_fetch = 1; 535771fe6b9SJerome Glisse rdev->cp.align_mask = 16 - 1; 536771fe6b9SJerome Glisse /* Write to CP_RB_WPTR will be delayed for pre_write_timer clocks */ 537771fe6b9SJerome Glisse pre_write_timer = 64; 538771fe6b9SJerome Glisse /* Force CP_RB_WPTR write if written more than one time before the 539771fe6b9SJerome Glisse * delay expire 540771fe6b9SJerome Glisse */ 541771fe6b9SJerome Glisse pre_write_limit = 0; 542771fe6b9SJerome Glisse /* Setup the cp cache like this (cache size is 96 dwords) : 543771fe6b9SJerome Glisse * RING 0 to 15 544771fe6b9SJerome Glisse * INDIRECT1 16 to 79 545771fe6b9SJerome Glisse * INDIRECT2 80 to 95 546771fe6b9SJerome Glisse * So ring cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) 547771fe6b9SJerome Glisse * indirect1 cache size is 64dwords (> (2 * max_fetch = 2 * 4dwords)) 548771fe6b9SJerome Glisse * indirect2 cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) 549771fe6b9SJerome Glisse * Idea being that most of the gpu cmd will be through indirect1 buffer 550771fe6b9SJerome Glisse * so it gets the bigger cache. 551771fe6b9SJerome Glisse */ 552771fe6b9SJerome Glisse indirect2_start = 80; 553771fe6b9SJerome Glisse indirect1_start = 16; 554771fe6b9SJerome Glisse /* cp setup */ 555771fe6b9SJerome Glisse WREG32(0x718, pre_write_timer | (pre_write_limit << 28)); 556771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, 5574e484e7dSMichel Dänzer #ifdef __BIG_ENDIAN 5584e484e7dSMichel Dänzer RADEON_BUF_SWAP_32BIT | 5594e484e7dSMichel Dänzer #endif 560771fe6b9SJerome Glisse REG_SET(RADEON_RB_BUFSZ, rb_bufsz) | 561771fe6b9SJerome Glisse REG_SET(RADEON_RB_BLKSZ, rb_blksz) | 562771fe6b9SJerome Glisse REG_SET(RADEON_MAX_FETCH, max_fetch) | 563771fe6b9SJerome Glisse RADEON_RB_NO_UPDATE); 564771fe6b9SJerome Glisse /* Set ring address */ 565771fe6b9SJerome Glisse DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr); 566771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr); 567771fe6b9SJerome Glisse /* Force read & write ptr to 0 */ 568771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_RB_CNTL); 569771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); 570771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_RPTR_WR, 0); 571771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_WPTR, 0); 572771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, tmp); 573771fe6b9SJerome Glisse udelay(10); 574771fe6b9SJerome Glisse rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); 575771fe6b9SJerome Glisse rdev->cp.wptr = RREG32(RADEON_CP_RB_WPTR); 576771fe6b9SJerome Glisse /* Set cp mode to bus mastering & enable cp*/ 577771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 578771fe6b9SJerome Glisse REG_SET(RADEON_INDIRECT2_START, indirect2_start) | 579771fe6b9SJerome Glisse REG_SET(RADEON_INDIRECT1_START, indirect1_start)); 580771fe6b9SJerome Glisse WREG32(0x718, 0); 581771fe6b9SJerome Glisse WREG32(0x744, 0x00004D4D); 582771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM); 583771fe6b9SJerome Glisse radeon_ring_start(rdev); 584771fe6b9SJerome Glisse r = radeon_ring_test(rdev); 585771fe6b9SJerome Glisse if (r) { 586771fe6b9SJerome Glisse DRM_ERROR("radeon: cp isn't working (%d).\n", r); 587771fe6b9SJerome Glisse return r; 588771fe6b9SJerome Glisse } 589771fe6b9SJerome Glisse rdev->cp.ready = true; 590771fe6b9SJerome Glisse return 0; 591771fe6b9SJerome Glisse } 592771fe6b9SJerome Glisse 593771fe6b9SJerome Glisse void r100_cp_fini(struct radeon_device *rdev) 594771fe6b9SJerome Glisse { 595771fe6b9SJerome Glisse /* Disable ring */ 596771fe6b9SJerome Glisse rdev->cp.ready = false; 597771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 598771fe6b9SJerome Glisse radeon_ring_fini(rdev); 599771fe6b9SJerome Glisse DRM_INFO("radeon: cp finalized\n"); 600771fe6b9SJerome Glisse } 601771fe6b9SJerome Glisse 602771fe6b9SJerome Glisse void r100_cp_disable(struct radeon_device *rdev) 603771fe6b9SJerome Glisse { 604771fe6b9SJerome Glisse /* Disable ring */ 605771fe6b9SJerome Glisse rdev->cp.ready = false; 606771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 607771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 608771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 609771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 610771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 611771fe6b9SJerome Glisse } 612771fe6b9SJerome Glisse } 613771fe6b9SJerome Glisse 614771fe6b9SJerome Glisse int r100_cp_reset(struct radeon_device *rdev) 615771fe6b9SJerome Glisse { 616771fe6b9SJerome Glisse uint32_t tmp; 617771fe6b9SJerome Glisse bool reinit_cp; 618771fe6b9SJerome Glisse int i; 619771fe6b9SJerome Glisse 620771fe6b9SJerome Glisse reinit_cp = rdev->cp.ready; 621771fe6b9SJerome Glisse rdev->cp.ready = false; 622771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 623771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 624771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP); 625771fe6b9SJerome Glisse (void)RREG32(RADEON_RBBM_SOFT_RESET); 626771fe6b9SJerome Glisse udelay(200); 627771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 628771fe6b9SJerome Glisse /* Wait to prevent race in RBBM_STATUS */ 629771fe6b9SJerome Glisse mdelay(1); 630771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 631771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 632771fe6b9SJerome Glisse if (!(tmp & (1 << 16))) { 633771fe6b9SJerome Glisse DRM_INFO("CP reset succeed (RBBM_STATUS=0x%08X)\n", 634771fe6b9SJerome Glisse tmp); 635771fe6b9SJerome Glisse if (reinit_cp) { 636771fe6b9SJerome Glisse return r100_cp_init(rdev, rdev->cp.ring_size); 637771fe6b9SJerome Glisse } 638771fe6b9SJerome Glisse return 0; 639771fe6b9SJerome Glisse } 640771fe6b9SJerome Glisse DRM_UDELAY(1); 641771fe6b9SJerome Glisse } 642771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 643771fe6b9SJerome Glisse DRM_ERROR("Failed to reset CP (RBBM_STATUS=0x%08X)!\n", tmp); 644771fe6b9SJerome Glisse return -1; 645771fe6b9SJerome Glisse } 646771fe6b9SJerome Glisse 647771fe6b9SJerome Glisse 648771fe6b9SJerome Glisse /* 649771fe6b9SJerome Glisse * CS functions 650771fe6b9SJerome Glisse */ 651771fe6b9SJerome Glisse int r100_cs_parse_packet0(struct radeon_cs_parser *p, 652771fe6b9SJerome Glisse struct radeon_cs_packet *pkt, 653068a117cSJerome Glisse const unsigned *auth, unsigned n, 654771fe6b9SJerome Glisse radeon_packet0_check_t check) 655771fe6b9SJerome Glisse { 656771fe6b9SJerome Glisse unsigned reg; 657771fe6b9SJerome Glisse unsigned i, j, m; 658771fe6b9SJerome Glisse unsigned idx; 659771fe6b9SJerome Glisse int r; 660771fe6b9SJerome Glisse 661771fe6b9SJerome Glisse idx = pkt->idx + 1; 662771fe6b9SJerome Glisse reg = pkt->reg; 663068a117cSJerome Glisse /* Check that register fall into register range 664068a117cSJerome Glisse * determined by the number of entry (n) in the 665068a117cSJerome Glisse * safe register bitmap. 666068a117cSJerome Glisse */ 667771fe6b9SJerome Glisse if (pkt->one_reg_wr) { 668771fe6b9SJerome Glisse if ((reg >> 7) > n) { 669771fe6b9SJerome Glisse return -EINVAL; 670771fe6b9SJerome Glisse } 671771fe6b9SJerome Glisse } else { 672771fe6b9SJerome Glisse if (((reg + (pkt->count << 2)) >> 7) > n) { 673771fe6b9SJerome Glisse return -EINVAL; 674771fe6b9SJerome Glisse } 675771fe6b9SJerome Glisse } 676771fe6b9SJerome Glisse for (i = 0; i <= pkt->count; i++, idx++) { 677771fe6b9SJerome Glisse j = (reg >> 7); 678771fe6b9SJerome Glisse m = 1 << ((reg >> 2) & 31); 679771fe6b9SJerome Glisse if (auth[j] & m) { 680771fe6b9SJerome Glisse r = check(p, pkt, idx, reg); 681771fe6b9SJerome Glisse if (r) { 682771fe6b9SJerome Glisse return r; 683771fe6b9SJerome Glisse } 684771fe6b9SJerome Glisse } 685771fe6b9SJerome Glisse if (pkt->one_reg_wr) { 686771fe6b9SJerome Glisse if (!(auth[j] & m)) { 687771fe6b9SJerome Glisse break; 688771fe6b9SJerome Glisse } 689771fe6b9SJerome Glisse } else { 690771fe6b9SJerome Glisse reg += 4; 691771fe6b9SJerome Glisse } 692771fe6b9SJerome Glisse } 693771fe6b9SJerome Glisse return 0; 694771fe6b9SJerome Glisse } 695771fe6b9SJerome Glisse 696771fe6b9SJerome Glisse void r100_cs_dump_packet(struct radeon_cs_parser *p, 697771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 698771fe6b9SJerome Glisse { 699771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 700771fe6b9SJerome Glisse volatile uint32_t *ib; 701771fe6b9SJerome Glisse unsigned i; 702771fe6b9SJerome Glisse unsigned idx; 703771fe6b9SJerome Glisse 704771fe6b9SJerome Glisse ib = p->ib->ptr; 705771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 706771fe6b9SJerome Glisse idx = pkt->idx; 707771fe6b9SJerome Glisse for (i = 0; i <= (pkt->count + 1); i++, idx++) { 708771fe6b9SJerome Glisse DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]); 709771fe6b9SJerome Glisse } 710771fe6b9SJerome Glisse } 711771fe6b9SJerome Glisse 712771fe6b9SJerome Glisse /** 713771fe6b9SJerome Glisse * r100_cs_packet_parse() - parse cp packet and point ib index to next packet 714771fe6b9SJerome Glisse * @parser: parser structure holding parsing context. 715771fe6b9SJerome Glisse * @pkt: where to store packet informations 716771fe6b9SJerome Glisse * 717771fe6b9SJerome Glisse * Assume that chunk_ib_index is properly set. Will return -EINVAL 718771fe6b9SJerome Glisse * if packet is bigger than remaining ib size. or if packets is unknown. 719771fe6b9SJerome Glisse **/ 720771fe6b9SJerome Glisse int r100_cs_packet_parse(struct radeon_cs_parser *p, 721771fe6b9SJerome Glisse struct radeon_cs_packet *pkt, 722771fe6b9SJerome Glisse unsigned idx) 723771fe6b9SJerome Glisse { 724771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; 725771fe6b9SJerome Glisse uint32_t header = ib_chunk->kdata[idx]; 726771fe6b9SJerome Glisse 727771fe6b9SJerome Glisse if (idx >= ib_chunk->length_dw) { 728771fe6b9SJerome Glisse DRM_ERROR("Can not parse packet at %d after CS end %d !\n", 729771fe6b9SJerome Glisse idx, ib_chunk->length_dw); 730771fe6b9SJerome Glisse return -EINVAL; 731771fe6b9SJerome Glisse } 732771fe6b9SJerome Glisse pkt->idx = idx; 733771fe6b9SJerome Glisse pkt->type = CP_PACKET_GET_TYPE(header); 734771fe6b9SJerome Glisse pkt->count = CP_PACKET_GET_COUNT(header); 735771fe6b9SJerome Glisse switch (pkt->type) { 736771fe6b9SJerome Glisse case PACKET_TYPE0: 737771fe6b9SJerome Glisse pkt->reg = CP_PACKET0_GET_REG(header); 738771fe6b9SJerome Glisse pkt->one_reg_wr = CP_PACKET0_GET_ONE_REG_WR(header); 739771fe6b9SJerome Glisse break; 740771fe6b9SJerome Glisse case PACKET_TYPE3: 741771fe6b9SJerome Glisse pkt->opcode = CP_PACKET3_GET_OPCODE(header); 742771fe6b9SJerome Glisse break; 743771fe6b9SJerome Glisse case PACKET_TYPE2: 744771fe6b9SJerome Glisse pkt->count = -1; 745771fe6b9SJerome Glisse break; 746771fe6b9SJerome Glisse default: 747771fe6b9SJerome Glisse DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx); 748771fe6b9SJerome Glisse return -EINVAL; 749771fe6b9SJerome Glisse } 750771fe6b9SJerome Glisse if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) { 751771fe6b9SJerome Glisse DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n", 752771fe6b9SJerome Glisse pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw); 753771fe6b9SJerome Glisse return -EINVAL; 754771fe6b9SJerome Glisse } 755771fe6b9SJerome Glisse return 0; 756771fe6b9SJerome Glisse } 757771fe6b9SJerome Glisse 758771fe6b9SJerome Glisse /** 759531369e6SDave Airlie * r100_cs_packet_next_vline() - parse userspace VLINE packet 760531369e6SDave Airlie * @parser: parser structure holding parsing context. 761531369e6SDave Airlie * 762531369e6SDave Airlie * Userspace sends a special sequence for VLINE waits. 763531369e6SDave Airlie * PACKET0 - VLINE_START_END + value 764531369e6SDave Airlie * PACKET0 - WAIT_UNTIL +_value 765531369e6SDave Airlie * RELOC (P3) - crtc_id in reloc. 766531369e6SDave Airlie * 767531369e6SDave Airlie * This function parses this and relocates the VLINE START END 768531369e6SDave Airlie * and WAIT UNTIL packets to the correct crtc. 769531369e6SDave Airlie * It also detects a switched off crtc and nulls out the 770531369e6SDave Airlie * wait in that case. 771531369e6SDave Airlie */ 772531369e6SDave Airlie int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) 773531369e6SDave Airlie { 774531369e6SDave Airlie struct radeon_cs_chunk *ib_chunk; 775531369e6SDave Airlie struct drm_mode_object *obj; 776531369e6SDave Airlie struct drm_crtc *crtc; 777531369e6SDave Airlie struct radeon_crtc *radeon_crtc; 778531369e6SDave Airlie struct radeon_cs_packet p3reloc, waitreloc; 779531369e6SDave Airlie int crtc_id; 780531369e6SDave Airlie int r; 781531369e6SDave Airlie uint32_t header, h_idx, reg; 782531369e6SDave Airlie 783531369e6SDave Airlie ib_chunk = &p->chunks[p->chunk_ib_idx]; 784531369e6SDave Airlie 785531369e6SDave Airlie /* parse the wait until */ 786531369e6SDave Airlie r = r100_cs_packet_parse(p, &waitreloc, p->idx); 787531369e6SDave Airlie if (r) 788531369e6SDave Airlie return r; 789531369e6SDave Airlie 790531369e6SDave Airlie /* check its a wait until and only 1 count */ 791531369e6SDave Airlie if (waitreloc.reg != RADEON_WAIT_UNTIL || 792531369e6SDave Airlie waitreloc.count != 0) { 793531369e6SDave Airlie DRM_ERROR("vline wait had illegal wait until segment\n"); 794531369e6SDave Airlie r = -EINVAL; 795531369e6SDave Airlie return r; 796531369e6SDave Airlie } 797531369e6SDave Airlie 798531369e6SDave Airlie if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) { 799531369e6SDave Airlie DRM_ERROR("vline wait had illegal wait until\n"); 800531369e6SDave Airlie r = -EINVAL; 801531369e6SDave Airlie return r; 802531369e6SDave Airlie } 803531369e6SDave Airlie 804531369e6SDave Airlie /* jump over the NOP */ 805531369e6SDave Airlie r = r100_cs_packet_parse(p, &p3reloc, p->idx); 806531369e6SDave Airlie if (r) 807531369e6SDave Airlie return r; 808531369e6SDave Airlie 809531369e6SDave Airlie h_idx = p->idx - 2; 810531369e6SDave Airlie p->idx += waitreloc.count; 811531369e6SDave Airlie p->idx += p3reloc.count; 812531369e6SDave Airlie 813531369e6SDave Airlie header = ib_chunk->kdata[h_idx]; 814531369e6SDave Airlie crtc_id = ib_chunk->kdata[h_idx + 5]; 815531369e6SDave Airlie reg = ib_chunk->kdata[h_idx] >> 2; 816531369e6SDave Airlie mutex_lock(&p->rdev->ddev->mode_config.mutex); 817531369e6SDave Airlie obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); 818531369e6SDave Airlie if (!obj) { 819531369e6SDave Airlie DRM_ERROR("cannot find crtc %d\n", crtc_id); 820531369e6SDave Airlie r = -EINVAL; 821531369e6SDave Airlie goto out; 822531369e6SDave Airlie } 823531369e6SDave Airlie crtc = obj_to_crtc(obj); 824531369e6SDave Airlie radeon_crtc = to_radeon_crtc(crtc); 825531369e6SDave Airlie crtc_id = radeon_crtc->crtc_id; 826531369e6SDave Airlie 827531369e6SDave Airlie if (!crtc->enabled) { 828531369e6SDave Airlie /* if the CRTC isn't enabled - we need to nop out the wait until */ 829531369e6SDave Airlie ib_chunk->kdata[h_idx + 2] = PACKET2(0); 830531369e6SDave Airlie ib_chunk->kdata[h_idx + 3] = PACKET2(0); 831531369e6SDave Airlie } else if (crtc_id == 1) { 832531369e6SDave Airlie switch (reg) { 833531369e6SDave Airlie case AVIVO_D1MODE_VLINE_START_END: 834531369e6SDave Airlie header &= R300_CP_PACKET0_REG_MASK; 835531369e6SDave Airlie header |= AVIVO_D2MODE_VLINE_START_END >> 2; 836531369e6SDave Airlie break; 837531369e6SDave Airlie case RADEON_CRTC_GUI_TRIG_VLINE: 838531369e6SDave Airlie header &= R300_CP_PACKET0_REG_MASK; 839531369e6SDave Airlie header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2; 840531369e6SDave Airlie break; 841531369e6SDave Airlie default: 842531369e6SDave Airlie DRM_ERROR("unknown crtc reloc\n"); 843531369e6SDave Airlie r = -EINVAL; 844531369e6SDave Airlie goto out; 845531369e6SDave Airlie } 846531369e6SDave Airlie ib_chunk->kdata[h_idx] = header; 847531369e6SDave Airlie ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; 848531369e6SDave Airlie } 849531369e6SDave Airlie out: 850531369e6SDave Airlie mutex_unlock(&p->rdev->ddev->mode_config.mutex); 851531369e6SDave Airlie return r; 852531369e6SDave Airlie } 853531369e6SDave Airlie 854531369e6SDave Airlie /** 855771fe6b9SJerome Glisse * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 856771fe6b9SJerome Glisse * @parser: parser structure holding parsing context. 857771fe6b9SJerome Glisse * @data: pointer to relocation data 858771fe6b9SJerome Glisse * @offset_start: starting offset 859771fe6b9SJerome Glisse * @offset_mask: offset mask (to align start offset on) 860771fe6b9SJerome Glisse * @reloc: reloc informations 861771fe6b9SJerome Glisse * 862771fe6b9SJerome Glisse * Check next packet is relocation packet3, do bo validation and compute 863771fe6b9SJerome Glisse * GPU offset using the provided start. 864771fe6b9SJerome Glisse **/ 865771fe6b9SJerome Glisse int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, 866771fe6b9SJerome Glisse struct radeon_cs_reloc **cs_reloc) 867771fe6b9SJerome Glisse { 868771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 869771fe6b9SJerome Glisse struct radeon_cs_chunk *relocs_chunk; 870771fe6b9SJerome Glisse struct radeon_cs_packet p3reloc; 871771fe6b9SJerome Glisse unsigned idx; 872771fe6b9SJerome Glisse int r; 873771fe6b9SJerome Glisse 874771fe6b9SJerome Glisse if (p->chunk_relocs_idx == -1) { 875771fe6b9SJerome Glisse DRM_ERROR("No relocation chunk !\n"); 876771fe6b9SJerome Glisse return -EINVAL; 877771fe6b9SJerome Glisse } 878771fe6b9SJerome Glisse *cs_reloc = NULL; 879771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 880771fe6b9SJerome Glisse relocs_chunk = &p->chunks[p->chunk_relocs_idx]; 881771fe6b9SJerome Glisse r = r100_cs_packet_parse(p, &p3reloc, p->idx); 882771fe6b9SJerome Glisse if (r) { 883771fe6b9SJerome Glisse return r; 884771fe6b9SJerome Glisse } 885771fe6b9SJerome Glisse p->idx += p3reloc.count + 2; 886771fe6b9SJerome Glisse if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { 887771fe6b9SJerome Glisse DRM_ERROR("No packet3 for relocation for packet at %d.\n", 888771fe6b9SJerome Glisse p3reloc.idx); 889771fe6b9SJerome Glisse r100_cs_dump_packet(p, &p3reloc); 890771fe6b9SJerome Glisse return -EINVAL; 891771fe6b9SJerome Glisse } 892771fe6b9SJerome Glisse idx = ib_chunk->kdata[p3reloc.idx + 1]; 893771fe6b9SJerome Glisse if (idx >= relocs_chunk->length_dw) { 894771fe6b9SJerome Glisse DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", 895771fe6b9SJerome Glisse idx, relocs_chunk->length_dw); 896771fe6b9SJerome Glisse r100_cs_dump_packet(p, &p3reloc); 897771fe6b9SJerome Glisse return -EINVAL; 898771fe6b9SJerome Glisse } 899771fe6b9SJerome Glisse /* FIXME: we assume reloc size is 4 dwords */ 900771fe6b9SJerome Glisse *cs_reloc = p->relocs_ptr[(idx / 4)]; 901771fe6b9SJerome Glisse return 0; 902771fe6b9SJerome Glisse } 903771fe6b9SJerome Glisse 904771fe6b9SJerome Glisse static int r100_packet0_check(struct radeon_cs_parser *p, 905771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 906771fe6b9SJerome Glisse { 907771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 908771fe6b9SJerome Glisse struct radeon_cs_reloc *reloc; 909771fe6b9SJerome Glisse volatile uint32_t *ib; 910771fe6b9SJerome Glisse uint32_t tmp; 911771fe6b9SJerome Glisse unsigned reg; 912771fe6b9SJerome Glisse unsigned i; 913771fe6b9SJerome Glisse unsigned idx; 914771fe6b9SJerome Glisse bool onereg; 915771fe6b9SJerome Glisse int r; 916e024e110SDave Airlie u32 tile_flags = 0; 917771fe6b9SJerome Glisse 918771fe6b9SJerome Glisse ib = p->ib->ptr; 919771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 920771fe6b9SJerome Glisse idx = pkt->idx + 1; 921771fe6b9SJerome Glisse reg = pkt->reg; 922771fe6b9SJerome Glisse onereg = false; 923771fe6b9SJerome Glisse if (CP_PACKET0_GET_ONE_REG_WR(ib_chunk->kdata[pkt->idx])) { 924771fe6b9SJerome Glisse onereg = true; 925771fe6b9SJerome Glisse } 926771fe6b9SJerome Glisse for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { 927771fe6b9SJerome Glisse switch (reg) { 928531369e6SDave Airlie case RADEON_CRTC_GUI_TRIG_VLINE: 929531369e6SDave Airlie r = r100_cs_packet_parse_vline(p); 930531369e6SDave Airlie if (r) { 931531369e6SDave Airlie DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 932531369e6SDave Airlie idx, reg); 933531369e6SDave Airlie r100_cs_dump_packet(p, pkt); 934531369e6SDave Airlie return r; 935531369e6SDave Airlie } 936531369e6SDave Airlie break; 937771fe6b9SJerome Glisse /* FIXME: only allow PACKET3 blit? easier to check for out of 938771fe6b9SJerome Glisse * range access */ 939771fe6b9SJerome Glisse case RADEON_DST_PITCH_OFFSET: 940771fe6b9SJerome Glisse case RADEON_SRC_PITCH_OFFSET: 941771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 942771fe6b9SJerome Glisse if (r) { 943771fe6b9SJerome Glisse DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 944771fe6b9SJerome Glisse idx, reg); 945771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 946771fe6b9SJerome Glisse return r; 947771fe6b9SJerome Glisse } 948771fe6b9SJerome Glisse tmp = ib_chunk->kdata[idx] & 0x003fffff; 949771fe6b9SJerome Glisse tmp += (((u32)reloc->lobj.gpu_offset) >> 10); 950e024e110SDave Airlie 951e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) 952e024e110SDave Airlie tile_flags |= RADEON_DST_TILE_MACRO; 953e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { 954e024e110SDave Airlie if (reg == RADEON_SRC_PITCH_OFFSET) { 955e024e110SDave Airlie DRM_ERROR("Cannot src blit from microtiled surface\n"); 956e024e110SDave Airlie r100_cs_dump_packet(p, pkt); 957e024e110SDave Airlie return -EINVAL; 958e024e110SDave Airlie } 959e024e110SDave Airlie tile_flags |= RADEON_DST_TILE_MICRO; 960e024e110SDave Airlie } 961e024e110SDave Airlie 962e024e110SDave Airlie tmp |= tile_flags; 963e024e110SDave Airlie ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp; 964771fe6b9SJerome Glisse break; 965771fe6b9SJerome Glisse case RADEON_RB3D_DEPTHOFFSET: 966771fe6b9SJerome Glisse case RADEON_RB3D_COLOROFFSET: 967771fe6b9SJerome Glisse case R300_RB3D_COLOROFFSET0: 968771fe6b9SJerome Glisse case R300_ZB_DEPTHOFFSET: 969771fe6b9SJerome Glisse case R200_PP_TXOFFSET_0: 970771fe6b9SJerome Glisse case R200_PP_TXOFFSET_1: 971771fe6b9SJerome Glisse case R200_PP_TXOFFSET_2: 972771fe6b9SJerome Glisse case R200_PP_TXOFFSET_3: 973771fe6b9SJerome Glisse case R200_PP_TXOFFSET_4: 974771fe6b9SJerome Glisse case R200_PP_TXOFFSET_5: 975771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_0: 976771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_1: 977771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_2: 978771fe6b9SJerome Glisse case R300_TX_OFFSET_0: 979771fe6b9SJerome Glisse case R300_TX_OFFSET_0+4: 980771fe6b9SJerome Glisse case R300_TX_OFFSET_0+8: 981771fe6b9SJerome Glisse case R300_TX_OFFSET_0+12: 982771fe6b9SJerome Glisse case R300_TX_OFFSET_0+16: 983771fe6b9SJerome Glisse case R300_TX_OFFSET_0+20: 984771fe6b9SJerome Glisse case R300_TX_OFFSET_0+24: 985771fe6b9SJerome Glisse case R300_TX_OFFSET_0+28: 986771fe6b9SJerome Glisse case R300_TX_OFFSET_0+32: 987771fe6b9SJerome Glisse case R300_TX_OFFSET_0+36: 988771fe6b9SJerome Glisse case R300_TX_OFFSET_0+40: 989771fe6b9SJerome Glisse case R300_TX_OFFSET_0+44: 990771fe6b9SJerome Glisse case R300_TX_OFFSET_0+48: 991771fe6b9SJerome Glisse case R300_TX_OFFSET_0+52: 992771fe6b9SJerome Glisse case R300_TX_OFFSET_0+56: 993771fe6b9SJerome Glisse case R300_TX_OFFSET_0+60: 994b995e433SDave Airlie /* rn50 has no 3D engine so fail on any 3d setup */ 995b995e433SDave Airlie if (ASIC_IS_RN50(p->rdev)) { 996b995e433SDave Airlie DRM_ERROR("attempt to use RN50 3D engine failed\n"); 997b995e433SDave Airlie return -EINVAL; 998b995e433SDave Airlie } 999771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1000771fe6b9SJerome Glisse if (r) { 1001771fe6b9SJerome Glisse DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1002771fe6b9SJerome Glisse idx, reg); 1003771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1004771fe6b9SJerome Glisse return r; 1005771fe6b9SJerome Glisse } 1006771fe6b9SJerome Glisse ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); 1007771fe6b9SJerome Glisse break; 1008e024e110SDave Airlie case R300_RB3D_COLORPITCH0: 1009e024e110SDave Airlie case RADEON_RB3D_COLORPITCH: 1010e024e110SDave Airlie r = r100_cs_packet_next_reloc(p, &reloc); 1011e024e110SDave Airlie if (r) { 1012e024e110SDave Airlie DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1013e024e110SDave Airlie idx, reg); 1014e024e110SDave Airlie r100_cs_dump_packet(p, pkt); 1015e024e110SDave Airlie return r; 1016e024e110SDave Airlie } 1017e024e110SDave Airlie 1018e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) 1019e024e110SDave Airlie tile_flags |= RADEON_COLOR_TILE_ENABLE; 1020e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) 1021e024e110SDave Airlie tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; 1022e024e110SDave Airlie 1023e024e110SDave Airlie tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); 1024e024e110SDave Airlie tmp |= tile_flags; 1025e024e110SDave Airlie ib[idx] = tmp; 1026e024e110SDave Airlie break; 1027771fe6b9SJerome Glisse default: 1028771fe6b9SJerome Glisse /* FIXME: we don't want to allow anyothers packet */ 1029771fe6b9SJerome Glisse break; 1030771fe6b9SJerome Glisse } 1031771fe6b9SJerome Glisse if (onereg) { 1032771fe6b9SJerome Glisse /* FIXME: forbid onereg write to register on relocate */ 1033771fe6b9SJerome Glisse break; 1034771fe6b9SJerome Glisse } 1035771fe6b9SJerome Glisse } 1036771fe6b9SJerome Glisse return 0; 1037771fe6b9SJerome Glisse } 1038771fe6b9SJerome Glisse 1039068a117cSJerome Glisse int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, 1040068a117cSJerome Glisse struct radeon_cs_packet *pkt, 1041068a117cSJerome Glisse struct radeon_object *robj) 1042068a117cSJerome Glisse { 1043068a117cSJerome Glisse struct radeon_cs_chunk *ib_chunk; 1044068a117cSJerome Glisse unsigned idx; 1045068a117cSJerome Glisse 1046068a117cSJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 1047068a117cSJerome Glisse idx = pkt->idx + 1; 1048068a117cSJerome Glisse if ((ib_chunk->kdata[idx+2] + 1) > radeon_object_size(robj)) { 1049068a117cSJerome Glisse DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER " 1050068a117cSJerome Glisse "(need %u have %lu) !\n", 1051068a117cSJerome Glisse ib_chunk->kdata[idx+2] + 1, 1052068a117cSJerome Glisse radeon_object_size(robj)); 1053068a117cSJerome Glisse return -EINVAL; 1054068a117cSJerome Glisse } 1055068a117cSJerome Glisse return 0; 1056068a117cSJerome Glisse } 1057068a117cSJerome Glisse 1058771fe6b9SJerome Glisse static int r100_packet3_check(struct radeon_cs_parser *p, 1059771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 1060771fe6b9SJerome Glisse { 1061771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 1062771fe6b9SJerome Glisse struct radeon_cs_reloc *reloc; 1063771fe6b9SJerome Glisse unsigned idx; 1064771fe6b9SJerome Glisse unsigned i, c; 1065771fe6b9SJerome Glisse volatile uint32_t *ib; 1066771fe6b9SJerome Glisse int r; 1067771fe6b9SJerome Glisse 1068771fe6b9SJerome Glisse ib = p->ib->ptr; 1069771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 1070771fe6b9SJerome Glisse idx = pkt->idx + 1; 1071771fe6b9SJerome Glisse switch (pkt->opcode) { 1072771fe6b9SJerome Glisse case PACKET3_3D_LOAD_VBPNTR: 1073771fe6b9SJerome Glisse c = ib_chunk->kdata[idx++]; 1074771fe6b9SJerome Glisse for (i = 0; i < (c - 1); i += 2, idx += 3) { 1075771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1076771fe6b9SJerome Glisse if (r) { 1077771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 1078771fe6b9SJerome Glisse pkt->opcode); 1079771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1080771fe6b9SJerome Glisse return r; 1081771fe6b9SJerome Glisse } 1082771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1083771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1084771fe6b9SJerome Glisse if (r) { 1085771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 1086771fe6b9SJerome Glisse pkt->opcode); 1087771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1088771fe6b9SJerome Glisse return r; 1089771fe6b9SJerome Glisse } 1090771fe6b9SJerome Glisse ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset); 1091771fe6b9SJerome Glisse } 1092771fe6b9SJerome Glisse if (c & 1) { 1093771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1094771fe6b9SJerome Glisse if (r) { 1095771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 1096771fe6b9SJerome Glisse pkt->opcode); 1097771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1098771fe6b9SJerome Glisse return r; 1099771fe6b9SJerome Glisse } 1100771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1101771fe6b9SJerome Glisse } 1102771fe6b9SJerome Glisse break; 1103771fe6b9SJerome Glisse case PACKET3_INDX_BUFFER: 1104771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1105771fe6b9SJerome Glisse if (r) { 1106771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 1107771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1108771fe6b9SJerome Glisse return r; 1109771fe6b9SJerome Glisse } 1110771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1111068a117cSJerome Glisse r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj); 1112068a117cSJerome Glisse if (r) { 1113068a117cSJerome Glisse return r; 1114068a117cSJerome Glisse } 1115771fe6b9SJerome Glisse break; 1116771fe6b9SJerome Glisse case 0x23: 1117771fe6b9SJerome Glisse /* FIXME: cleanup */ 1118771fe6b9SJerome Glisse /* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */ 1119771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1120771fe6b9SJerome Glisse if (r) { 1121771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 1122771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1123771fe6b9SJerome Glisse return r; 1124771fe6b9SJerome Glisse } 1125771fe6b9SJerome Glisse ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); 1126771fe6b9SJerome Glisse break; 1127771fe6b9SJerome Glisse case PACKET3_3D_DRAW_IMMD: 1128771fe6b9SJerome Glisse /* triggers drawing using in-packet vertex data */ 1129771fe6b9SJerome Glisse case PACKET3_3D_DRAW_IMMD_2: 1130771fe6b9SJerome Glisse /* triggers drawing using in-packet vertex data */ 1131771fe6b9SJerome Glisse case PACKET3_3D_DRAW_VBUF_2: 1132771fe6b9SJerome Glisse /* triggers drawing of vertex buffers setup elsewhere */ 1133771fe6b9SJerome Glisse case PACKET3_3D_DRAW_INDX_2: 1134771fe6b9SJerome Glisse /* triggers drawing using indices to vertex buffer */ 1135771fe6b9SJerome Glisse case PACKET3_3D_DRAW_VBUF: 1136771fe6b9SJerome Glisse /* triggers drawing of vertex buffers setup elsewhere */ 1137771fe6b9SJerome Glisse case PACKET3_3D_DRAW_INDX: 1138771fe6b9SJerome Glisse /* triggers drawing using indices to vertex buffer */ 1139771fe6b9SJerome Glisse case PACKET3_NOP: 1140771fe6b9SJerome Glisse break; 1141771fe6b9SJerome Glisse default: 1142771fe6b9SJerome Glisse DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); 1143771fe6b9SJerome Glisse return -EINVAL; 1144771fe6b9SJerome Glisse } 1145771fe6b9SJerome Glisse return 0; 1146771fe6b9SJerome Glisse } 1147771fe6b9SJerome Glisse 1148771fe6b9SJerome Glisse int r100_cs_parse(struct radeon_cs_parser *p) 1149771fe6b9SJerome Glisse { 1150771fe6b9SJerome Glisse struct radeon_cs_packet pkt; 1151771fe6b9SJerome Glisse int r; 1152771fe6b9SJerome Glisse 1153771fe6b9SJerome Glisse do { 1154771fe6b9SJerome Glisse r = r100_cs_packet_parse(p, &pkt, p->idx); 1155771fe6b9SJerome Glisse if (r) { 1156771fe6b9SJerome Glisse return r; 1157771fe6b9SJerome Glisse } 1158771fe6b9SJerome Glisse p->idx += pkt.count + 2; 1159771fe6b9SJerome Glisse switch (pkt.type) { 1160771fe6b9SJerome Glisse case PACKET_TYPE0: 1161771fe6b9SJerome Glisse r = r100_packet0_check(p, &pkt); 1162771fe6b9SJerome Glisse break; 1163771fe6b9SJerome Glisse case PACKET_TYPE2: 1164771fe6b9SJerome Glisse break; 1165771fe6b9SJerome Glisse case PACKET_TYPE3: 1166771fe6b9SJerome Glisse r = r100_packet3_check(p, &pkt); 1167771fe6b9SJerome Glisse break; 1168771fe6b9SJerome Glisse default: 1169771fe6b9SJerome Glisse DRM_ERROR("Unknown packet type %d !\n", 1170771fe6b9SJerome Glisse pkt.type); 1171771fe6b9SJerome Glisse return -EINVAL; 1172771fe6b9SJerome Glisse } 1173771fe6b9SJerome Glisse if (r) { 1174771fe6b9SJerome Glisse return r; 1175771fe6b9SJerome Glisse } 1176771fe6b9SJerome Glisse } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); 1177771fe6b9SJerome Glisse return 0; 1178771fe6b9SJerome Glisse } 1179771fe6b9SJerome Glisse 1180771fe6b9SJerome Glisse 1181771fe6b9SJerome Glisse /* 1182771fe6b9SJerome Glisse * Global GPU functions 1183771fe6b9SJerome Glisse */ 1184771fe6b9SJerome Glisse void r100_errata(struct radeon_device *rdev) 1185771fe6b9SJerome Glisse { 1186771fe6b9SJerome Glisse rdev->pll_errata = 0; 1187771fe6b9SJerome Glisse 1188771fe6b9SJerome Glisse if (rdev->family == CHIP_RV200 || rdev->family == CHIP_RS200) { 1189771fe6b9SJerome Glisse rdev->pll_errata |= CHIP_ERRATA_PLL_DUMMYREADS; 1190771fe6b9SJerome Glisse } 1191771fe6b9SJerome Glisse 1192771fe6b9SJerome Glisse if (rdev->family == CHIP_RV100 || 1193771fe6b9SJerome Glisse rdev->family == CHIP_RS100 || 1194771fe6b9SJerome Glisse rdev->family == CHIP_RS200) { 1195771fe6b9SJerome Glisse rdev->pll_errata |= CHIP_ERRATA_PLL_DELAY; 1196771fe6b9SJerome Glisse } 1197771fe6b9SJerome Glisse } 1198771fe6b9SJerome Glisse 1199771fe6b9SJerome Glisse /* Wait for vertical sync on primary CRTC */ 1200771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync(struct radeon_device *rdev) 1201771fe6b9SJerome Glisse { 1202771fe6b9SJerome Glisse uint32_t crtc_gen_cntl, tmp; 1203771fe6b9SJerome Glisse int i; 1204771fe6b9SJerome Glisse 1205771fe6b9SJerome Glisse crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); 1206771fe6b9SJerome Glisse if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || 1207771fe6b9SJerome Glisse !(crtc_gen_cntl & RADEON_CRTC_EN)) { 1208771fe6b9SJerome Glisse return; 1209771fe6b9SJerome Glisse } 1210771fe6b9SJerome Glisse /* Clear the CRTC_VBLANK_SAVE bit */ 1211771fe6b9SJerome Glisse WREG32(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); 1212771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1213771fe6b9SJerome Glisse tmp = RREG32(RADEON_CRTC_STATUS); 1214771fe6b9SJerome Glisse if (tmp & RADEON_CRTC_VBLANK_SAVE) { 1215771fe6b9SJerome Glisse return; 1216771fe6b9SJerome Glisse } 1217771fe6b9SJerome Glisse DRM_UDELAY(1); 1218771fe6b9SJerome Glisse } 1219771fe6b9SJerome Glisse } 1220771fe6b9SJerome Glisse 1221771fe6b9SJerome Glisse /* Wait for vertical sync on secondary CRTC */ 1222771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync2(struct radeon_device *rdev) 1223771fe6b9SJerome Glisse { 1224771fe6b9SJerome Glisse uint32_t crtc2_gen_cntl, tmp; 1225771fe6b9SJerome Glisse int i; 1226771fe6b9SJerome Glisse 1227771fe6b9SJerome Glisse crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 1228771fe6b9SJerome Glisse if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || 1229771fe6b9SJerome Glisse !(crtc2_gen_cntl & RADEON_CRTC2_EN)) 1230771fe6b9SJerome Glisse return; 1231771fe6b9SJerome Glisse 1232771fe6b9SJerome Glisse /* Clear the CRTC_VBLANK_SAVE bit */ 1233771fe6b9SJerome Glisse WREG32(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); 1234771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1235771fe6b9SJerome Glisse tmp = RREG32(RADEON_CRTC2_STATUS); 1236771fe6b9SJerome Glisse if (tmp & RADEON_CRTC2_VBLANK_SAVE) { 1237771fe6b9SJerome Glisse return; 1238771fe6b9SJerome Glisse } 1239771fe6b9SJerome Glisse DRM_UDELAY(1); 1240771fe6b9SJerome Glisse } 1241771fe6b9SJerome Glisse } 1242771fe6b9SJerome Glisse 1243771fe6b9SJerome Glisse int r100_rbbm_fifo_wait_for_entry(struct radeon_device *rdev, unsigned n) 1244771fe6b9SJerome Glisse { 1245771fe6b9SJerome Glisse unsigned i; 1246771fe6b9SJerome Glisse uint32_t tmp; 1247771fe6b9SJerome Glisse 1248771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1249771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; 1250771fe6b9SJerome Glisse if (tmp >= n) { 1251771fe6b9SJerome Glisse return 0; 1252771fe6b9SJerome Glisse } 1253771fe6b9SJerome Glisse DRM_UDELAY(1); 1254771fe6b9SJerome Glisse } 1255771fe6b9SJerome Glisse return -1; 1256771fe6b9SJerome Glisse } 1257771fe6b9SJerome Glisse 1258771fe6b9SJerome Glisse int r100_gui_wait_for_idle(struct radeon_device *rdev) 1259771fe6b9SJerome Glisse { 1260771fe6b9SJerome Glisse unsigned i; 1261771fe6b9SJerome Glisse uint32_t tmp; 1262771fe6b9SJerome Glisse 1263771fe6b9SJerome Glisse if (r100_rbbm_fifo_wait_for_entry(rdev, 64)) { 1264771fe6b9SJerome Glisse printk(KERN_WARNING "radeon: wait for empty RBBM fifo failed !" 1265771fe6b9SJerome Glisse " Bad things might happen.\n"); 1266771fe6b9SJerome Glisse } 1267771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1268771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1269771fe6b9SJerome Glisse if (!(tmp & (1 << 31))) { 1270771fe6b9SJerome Glisse return 0; 1271771fe6b9SJerome Glisse } 1272771fe6b9SJerome Glisse DRM_UDELAY(1); 1273771fe6b9SJerome Glisse } 1274771fe6b9SJerome Glisse return -1; 1275771fe6b9SJerome Glisse } 1276771fe6b9SJerome Glisse 1277771fe6b9SJerome Glisse int r100_mc_wait_for_idle(struct radeon_device *rdev) 1278771fe6b9SJerome Glisse { 1279771fe6b9SJerome Glisse unsigned i; 1280771fe6b9SJerome Glisse uint32_t tmp; 1281771fe6b9SJerome Glisse 1282771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1283771fe6b9SJerome Glisse /* read MC_STATUS */ 1284771fe6b9SJerome Glisse tmp = RREG32(0x0150); 1285771fe6b9SJerome Glisse if (tmp & (1 << 2)) { 1286771fe6b9SJerome Glisse return 0; 1287771fe6b9SJerome Glisse } 1288771fe6b9SJerome Glisse DRM_UDELAY(1); 1289771fe6b9SJerome Glisse } 1290771fe6b9SJerome Glisse return -1; 1291771fe6b9SJerome Glisse } 1292771fe6b9SJerome Glisse 1293771fe6b9SJerome Glisse void r100_gpu_init(struct radeon_device *rdev) 1294771fe6b9SJerome Glisse { 1295771fe6b9SJerome Glisse /* TODO: anythings to do here ? pipes ? */ 1296771fe6b9SJerome Glisse r100_hdp_reset(rdev); 1297771fe6b9SJerome Glisse } 1298771fe6b9SJerome Glisse 1299771fe6b9SJerome Glisse void r100_hdp_reset(struct radeon_device *rdev) 1300771fe6b9SJerome Glisse { 1301771fe6b9SJerome Glisse uint32_t tmp; 1302771fe6b9SJerome Glisse 1303771fe6b9SJerome Glisse tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; 1304771fe6b9SJerome Glisse tmp |= (7 << 28); 1305771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); 1306771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 1307771fe6b9SJerome Glisse udelay(200); 1308771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 1309771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp); 1310771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 1311771fe6b9SJerome Glisse } 1312771fe6b9SJerome Glisse 1313771fe6b9SJerome Glisse int r100_rb2d_reset(struct radeon_device *rdev) 1314771fe6b9SJerome Glisse { 1315771fe6b9SJerome Glisse uint32_t tmp; 1316771fe6b9SJerome Glisse int i; 1317771fe6b9SJerome Glisse 1318771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_E2); 1319771fe6b9SJerome Glisse (void)RREG32(RADEON_RBBM_SOFT_RESET); 1320771fe6b9SJerome Glisse udelay(200); 1321771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 1322771fe6b9SJerome Glisse /* Wait to prevent race in RBBM_STATUS */ 1323771fe6b9SJerome Glisse mdelay(1); 1324771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1325771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1326771fe6b9SJerome Glisse if (!(tmp & (1 << 26))) { 1327771fe6b9SJerome Glisse DRM_INFO("RB2D reset succeed (RBBM_STATUS=0x%08X)\n", 1328771fe6b9SJerome Glisse tmp); 1329771fe6b9SJerome Glisse return 0; 1330771fe6b9SJerome Glisse } 1331771fe6b9SJerome Glisse DRM_UDELAY(1); 1332771fe6b9SJerome Glisse } 1333771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1334771fe6b9SJerome Glisse DRM_ERROR("Failed to reset RB2D (RBBM_STATUS=0x%08X)!\n", tmp); 1335771fe6b9SJerome Glisse return -1; 1336771fe6b9SJerome Glisse } 1337771fe6b9SJerome Glisse 1338771fe6b9SJerome Glisse int r100_gpu_reset(struct radeon_device *rdev) 1339771fe6b9SJerome Glisse { 1340771fe6b9SJerome Glisse uint32_t status; 1341771fe6b9SJerome Glisse 1342771fe6b9SJerome Glisse /* reset order likely matter */ 1343771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1344771fe6b9SJerome Glisse /* reset HDP */ 1345771fe6b9SJerome Glisse r100_hdp_reset(rdev); 1346771fe6b9SJerome Glisse /* reset rb2d */ 1347771fe6b9SJerome Glisse if (status & ((1 << 17) | (1 << 18) | (1 << 27))) { 1348771fe6b9SJerome Glisse r100_rb2d_reset(rdev); 1349771fe6b9SJerome Glisse } 1350771fe6b9SJerome Glisse /* TODO: reset 3D engine */ 1351771fe6b9SJerome Glisse /* reset CP */ 1352771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1353771fe6b9SJerome Glisse if (status & (1 << 16)) { 1354771fe6b9SJerome Glisse r100_cp_reset(rdev); 1355771fe6b9SJerome Glisse } 1356771fe6b9SJerome Glisse /* Check if GPU is idle */ 1357771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1358771fe6b9SJerome Glisse if (status & (1 << 31)) { 1359771fe6b9SJerome Glisse DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); 1360771fe6b9SJerome Glisse return -1; 1361771fe6b9SJerome Glisse } 1362771fe6b9SJerome Glisse DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status); 1363771fe6b9SJerome Glisse return 0; 1364771fe6b9SJerome Glisse } 1365771fe6b9SJerome Glisse 1366771fe6b9SJerome Glisse 1367771fe6b9SJerome Glisse /* 1368771fe6b9SJerome Glisse * VRAM info 1369771fe6b9SJerome Glisse */ 1370771fe6b9SJerome Glisse static void r100_vram_get_type(struct radeon_device *rdev) 1371771fe6b9SJerome Glisse { 1372771fe6b9SJerome Glisse uint32_t tmp; 1373771fe6b9SJerome Glisse 1374771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = false; 1375771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_IGP) 1376771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1377771fe6b9SJerome Glisse else if (RREG32(RADEON_MEM_SDRAM_MODE_REG) & RADEON_MEM_CFG_TYPE_DDR) 1378771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1379771fe6b9SJerome Glisse if ((rdev->family == CHIP_RV100) || 1380771fe6b9SJerome Glisse (rdev->family == CHIP_RS100) || 1381771fe6b9SJerome Glisse (rdev->family == CHIP_RS200)) { 1382771fe6b9SJerome Glisse tmp = RREG32(RADEON_MEM_CNTL); 1383771fe6b9SJerome Glisse if (tmp & RV100_HALF_MODE) { 1384771fe6b9SJerome Glisse rdev->mc.vram_width = 32; 1385771fe6b9SJerome Glisse } else { 1386771fe6b9SJerome Glisse rdev->mc.vram_width = 64; 1387771fe6b9SJerome Glisse } 1388771fe6b9SJerome Glisse if (rdev->flags & RADEON_SINGLE_CRTC) { 1389771fe6b9SJerome Glisse rdev->mc.vram_width /= 4; 1390771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1391771fe6b9SJerome Glisse } 1392771fe6b9SJerome Glisse } else if (rdev->family <= CHIP_RV280) { 1393771fe6b9SJerome Glisse tmp = RREG32(RADEON_MEM_CNTL); 1394771fe6b9SJerome Glisse if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) { 1395771fe6b9SJerome Glisse rdev->mc.vram_width = 128; 1396771fe6b9SJerome Glisse } else { 1397771fe6b9SJerome Glisse rdev->mc.vram_width = 64; 1398771fe6b9SJerome Glisse } 1399771fe6b9SJerome Glisse } else { 1400771fe6b9SJerome Glisse /* newer IGPs */ 1401771fe6b9SJerome Glisse rdev->mc.vram_width = 128; 1402771fe6b9SJerome Glisse } 1403771fe6b9SJerome Glisse } 1404771fe6b9SJerome Glisse 14052a0f8918SDave Airlie static u32 r100_get_accessible_vram(struct radeon_device *rdev) 1406771fe6b9SJerome Glisse { 14072a0f8918SDave Airlie u32 aper_size; 14082a0f8918SDave Airlie u8 byte; 14092a0f8918SDave Airlie 14102a0f8918SDave Airlie aper_size = RREG32(RADEON_CONFIG_APER_SIZE); 14112a0f8918SDave Airlie 14122a0f8918SDave Airlie /* Set HDP_APER_CNTL only on cards that are known not to be broken, 14132a0f8918SDave Airlie * that is has the 2nd generation multifunction PCI interface 14142a0f8918SDave Airlie */ 14152a0f8918SDave Airlie if (rdev->family == CHIP_RV280 || 14162a0f8918SDave Airlie rdev->family >= CHIP_RV350) { 14172a0f8918SDave Airlie WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, 14182a0f8918SDave Airlie ~RADEON_HDP_APER_CNTL); 14192a0f8918SDave Airlie DRM_INFO("Generation 2 PCI interface, using max accessible memory\n"); 14202a0f8918SDave Airlie return aper_size * 2; 14212a0f8918SDave Airlie } 14222a0f8918SDave Airlie 14232a0f8918SDave Airlie /* Older cards have all sorts of funny issues to deal with. First 14242a0f8918SDave Airlie * check if it's a multifunction card by reading the PCI config 14252a0f8918SDave Airlie * header type... Limit those to one aperture size 14262a0f8918SDave Airlie */ 14272a0f8918SDave Airlie pci_read_config_byte(rdev->pdev, 0xe, &byte); 14282a0f8918SDave Airlie if (byte & 0x80) { 14292a0f8918SDave Airlie DRM_INFO("Generation 1 PCI interface in multifunction mode\n"); 14302a0f8918SDave Airlie DRM_INFO("Limiting VRAM to one aperture\n"); 14312a0f8918SDave Airlie return aper_size; 14322a0f8918SDave Airlie } 14332a0f8918SDave Airlie 14342a0f8918SDave Airlie /* Single function older card. We read HDP_APER_CNTL to see how the BIOS 14352a0f8918SDave Airlie * have set it up. We don't write this as it's broken on some ASICs but 14362a0f8918SDave Airlie * we expect the BIOS to have done the right thing (might be too optimistic...) 14372a0f8918SDave Airlie */ 14382a0f8918SDave Airlie if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) 14392a0f8918SDave Airlie return aper_size * 2; 14402a0f8918SDave Airlie return aper_size; 14412a0f8918SDave Airlie } 14422a0f8918SDave Airlie 14432a0f8918SDave Airlie void r100_vram_init_sizes(struct radeon_device *rdev) 14442a0f8918SDave Airlie { 14452a0f8918SDave Airlie u64 config_aper_size; 14462a0f8918SDave Airlie u32 accessible; 14472a0f8918SDave Airlie 14482a0f8918SDave Airlie config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); 1449771fe6b9SJerome Glisse 1450771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_IGP) { 1451771fe6b9SJerome Glisse uint32_t tom; 1452771fe6b9SJerome Glisse /* read NB_TOM to get the amount of ram stolen for the GPU */ 1453771fe6b9SJerome Glisse tom = RREG32(RADEON_NB_TOM); 1454*7a50f01aSDave Airlie rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); 14553e43d821SDave Airlie /* for IGPs we need to keep VRAM where it was put by the BIOS */ 14563e43d821SDave Airlie rdev->mc.vram_location = (tom & 0xffff) << 16; 1457*7a50f01aSDave Airlie WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 1458*7a50f01aSDave Airlie rdev->mc.mc_vram_size = rdev->mc.real_vram_size; 1459771fe6b9SJerome Glisse } else { 1460*7a50f01aSDave Airlie rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); 1461771fe6b9SJerome Glisse /* Some production boards of m6 will report 0 1462771fe6b9SJerome Glisse * if it's 8 MB 1463771fe6b9SJerome Glisse */ 1464*7a50f01aSDave Airlie if (rdev->mc.real_vram_size == 0) { 1465*7a50f01aSDave Airlie rdev->mc.real_vram_size = 8192 * 1024; 1466*7a50f01aSDave Airlie WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 1467771fe6b9SJerome Glisse } 14683e43d821SDave Airlie /* let driver place VRAM */ 14693e43d821SDave Airlie rdev->mc.vram_location = 0xFFFFFFFFUL; 14702a0f8918SDave Airlie /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - 14712a0f8918SDave Airlie * Novell bug 204882 + along with lots of ubuntu ones */ 1472*7a50f01aSDave Airlie if (config_aper_size > rdev->mc.real_vram_size) 1473*7a50f01aSDave Airlie rdev->mc.mc_vram_size = config_aper_size; 1474*7a50f01aSDave Airlie else 1475*7a50f01aSDave Airlie rdev->mc.mc_vram_size = rdev->mc.real_vram_size; 1476771fe6b9SJerome Glisse } 1477771fe6b9SJerome Glisse 14782a0f8918SDave Airlie /* work out accessible VRAM */ 14792a0f8918SDave Airlie accessible = r100_get_accessible_vram(rdev); 14802a0f8918SDave Airlie 1481771fe6b9SJerome Glisse rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); 1482771fe6b9SJerome Glisse rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); 14832a0f8918SDave Airlie 14842a0f8918SDave Airlie if (accessible > rdev->mc.aper_size) 14852a0f8918SDave Airlie accessible = rdev->mc.aper_size; 14862a0f8918SDave Airlie 1487*7a50f01aSDave Airlie if (rdev->mc.mc_vram_size > rdev->mc.aper_size) 1488*7a50f01aSDave Airlie rdev->mc.mc_vram_size = rdev->mc.aper_size; 1489*7a50f01aSDave Airlie 1490*7a50f01aSDave Airlie if (rdev->mc.real_vram_size > rdev->mc.aper_size) 1491*7a50f01aSDave Airlie rdev->mc.real_vram_size = rdev->mc.aper_size; 14922a0f8918SDave Airlie } 14932a0f8918SDave Airlie 14942a0f8918SDave Airlie void r100_vram_info(struct radeon_device *rdev) 14952a0f8918SDave Airlie { 14962a0f8918SDave Airlie r100_vram_get_type(rdev); 14972a0f8918SDave Airlie 14982a0f8918SDave Airlie r100_vram_init_sizes(rdev); 1499771fe6b9SJerome Glisse } 1500771fe6b9SJerome Glisse 1501771fe6b9SJerome Glisse 1502771fe6b9SJerome Glisse /* 1503771fe6b9SJerome Glisse * Indirect registers accessor 1504771fe6b9SJerome Glisse */ 1505771fe6b9SJerome Glisse void r100_pll_errata_after_index(struct radeon_device *rdev) 1506771fe6b9SJerome Glisse { 1507771fe6b9SJerome Glisse if (!(rdev->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS)) { 1508771fe6b9SJerome Glisse return; 1509771fe6b9SJerome Glisse } 1510771fe6b9SJerome Glisse (void)RREG32(RADEON_CLOCK_CNTL_DATA); 1511771fe6b9SJerome Glisse (void)RREG32(RADEON_CRTC_GEN_CNTL); 1512771fe6b9SJerome Glisse } 1513771fe6b9SJerome Glisse 1514771fe6b9SJerome Glisse static void r100_pll_errata_after_data(struct radeon_device *rdev) 1515771fe6b9SJerome Glisse { 1516771fe6b9SJerome Glisse /* This workarounds is necessary on RV100, RS100 and RS200 chips 1517771fe6b9SJerome Glisse * or the chip could hang on a subsequent access 1518771fe6b9SJerome Glisse */ 1519771fe6b9SJerome Glisse if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) { 1520771fe6b9SJerome Glisse udelay(5000); 1521771fe6b9SJerome Glisse } 1522771fe6b9SJerome Glisse 1523771fe6b9SJerome Glisse /* This function is required to workaround a hardware bug in some (all?) 1524771fe6b9SJerome Glisse * revisions of the R300. This workaround should be called after every 1525771fe6b9SJerome Glisse * CLOCK_CNTL_INDEX register access. If not, register reads afterward 1526771fe6b9SJerome Glisse * may not be correct. 1527771fe6b9SJerome Glisse */ 1528771fe6b9SJerome Glisse if (rdev->pll_errata & CHIP_ERRATA_R300_CG) { 1529771fe6b9SJerome Glisse uint32_t save, tmp; 1530771fe6b9SJerome Glisse 1531771fe6b9SJerome Glisse save = RREG32(RADEON_CLOCK_CNTL_INDEX); 1532771fe6b9SJerome Glisse tmp = save & ~(0x3f | RADEON_PLL_WR_EN); 1533771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_INDEX, tmp); 1534771fe6b9SJerome Glisse tmp = RREG32(RADEON_CLOCK_CNTL_DATA); 1535771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_INDEX, save); 1536771fe6b9SJerome Glisse } 1537771fe6b9SJerome Glisse } 1538771fe6b9SJerome Glisse 1539771fe6b9SJerome Glisse uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg) 1540771fe6b9SJerome Glisse { 1541771fe6b9SJerome Glisse uint32_t data; 1542771fe6b9SJerome Glisse 1543771fe6b9SJerome Glisse WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f); 1544771fe6b9SJerome Glisse r100_pll_errata_after_index(rdev); 1545771fe6b9SJerome Glisse data = RREG32(RADEON_CLOCK_CNTL_DATA); 1546771fe6b9SJerome Glisse r100_pll_errata_after_data(rdev); 1547771fe6b9SJerome Glisse return data; 1548771fe6b9SJerome Glisse } 1549771fe6b9SJerome Glisse 1550771fe6b9SJerome Glisse void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 1551771fe6b9SJerome Glisse { 1552771fe6b9SJerome Glisse WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN)); 1553771fe6b9SJerome Glisse r100_pll_errata_after_index(rdev); 1554771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_DATA, v); 1555771fe6b9SJerome Glisse r100_pll_errata_after_data(rdev); 1556771fe6b9SJerome Glisse } 1557771fe6b9SJerome Glisse 1558771fe6b9SJerome Glisse uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) 1559771fe6b9SJerome Glisse { 1560771fe6b9SJerome Glisse if (reg < 0x10000) 1561771fe6b9SJerome Glisse return readl(((void __iomem *)rdev->rmmio) + reg); 1562771fe6b9SJerome Glisse else { 1563771fe6b9SJerome Glisse writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); 1564771fe6b9SJerome Glisse return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); 1565771fe6b9SJerome Glisse } 1566771fe6b9SJerome Glisse } 1567771fe6b9SJerome Glisse 1568771fe6b9SJerome Glisse void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 1569771fe6b9SJerome Glisse { 1570771fe6b9SJerome Glisse if (reg < 0x10000) 1571771fe6b9SJerome Glisse writel(v, ((void __iomem *)rdev->rmmio) + reg); 1572771fe6b9SJerome Glisse else { 1573771fe6b9SJerome Glisse writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); 1574771fe6b9SJerome Glisse writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); 1575771fe6b9SJerome Glisse } 1576771fe6b9SJerome Glisse } 1577771fe6b9SJerome Glisse 1578068a117cSJerome Glisse int r100_init(struct radeon_device *rdev) 1579068a117cSJerome Glisse { 1580068a117cSJerome Glisse return 0; 1581068a117cSJerome Glisse } 1582068a117cSJerome Glisse 1583771fe6b9SJerome Glisse /* 1584771fe6b9SJerome Glisse * Debugfs info 1585771fe6b9SJerome Glisse */ 1586771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1587771fe6b9SJerome Glisse static int r100_debugfs_rbbm_info(struct seq_file *m, void *data) 1588771fe6b9SJerome Glisse { 1589771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1590771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1591771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1592771fe6b9SJerome Glisse uint32_t reg, value; 1593771fe6b9SJerome Glisse unsigned i; 1594771fe6b9SJerome Glisse 1595771fe6b9SJerome Glisse seq_printf(m, "RBBM_STATUS 0x%08x\n", RREG32(RADEON_RBBM_STATUS)); 1596771fe6b9SJerome Glisse seq_printf(m, "RBBM_CMDFIFO_STAT 0x%08x\n", RREG32(0xE7C)); 1597771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1598771fe6b9SJerome Glisse for (i = 0; i < 64; i++) { 1599771fe6b9SJerome Glisse WREG32(RADEON_RBBM_CMDFIFO_ADDR, i | 0x100); 1600771fe6b9SJerome Glisse reg = (RREG32(RADEON_RBBM_CMDFIFO_DATA) - 1) >> 2; 1601771fe6b9SJerome Glisse WREG32(RADEON_RBBM_CMDFIFO_ADDR, i); 1602771fe6b9SJerome Glisse value = RREG32(RADEON_RBBM_CMDFIFO_DATA); 1603771fe6b9SJerome Glisse seq_printf(m, "[0x%03X] 0x%04X=0x%08X\n", i, reg, value); 1604771fe6b9SJerome Glisse } 1605771fe6b9SJerome Glisse return 0; 1606771fe6b9SJerome Glisse } 1607771fe6b9SJerome Glisse 1608771fe6b9SJerome Glisse static int r100_debugfs_cp_ring_info(struct seq_file *m, void *data) 1609771fe6b9SJerome Glisse { 1610771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1611771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1612771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1613771fe6b9SJerome Glisse uint32_t rdp, wdp; 1614771fe6b9SJerome Glisse unsigned count, i, j; 1615771fe6b9SJerome Glisse 1616771fe6b9SJerome Glisse radeon_ring_free_size(rdev); 1617771fe6b9SJerome Glisse rdp = RREG32(RADEON_CP_RB_RPTR); 1618771fe6b9SJerome Glisse wdp = RREG32(RADEON_CP_RB_WPTR); 1619771fe6b9SJerome Glisse count = (rdp + rdev->cp.ring_size - wdp) & rdev->cp.ptr_mask; 1620771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1621771fe6b9SJerome Glisse seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp); 1622771fe6b9SJerome Glisse seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp); 1623771fe6b9SJerome Glisse seq_printf(m, "%u free dwords in ring\n", rdev->cp.ring_free_dw); 1624771fe6b9SJerome Glisse seq_printf(m, "%u dwords in ring\n", count); 1625771fe6b9SJerome Glisse for (j = 0; j <= count; j++) { 1626771fe6b9SJerome Glisse i = (rdp + j) & rdev->cp.ptr_mask; 1627771fe6b9SJerome Glisse seq_printf(m, "r[%04d]=0x%08x\n", i, rdev->cp.ring[i]); 1628771fe6b9SJerome Glisse } 1629771fe6b9SJerome Glisse return 0; 1630771fe6b9SJerome Glisse } 1631771fe6b9SJerome Glisse 1632771fe6b9SJerome Glisse 1633771fe6b9SJerome Glisse static int r100_debugfs_cp_csq_fifo(struct seq_file *m, void *data) 1634771fe6b9SJerome Glisse { 1635771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1636771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1637771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1638771fe6b9SJerome Glisse uint32_t csq_stat, csq2_stat, tmp; 1639771fe6b9SJerome Glisse unsigned r_rptr, r_wptr, ib1_rptr, ib1_wptr, ib2_rptr, ib2_wptr; 1640771fe6b9SJerome Glisse unsigned i; 1641771fe6b9SJerome Glisse 1642771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1643771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ_MODE 0x%08x\n", RREG32(RADEON_CP_CSQ_MODE)); 1644771fe6b9SJerome Glisse csq_stat = RREG32(RADEON_CP_CSQ_STAT); 1645771fe6b9SJerome Glisse csq2_stat = RREG32(RADEON_CP_CSQ2_STAT); 1646771fe6b9SJerome Glisse r_rptr = (csq_stat >> 0) & 0x3ff; 1647771fe6b9SJerome Glisse r_wptr = (csq_stat >> 10) & 0x3ff; 1648771fe6b9SJerome Glisse ib1_rptr = (csq_stat >> 20) & 0x3ff; 1649771fe6b9SJerome Glisse ib1_wptr = (csq2_stat >> 0) & 0x3ff; 1650771fe6b9SJerome Glisse ib2_rptr = (csq2_stat >> 10) & 0x3ff; 1651771fe6b9SJerome Glisse ib2_wptr = (csq2_stat >> 20) & 0x3ff; 1652771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ_STAT 0x%08x\n", csq_stat); 1653771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ2_STAT 0x%08x\n", csq2_stat); 1654771fe6b9SJerome Glisse seq_printf(m, "Ring rptr %u\n", r_rptr); 1655771fe6b9SJerome Glisse seq_printf(m, "Ring wptr %u\n", r_wptr); 1656771fe6b9SJerome Glisse seq_printf(m, "Indirect1 rptr %u\n", ib1_rptr); 1657771fe6b9SJerome Glisse seq_printf(m, "Indirect1 wptr %u\n", ib1_wptr); 1658771fe6b9SJerome Glisse seq_printf(m, "Indirect2 rptr %u\n", ib2_rptr); 1659771fe6b9SJerome Glisse seq_printf(m, "Indirect2 wptr %u\n", ib2_wptr); 1660771fe6b9SJerome Glisse /* FIXME: 0, 128, 640 depends on fifo setup see cp_init_kms 1661771fe6b9SJerome Glisse * 128 = indirect1_start * 8 & 640 = indirect2_start * 8 */ 1662771fe6b9SJerome Glisse seq_printf(m, "Ring fifo:\n"); 1663771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 1664771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1665771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1666771fe6b9SJerome Glisse seq_printf(m, "rfifo[%04d]=0x%08X\n", i, tmp); 1667771fe6b9SJerome Glisse } 1668771fe6b9SJerome Glisse seq_printf(m, "Indirect1 fifo:\n"); 1669771fe6b9SJerome Glisse for (i = 256; i <= 512; i++) { 1670771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1671771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1672771fe6b9SJerome Glisse seq_printf(m, "ib1fifo[%04d]=0x%08X\n", i, tmp); 1673771fe6b9SJerome Glisse } 1674771fe6b9SJerome Glisse seq_printf(m, "Indirect2 fifo:\n"); 1675771fe6b9SJerome Glisse for (i = 640; i < ib1_wptr; i++) { 1676771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1677771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1678771fe6b9SJerome Glisse seq_printf(m, "ib2fifo[%04d]=0x%08X\n", i, tmp); 1679771fe6b9SJerome Glisse } 1680771fe6b9SJerome Glisse return 0; 1681771fe6b9SJerome Glisse } 1682771fe6b9SJerome Glisse 1683771fe6b9SJerome Glisse static int r100_debugfs_mc_info(struct seq_file *m, void *data) 1684771fe6b9SJerome Glisse { 1685771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1686771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1687771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1688771fe6b9SJerome Glisse uint32_t tmp; 1689771fe6b9SJerome Glisse 1690771fe6b9SJerome Glisse tmp = RREG32(RADEON_CONFIG_MEMSIZE); 1691771fe6b9SJerome Glisse seq_printf(m, "CONFIG_MEMSIZE 0x%08x\n", tmp); 1692771fe6b9SJerome Glisse tmp = RREG32(RADEON_MC_FB_LOCATION); 1693771fe6b9SJerome Glisse seq_printf(m, "MC_FB_LOCATION 0x%08x\n", tmp); 1694771fe6b9SJerome Glisse tmp = RREG32(RADEON_BUS_CNTL); 1695771fe6b9SJerome Glisse seq_printf(m, "BUS_CNTL 0x%08x\n", tmp); 1696771fe6b9SJerome Glisse tmp = RREG32(RADEON_MC_AGP_LOCATION); 1697771fe6b9SJerome Glisse seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp); 1698771fe6b9SJerome Glisse tmp = RREG32(RADEON_AGP_BASE); 1699771fe6b9SJerome Glisse seq_printf(m, "AGP_BASE 0x%08x\n", tmp); 1700771fe6b9SJerome Glisse tmp = RREG32(RADEON_HOST_PATH_CNTL); 1701771fe6b9SJerome Glisse seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp); 1702771fe6b9SJerome Glisse tmp = RREG32(0x01D0); 1703771fe6b9SJerome Glisse seq_printf(m, "AIC_CTRL 0x%08x\n", tmp); 1704771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_LO_ADDR); 1705771fe6b9SJerome Glisse seq_printf(m, "AIC_LO_ADDR 0x%08x\n", tmp); 1706771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_HI_ADDR); 1707771fe6b9SJerome Glisse seq_printf(m, "AIC_HI_ADDR 0x%08x\n", tmp); 1708771fe6b9SJerome Glisse tmp = RREG32(0x01E4); 1709771fe6b9SJerome Glisse seq_printf(m, "AIC_TLB_ADDR 0x%08x\n", tmp); 1710771fe6b9SJerome Glisse return 0; 1711771fe6b9SJerome Glisse } 1712771fe6b9SJerome Glisse 1713771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_rbbm_list[] = { 1714771fe6b9SJerome Glisse {"r100_rbbm_info", r100_debugfs_rbbm_info, 0, NULL}, 1715771fe6b9SJerome Glisse }; 1716771fe6b9SJerome Glisse 1717771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_cp_list[] = { 1718771fe6b9SJerome Glisse {"r100_cp_ring_info", r100_debugfs_cp_ring_info, 0, NULL}, 1719771fe6b9SJerome Glisse {"r100_cp_csq_fifo", r100_debugfs_cp_csq_fifo, 0, NULL}, 1720771fe6b9SJerome Glisse }; 1721771fe6b9SJerome Glisse 1722771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_mc_info_list[] = { 1723771fe6b9SJerome Glisse {"r100_mc_info", r100_debugfs_mc_info, 0, NULL}, 1724771fe6b9SJerome Glisse }; 1725771fe6b9SJerome Glisse #endif 1726771fe6b9SJerome Glisse 1727771fe6b9SJerome Glisse int r100_debugfs_rbbm_init(struct radeon_device *rdev) 1728771fe6b9SJerome Glisse { 1729771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1730771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_rbbm_list, 1); 1731771fe6b9SJerome Glisse #else 1732771fe6b9SJerome Glisse return 0; 1733771fe6b9SJerome Glisse #endif 1734771fe6b9SJerome Glisse } 1735771fe6b9SJerome Glisse 1736771fe6b9SJerome Glisse int r100_debugfs_cp_init(struct radeon_device *rdev) 1737771fe6b9SJerome Glisse { 1738771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1739771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_cp_list, 2); 1740771fe6b9SJerome Glisse #else 1741771fe6b9SJerome Glisse return 0; 1742771fe6b9SJerome Glisse #endif 1743771fe6b9SJerome Glisse } 1744771fe6b9SJerome Glisse 1745771fe6b9SJerome Glisse int r100_debugfs_mc_info_init(struct radeon_device *rdev) 1746771fe6b9SJerome Glisse { 1747771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1748771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_mc_info_list, 1); 1749771fe6b9SJerome Glisse #else 1750771fe6b9SJerome Glisse return 0; 1751771fe6b9SJerome Glisse #endif 1752771fe6b9SJerome Glisse } 1753e024e110SDave Airlie 1754e024e110SDave Airlie int r100_set_surface_reg(struct radeon_device *rdev, int reg, 1755e024e110SDave Airlie uint32_t tiling_flags, uint32_t pitch, 1756e024e110SDave Airlie uint32_t offset, uint32_t obj_size) 1757e024e110SDave Airlie { 1758e024e110SDave Airlie int surf_index = reg * 16; 1759e024e110SDave Airlie int flags = 0; 1760e024e110SDave Airlie 1761e024e110SDave Airlie /* r100/r200 divide by 16 */ 1762e024e110SDave Airlie if (rdev->family < CHIP_R300) 1763e024e110SDave Airlie flags = pitch / 16; 1764e024e110SDave Airlie else 1765e024e110SDave Airlie flags = pitch / 8; 1766e024e110SDave Airlie 1767e024e110SDave Airlie if (rdev->family <= CHIP_RS200) { 1768e024e110SDave Airlie if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) 1769e024e110SDave Airlie == (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) 1770e024e110SDave Airlie flags |= RADEON_SURF_TILE_COLOR_BOTH; 1771e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MACRO) 1772e024e110SDave Airlie flags |= RADEON_SURF_TILE_COLOR_MACRO; 1773e024e110SDave Airlie } else if (rdev->family <= CHIP_RV280) { 1774e024e110SDave Airlie if (tiling_flags & (RADEON_TILING_MACRO)) 1775e024e110SDave Airlie flags |= R200_SURF_TILE_COLOR_MACRO; 1776e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MICRO) 1777e024e110SDave Airlie flags |= R200_SURF_TILE_COLOR_MICRO; 1778e024e110SDave Airlie } else { 1779e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MACRO) 1780e024e110SDave Airlie flags |= R300_SURF_TILE_MACRO; 1781e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MICRO) 1782e024e110SDave Airlie flags |= R300_SURF_TILE_MICRO; 1783e024e110SDave Airlie } 1784e024e110SDave Airlie 1785e024e110SDave Airlie DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1); 1786e024e110SDave Airlie WREG32(RADEON_SURFACE0_INFO + surf_index, flags); 1787e024e110SDave Airlie WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); 1788e024e110SDave Airlie WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1); 1789e024e110SDave Airlie return 0; 1790e024e110SDave Airlie } 1791e024e110SDave Airlie 1792e024e110SDave Airlie void r100_clear_surface_reg(struct radeon_device *rdev, int reg) 1793e024e110SDave Airlie { 1794e024e110SDave Airlie int surf_index = reg * 16; 1795e024e110SDave Airlie WREG32(RADEON_SURFACE0_INFO + surf_index, 0); 1796e024e110SDave Airlie } 1797c93bb85bSJerome Glisse 1798c93bb85bSJerome Glisse void r100_bandwidth_update(struct radeon_device *rdev) 1799c93bb85bSJerome Glisse { 1800c93bb85bSJerome Glisse fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; 1801c93bb85bSJerome Glisse fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; 1802c93bb85bSJerome Glisse fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; 1803c93bb85bSJerome Glisse uint32_t temp, data, mem_trcd, mem_trp, mem_tras; 1804c93bb85bSJerome Glisse fixed20_12 memtcas_ff[8] = { 1805c93bb85bSJerome Glisse fixed_init(1), 1806c93bb85bSJerome Glisse fixed_init(2), 1807c93bb85bSJerome Glisse fixed_init(3), 1808c93bb85bSJerome Glisse fixed_init(0), 1809c93bb85bSJerome Glisse fixed_init_half(1), 1810c93bb85bSJerome Glisse fixed_init_half(2), 1811c93bb85bSJerome Glisse fixed_init(0), 1812c93bb85bSJerome Glisse }; 1813c93bb85bSJerome Glisse fixed20_12 memtcas_rs480_ff[8] = { 1814c93bb85bSJerome Glisse fixed_init(0), 1815c93bb85bSJerome Glisse fixed_init(1), 1816c93bb85bSJerome Glisse fixed_init(2), 1817c93bb85bSJerome Glisse fixed_init(3), 1818c93bb85bSJerome Glisse fixed_init(0), 1819c93bb85bSJerome Glisse fixed_init_half(1), 1820c93bb85bSJerome Glisse fixed_init_half(2), 1821c93bb85bSJerome Glisse fixed_init_half(3), 1822c93bb85bSJerome Glisse }; 1823c93bb85bSJerome Glisse fixed20_12 memtcas2_ff[8] = { 1824c93bb85bSJerome Glisse fixed_init(0), 1825c93bb85bSJerome Glisse fixed_init(1), 1826c93bb85bSJerome Glisse fixed_init(2), 1827c93bb85bSJerome Glisse fixed_init(3), 1828c93bb85bSJerome Glisse fixed_init(4), 1829c93bb85bSJerome Glisse fixed_init(5), 1830c93bb85bSJerome Glisse fixed_init(6), 1831c93bb85bSJerome Glisse fixed_init(7), 1832c93bb85bSJerome Glisse }; 1833c93bb85bSJerome Glisse fixed20_12 memtrbs[8] = { 1834c93bb85bSJerome Glisse fixed_init(1), 1835c93bb85bSJerome Glisse fixed_init_half(1), 1836c93bb85bSJerome Glisse fixed_init(2), 1837c93bb85bSJerome Glisse fixed_init_half(2), 1838c93bb85bSJerome Glisse fixed_init(3), 1839c93bb85bSJerome Glisse fixed_init_half(3), 1840c93bb85bSJerome Glisse fixed_init(4), 1841c93bb85bSJerome Glisse fixed_init_half(4) 1842c93bb85bSJerome Glisse }; 1843c93bb85bSJerome Glisse fixed20_12 memtrbs_r4xx[8] = { 1844c93bb85bSJerome Glisse fixed_init(4), 1845c93bb85bSJerome Glisse fixed_init(5), 1846c93bb85bSJerome Glisse fixed_init(6), 1847c93bb85bSJerome Glisse fixed_init(7), 1848c93bb85bSJerome Glisse fixed_init(8), 1849c93bb85bSJerome Glisse fixed_init(9), 1850c93bb85bSJerome Glisse fixed_init(10), 1851c93bb85bSJerome Glisse fixed_init(11) 1852c93bb85bSJerome Glisse }; 1853c93bb85bSJerome Glisse fixed20_12 min_mem_eff; 1854c93bb85bSJerome Glisse fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; 1855c93bb85bSJerome Glisse fixed20_12 cur_latency_mclk, cur_latency_sclk; 1856c93bb85bSJerome Glisse fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, 1857c93bb85bSJerome Glisse disp_drain_rate2, read_return_rate; 1858c93bb85bSJerome Glisse fixed20_12 time_disp1_drop_priority; 1859c93bb85bSJerome Glisse int c; 1860c93bb85bSJerome Glisse int cur_size = 16; /* in octawords */ 1861c93bb85bSJerome Glisse int critical_point = 0, critical_point2; 1862c93bb85bSJerome Glisse /* uint32_t read_return_rate, time_disp1_drop_priority; */ 1863c93bb85bSJerome Glisse int stop_req, max_stop_req; 1864c93bb85bSJerome Glisse struct drm_display_mode *mode1 = NULL; 1865c93bb85bSJerome Glisse struct drm_display_mode *mode2 = NULL; 1866c93bb85bSJerome Glisse uint32_t pixel_bytes1 = 0; 1867c93bb85bSJerome Glisse uint32_t pixel_bytes2 = 0; 1868c93bb85bSJerome Glisse 1869c93bb85bSJerome Glisse if (rdev->mode_info.crtcs[0]->base.enabled) { 1870c93bb85bSJerome Glisse mode1 = &rdev->mode_info.crtcs[0]->base.mode; 1871c93bb85bSJerome Glisse pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; 1872c93bb85bSJerome Glisse } 1873c93bb85bSJerome Glisse if (rdev->mode_info.crtcs[1]->base.enabled) { 1874c93bb85bSJerome Glisse mode2 = &rdev->mode_info.crtcs[1]->base.mode; 1875c93bb85bSJerome Glisse pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; 1876c93bb85bSJerome Glisse } 1877c93bb85bSJerome Glisse 1878c93bb85bSJerome Glisse min_mem_eff.full = rfixed_const_8(0); 1879c93bb85bSJerome Glisse /* get modes */ 1880c93bb85bSJerome Glisse if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { 1881c93bb85bSJerome Glisse uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); 1882c93bb85bSJerome Glisse mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); 1883c93bb85bSJerome Glisse mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); 1884c93bb85bSJerome Glisse /* check crtc enables */ 1885c93bb85bSJerome Glisse if (mode2) 1886c93bb85bSJerome Glisse mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); 1887c93bb85bSJerome Glisse if (mode1) 1888c93bb85bSJerome Glisse mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); 1889c93bb85bSJerome Glisse WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); 1890c93bb85bSJerome Glisse } 1891c93bb85bSJerome Glisse 1892c93bb85bSJerome Glisse /* 1893c93bb85bSJerome Glisse * determine is there is enough bw for current mode 1894c93bb85bSJerome Glisse */ 1895c93bb85bSJerome Glisse mclk_ff.full = rfixed_const(rdev->clock.default_mclk); 1896c93bb85bSJerome Glisse temp_ff.full = rfixed_const(100); 1897c93bb85bSJerome Glisse mclk_ff.full = rfixed_div(mclk_ff, temp_ff); 1898c93bb85bSJerome Glisse sclk_ff.full = rfixed_const(rdev->clock.default_sclk); 1899c93bb85bSJerome Glisse sclk_ff.full = rfixed_div(sclk_ff, temp_ff); 1900c93bb85bSJerome Glisse 1901c93bb85bSJerome Glisse temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); 1902c93bb85bSJerome Glisse temp_ff.full = rfixed_const(temp); 1903c93bb85bSJerome Glisse mem_bw.full = rfixed_mul(mclk_ff, temp_ff); 1904c93bb85bSJerome Glisse 1905c93bb85bSJerome Glisse pix_clk.full = 0; 1906c93bb85bSJerome Glisse pix_clk2.full = 0; 1907c93bb85bSJerome Glisse peak_disp_bw.full = 0; 1908c93bb85bSJerome Glisse if (mode1) { 1909c93bb85bSJerome Glisse temp_ff.full = rfixed_const(1000); 1910c93bb85bSJerome Glisse pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ 1911c93bb85bSJerome Glisse pix_clk.full = rfixed_div(pix_clk, temp_ff); 1912c93bb85bSJerome Glisse temp_ff.full = rfixed_const(pixel_bytes1); 1913c93bb85bSJerome Glisse peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); 1914c93bb85bSJerome Glisse } 1915c93bb85bSJerome Glisse if (mode2) { 1916c93bb85bSJerome Glisse temp_ff.full = rfixed_const(1000); 1917c93bb85bSJerome Glisse pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ 1918c93bb85bSJerome Glisse pix_clk2.full = rfixed_div(pix_clk2, temp_ff); 1919c93bb85bSJerome Glisse temp_ff.full = rfixed_const(pixel_bytes2); 1920c93bb85bSJerome Glisse peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); 1921c93bb85bSJerome Glisse } 1922c93bb85bSJerome Glisse 1923c93bb85bSJerome Glisse mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); 1924c93bb85bSJerome Glisse if (peak_disp_bw.full >= mem_bw.full) { 1925c93bb85bSJerome Glisse DRM_ERROR("You may not have enough display bandwidth for current mode\n" 1926c93bb85bSJerome Glisse "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); 1927c93bb85bSJerome Glisse } 1928c93bb85bSJerome Glisse 1929c93bb85bSJerome Glisse /* Get values from the EXT_MEM_CNTL register...converting its contents. */ 1930c93bb85bSJerome Glisse temp = RREG32(RADEON_MEM_TIMING_CNTL); 1931c93bb85bSJerome Glisse if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ 1932c93bb85bSJerome Glisse mem_trcd = ((temp >> 2) & 0x3) + 1; 1933c93bb85bSJerome Glisse mem_trp = ((temp & 0x3)) + 1; 1934c93bb85bSJerome Glisse mem_tras = ((temp & 0x70) >> 4) + 1; 1935c93bb85bSJerome Glisse } else if (rdev->family == CHIP_R300 || 1936c93bb85bSJerome Glisse rdev->family == CHIP_R350) { /* r300, r350 */ 1937c93bb85bSJerome Glisse mem_trcd = (temp & 0x7) + 1; 1938c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0x7) + 1; 1939c93bb85bSJerome Glisse mem_tras = ((temp >> 11) & 0xf) + 4; 1940c93bb85bSJerome Glisse } else if (rdev->family == CHIP_RV350 || 1941c93bb85bSJerome Glisse rdev->family <= CHIP_RV380) { 1942c93bb85bSJerome Glisse /* rv3x0 */ 1943c93bb85bSJerome Glisse mem_trcd = (temp & 0x7) + 3; 1944c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0x7) + 3; 1945c93bb85bSJerome Glisse mem_tras = ((temp >> 11) & 0xf) + 6; 1946c93bb85bSJerome Glisse } else if (rdev->family == CHIP_R420 || 1947c93bb85bSJerome Glisse rdev->family == CHIP_R423 || 1948c93bb85bSJerome Glisse rdev->family == CHIP_RV410) { 1949c93bb85bSJerome Glisse /* r4xx */ 1950c93bb85bSJerome Glisse mem_trcd = (temp & 0xf) + 3; 1951c93bb85bSJerome Glisse if (mem_trcd > 15) 1952c93bb85bSJerome Glisse mem_trcd = 15; 1953c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0xf) + 3; 1954c93bb85bSJerome Glisse if (mem_trp > 15) 1955c93bb85bSJerome Glisse mem_trp = 15; 1956c93bb85bSJerome Glisse mem_tras = ((temp >> 12) & 0x1f) + 6; 1957c93bb85bSJerome Glisse if (mem_tras > 31) 1958c93bb85bSJerome Glisse mem_tras = 31; 1959c93bb85bSJerome Glisse } else { /* RV200, R200 */ 1960c93bb85bSJerome Glisse mem_trcd = (temp & 0x7) + 1; 1961c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0x7) + 1; 1962c93bb85bSJerome Glisse mem_tras = ((temp >> 12) & 0xf) + 4; 1963c93bb85bSJerome Glisse } 1964c93bb85bSJerome Glisse /* convert to FF */ 1965c93bb85bSJerome Glisse trcd_ff.full = rfixed_const(mem_trcd); 1966c93bb85bSJerome Glisse trp_ff.full = rfixed_const(mem_trp); 1967c93bb85bSJerome Glisse tras_ff.full = rfixed_const(mem_tras); 1968c93bb85bSJerome Glisse 1969c93bb85bSJerome Glisse /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ 1970c93bb85bSJerome Glisse temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); 1971c93bb85bSJerome Glisse data = (temp & (7 << 20)) >> 20; 1972c93bb85bSJerome Glisse if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { 1973c93bb85bSJerome Glisse if (rdev->family == CHIP_RS480) /* don't think rs400 */ 1974c93bb85bSJerome Glisse tcas_ff = memtcas_rs480_ff[data]; 1975c93bb85bSJerome Glisse else 1976c93bb85bSJerome Glisse tcas_ff = memtcas_ff[data]; 1977c93bb85bSJerome Glisse } else 1978c93bb85bSJerome Glisse tcas_ff = memtcas2_ff[data]; 1979c93bb85bSJerome Glisse 1980c93bb85bSJerome Glisse if (rdev->family == CHIP_RS400 || 1981c93bb85bSJerome Glisse rdev->family == CHIP_RS480) { 1982c93bb85bSJerome Glisse /* extra cas latency stored in bits 23-25 0-4 clocks */ 1983c93bb85bSJerome Glisse data = (temp >> 23) & 0x7; 1984c93bb85bSJerome Glisse if (data < 5) 1985c93bb85bSJerome Glisse tcas_ff.full += rfixed_const(data); 1986c93bb85bSJerome Glisse } 1987c93bb85bSJerome Glisse 1988c93bb85bSJerome Glisse if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { 1989c93bb85bSJerome Glisse /* on the R300, Tcas is included in Trbs. 1990c93bb85bSJerome Glisse */ 1991c93bb85bSJerome Glisse temp = RREG32(RADEON_MEM_CNTL); 1992c93bb85bSJerome Glisse data = (R300_MEM_NUM_CHANNELS_MASK & temp); 1993c93bb85bSJerome Glisse if (data == 1) { 1994c93bb85bSJerome Glisse if (R300_MEM_USE_CD_CH_ONLY & temp) { 1995c93bb85bSJerome Glisse temp = RREG32(R300_MC_IND_INDEX); 1996c93bb85bSJerome Glisse temp &= ~R300_MC_IND_ADDR_MASK; 1997c93bb85bSJerome Glisse temp |= R300_MC_READ_CNTL_CD_mcind; 1998c93bb85bSJerome Glisse WREG32(R300_MC_IND_INDEX, temp); 1999c93bb85bSJerome Glisse temp = RREG32(R300_MC_IND_DATA); 2000c93bb85bSJerome Glisse data = (R300_MEM_RBS_POSITION_C_MASK & temp); 2001c93bb85bSJerome Glisse } else { 2002c93bb85bSJerome Glisse temp = RREG32(R300_MC_READ_CNTL_AB); 2003c93bb85bSJerome Glisse data = (R300_MEM_RBS_POSITION_A_MASK & temp); 2004c93bb85bSJerome Glisse } 2005c93bb85bSJerome Glisse } else { 2006c93bb85bSJerome Glisse temp = RREG32(R300_MC_READ_CNTL_AB); 2007c93bb85bSJerome Glisse data = (R300_MEM_RBS_POSITION_A_MASK & temp); 2008c93bb85bSJerome Glisse } 2009c93bb85bSJerome Glisse if (rdev->family == CHIP_RV410 || 2010c93bb85bSJerome Glisse rdev->family == CHIP_R420 || 2011c93bb85bSJerome Glisse rdev->family == CHIP_R423) 2012c93bb85bSJerome Glisse trbs_ff = memtrbs_r4xx[data]; 2013c93bb85bSJerome Glisse else 2014c93bb85bSJerome Glisse trbs_ff = memtrbs[data]; 2015c93bb85bSJerome Glisse tcas_ff.full += trbs_ff.full; 2016c93bb85bSJerome Glisse } 2017c93bb85bSJerome Glisse 2018c93bb85bSJerome Glisse sclk_eff_ff.full = sclk_ff.full; 2019c93bb85bSJerome Glisse 2020c93bb85bSJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 2021c93bb85bSJerome Glisse fixed20_12 agpmode_ff; 2022c93bb85bSJerome Glisse agpmode_ff.full = rfixed_const(radeon_agpmode); 2023c93bb85bSJerome Glisse temp_ff.full = rfixed_const_666(16); 2024c93bb85bSJerome Glisse sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff); 2025c93bb85bSJerome Glisse } 2026c93bb85bSJerome Glisse /* TODO PCIE lanes may affect this - agpmode == 16?? */ 2027c93bb85bSJerome Glisse 2028c93bb85bSJerome Glisse if (ASIC_IS_R300(rdev)) { 2029c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(250); 2030c93bb85bSJerome Glisse } else { 2031c93bb85bSJerome Glisse if ((rdev->family == CHIP_RV100) || 2032c93bb85bSJerome Glisse rdev->flags & RADEON_IS_IGP) { 2033c93bb85bSJerome Glisse if (rdev->mc.vram_is_ddr) 2034c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(41); 2035c93bb85bSJerome Glisse else 2036c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(33); 2037c93bb85bSJerome Glisse } else { 2038c93bb85bSJerome Glisse if (rdev->mc.vram_width == 128) 2039c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(57); 2040c93bb85bSJerome Glisse else 2041c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(41); 2042c93bb85bSJerome Glisse } 2043c93bb85bSJerome Glisse } 2044c93bb85bSJerome Glisse 2045c93bb85bSJerome Glisse mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff); 2046c93bb85bSJerome Glisse 2047c93bb85bSJerome Glisse if (rdev->mc.vram_is_ddr) { 2048c93bb85bSJerome Glisse if (rdev->mc.vram_width == 32) { 2049c93bb85bSJerome Glisse k1.full = rfixed_const(40); 2050c93bb85bSJerome Glisse c = 3; 2051c93bb85bSJerome Glisse } else { 2052c93bb85bSJerome Glisse k1.full = rfixed_const(20); 2053c93bb85bSJerome Glisse c = 1; 2054c93bb85bSJerome Glisse } 2055c93bb85bSJerome Glisse } else { 2056c93bb85bSJerome Glisse k1.full = rfixed_const(40); 2057c93bb85bSJerome Glisse c = 3; 2058c93bb85bSJerome Glisse } 2059c93bb85bSJerome Glisse 2060c93bb85bSJerome Glisse temp_ff.full = rfixed_const(2); 2061c93bb85bSJerome Glisse mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff); 2062c93bb85bSJerome Glisse temp_ff.full = rfixed_const(c); 2063c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff); 2064c93bb85bSJerome Glisse temp_ff.full = rfixed_const(4); 2065c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff); 2066c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff); 2067c93bb85bSJerome Glisse mc_latency_mclk.full += k1.full; 2068c93bb85bSJerome Glisse 2069c93bb85bSJerome Glisse mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff); 2070c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff); 2071c93bb85bSJerome Glisse 2072c93bb85bSJerome Glisse /* 2073c93bb85bSJerome Glisse HW cursor time assuming worst case of full size colour cursor. 2074c93bb85bSJerome Glisse */ 2075c93bb85bSJerome Glisse temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); 2076c93bb85bSJerome Glisse temp_ff.full += trcd_ff.full; 2077c93bb85bSJerome Glisse if (temp_ff.full < tras_ff.full) 2078c93bb85bSJerome Glisse temp_ff.full = tras_ff.full; 2079c93bb85bSJerome Glisse cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff); 2080c93bb85bSJerome Glisse 2081c93bb85bSJerome Glisse temp_ff.full = rfixed_const(cur_size); 2082c93bb85bSJerome Glisse cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff); 2083c93bb85bSJerome Glisse /* 2084c93bb85bSJerome Glisse Find the total latency for the display data. 2085c93bb85bSJerome Glisse */ 2086c93bb85bSJerome Glisse disp_latency_overhead.full = rfixed_const(80); 2087c93bb85bSJerome Glisse disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff); 2088c93bb85bSJerome Glisse mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; 2089c93bb85bSJerome Glisse mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; 2090c93bb85bSJerome Glisse 2091c93bb85bSJerome Glisse if (mc_latency_mclk.full > mc_latency_sclk.full) 2092c93bb85bSJerome Glisse disp_latency.full = mc_latency_mclk.full; 2093c93bb85bSJerome Glisse else 2094c93bb85bSJerome Glisse disp_latency.full = mc_latency_sclk.full; 2095c93bb85bSJerome Glisse 2096c93bb85bSJerome Glisse /* setup Max GRPH_STOP_REQ default value */ 2097c93bb85bSJerome Glisse if (ASIC_IS_RV100(rdev)) 2098c93bb85bSJerome Glisse max_stop_req = 0x5c; 2099c93bb85bSJerome Glisse else 2100c93bb85bSJerome Glisse max_stop_req = 0x7c; 2101c93bb85bSJerome Glisse 2102c93bb85bSJerome Glisse if (mode1) { 2103c93bb85bSJerome Glisse /* CRTC1 2104c93bb85bSJerome Glisse Set GRPH_BUFFER_CNTL register using h/w defined optimal values. 2105c93bb85bSJerome Glisse GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] 2106c93bb85bSJerome Glisse */ 2107c93bb85bSJerome Glisse stop_req = mode1->hdisplay * pixel_bytes1 / 16; 2108c93bb85bSJerome Glisse 2109c93bb85bSJerome Glisse if (stop_req > max_stop_req) 2110c93bb85bSJerome Glisse stop_req = max_stop_req; 2111c93bb85bSJerome Glisse 2112c93bb85bSJerome Glisse /* 2113c93bb85bSJerome Glisse Find the drain rate of the display buffer. 2114c93bb85bSJerome Glisse */ 2115c93bb85bSJerome Glisse temp_ff.full = rfixed_const((16/pixel_bytes1)); 2116c93bb85bSJerome Glisse disp_drain_rate.full = rfixed_div(pix_clk, temp_ff); 2117c93bb85bSJerome Glisse 2118c93bb85bSJerome Glisse /* 2119c93bb85bSJerome Glisse Find the critical point of the display buffer. 2120c93bb85bSJerome Glisse */ 2121c93bb85bSJerome Glisse crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency); 2122c93bb85bSJerome Glisse crit_point_ff.full += rfixed_const_half(0); 2123c93bb85bSJerome Glisse 2124c93bb85bSJerome Glisse critical_point = rfixed_trunc(crit_point_ff); 2125c93bb85bSJerome Glisse 2126c93bb85bSJerome Glisse if (rdev->disp_priority == 2) { 2127c93bb85bSJerome Glisse critical_point = 0; 2128c93bb85bSJerome Glisse } 2129c93bb85bSJerome Glisse 2130c93bb85bSJerome Glisse /* 2131c93bb85bSJerome Glisse The critical point should never be above max_stop_req-4. Setting 2132c93bb85bSJerome Glisse GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. 2133c93bb85bSJerome Glisse */ 2134c93bb85bSJerome Glisse if (max_stop_req - critical_point < 4) 2135c93bb85bSJerome Glisse critical_point = 0; 2136c93bb85bSJerome Glisse 2137c93bb85bSJerome Glisse if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { 2138c93bb85bSJerome Glisse /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ 2139c93bb85bSJerome Glisse critical_point = 0x10; 2140c93bb85bSJerome Glisse } 2141c93bb85bSJerome Glisse 2142c93bb85bSJerome Glisse temp = RREG32(RADEON_GRPH_BUFFER_CNTL); 2143c93bb85bSJerome Glisse temp &= ~(RADEON_GRPH_STOP_REQ_MASK); 2144c93bb85bSJerome Glisse temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); 2145c93bb85bSJerome Glisse temp &= ~(RADEON_GRPH_START_REQ_MASK); 2146c93bb85bSJerome Glisse if ((rdev->family == CHIP_R350) && 2147c93bb85bSJerome Glisse (stop_req > 0x15)) { 2148c93bb85bSJerome Glisse stop_req -= 0x10; 2149c93bb85bSJerome Glisse } 2150c93bb85bSJerome Glisse temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); 2151c93bb85bSJerome Glisse temp |= RADEON_GRPH_BUFFER_SIZE; 2152c93bb85bSJerome Glisse temp &= ~(RADEON_GRPH_CRITICAL_CNTL | 2153c93bb85bSJerome Glisse RADEON_GRPH_CRITICAL_AT_SOF | 2154c93bb85bSJerome Glisse RADEON_GRPH_STOP_CNTL); 2155c93bb85bSJerome Glisse /* 2156c93bb85bSJerome Glisse Write the result into the register. 2157c93bb85bSJerome Glisse */ 2158c93bb85bSJerome Glisse WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | 2159c93bb85bSJerome Glisse (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); 2160c93bb85bSJerome Glisse 2161c93bb85bSJerome Glisse #if 0 2162c93bb85bSJerome Glisse if ((rdev->family == CHIP_RS400) || 2163c93bb85bSJerome Glisse (rdev->family == CHIP_RS480)) { 2164c93bb85bSJerome Glisse /* attempt to program RS400 disp regs correctly ??? */ 2165c93bb85bSJerome Glisse temp = RREG32(RS400_DISP1_REG_CNTL); 2166c93bb85bSJerome Glisse temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | 2167c93bb85bSJerome Glisse RS400_DISP1_STOP_REQ_LEVEL_MASK); 2168c93bb85bSJerome Glisse WREG32(RS400_DISP1_REQ_CNTL1, (temp | 2169c93bb85bSJerome Glisse (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | 2170c93bb85bSJerome Glisse (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); 2171c93bb85bSJerome Glisse temp = RREG32(RS400_DMIF_MEM_CNTL1); 2172c93bb85bSJerome Glisse temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | 2173c93bb85bSJerome Glisse RS400_DISP1_CRITICAL_POINT_STOP_MASK); 2174c93bb85bSJerome Glisse WREG32(RS400_DMIF_MEM_CNTL1, (temp | 2175c93bb85bSJerome Glisse (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | 2176c93bb85bSJerome Glisse (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); 2177c93bb85bSJerome Glisse } 2178c93bb85bSJerome Glisse #endif 2179c93bb85bSJerome Glisse 2180c93bb85bSJerome Glisse DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n", 2181c93bb85bSJerome Glisse /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ 2182c93bb85bSJerome Glisse (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); 2183c93bb85bSJerome Glisse } 2184c93bb85bSJerome Glisse 2185c93bb85bSJerome Glisse if (mode2) { 2186c93bb85bSJerome Glisse u32 grph2_cntl; 2187c93bb85bSJerome Glisse stop_req = mode2->hdisplay * pixel_bytes2 / 16; 2188c93bb85bSJerome Glisse 2189c93bb85bSJerome Glisse if (stop_req > max_stop_req) 2190c93bb85bSJerome Glisse stop_req = max_stop_req; 2191c93bb85bSJerome Glisse 2192c93bb85bSJerome Glisse /* 2193c93bb85bSJerome Glisse Find the drain rate of the display buffer. 2194c93bb85bSJerome Glisse */ 2195c93bb85bSJerome Glisse temp_ff.full = rfixed_const((16/pixel_bytes2)); 2196c93bb85bSJerome Glisse disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff); 2197c93bb85bSJerome Glisse 2198c93bb85bSJerome Glisse grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); 2199c93bb85bSJerome Glisse grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); 2200c93bb85bSJerome Glisse grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); 2201c93bb85bSJerome Glisse grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); 2202c93bb85bSJerome Glisse if ((rdev->family == CHIP_R350) && 2203c93bb85bSJerome Glisse (stop_req > 0x15)) { 2204c93bb85bSJerome Glisse stop_req -= 0x10; 2205c93bb85bSJerome Glisse } 2206c93bb85bSJerome Glisse grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); 2207c93bb85bSJerome Glisse grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; 2208c93bb85bSJerome Glisse grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | 2209c93bb85bSJerome Glisse RADEON_GRPH_CRITICAL_AT_SOF | 2210c93bb85bSJerome Glisse RADEON_GRPH_STOP_CNTL); 2211c93bb85bSJerome Glisse 2212c93bb85bSJerome Glisse if ((rdev->family == CHIP_RS100) || 2213c93bb85bSJerome Glisse (rdev->family == CHIP_RS200)) 2214c93bb85bSJerome Glisse critical_point2 = 0; 2215c93bb85bSJerome Glisse else { 2216c93bb85bSJerome Glisse temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; 2217c93bb85bSJerome Glisse temp_ff.full = rfixed_const(temp); 2218c93bb85bSJerome Glisse temp_ff.full = rfixed_mul(mclk_ff, temp_ff); 2219c93bb85bSJerome Glisse if (sclk_ff.full < temp_ff.full) 2220c93bb85bSJerome Glisse temp_ff.full = sclk_ff.full; 2221c93bb85bSJerome Glisse 2222c93bb85bSJerome Glisse read_return_rate.full = temp_ff.full; 2223c93bb85bSJerome Glisse 2224c93bb85bSJerome Glisse if (mode1) { 2225c93bb85bSJerome Glisse temp_ff.full = read_return_rate.full - disp_drain_rate.full; 2226c93bb85bSJerome Glisse time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff); 2227c93bb85bSJerome Glisse } else { 2228c93bb85bSJerome Glisse time_disp1_drop_priority.full = 0; 2229c93bb85bSJerome Glisse } 2230c93bb85bSJerome Glisse crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; 2231c93bb85bSJerome Glisse crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2); 2232c93bb85bSJerome Glisse crit_point_ff.full += rfixed_const_half(0); 2233c93bb85bSJerome Glisse 2234c93bb85bSJerome Glisse critical_point2 = rfixed_trunc(crit_point_ff); 2235c93bb85bSJerome Glisse 2236c93bb85bSJerome Glisse if (rdev->disp_priority == 2) { 2237c93bb85bSJerome Glisse critical_point2 = 0; 2238c93bb85bSJerome Glisse } 2239c93bb85bSJerome Glisse 2240c93bb85bSJerome Glisse if (max_stop_req - critical_point2 < 4) 2241c93bb85bSJerome Glisse critical_point2 = 0; 2242c93bb85bSJerome Glisse 2243c93bb85bSJerome Glisse } 2244c93bb85bSJerome Glisse 2245c93bb85bSJerome Glisse if (critical_point2 == 0 && rdev->family == CHIP_R300) { 2246c93bb85bSJerome Glisse /* some R300 cards have problem with this set to 0 */ 2247c93bb85bSJerome Glisse critical_point2 = 0x10; 2248c93bb85bSJerome Glisse } 2249c93bb85bSJerome Glisse 2250c93bb85bSJerome Glisse WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | 2251c93bb85bSJerome Glisse (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); 2252c93bb85bSJerome Glisse 2253c93bb85bSJerome Glisse if ((rdev->family == CHIP_RS400) || 2254c93bb85bSJerome Glisse (rdev->family == CHIP_RS480)) { 2255c93bb85bSJerome Glisse #if 0 2256c93bb85bSJerome Glisse /* attempt to program RS400 disp2 regs correctly ??? */ 2257c93bb85bSJerome Glisse temp = RREG32(RS400_DISP2_REQ_CNTL1); 2258c93bb85bSJerome Glisse temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | 2259c93bb85bSJerome Glisse RS400_DISP2_STOP_REQ_LEVEL_MASK); 2260c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL1, (temp | 2261c93bb85bSJerome Glisse (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | 2262c93bb85bSJerome Glisse (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); 2263c93bb85bSJerome Glisse temp = RREG32(RS400_DISP2_REQ_CNTL2); 2264c93bb85bSJerome Glisse temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | 2265c93bb85bSJerome Glisse RS400_DISP2_CRITICAL_POINT_STOP_MASK); 2266c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL2, (temp | 2267c93bb85bSJerome Glisse (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | 2268c93bb85bSJerome Glisse (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); 2269c93bb85bSJerome Glisse #endif 2270c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); 2271c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); 2272c93bb85bSJerome Glisse WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); 2273c93bb85bSJerome Glisse WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); 2274c93bb85bSJerome Glisse } 2275c93bb85bSJerome Glisse 2276c93bb85bSJerome Glisse DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n", 2277c93bb85bSJerome Glisse (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); 2278c93bb85bSJerome Glisse } 2279c93bb85bSJerome Glisse } 2280