1*771fe6b9SJerome Glisse /* 2*771fe6b9SJerome Glisse * Copyright 2008 Advanced Micro Devices, Inc. 3*771fe6b9SJerome Glisse * Copyright 2008 Red Hat Inc. 4*771fe6b9SJerome Glisse * Copyright 2009 Jerome Glisse. 5*771fe6b9SJerome Glisse * 6*771fe6b9SJerome Glisse * Permission is hereby granted, free of charge, to any person obtaining a 7*771fe6b9SJerome Glisse * copy of this software and associated documentation files (the "Software"), 8*771fe6b9SJerome Glisse * to deal in the Software without restriction, including without limitation 9*771fe6b9SJerome Glisse * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10*771fe6b9SJerome Glisse * and/or sell copies of the Software, and to permit persons to whom the 11*771fe6b9SJerome Glisse * Software is furnished to do so, subject to the following conditions: 12*771fe6b9SJerome Glisse * 13*771fe6b9SJerome Glisse * The above copyright notice and this permission notice shall be included in 14*771fe6b9SJerome Glisse * all copies or substantial portions of the Software. 15*771fe6b9SJerome Glisse * 16*771fe6b9SJerome Glisse * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17*771fe6b9SJerome Glisse * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18*771fe6b9SJerome Glisse * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19*771fe6b9SJerome Glisse * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20*771fe6b9SJerome Glisse * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21*771fe6b9SJerome Glisse * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22*771fe6b9SJerome Glisse * OTHER DEALINGS IN THE SOFTWARE. 23*771fe6b9SJerome Glisse * 24*771fe6b9SJerome Glisse * Authors: Dave Airlie 25*771fe6b9SJerome Glisse * Alex Deucher 26*771fe6b9SJerome Glisse * Jerome Glisse 27*771fe6b9SJerome Glisse */ 28*771fe6b9SJerome Glisse #include <linux/seq_file.h> 29*771fe6b9SJerome Glisse #include "drmP.h" 30*771fe6b9SJerome Glisse #include "drm.h" 31*771fe6b9SJerome Glisse #include "radeon_drm.h" 32*771fe6b9SJerome Glisse #include "radeon_microcode.h" 33*771fe6b9SJerome Glisse #include "radeon_reg.h" 34*771fe6b9SJerome Glisse #include "radeon.h" 35*771fe6b9SJerome Glisse 36*771fe6b9SJerome Glisse /* This files gather functions specifics to: 37*771fe6b9SJerome Glisse * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 38*771fe6b9SJerome Glisse * 39*771fe6b9SJerome Glisse * Some of these functions might be used by newer ASICs. 40*771fe6b9SJerome Glisse */ 41*771fe6b9SJerome Glisse void r100_hdp_reset(struct radeon_device *rdev); 42*771fe6b9SJerome Glisse void r100_gpu_init(struct radeon_device *rdev); 43*771fe6b9SJerome Glisse int r100_gui_wait_for_idle(struct radeon_device *rdev); 44*771fe6b9SJerome Glisse int r100_mc_wait_for_idle(struct radeon_device *rdev); 45*771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync(struct radeon_device *rdev); 46*771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync2(struct radeon_device *rdev); 47*771fe6b9SJerome Glisse int r100_debugfs_mc_info_init(struct radeon_device *rdev); 48*771fe6b9SJerome Glisse 49*771fe6b9SJerome Glisse 50*771fe6b9SJerome Glisse /* 51*771fe6b9SJerome Glisse * PCI GART 52*771fe6b9SJerome Glisse */ 53*771fe6b9SJerome Glisse void r100_pci_gart_tlb_flush(struct radeon_device *rdev) 54*771fe6b9SJerome Glisse { 55*771fe6b9SJerome Glisse /* TODO: can we do somethings here ? */ 56*771fe6b9SJerome Glisse /* It seems hw only cache one entry so we should discard this 57*771fe6b9SJerome Glisse * entry otherwise if first GPU GART read hit this entry it 58*771fe6b9SJerome Glisse * could end up in wrong address. */ 59*771fe6b9SJerome Glisse } 60*771fe6b9SJerome Glisse 61*771fe6b9SJerome Glisse int r100_pci_gart_enable(struct radeon_device *rdev) 62*771fe6b9SJerome Glisse { 63*771fe6b9SJerome Glisse uint32_t tmp; 64*771fe6b9SJerome Glisse int r; 65*771fe6b9SJerome Glisse 66*771fe6b9SJerome Glisse /* Initialize common gart structure */ 67*771fe6b9SJerome Glisse r = radeon_gart_init(rdev); 68*771fe6b9SJerome Glisse if (r) { 69*771fe6b9SJerome Glisse return r; 70*771fe6b9SJerome Glisse } 71*771fe6b9SJerome Glisse if (rdev->gart.table.ram.ptr == NULL) { 72*771fe6b9SJerome Glisse rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; 73*771fe6b9SJerome Glisse r = radeon_gart_table_ram_alloc(rdev); 74*771fe6b9SJerome Glisse if (r) { 75*771fe6b9SJerome Glisse return r; 76*771fe6b9SJerome Glisse } 77*771fe6b9SJerome Glisse } 78*771fe6b9SJerome Glisse /* discard memory request outside of configured range */ 79*771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; 80*771fe6b9SJerome Glisse WREG32(RADEON_AIC_CNTL, tmp); 81*771fe6b9SJerome Glisse /* set address range for PCI address translate */ 82*771fe6b9SJerome Glisse WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location); 83*771fe6b9SJerome Glisse tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; 84*771fe6b9SJerome Glisse WREG32(RADEON_AIC_HI_ADDR, tmp); 85*771fe6b9SJerome Glisse /* Enable bus mastering */ 86*771fe6b9SJerome Glisse tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; 87*771fe6b9SJerome Glisse WREG32(RADEON_BUS_CNTL, tmp); 88*771fe6b9SJerome Glisse /* set PCI GART page-table base address */ 89*771fe6b9SJerome Glisse WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr); 90*771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN; 91*771fe6b9SJerome Glisse WREG32(RADEON_AIC_CNTL, tmp); 92*771fe6b9SJerome Glisse r100_pci_gart_tlb_flush(rdev); 93*771fe6b9SJerome Glisse rdev->gart.ready = true; 94*771fe6b9SJerome Glisse return 0; 95*771fe6b9SJerome Glisse } 96*771fe6b9SJerome Glisse 97*771fe6b9SJerome Glisse void r100_pci_gart_disable(struct radeon_device *rdev) 98*771fe6b9SJerome Glisse { 99*771fe6b9SJerome Glisse uint32_t tmp; 100*771fe6b9SJerome Glisse 101*771fe6b9SJerome Glisse /* discard memory request outside of configured range */ 102*771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; 103*771fe6b9SJerome Glisse WREG32(RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN); 104*771fe6b9SJerome Glisse WREG32(RADEON_AIC_LO_ADDR, 0); 105*771fe6b9SJerome Glisse WREG32(RADEON_AIC_HI_ADDR, 0); 106*771fe6b9SJerome Glisse } 107*771fe6b9SJerome Glisse 108*771fe6b9SJerome Glisse int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) 109*771fe6b9SJerome Glisse { 110*771fe6b9SJerome Glisse if (i < 0 || i > rdev->gart.num_gpu_pages) { 111*771fe6b9SJerome Glisse return -EINVAL; 112*771fe6b9SJerome Glisse } 113*771fe6b9SJerome Glisse rdev->gart.table.ram.ptr[i] = cpu_to_le32((uint32_t)addr); 114*771fe6b9SJerome Glisse return 0; 115*771fe6b9SJerome Glisse } 116*771fe6b9SJerome Glisse 117*771fe6b9SJerome Glisse int r100_gart_enable(struct radeon_device *rdev) 118*771fe6b9SJerome Glisse { 119*771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 120*771fe6b9SJerome Glisse r100_pci_gart_disable(rdev); 121*771fe6b9SJerome Glisse return 0; 122*771fe6b9SJerome Glisse } 123*771fe6b9SJerome Glisse return r100_pci_gart_enable(rdev); 124*771fe6b9SJerome Glisse } 125*771fe6b9SJerome Glisse 126*771fe6b9SJerome Glisse 127*771fe6b9SJerome Glisse /* 128*771fe6b9SJerome Glisse * MC 129*771fe6b9SJerome Glisse */ 130*771fe6b9SJerome Glisse void r100_mc_disable_clients(struct radeon_device *rdev) 131*771fe6b9SJerome Glisse { 132*771fe6b9SJerome Glisse uint32_t ov0_scale_cntl, crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl; 133*771fe6b9SJerome Glisse 134*771fe6b9SJerome Glisse /* FIXME: is this function correct for rs100,rs200,rs300 ? */ 135*771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 136*771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 137*771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 138*771fe6b9SJerome Glisse } 139*771fe6b9SJerome Glisse 140*771fe6b9SJerome Glisse /* stop display and memory access */ 141*771fe6b9SJerome Glisse ov0_scale_cntl = RREG32(RADEON_OV0_SCALE_CNTL); 142*771fe6b9SJerome Glisse WREG32(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE); 143*771fe6b9SJerome Glisse crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); 144*771fe6b9SJerome Glisse WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS); 145*771fe6b9SJerome Glisse crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); 146*771fe6b9SJerome Glisse 147*771fe6b9SJerome Glisse r100_gpu_wait_for_vsync(rdev); 148*771fe6b9SJerome Glisse 149*771fe6b9SJerome Glisse WREG32(RADEON_CRTC_GEN_CNTL, 150*771fe6b9SJerome Glisse (crtc_gen_cntl & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) | 151*771fe6b9SJerome Glisse RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN); 152*771fe6b9SJerome Glisse 153*771fe6b9SJerome Glisse if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 154*771fe6b9SJerome Glisse crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 155*771fe6b9SJerome Glisse 156*771fe6b9SJerome Glisse r100_gpu_wait_for_vsync2(rdev); 157*771fe6b9SJerome Glisse WREG32(RADEON_CRTC2_GEN_CNTL, 158*771fe6b9SJerome Glisse (crtc2_gen_cntl & 159*771fe6b9SJerome Glisse ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) | 160*771fe6b9SJerome Glisse RADEON_CRTC2_DISP_REQ_EN_B); 161*771fe6b9SJerome Glisse } 162*771fe6b9SJerome Glisse 163*771fe6b9SJerome Glisse udelay(500); 164*771fe6b9SJerome Glisse } 165*771fe6b9SJerome Glisse 166*771fe6b9SJerome Glisse void r100_mc_setup(struct radeon_device *rdev) 167*771fe6b9SJerome Glisse { 168*771fe6b9SJerome Glisse uint32_t tmp; 169*771fe6b9SJerome Glisse int r; 170*771fe6b9SJerome Glisse 171*771fe6b9SJerome Glisse r = r100_debugfs_mc_info_init(rdev); 172*771fe6b9SJerome Glisse if (r) { 173*771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for R100 MC !\n"); 174*771fe6b9SJerome Glisse } 175*771fe6b9SJerome Glisse /* Write VRAM size in case we are limiting it */ 176*771fe6b9SJerome Glisse WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); 177*771fe6b9SJerome Glisse tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; 178*771fe6b9SJerome Glisse tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); 179*771fe6b9SJerome Glisse tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); 180*771fe6b9SJerome Glisse WREG32(RADEON_MC_FB_LOCATION, tmp); 181*771fe6b9SJerome Glisse 182*771fe6b9SJerome Glisse /* Enable bus mastering */ 183*771fe6b9SJerome Glisse tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; 184*771fe6b9SJerome Glisse WREG32(RADEON_BUS_CNTL, tmp); 185*771fe6b9SJerome Glisse 186*771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 187*771fe6b9SJerome Glisse tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; 188*771fe6b9SJerome Glisse tmp = REG_SET(RADEON_MC_AGP_TOP, tmp >> 16); 189*771fe6b9SJerome Glisse tmp |= REG_SET(RADEON_MC_AGP_START, rdev->mc.gtt_location >> 16); 190*771fe6b9SJerome Glisse WREG32(RADEON_MC_AGP_LOCATION, tmp); 191*771fe6b9SJerome Glisse WREG32(RADEON_AGP_BASE, rdev->mc.agp_base); 192*771fe6b9SJerome Glisse } else { 193*771fe6b9SJerome Glisse WREG32(RADEON_MC_AGP_LOCATION, 0x0FFFFFFF); 194*771fe6b9SJerome Glisse WREG32(RADEON_AGP_BASE, 0); 195*771fe6b9SJerome Glisse } 196*771fe6b9SJerome Glisse 197*771fe6b9SJerome Glisse tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; 198*771fe6b9SJerome Glisse tmp |= (7 << 28); 199*771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); 200*771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 201*771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp); 202*771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 203*771fe6b9SJerome Glisse } 204*771fe6b9SJerome Glisse 205*771fe6b9SJerome Glisse int r100_mc_init(struct radeon_device *rdev) 206*771fe6b9SJerome Glisse { 207*771fe6b9SJerome Glisse int r; 208*771fe6b9SJerome Glisse 209*771fe6b9SJerome Glisse if (r100_debugfs_rbbm_init(rdev)) { 210*771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for RBBM !\n"); 211*771fe6b9SJerome Glisse } 212*771fe6b9SJerome Glisse 213*771fe6b9SJerome Glisse r100_gpu_init(rdev); 214*771fe6b9SJerome Glisse /* Disable gart which also disable out of gart access */ 215*771fe6b9SJerome Glisse r100_pci_gart_disable(rdev); 216*771fe6b9SJerome Glisse 217*771fe6b9SJerome Glisse /* Setup GPU memory space */ 218*771fe6b9SJerome Glisse rdev->mc.vram_location = 0xFFFFFFFFUL; 219*771fe6b9SJerome Glisse rdev->mc.gtt_location = 0xFFFFFFFFUL; 220*771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 221*771fe6b9SJerome Glisse r = radeon_agp_init(rdev); 222*771fe6b9SJerome Glisse if (r) { 223*771fe6b9SJerome Glisse printk(KERN_WARNING "[drm] Disabling AGP\n"); 224*771fe6b9SJerome Glisse rdev->flags &= ~RADEON_IS_AGP; 225*771fe6b9SJerome Glisse rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; 226*771fe6b9SJerome Glisse } else { 227*771fe6b9SJerome Glisse rdev->mc.gtt_location = rdev->mc.agp_base; 228*771fe6b9SJerome Glisse } 229*771fe6b9SJerome Glisse } 230*771fe6b9SJerome Glisse r = radeon_mc_setup(rdev); 231*771fe6b9SJerome Glisse if (r) { 232*771fe6b9SJerome Glisse return r; 233*771fe6b9SJerome Glisse } 234*771fe6b9SJerome Glisse 235*771fe6b9SJerome Glisse r100_mc_disable_clients(rdev); 236*771fe6b9SJerome Glisse if (r100_mc_wait_for_idle(rdev)) { 237*771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait MC idle while " 238*771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 239*771fe6b9SJerome Glisse } 240*771fe6b9SJerome Glisse 241*771fe6b9SJerome Glisse r100_mc_setup(rdev); 242*771fe6b9SJerome Glisse return 0; 243*771fe6b9SJerome Glisse } 244*771fe6b9SJerome Glisse 245*771fe6b9SJerome Glisse void r100_mc_fini(struct radeon_device *rdev) 246*771fe6b9SJerome Glisse { 247*771fe6b9SJerome Glisse r100_pci_gart_disable(rdev); 248*771fe6b9SJerome Glisse radeon_gart_table_ram_free(rdev); 249*771fe6b9SJerome Glisse radeon_gart_fini(rdev); 250*771fe6b9SJerome Glisse } 251*771fe6b9SJerome Glisse 252*771fe6b9SJerome Glisse 253*771fe6b9SJerome Glisse /* 254*771fe6b9SJerome Glisse * Fence emission 255*771fe6b9SJerome Glisse */ 256*771fe6b9SJerome Glisse void r100_fence_ring_emit(struct radeon_device *rdev, 257*771fe6b9SJerome Glisse struct radeon_fence *fence) 258*771fe6b9SJerome Glisse { 259*771fe6b9SJerome Glisse /* Who ever call radeon_fence_emit should call ring_lock and ask 260*771fe6b9SJerome Glisse * for enough space (today caller are ib schedule and buffer move) */ 261*771fe6b9SJerome Glisse /* Wait until IDLE & CLEAN */ 262*771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(0x1720, 0)); 263*771fe6b9SJerome Glisse radeon_ring_write(rdev, (1 << 16) | (1 << 17)); 264*771fe6b9SJerome Glisse /* Emit fence sequence & fire IRQ */ 265*771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0)); 266*771fe6b9SJerome Glisse radeon_ring_write(rdev, fence->seq); 267*771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_GEN_INT_STATUS, 0)); 268*771fe6b9SJerome Glisse radeon_ring_write(rdev, RADEON_SW_INT_FIRE); 269*771fe6b9SJerome Glisse } 270*771fe6b9SJerome Glisse 271*771fe6b9SJerome Glisse 272*771fe6b9SJerome Glisse /* 273*771fe6b9SJerome Glisse * Writeback 274*771fe6b9SJerome Glisse */ 275*771fe6b9SJerome Glisse int r100_wb_init(struct radeon_device *rdev) 276*771fe6b9SJerome Glisse { 277*771fe6b9SJerome Glisse int r; 278*771fe6b9SJerome Glisse 279*771fe6b9SJerome Glisse if (rdev->wb.wb_obj == NULL) { 280*771fe6b9SJerome Glisse r = radeon_object_create(rdev, NULL, 4096, 281*771fe6b9SJerome Glisse true, 282*771fe6b9SJerome Glisse RADEON_GEM_DOMAIN_GTT, 283*771fe6b9SJerome Glisse false, &rdev->wb.wb_obj); 284*771fe6b9SJerome Glisse if (r) { 285*771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to create WB buffer (%d).\n", r); 286*771fe6b9SJerome Glisse return r; 287*771fe6b9SJerome Glisse } 288*771fe6b9SJerome Glisse r = radeon_object_pin(rdev->wb.wb_obj, 289*771fe6b9SJerome Glisse RADEON_GEM_DOMAIN_GTT, 290*771fe6b9SJerome Glisse &rdev->wb.gpu_addr); 291*771fe6b9SJerome Glisse if (r) { 292*771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to pin WB buffer (%d).\n", r); 293*771fe6b9SJerome Glisse return r; 294*771fe6b9SJerome Glisse } 295*771fe6b9SJerome Glisse r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); 296*771fe6b9SJerome Glisse if (r) { 297*771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to map WB buffer (%d).\n", r); 298*771fe6b9SJerome Glisse return r; 299*771fe6b9SJerome Glisse } 300*771fe6b9SJerome Glisse } 301*771fe6b9SJerome Glisse WREG32(0x774, rdev->wb.gpu_addr); 302*771fe6b9SJerome Glisse WREG32(0x70C, rdev->wb.gpu_addr + 1024); 303*771fe6b9SJerome Glisse WREG32(0x770, 0xff); 304*771fe6b9SJerome Glisse return 0; 305*771fe6b9SJerome Glisse } 306*771fe6b9SJerome Glisse 307*771fe6b9SJerome Glisse void r100_wb_fini(struct radeon_device *rdev) 308*771fe6b9SJerome Glisse { 309*771fe6b9SJerome Glisse if (rdev->wb.wb_obj) { 310*771fe6b9SJerome Glisse radeon_object_kunmap(rdev->wb.wb_obj); 311*771fe6b9SJerome Glisse radeon_object_unpin(rdev->wb.wb_obj); 312*771fe6b9SJerome Glisse radeon_object_unref(&rdev->wb.wb_obj); 313*771fe6b9SJerome Glisse rdev->wb.wb = NULL; 314*771fe6b9SJerome Glisse rdev->wb.wb_obj = NULL; 315*771fe6b9SJerome Glisse } 316*771fe6b9SJerome Glisse } 317*771fe6b9SJerome Glisse 318*771fe6b9SJerome Glisse int r100_copy_blit(struct radeon_device *rdev, 319*771fe6b9SJerome Glisse uint64_t src_offset, 320*771fe6b9SJerome Glisse uint64_t dst_offset, 321*771fe6b9SJerome Glisse unsigned num_pages, 322*771fe6b9SJerome Glisse struct radeon_fence *fence) 323*771fe6b9SJerome Glisse { 324*771fe6b9SJerome Glisse uint32_t cur_pages; 325*771fe6b9SJerome Glisse uint32_t stride_bytes = PAGE_SIZE; 326*771fe6b9SJerome Glisse uint32_t pitch; 327*771fe6b9SJerome Glisse uint32_t stride_pixels; 328*771fe6b9SJerome Glisse unsigned ndw; 329*771fe6b9SJerome Glisse int num_loops; 330*771fe6b9SJerome Glisse int r = 0; 331*771fe6b9SJerome Glisse 332*771fe6b9SJerome Glisse /* radeon limited to 16k stride */ 333*771fe6b9SJerome Glisse stride_bytes &= 0x3fff; 334*771fe6b9SJerome Glisse /* radeon pitch is /64 */ 335*771fe6b9SJerome Glisse pitch = stride_bytes / 64; 336*771fe6b9SJerome Glisse stride_pixels = stride_bytes / 4; 337*771fe6b9SJerome Glisse num_loops = DIV_ROUND_UP(num_pages, 8191); 338*771fe6b9SJerome Glisse 339*771fe6b9SJerome Glisse /* Ask for enough room for blit + flush + fence */ 340*771fe6b9SJerome Glisse ndw = 64 + (10 * num_loops); 341*771fe6b9SJerome Glisse r = radeon_ring_lock(rdev, ndw); 342*771fe6b9SJerome Glisse if (r) { 343*771fe6b9SJerome Glisse DRM_ERROR("radeon: moving bo (%d) asking for %u dw.\n", r, ndw); 344*771fe6b9SJerome Glisse return -EINVAL; 345*771fe6b9SJerome Glisse } 346*771fe6b9SJerome Glisse while (num_pages > 0) { 347*771fe6b9SJerome Glisse cur_pages = num_pages; 348*771fe6b9SJerome Glisse if (cur_pages > 8191) { 349*771fe6b9SJerome Glisse cur_pages = 8191; 350*771fe6b9SJerome Glisse } 351*771fe6b9SJerome Glisse num_pages -= cur_pages; 352*771fe6b9SJerome Glisse 353*771fe6b9SJerome Glisse /* pages are in Y direction - height 354*771fe6b9SJerome Glisse page width in X direction - width */ 355*771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET3(PACKET3_BITBLT_MULTI, 8)); 356*771fe6b9SJerome Glisse radeon_ring_write(rdev, 357*771fe6b9SJerome Glisse RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 358*771fe6b9SJerome Glisse RADEON_GMC_DST_PITCH_OFFSET_CNTL | 359*771fe6b9SJerome Glisse RADEON_GMC_SRC_CLIPPING | 360*771fe6b9SJerome Glisse RADEON_GMC_DST_CLIPPING | 361*771fe6b9SJerome Glisse RADEON_GMC_BRUSH_NONE | 362*771fe6b9SJerome Glisse (RADEON_COLOR_FORMAT_ARGB8888 << 8) | 363*771fe6b9SJerome Glisse RADEON_GMC_SRC_DATATYPE_COLOR | 364*771fe6b9SJerome Glisse RADEON_ROP3_S | 365*771fe6b9SJerome Glisse RADEON_DP_SRC_SOURCE_MEMORY | 366*771fe6b9SJerome Glisse RADEON_GMC_CLR_CMP_CNTL_DIS | 367*771fe6b9SJerome Glisse RADEON_GMC_WR_MSK_DIS); 368*771fe6b9SJerome Glisse radeon_ring_write(rdev, (pitch << 22) | (src_offset >> 10)); 369*771fe6b9SJerome Glisse radeon_ring_write(rdev, (pitch << 22) | (dst_offset >> 10)); 370*771fe6b9SJerome Glisse radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); 371*771fe6b9SJerome Glisse radeon_ring_write(rdev, 0); 372*771fe6b9SJerome Glisse radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); 373*771fe6b9SJerome Glisse radeon_ring_write(rdev, num_pages); 374*771fe6b9SJerome Glisse radeon_ring_write(rdev, num_pages); 375*771fe6b9SJerome Glisse radeon_ring_write(rdev, cur_pages | (stride_pixels << 16)); 376*771fe6b9SJerome Glisse } 377*771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0)); 378*771fe6b9SJerome Glisse radeon_ring_write(rdev, RADEON_RB2D_DC_FLUSH_ALL); 379*771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); 380*771fe6b9SJerome Glisse radeon_ring_write(rdev, 381*771fe6b9SJerome Glisse RADEON_WAIT_2D_IDLECLEAN | 382*771fe6b9SJerome Glisse RADEON_WAIT_HOST_IDLECLEAN | 383*771fe6b9SJerome Glisse RADEON_WAIT_DMA_GUI_IDLE); 384*771fe6b9SJerome Glisse if (fence) { 385*771fe6b9SJerome Glisse r = radeon_fence_emit(rdev, fence); 386*771fe6b9SJerome Glisse } 387*771fe6b9SJerome Glisse radeon_ring_unlock_commit(rdev); 388*771fe6b9SJerome Glisse return r; 389*771fe6b9SJerome Glisse } 390*771fe6b9SJerome Glisse 391*771fe6b9SJerome Glisse 392*771fe6b9SJerome Glisse /* 393*771fe6b9SJerome Glisse * CP 394*771fe6b9SJerome Glisse */ 395*771fe6b9SJerome Glisse void r100_ring_start(struct radeon_device *rdev) 396*771fe6b9SJerome Glisse { 397*771fe6b9SJerome Glisse int r; 398*771fe6b9SJerome Glisse 399*771fe6b9SJerome Glisse r = radeon_ring_lock(rdev, 2); 400*771fe6b9SJerome Glisse if (r) { 401*771fe6b9SJerome Glisse return; 402*771fe6b9SJerome Glisse } 403*771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0)); 404*771fe6b9SJerome Glisse radeon_ring_write(rdev, 405*771fe6b9SJerome Glisse RADEON_ISYNC_ANY2D_IDLE3D | 406*771fe6b9SJerome Glisse RADEON_ISYNC_ANY3D_IDLE2D | 407*771fe6b9SJerome Glisse RADEON_ISYNC_WAIT_IDLEGUI | 408*771fe6b9SJerome Glisse RADEON_ISYNC_CPSCRATCH_IDLEGUI); 409*771fe6b9SJerome Glisse radeon_ring_unlock_commit(rdev); 410*771fe6b9SJerome Glisse } 411*771fe6b9SJerome Glisse 412*771fe6b9SJerome Glisse static void r100_cp_load_microcode(struct radeon_device *rdev) 413*771fe6b9SJerome Glisse { 414*771fe6b9SJerome Glisse int i; 415*771fe6b9SJerome Glisse 416*771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 417*771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 418*771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 419*771fe6b9SJerome Glisse } 420*771fe6b9SJerome Glisse 421*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_ADDR, 0); 422*771fe6b9SJerome Glisse if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) || 423*771fe6b9SJerome Glisse (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) || 424*771fe6b9SJerome Glisse (rdev->family == CHIP_RS200)) { 425*771fe6b9SJerome Glisse DRM_INFO("Loading R100 Microcode\n"); 426*771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 427*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R100_cp_microcode[i][1]); 428*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R100_cp_microcode[i][0]); 429*771fe6b9SJerome Glisse } 430*771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R200) || 431*771fe6b9SJerome Glisse (rdev->family == CHIP_RV250) || 432*771fe6b9SJerome Glisse (rdev->family == CHIP_RV280) || 433*771fe6b9SJerome Glisse (rdev->family == CHIP_RS300)) { 434*771fe6b9SJerome Glisse DRM_INFO("Loading R200 Microcode\n"); 435*771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 436*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R200_cp_microcode[i][1]); 437*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R200_cp_microcode[i][0]); 438*771fe6b9SJerome Glisse } 439*771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R300) || 440*771fe6b9SJerome Glisse (rdev->family == CHIP_R350) || 441*771fe6b9SJerome Glisse (rdev->family == CHIP_RV350) || 442*771fe6b9SJerome Glisse (rdev->family == CHIP_RV380) || 443*771fe6b9SJerome Glisse (rdev->family == CHIP_RS400) || 444*771fe6b9SJerome Glisse (rdev->family == CHIP_RS480)) { 445*771fe6b9SJerome Glisse DRM_INFO("Loading R300 Microcode\n"); 446*771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 447*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R300_cp_microcode[i][1]); 448*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R300_cp_microcode[i][0]); 449*771fe6b9SJerome Glisse } 450*771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R420) || 451*771fe6b9SJerome Glisse (rdev->family == CHIP_R423) || 452*771fe6b9SJerome Glisse (rdev->family == CHIP_RV410)) { 453*771fe6b9SJerome Glisse DRM_INFO("Loading R400 Microcode\n"); 454*771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 455*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R420_cp_microcode[i][1]); 456*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R420_cp_microcode[i][0]); 457*771fe6b9SJerome Glisse } 458*771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_RS690) || 459*771fe6b9SJerome Glisse (rdev->family == CHIP_RS740)) { 460*771fe6b9SJerome Glisse DRM_INFO("Loading RS690/RS740 Microcode\n"); 461*771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 462*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, RS690_cp_microcode[i][1]); 463*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, RS690_cp_microcode[i][0]); 464*771fe6b9SJerome Glisse } 465*771fe6b9SJerome Glisse } else if (rdev->family == CHIP_RS600) { 466*771fe6b9SJerome Glisse DRM_INFO("Loading RS600 Microcode\n"); 467*771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 468*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, RS600_cp_microcode[i][1]); 469*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, RS600_cp_microcode[i][0]); 470*771fe6b9SJerome Glisse } 471*771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_RV515) || 472*771fe6b9SJerome Glisse (rdev->family == CHIP_R520) || 473*771fe6b9SJerome Glisse (rdev->family == CHIP_RV530) || 474*771fe6b9SJerome Glisse (rdev->family == CHIP_R580) || 475*771fe6b9SJerome Glisse (rdev->family == CHIP_RV560) || 476*771fe6b9SJerome Glisse (rdev->family == CHIP_RV570)) { 477*771fe6b9SJerome Glisse DRM_INFO("Loading R500 Microcode\n"); 478*771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 479*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R520_cp_microcode[i][1]); 480*771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R520_cp_microcode[i][0]); 481*771fe6b9SJerome Glisse } 482*771fe6b9SJerome Glisse } 483*771fe6b9SJerome Glisse } 484*771fe6b9SJerome Glisse 485*771fe6b9SJerome Glisse int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) 486*771fe6b9SJerome Glisse { 487*771fe6b9SJerome Glisse unsigned rb_bufsz; 488*771fe6b9SJerome Glisse unsigned rb_blksz; 489*771fe6b9SJerome Glisse unsigned max_fetch; 490*771fe6b9SJerome Glisse unsigned pre_write_timer; 491*771fe6b9SJerome Glisse unsigned pre_write_limit; 492*771fe6b9SJerome Glisse unsigned indirect2_start; 493*771fe6b9SJerome Glisse unsigned indirect1_start; 494*771fe6b9SJerome Glisse uint32_t tmp; 495*771fe6b9SJerome Glisse int r; 496*771fe6b9SJerome Glisse 497*771fe6b9SJerome Glisse if (r100_debugfs_cp_init(rdev)) { 498*771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for CP !\n"); 499*771fe6b9SJerome Glisse } 500*771fe6b9SJerome Glisse /* Reset CP */ 501*771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_STAT); 502*771fe6b9SJerome Glisse if ((tmp & (1 << 31))) { 503*771fe6b9SJerome Glisse DRM_INFO("radeon: cp busy (0x%08X) resetting\n", tmp); 504*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 505*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 506*771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP); 507*771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_SOFT_RESET); 508*771fe6b9SJerome Glisse mdelay(2); 509*771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 510*771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_SOFT_RESET); 511*771fe6b9SJerome Glisse mdelay(2); 512*771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_STAT); 513*771fe6b9SJerome Glisse if ((tmp & (1 << 31))) { 514*771fe6b9SJerome Glisse DRM_INFO("radeon: cp reset failed (0x%08X)\n", tmp); 515*771fe6b9SJerome Glisse } 516*771fe6b9SJerome Glisse } else { 517*771fe6b9SJerome Glisse DRM_INFO("radeon: cp idle (0x%08X)\n", tmp); 518*771fe6b9SJerome Glisse } 519*771fe6b9SJerome Glisse /* Align ring size */ 520*771fe6b9SJerome Glisse rb_bufsz = drm_order(ring_size / 8); 521*771fe6b9SJerome Glisse ring_size = (1 << (rb_bufsz + 1)) * 4; 522*771fe6b9SJerome Glisse r100_cp_load_microcode(rdev); 523*771fe6b9SJerome Glisse r = radeon_ring_init(rdev, ring_size); 524*771fe6b9SJerome Glisse if (r) { 525*771fe6b9SJerome Glisse return r; 526*771fe6b9SJerome Glisse } 527*771fe6b9SJerome Glisse /* Each time the cp read 1024 bytes (16 dword/quadword) update 528*771fe6b9SJerome Glisse * the rptr copy in system ram */ 529*771fe6b9SJerome Glisse rb_blksz = 9; 530*771fe6b9SJerome Glisse /* cp will read 128bytes at a time (4 dwords) */ 531*771fe6b9SJerome Glisse max_fetch = 1; 532*771fe6b9SJerome Glisse rdev->cp.align_mask = 16 - 1; 533*771fe6b9SJerome Glisse /* Write to CP_RB_WPTR will be delayed for pre_write_timer clocks */ 534*771fe6b9SJerome Glisse pre_write_timer = 64; 535*771fe6b9SJerome Glisse /* Force CP_RB_WPTR write if written more than one time before the 536*771fe6b9SJerome Glisse * delay expire 537*771fe6b9SJerome Glisse */ 538*771fe6b9SJerome Glisse pre_write_limit = 0; 539*771fe6b9SJerome Glisse /* Setup the cp cache like this (cache size is 96 dwords) : 540*771fe6b9SJerome Glisse * RING 0 to 15 541*771fe6b9SJerome Glisse * INDIRECT1 16 to 79 542*771fe6b9SJerome Glisse * INDIRECT2 80 to 95 543*771fe6b9SJerome Glisse * So ring cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) 544*771fe6b9SJerome Glisse * indirect1 cache size is 64dwords (> (2 * max_fetch = 2 * 4dwords)) 545*771fe6b9SJerome Glisse * indirect2 cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) 546*771fe6b9SJerome Glisse * Idea being that most of the gpu cmd will be through indirect1 buffer 547*771fe6b9SJerome Glisse * so it gets the bigger cache. 548*771fe6b9SJerome Glisse */ 549*771fe6b9SJerome Glisse indirect2_start = 80; 550*771fe6b9SJerome Glisse indirect1_start = 16; 551*771fe6b9SJerome Glisse /* cp setup */ 552*771fe6b9SJerome Glisse WREG32(0x718, pre_write_timer | (pre_write_limit << 28)); 553*771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, 554*771fe6b9SJerome Glisse REG_SET(RADEON_RB_BUFSZ, rb_bufsz) | 555*771fe6b9SJerome Glisse REG_SET(RADEON_RB_BLKSZ, rb_blksz) | 556*771fe6b9SJerome Glisse REG_SET(RADEON_MAX_FETCH, max_fetch) | 557*771fe6b9SJerome Glisse RADEON_RB_NO_UPDATE); 558*771fe6b9SJerome Glisse /* Set ring address */ 559*771fe6b9SJerome Glisse DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr); 560*771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr); 561*771fe6b9SJerome Glisse /* Force read & write ptr to 0 */ 562*771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_RB_CNTL); 563*771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); 564*771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_RPTR_WR, 0); 565*771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_WPTR, 0); 566*771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, tmp); 567*771fe6b9SJerome Glisse udelay(10); 568*771fe6b9SJerome Glisse rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); 569*771fe6b9SJerome Glisse rdev->cp.wptr = RREG32(RADEON_CP_RB_WPTR); 570*771fe6b9SJerome Glisse /* Set cp mode to bus mastering & enable cp*/ 571*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 572*771fe6b9SJerome Glisse REG_SET(RADEON_INDIRECT2_START, indirect2_start) | 573*771fe6b9SJerome Glisse REG_SET(RADEON_INDIRECT1_START, indirect1_start)); 574*771fe6b9SJerome Glisse WREG32(0x718, 0); 575*771fe6b9SJerome Glisse WREG32(0x744, 0x00004D4D); 576*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM); 577*771fe6b9SJerome Glisse radeon_ring_start(rdev); 578*771fe6b9SJerome Glisse r = radeon_ring_test(rdev); 579*771fe6b9SJerome Glisse if (r) { 580*771fe6b9SJerome Glisse DRM_ERROR("radeon: cp isn't working (%d).\n", r); 581*771fe6b9SJerome Glisse return r; 582*771fe6b9SJerome Glisse } 583*771fe6b9SJerome Glisse rdev->cp.ready = true; 584*771fe6b9SJerome Glisse return 0; 585*771fe6b9SJerome Glisse } 586*771fe6b9SJerome Glisse 587*771fe6b9SJerome Glisse void r100_cp_fini(struct radeon_device *rdev) 588*771fe6b9SJerome Glisse { 589*771fe6b9SJerome Glisse /* Disable ring */ 590*771fe6b9SJerome Glisse rdev->cp.ready = false; 591*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 592*771fe6b9SJerome Glisse radeon_ring_fini(rdev); 593*771fe6b9SJerome Glisse DRM_INFO("radeon: cp finalized\n"); 594*771fe6b9SJerome Glisse } 595*771fe6b9SJerome Glisse 596*771fe6b9SJerome Glisse void r100_cp_disable(struct radeon_device *rdev) 597*771fe6b9SJerome Glisse { 598*771fe6b9SJerome Glisse /* Disable ring */ 599*771fe6b9SJerome Glisse rdev->cp.ready = false; 600*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 601*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 602*771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 603*771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 604*771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 605*771fe6b9SJerome Glisse } 606*771fe6b9SJerome Glisse } 607*771fe6b9SJerome Glisse 608*771fe6b9SJerome Glisse int r100_cp_reset(struct radeon_device *rdev) 609*771fe6b9SJerome Glisse { 610*771fe6b9SJerome Glisse uint32_t tmp; 611*771fe6b9SJerome Glisse bool reinit_cp; 612*771fe6b9SJerome Glisse int i; 613*771fe6b9SJerome Glisse 614*771fe6b9SJerome Glisse reinit_cp = rdev->cp.ready; 615*771fe6b9SJerome Glisse rdev->cp.ready = false; 616*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 617*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 618*771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP); 619*771fe6b9SJerome Glisse (void)RREG32(RADEON_RBBM_SOFT_RESET); 620*771fe6b9SJerome Glisse udelay(200); 621*771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 622*771fe6b9SJerome Glisse /* Wait to prevent race in RBBM_STATUS */ 623*771fe6b9SJerome Glisse mdelay(1); 624*771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 625*771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 626*771fe6b9SJerome Glisse if (!(tmp & (1 << 16))) { 627*771fe6b9SJerome Glisse DRM_INFO("CP reset succeed (RBBM_STATUS=0x%08X)\n", 628*771fe6b9SJerome Glisse tmp); 629*771fe6b9SJerome Glisse if (reinit_cp) { 630*771fe6b9SJerome Glisse return r100_cp_init(rdev, rdev->cp.ring_size); 631*771fe6b9SJerome Glisse } 632*771fe6b9SJerome Glisse return 0; 633*771fe6b9SJerome Glisse } 634*771fe6b9SJerome Glisse DRM_UDELAY(1); 635*771fe6b9SJerome Glisse } 636*771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 637*771fe6b9SJerome Glisse DRM_ERROR("Failed to reset CP (RBBM_STATUS=0x%08X)!\n", tmp); 638*771fe6b9SJerome Glisse return -1; 639*771fe6b9SJerome Glisse } 640*771fe6b9SJerome Glisse 641*771fe6b9SJerome Glisse 642*771fe6b9SJerome Glisse /* 643*771fe6b9SJerome Glisse * CS functions 644*771fe6b9SJerome Glisse */ 645*771fe6b9SJerome Glisse int r100_cs_parse_packet0(struct radeon_cs_parser *p, 646*771fe6b9SJerome Glisse struct radeon_cs_packet *pkt, 647*771fe6b9SJerome Glisse unsigned *auth, unsigned n, 648*771fe6b9SJerome Glisse radeon_packet0_check_t check) 649*771fe6b9SJerome Glisse { 650*771fe6b9SJerome Glisse unsigned reg; 651*771fe6b9SJerome Glisse unsigned i, j, m; 652*771fe6b9SJerome Glisse unsigned idx; 653*771fe6b9SJerome Glisse int r; 654*771fe6b9SJerome Glisse 655*771fe6b9SJerome Glisse idx = pkt->idx + 1; 656*771fe6b9SJerome Glisse reg = pkt->reg; 657*771fe6b9SJerome Glisse if (pkt->one_reg_wr) { 658*771fe6b9SJerome Glisse if ((reg >> 7) > n) { 659*771fe6b9SJerome Glisse return -EINVAL; 660*771fe6b9SJerome Glisse } 661*771fe6b9SJerome Glisse } else { 662*771fe6b9SJerome Glisse if (((reg + (pkt->count << 2)) >> 7) > n) { 663*771fe6b9SJerome Glisse return -EINVAL; 664*771fe6b9SJerome Glisse } 665*771fe6b9SJerome Glisse } 666*771fe6b9SJerome Glisse for (i = 0; i <= pkt->count; i++, idx++) { 667*771fe6b9SJerome Glisse j = (reg >> 7); 668*771fe6b9SJerome Glisse m = 1 << ((reg >> 2) & 31); 669*771fe6b9SJerome Glisse if (auth[j] & m) { 670*771fe6b9SJerome Glisse r = check(p, pkt, idx, reg); 671*771fe6b9SJerome Glisse if (r) { 672*771fe6b9SJerome Glisse return r; 673*771fe6b9SJerome Glisse } 674*771fe6b9SJerome Glisse } 675*771fe6b9SJerome Glisse if (pkt->one_reg_wr) { 676*771fe6b9SJerome Glisse if (!(auth[j] & m)) { 677*771fe6b9SJerome Glisse break; 678*771fe6b9SJerome Glisse } 679*771fe6b9SJerome Glisse } else { 680*771fe6b9SJerome Glisse reg += 4; 681*771fe6b9SJerome Glisse } 682*771fe6b9SJerome Glisse } 683*771fe6b9SJerome Glisse return 0; 684*771fe6b9SJerome Glisse } 685*771fe6b9SJerome Glisse 686*771fe6b9SJerome Glisse int r100_cs_parse_packet3(struct radeon_cs_parser *p, 687*771fe6b9SJerome Glisse struct radeon_cs_packet *pkt, 688*771fe6b9SJerome Glisse unsigned *auth, unsigned n, 689*771fe6b9SJerome Glisse radeon_packet3_check_t check) 690*771fe6b9SJerome Glisse { 691*771fe6b9SJerome Glisse unsigned i, m; 692*771fe6b9SJerome Glisse 693*771fe6b9SJerome Glisse if ((pkt->opcode >> 5) > n) { 694*771fe6b9SJerome Glisse return -EINVAL; 695*771fe6b9SJerome Glisse } 696*771fe6b9SJerome Glisse i = pkt->opcode >> 5; 697*771fe6b9SJerome Glisse m = 1 << (pkt->opcode & 31); 698*771fe6b9SJerome Glisse if (auth[i] & m) { 699*771fe6b9SJerome Glisse return check(p, pkt); 700*771fe6b9SJerome Glisse } 701*771fe6b9SJerome Glisse return 0; 702*771fe6b9SJerome Glisse } 703*771fe6b9SJerome Glisse 704*771fe6b9SJerome Glisse void r100_cs_dump_packet(struct radeon_cs_parser *p, 705*771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 706*771fe6b9SJerome Glisse { 707*771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 708*771fe6b9SJerome Glisse volatile uint32_t *ib; 709*771fe6b9SJerome Glisse unsigned i; 710*771fe6b9SJerome Glisse unsigned idx; 711*771fe6b9SJerome Glisse 712*771fe6b9SJerome Glisse ib = p->ib->ptr; 713*771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 714*771fe6b9SJerome Glisse idx = pkt->idx; 715*771fe6b9SJerome Glisse for (i = 0; i <= (pkt->count + 1); i++, idx++) { 716*771fe6b9SJerome Glisse DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]); 717*771fe6b9SJerome Glisse } 718*771fe6b9SJerome Glisse } 719*771fe6b9SJerome Glisse 720*771fe6b9SJerome Glisse /** 721*771fe6b9SJerome Glisse * r100_cs_packet_parse() - parse cp packet and point ib index to next packet 722*771fe6b9SJerome Glisse * @parser: parser structure holding parsing context. 723*771fe6b9SJerome Glisse * @pkt: where to store packet informations 724*771fe6b9SJerome Glisse * 725*771fe6b9SJerome Glisse * Assume that chunk_ib_index is properly set. Will return -EINVAL 726*771fe6b9SJerome Glisse * if packet is bigger than remaining ib size. or if packets is unknown. 727*771fe6b9SJerome Glisse **/ 728*771fe6b9SJerome Glisse int r100_cs_packet_parse(struct radeon_cs_parser *p, 729*771fe6b9SJerome Glisse struct radeon_cs_packet *pkt, 730*771fe6b9SJerome Glisse unsigned idx) 731*771fe6b9SJerome Glisse { 732*771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; 733*771fe6b9SJerome Glisse uint32_t header = ib_chunk->kdata[idx]; 734*771fe6b9SJerome Glisse 735*771fe6b9SJerome Glisse if (idx >= ib_chunk->length_dw) { 736*771fe6b9SJerome Glisse DRM_ERROR("Can not parse packet at %d after CS end %d !\n", 737*771fe6b9SJerome Glisse idx, ib_chunk->length_dw); 738*771fe6b9SJerome Glisse return -EINVAL; 739*771fe6b9SJerome Glisse } 740*771fe6b9SJerome Glisse pkt->idx = idx; 741*771fe6b9SJerome Glisse pkt->type = CP_PACKET_GET_TYPE(header); 742*771fe6b9SJerome Glisse pkt->count = CP_PACKET_GET_COUNT(header); 743*771fe6b9SJerome Glisse switch (pkt->type) { 744*771fe6b9SJerome Glisse case PACKET_TYPE0: 745*771fe6b9SJerome Glisse pkt->reg = CP_PACKET0_GET_REG(header); 746*771fe6b9SJerome Glisse pkt->one_reg_wr = CP_PACKET0_GET_ONE_REG_WR(header); 747*771fe6b9SJerome Glisse break; 748*771fe6b9SJerome Glisse case PACKET_TYPE3: 749*771fe6b9SJerome Glisse pkt->opcode = CP_PACKET3_GET_OPCODE(header); 750*771fe6b9SJerome Glisse break; 751*771fe6b9SJerome Glisse case PACKET_TYPE2: 752*771fe6b9SJerome Glisse pkt->count = -1; 753*771fe6b9SJerome Glisse break; 754*771fe6b9SJerome Glisse default: 755*771fe6b9SJerome Glisse DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx); 756*771fe6b9SJerome Glisse return -EINVAL; 757*771fe6b9SJerome Glisse } 758*771fe6b9SJerome Glisse if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) { 759*771fe6b9SJerome Glisse DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n", 760*771fe6b9SJerome Glisse pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw); 761*771fe6b9SJerome Glisse return -EINVAL; 762*771fe6b9SJerome Glisse } 763*771fe6b9SJerome Glisse return 0; 764*771fe6b9SJerome Glisse } 765*771fe6b9SJerome Glisse 766*771fe6b9SJerome Glisse /** 767*771fe6b9SJerome Glisse * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 768*771fe6b9SJerome Glisse * @parser: parser structure holding parsing context. 769*771fe6b9SJerome Glisse * @data: pointer to relocation data 770*771fe6b9SJerome Glisse * @offset_start: starting offset 771*771fe6b9SJerome Glisse * @offset_mask: offset mask (to align start offset on) 772*771fe6b9SJerome Glisse * @reloc: reloc informations 773*771fe6b9SJerome Glisse * 774*771fe6b9SJerome Glisse * Check next packet is relocation packet3, do bo validation and compute 775*771fe6b9SJerome Glisse * GPU offset using the provided start. 776*771fe6b9SJerome Glisse **/ 777*771fe6b9SJerome Glisse int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, 778*771fe6b9SJerome Glisse struct radeon_cs_reloc **cs_reloc) 779*771fe6b9SJerome Glisse { 780*771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 781*771fe6b9SJerome Glisse struct radeon_cs_chunk *relocs_chunk; 782*771fe6b9SJerome Glisse struct radeon_cs_packet p3reloc; 783*771fe6b9SJerome Glisse unsigned idx; 784*771fe6b9SJerome Glisse int r; 785*771fe6b9SJerome Glisse 786*771fe6b9SJerome Glisse if (p->chunk_relocs_idx == -1) { 787*771fe6b9SJerome Glisse DRM_ERROR("No relocation chunk !\n"); 788*771fe6b9SJerome Glisse return -EINVAL; 789*771fe6b9SJerome Glisse } 790*771fe6b9SJerome Glisse *cs_reloc = NULL; 791*771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 792*771fe6b9SJerome Glisse relocs_chunk = &p->chunks[p->chunk_relocs_idx]; 793*771fe6b9SJerome Glisse r = r100_cs_packet_parse(p, &p3reloc, p->idx); 794*771fe6b9SJerome Glisse if (r) { 795*771fe6b9SJerome Glisse return r; 796*771fe6b9SJerome Glisse } 797*771fe6b9SJerome Glisse p->idx += p3reloc.count + 2; 798*771fe6b9SJerome Glisse if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { 799*771fe6b9SJerome Glisse DRM_ERROR("No packet3 for relocation for packet at %d.\n", 800*771fe6b9SJerome Glisse p3reloc.idx); 801*771fe6b9SJerome Glisse r100_cs_dump_packet(p, &p3reloc); 802*771fe6b9SJerome Glisse return -EINVAL; 803*771fe6b9SJerome Glisse } 804*771fe6b9SJerome Glisse idx = ib_chunk->kdata[p3reloc.idx + 1]; 805*771fe6b9SJerome Glisse if (idx >= relocs_chunk->length_dw) { 806*771fe6b9SJerome Glisse DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", 807*771fe6b9SJerome Glisse idx, relocs_chunk->length_dw); 808*771fe6b9SJerome Glisse r100_cs_dump_packet(p, &p3reloc); 809*771fe6b9SJerome Glisse return -EINVAL; 810*771fe6b9SJerome Glisse } 811*771fe6b9SJerome Glisse /* FIXME: we assume reloc size is 4 dwords */ 812*771fe6b9SJerome Glisse *cs_reloc = p->relocs_ptr[(idx / 4)]; 813*771fe6b9SJerome Glisse return 0; 814*771fe6b9SJerome Glisse } 815*771fe6b9SJerome Glisse 816*771fe6b9SJerome Glisse static int r100_packet0_check(struct radeon_cs_parser *p, 817*771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 818*771fe6b9SJerome Glisse { 819*771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 820*771fe6b9SJerome Glisse struct radeon_cs_reloc *reloc; 821*771fe6b9SJerome Glisse volatile uint32_t *ib; 822*771fe6b9SJerome Glisse uint32_t tmp; 823*771fe6b9SJerome Glisse unsigned reg; 824*771fe6b9SJerome Glisse unsigned i; 825*771fe6b9SJerome Glisse unsigned idx; 826*771fe6b9SJerome Glisse bool onereg; 827*771fe6b9SJerome Glisse int r; 828*771fe6b9SJerome Glisse 829*771fe6b9SJerome Glisse ib = p->ib->ptr; 830*771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 831*771fe6b9SJerome Glisse idx = pkt->idx + 1; 832*771fe6b9SJerome Glisse reg = pkt->reg; 833*771fe6b9SJerome Glisse onereg = false; 834*771fe6b9SJerome Glisse if (CP_PACKET0_GET_ONE_REG_WR(ib_chunk->kdata[pkt->idx])) { 835*771fe6b9SJerome Glisse onereg = true; 836*771fe6b9SJerome Glisse } 837*771fe6b9SJerome Glisse for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { 838*771fe6b9SJerome Glisse switch (reg) { 839*771fe6b9SJerome Glisse /* FIXME: only allow PACKET3 blit? easier to check for out of 840*771fe6b9SJerome Glisse * range access */ 841*771fe6b9SJerome Glisse case RADEON_DST_PITCH_OFFSET: 842*771fe6b9SJerome Glisse case RADEON_SRC_PITCH_OFFSET: 843*771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 844*771fe6b9SJerome Glisse if (r) { 845*771fe6b9SJerome Glisse DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 846*771fe6b9SJerome Glisse idx, reg); 847*771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 848*771fe6b9SJerome Glisse return r; 849*771fe6b9SJerome Glisse } 850*771fe6b9SJerome Glisse tmp = ib_chunk->kdata[idx] & 0x003fffff; 851*771fe6b9SJerome Glisse tmp += (((u32)reloc->lobj.gpu_offset) >> 10); 852*771fe6b9SJerome Glisse ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp; 853*771fe6b9SJerome Glisse break; 854*771fe6b9SJerome Glisse case RADEON_RB3D_DEPTHOFFSET: 855*771fe6b9SJerome Glisse case RADEON_RB3D_COLOROFFSET: 856*771fe6b9SJerome Glisse case R300_RB3D_COLOROFFSET0: 857*771fe6b9SJerome Glisse case R300_ZB_DEPTHOFFSET: 858*771fe6b9SJerome Glisse case R200_PP_TXOFFSET_0: 859*771fe6b9SJerome Glisse case R200_PP_TXOFFSET_1: 860*771fe6b9SJerome Glisse case R200_PP_TXOFFSET_2: 861*771fe6b9SJerome Glisse case R200_PP_TXOFFSET_3: 862*771fe6b9SJerome Glisse case R200_PP_TXOFFSET_4: 863*771fe6b9SJerome Glisse case R200_PP_TXOFFSET_5: 864*771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_0: 865*771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_1: 866*771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_2: 867*771fe6b9SJerome Glisse case R300_TX_OFFSET_0: 868*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+4: 869*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+8: 870*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+12: 871*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+16: 872*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+20: 873*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+24: 874*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+28: 875*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+32: 876*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+36: 877*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+40: 878*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+44: 879*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+48: 880*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+52: 881*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+56: 882*771fe6b9SJerome Glisse case R300_TX_OFFSET_0+60: 883*771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 884*771fe6b9SJerome Glisse if (r) { 885*771fe6b9SJerome Glisse DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 886*771fe6b9SJerome Glisse idx, reg); 887*771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 888*771fe6b9SJerome Glisse return r; 889*771fe6b9SJerome Glisse } 890*771fe6b9SJerome Glisse ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); 891*771fe6b9SJerome Glisse break; 892*771fe6b9SJerome Glisse default: 893*771fe6b9SJerome Glisse /* FIXME: we don't want to allow anyothers packet */ 894*771fe6b9SJerome Glisse break; 895*771fe6b9SJerome Glisse } 896*771fe6b9SJerome Glisse if (onereg) { 897*771fe6b9SJerome Glisse /* FIXME: forbid onereg write to register on relocate */ 898*771fe6b9SJerome Glisse break; 899*771fe6b9SJerome Glisse } 900*771fe6b9SJerome Glisse } 901*771fe6b9SJerome Glisse return 0; 902*771fe6b9SJerome Glisse } 903*771fe6b9SJerome Glisse 904*771fe6b9SJerome Glisse static int r100_packet3_check(struct radeon_cs_parser *p, 905*771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 906*771fe6b9SJerome Glisse { 907*771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 908*771fe6b9SJerome Glisse struct radeon_cs_reloc *reloc; 909*771fe6b9SJerome Glisse unsigned idx; 910*771fe6b9SJerome Glisse unsigned i, c; 911*771fe6b9SJerome Glisse volatile uint32_t *ib; 912*771fe6b9SJerome Glisse int r; 913*771fe6b9SJerome Glisse 914*771fe6b9SJerome Glisse ib = p->ib->ptr; 915*771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 916*771fe6b9SJerome Glisse idx = pkt->idx + 1; 917*771fe6b9SJerome Glisse switch (pkt->opcode) { 918*771fe6b9SJerome Glisse case PACKET3_3D_LOAD_VBPNTR: 919*771fe6b9SJerome Glisse c = ib_chunk->kdata[idx++]; 920*771fe6b9SJerome Glisse for (i = 0; i < (c - 1); i += 2, idx += 3) { 921*771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 922*771fe6b9SJerome Glisse if (r) { 923*771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 924*771fe6b9SJerome Glisse pkt->opcode); 925*771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 926*771fe6b9SJerome Glisse return r; 927*771fe6b9SJerome Glisse } 928*771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 929*771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 930*771fe6b9SJerome Glisse if (r) { 931*771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 932*771fe6b9SJerome Glisse pkt->opcode); 933*771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 934*771fe6b9SJerome Glisse return r; 935*771fe6b9SJerome Glisse } 936*771fe6b9SJerome Glisse ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset); 937*771fe6b9SJerome Glisse } 938*771fe6b9SJerome Glisse if (c & 1) { 939*771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 940*771fe6b9SJerome Glisse if (r) { 941*771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 942*771fe6b9SJerome Glisse pkt->opcode); 943*771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 944*771fe6b9SJerome Glisse return r; 945*771fe6b9SJerome Glisse } 946*771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 947*771fe6b9SJerome Glisse } 948*771fe6b9SJerome Glisse break; 949*771fe6b9SJerome Glisse case PACKET3_INDX_BUFFER: 950*771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 951*771fe6b9SJerome Glisse if (r) { 952*771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 953*771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 954*771fe6b9SJerome Glisse return r; 955*771fe6b9SJerome Glisse } 956*771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 957*771fe6b9SJerome Glisse break; 958*771fe6b9SJerome Glisse case 0x23: 959*771fe6b9SJerome Glisse /* FIXME: cleanup */ 960*771fe6b9SJerome Glisse /* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */ 961*771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 962*771fe6b9SJerome Glisse if (r) { 963*771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 964*771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 965*771fe6b9SJerome Glisse return r; 966*771fe6b9SJerome Glisse } 967*771fe6b9SJerome Glisse ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); 968*771fe6b9SJerome Glisse break; 969*771fe6b9SJerome Glisse case PACKET3_3D_DRAW_IMMD: 970*771fe6b9SJerome Glisse /* triggers drawing using in-packet vertex data */ 971*771fe6b9SJerome Glisse case PACKET3_3D_DRAW_IMMD_2: 972*771fe6b9SJerome Glisse /* triggers drawing using in-packet vertex data */ 973*771fe6b9SJerome Glisse case PACKET3_3D_DRAW_VBUF_2: 974*771fe6b9SJerome Glisse /* triggers drawing of vertex buffers setup elsewhere */ 975*771fe6b9SJerome Glisse case PACKET3_3D_DRAW_INDX_2: 976*771fe6b9SJerome Glisse /* triggers drawing using indices to vertex buffer */ 977*771fe6b9SJerome Glisse case PACKET3_3D_DRAW_VBUF: 978*771fe6b9SJerome Glisse /* triggers drawing of vertex buffers setup elsewhere */ 979*771fe6b9SJerome Glisse case PACKET3_3D_DRAW_INDX: 980*771fe6b9SJerome Glisse /* triggers drawing using indices to vertex buffer */ 981*771fe6b9SJerome Glisse case PACKET3_NOP: 982*771fe6b9SJerome Glisse break; 983*771fe6b9SJerome Glisse default: 984*771fe6b9SJerome Glisse DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); 985*771fe6b9SJerome Glisse return -EINVAL; 986*771fe6b9SJerome Glisse } 987*771fe6b9SJerome Glisse return 0; 988*771fe6b9SJerome Glisse } 989*771fe6b9SJerome Glisse 990*771fe6b9SJerome Glisse int r100_cs_parse(struct radeon_cs_parser *p) 991*771fe6b9SJerome Glisse { 992*771fe6b9SJerome Glisse struct radeon_cs_packet pkt; 993*771fe6b9SJerome Glisse int r; 994*771fe6b9SJerome Glisse 995*771fe6b9SJerome Glisse do { 996*771fe6b9SJerome Glisse r = r100_cs_packet_parse(p, &pkt, p->idx); 997*771fe6b9SJerome Glisse if (r) { 998*771fe6b9SJerome Glisse return r; 999*771fe6b9SJerome Glisse } 1000*771fe6b9SJerome Glisse p->idx += pkt.count + 2; 1001*771fe6b9SJerome Glisse switch (pkt.type) { 1002*771fe6b9SJerome Glisse case PACKET_TYPE0: 1003*771fe6b9SJerome Glisse r = r100_packet0_check(p, &pkt); 1004*771fe6b9SJerome Glisse break; 1005*771fe6b9SJerome Glisse case PACKET_TYPE2: 1006*771fe6b9SJerome Glisse break; 1007*771fe6b9SJerome Glisse case PACKET_TYPE3: 1008*771fe6b9SJerome Glisse r = r100_packet3_check(p, &pkt); 1009*771fe6b9SJerome Glisse break; 1010*771fe6b9SJerome Glisse default: 1011*771fe6b9SJerome Glisse DRM_ERROR("Unknown packet type %d !\n", 1012*771fe6b9SJerome Glisse pkt.type); 1013*771fe6b9SJerome Glisse return -EINVAL; 1014*771fe6b9SJerome Glisse } 1015*771fe6b9SJerome Glisse if (r) { 1016*771fe6b9SJerome Glisse return r; 1017*771fe6b9SJerome Glisse } 1018*771fe6b9SJerome Glisse } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); 1019*771fe6b9SJerome Glisse return 0; 1020*771fe6b9SJerome Glisse } 1021*771fe6b9SJerome Glisse 1022*771fe6b9SJerome Glisse 1023*771fe6b9SJerome Glisse /* 1024*771fe6b9SJerome Glisse * Global GPU functions 1025*771fe6b9SJerome Glisse */ 1026*771fe6b9SJerome Glisse void r100_errata(struct radeon_device *rdev) 1027*771fe6b9SJerome Glisse { 1028*771fe6b9SJerome Glisse rdev->pll_errata = 0; 1029*771fe6b9SJerome Glisse 1030*771fe6b9SJerome Glisse if (rdev->family == CHIP_RV200 || rdev->family == CHIP_RS200) { 1031*771fe6b9SJerome Glisse rdev->pll_errata |= CHIP_ERRATA_PLL_DUMMYREADS; 1032*771fe6b9SJerome Glisse } 1033*771fe6b9SJerome Glisse 1034*771fe6b9SJerome Glisse if (rdev->family == CHIP_RV100 || 1035*771fe6b9SJerome Glisse rdev->family == CHIP_RS100 || 1036*771fe6b9SJerome Glisse rdev->family == CHIP_RS200) { 1037*771fe6b9SJerome Glisse rdev->pll_errata |= CHIP_ERRATA_PLL_DELAY; 1038*771fe6b9SJerome Glisse } 1039*771fe6b9SJerome Glisse } 1040*771fe6b9SJerome Glisse 1041*771fe6b9SJerome Glisse /* Wait for vertical sync on primary CRTC */ 1042*771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync(struct radeon_device *rdev) 1043*771fe6b9SJerome Glisse { 1044*771fe6b9SJerome Glisse uint32_t crtc_gen_cntl, tmp; 1045*771fe6b9SJerome Glisse int i; 1046*771fe6b9SJerome Glisse 1047*771fe6b9SJerome Glisse crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); 1048*771fe6b9SJerome Glisse if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || 1049*771fe6b9SJerome Glisse !(crtc_gen_cntl & RADEON_CRTC_EN)) { 1050*771fe6b9SJerome Glisse return; 1051*771fe6b9SJerome Glisse } 1052*771fe6b9SJerome Glisse /* Clear the CRTC_VBLANK_SAVE bit */ 1053*771fe6b9SJerome Glisse WREG32(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); 1054*771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1055*771fe6b9SJerome Glisse tmp = RREG32(RADEON_CRTC_STATUS); 1056*771fe6b9SJerome Glisse if (tmp & RADEON_CRTC_VBLANK_SAVE) { 1057*771fe6b9SJerome Glisse return; 1058*771fe6b9SJerome Glisse } 1059*771fe6b9SJerome Glisse DRM_UDELAY(1); 1060*771fe6b9SJerome Glisse } 1061*771fe6b9SJerome Glisse } 1062*771fe6b9SJerome Glisse 1063*771fe6b9SJerome Glisse /* Wait for vertical sync on secondary CRTC */ 1064*771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync2(struct radeon_device *rdev) 1065*771fe6b9SJerome Glisse { 1066*771fe6b9SJerome Glisse uint32_t crtc2_gen_cntl, tmp; 1067*771fe6b9SJerome Glisse int i; 1068*771fe6b9SJerome Glisse 1069*771fe6b9SJerome Glisse crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 1070*771fe6b9SJerome Glisse if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || 1071*771fe6b9SJerome Glisse !(crtc2_gen_cntl & RADEON_CRTC2_EN)) 1072*771fe6b9SJerome Glisse return; 1073*771fe6b9SJerome Glisse 1074*771fe6b9SJerome Glisse /* Clear the CRTC_VBLANK_SAVE bit */ 1075*771fe6b9SJerome Glisse WREG32(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); 1076*771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1077*771fe6b9SJerome Glisse tmp = RREG32(RADEON_CRTC2_STATUS); 1078*771fe6b9SJerome Glisse if (tmp & RADEON_CRTC2_VBLANK_SAVE) { 1079*771fe6b9SJerome Glisse return; 1080*771fe6b9SJerome Glisse } 1081*771fe6b9SJerome Glisse DRM_UDELAY(1); 1082*771fe6b9SJerome Glisse } 1083*771fe6b9SJerome Glisse } 1084*771fe6b9SJerome Glisse 1085*771fe6b9SJerome Glisse int r100_rbbm_fifo_wait_for_entry(struct radeon_device *rdev, unsigned n) 1086*771fe6b9SJerome Glisse { 1087*771fe6b9SJerome Glisse unsigned i; 1088*771fe6b9SJerome Glisse uint32_t tmp; 1089*771fe6b9SJerome Glisse 1090*771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1091*771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; 1092*771fe6b9SJerome Glisse if (tmp >= n) { 1093*771fe6b9SJerome Glisse return 0; 1094*771fe6b9SJerome Glisse } 1095*771fe6b9SJerome Glisse DRM_UDELAY(1); 1096*771fe6b9SJerome Glisse } 1097*771fe6b9SJerome Glisse return -1; 1098*771fe6b9SJerome Glisse } 1099*771fe6b9SJerome Glisse 1100*771fe6b9SJerome Glisse int r100_gui_wait_for_idle(struct radeon_device *rdev) 1101*771fe6b9SJerome Glisse { 1102*771fe6b9SJerome Glisse unsigned i; 1103*771fe6b9SJerome Glisse uint32_t tmp; 1104*771fe6b9SJerome Glisse 1105*771fe6b9SJerome Glisse if (r100_rbbm_fifo_wait_for_entry(rdev, 64)) { 1106*771fe6b9SJerome Glisse printk(KERN_WARNING "radeon: wait for empty RBBM fifo failed !" 1107*771fe6b9SJerome Glisse " Bad things might happen.\n"); 1108*771fe6b9SJerome Glisse } 1109*771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1110*771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1111*771fe6b9SJerome Glisse if (!(tmp & (1 << 31))) { 1112*771fe6b9SJerome Glisse return 0; 1113*771fe6b9SJerome Glisse } 1114*771fe6b9SJerome Glisse DRM_UDELAY(1); 1115*771fe6b9SJerome Glisse } 1116*771fe6b9SJerome Glisse return -1; 1117*771fe6b9SJerome Glisse } 1118*771fe6b9SJerome Glisse 1119*771fe6b9SJerome Glisse int r100_mc_wait_for_idle(struct radeon_device *rdev) 1120*771fe6b9SJerome Glisse { 1121*771fe6b9SJerome Glisse unsigned i; 1122*771fe6b9SJerome Glisse uint32_t tmp; 1123*771fe6b9SJerome Glisse 1124*771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1125*771fe6b9SJerome Glisse /* read MC_STATUS */ 1126*771fe6b9SJerome Glisse tmp = RREG32(0x0150); 1127*771fe6b9SJerome Glisse if (tmp & (1 << 2)) { 1128*771fe6b9SJerome Glisse return 0; 1129*771fe6b9SJerome Glisse } 1130*771fe6b9SJerome Glisse DRM_UDELAY(1); 1131*771fe6b9SJerome Glisse } 1132*771fe6b9SJerome Glisse return -1; 1133*771fe6b9SJerome Glisse } 1134*771fe6b9SJerome Glisse 1135*771fe6b9SJerome Glisse void r100_gpu_init(struct radeon_device *rdev) 1136*771fe6b9SJerome Glisse { 1137*771fe6b9SJerome Glisse /* TODO: anythings to do here ? pipes ? */ 1138*771fe6b9SJerome Glisse r100_hdp_reset(rdev); 1139*771fe6b9SJerome Glisse } 1140*771fe6b9SJerome Glisse 1141*771fe6b9SJerome Glisse void r100_hdp_reset(struct radeon_device *rdev) 1142*771fe6b9SJerome Glisse { 1143*771fe6b9SJerome Glisse uint32_t tmp; 1144*771fe6b9SJerome Glisse 1145*771fe6b9SJerome Glisse tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; 1146*771fe6b9SJerome Glisse tmp |= (7 << 28); 1147*771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); 1148*771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 1149*771fe6b9SJerome Glisse udelay(200); 1150*771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 1151*771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp); 1152*771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 1153*771fe6b9SJerome Glisse } 1154*771fe6b9SJerome Glisse 1155*771fe6b9SJerome Glisse int r100_rb2d_reset(struct radeon_device *rdev) 1156*771fe6b9SJerome Glisse { 1157*771fe6b9SJerome Glisse uint32_t tmp; 1158*771fe6b9SJerome Glisse int i; 1159*771fe6b9SJerome Glisse 1160*771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_E2); 1161*771fe6b9SJerome Glisse (void)RREG32(RADEON_RBBM_SOFT_RESET); 1162*771fe6b9SJerome Glisse udelay(200); 1163*771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 1164*771fe6b9SJerome Glisse /* Wait to prevent race in RBBM_STATUS */ 1165*771fe6b9SJerome Glisse mdelay(1); 1166*771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1167*771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1168*771fe6b9SJerome Glisse if (!(tmp & (1 << 26))) { 1169*771fe6b9SJerome Glisse DRM_INFO("RB2D reset succeed (RBBM_STATUS=0x%08X)\n", 1170*771fe6b9SJerome Glisse tmp); 1171*771fe6b9SJerome Glisse return 0; 1172*771fe6b9SJerome Glisse } 1173*771fe6b9SJerome Glisse DRM_UDELAY(1); 1174*771fe6b9SJerome Glisse } 1175*771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1176*771fe6b9SJerome Glisse DRM_ERROR("Failed to reset RB2D (RBBM_STATUS=0x%08X)!\n", tmp); 1177*771fe6b9SJerome Glisse return -1; 1178*771fe6b9SJerome Glisse } 1179*771fe6b9SJerome Glisse 1180*771fe6b9SJerome Glisse int r100_gpu_reset(struct radeon_device *rdev) 1181*771fe6b9SJerome Glisse { 1182*771fe6b9SJerome Glisse uint32_t status; 1183*771fe6b9SJerome Glisse 1184*771fe6b9SJerome Glisse /* reset order likely matter */ 1185*771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1186*771fe6b9SJerome Glisse /* reset HDP */ 1187*771fe6b9SJerome Glisse r100_hdp_reset(rdev); 1188*771fe6b9SJerome Glisse /* reset rb2d */ 1189*771fe6b9SJerome Glisse if (status & ((1 << 17) | (1 << 18) | (1 << 27))) { 1190*771fe6b9SJerome Glisse r100_rb2d_reset(rdev); 1191*771fe6b9SJerome Glisse } 1192*771fe6b9SJerome Glisse /* TODO: reset 3D engine */ 1193*771fe6b9SJerome Glisse /* reset CP */ 1194*771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1195*771fe6b9SJerome Glisse if (status & (1 << 16)) { 1196*771fe6b9SJerome Glisse r100_cp_reset(rdev); 1197*771fe6b9SJerome Glisse } 1198*771fe6b9SJerome Glisse /* Check if GPU is idle */ 1199*771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1200*771fe6b9SJerome Glisse if (status & (1 << 31)) { 1201*771fe6b9SJerome Glisse DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); 1202*771fe6b9SJerome Glisse return -1; 1203*771fe6b9SJerome Glisse } 1204*771fe6b9SJerome Glisse DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status); 1205*771fe6b9SJerome Glisse return 0; 1206*771fe6b9SJerome Glisse } 1207*771fe6b9SJerome Glisse 1208*771fe6b9SJerome Glisse 1209*771fe6b9SJerome Glisse /* 1210*771fe6b9SJerome Glisse * VRAM info 1211*771fe6b9SJerome Glisse */ 1212*771fe6b9SJerome Glisse static void r100_vram_get_type(struct radeon_device *rdev) 1213*771fe6b9SJerome Glisse { 1214*771fe6b9SJerome Glisse uint32_t tmp; 1215*771fe6b9SJerome Glisse 1216*771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = false; 1217*771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_IGP) 1218*771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1219*771fe6b9SJerome Glisse else if (RREG32(RADEON_MEM_SDRAM_MODE_REG) & RADEON_MEM_CFG_TYPE_DDR) 1220*771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1221*771fe6b9SJerome Glisse if ((rdev->family == CHIP_RV100) || 1222*771fe6b9SJerome Glisse (rdev->family == CHIP_RS100) || 1223*771fe6b9SJerome Glisse (rdev->family == CHIP_RS200)) { 1224*771fe6b9SJerome Glisse tmp = RREG32(RADEON_MEM_CNTL); 1225*771fe6b9SJerome Glisse if (tmp & RV100_HALF_MODE) { 1226*771fe6b9SJerome Glisse rdev->mc.vram_width = 32; 1227*771fe6b9SJerome Glisse } else { 1228*771fe6b9SJerome Glisse rdev->mc.vram_width = 64; 1229*771fe6b9SJerome Glisse } 1230*771fe6b9SJerome Glisse if (rdev->flags & RADEON_SINGLE_CRTC) { 1231*771fe6b9SJerome Glisse rdev->mc.vram_width /= 4; 1232*771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1233*771fe6b9SJerome Glisse } 1234*771fe6b9SJerome Glisse } else if (rdev->family <= CHIP_RV280) { 1235*771fe6b9SJerome Glisse tmp = RREG32(RADEON_MEM_CNTL); 1236*771fe6b9SJerome Glisse if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) { 1237*771fe6b9SJerome Glisse rdev->mc.vram_width = 128; 1238*771fe6b9SJerome Glisse } else { 1239*771fe6b9SJerome Glisse rdev->mc.vram_width = 64; 1240*771fe6b9SJerome Glisse } 1241*771fe6b9SJerome Glisse } else { 1242*771fe6b9SJerome Glisse /* newer IGPs */ 1243*771fe6b9SJerome Glisse rdev->mc.vram_width = 128; 1244*771fe6b9SJerome Glisse } 1245*771fe6b9SJerome Glisse } 1246*771fe6b9SJerome Glisse 1247*771fe6b9SJerome Glisse void r100_vram_info(struct radeon_device *rdev) 1248*771fe6b9SJerome Glisse { 1249*771fe6b9SJerome Glisse r100_vram_get_type(rdev); 1250*771fe6b9SJerome Glisse 1251*771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_IGP) { 1252*771fe6b9SJerome Glisse uint32_t tom; 1253*771fe6b9SJerome Glisse /* read NB_TOM to get the amount of ram stolen for the GPU */ 1254*771fe6b9SJerome Glisse tom = RREG32(RADEON_NB_TOM); 1255*771fe6b9SJerome Glisse rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); 1256*771fe6b9SJerome Glisse WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); 1257*771fe6b9SJerome Glisse } else { 1258*771fe6b9SJerome Glisse rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); 1259*771fe6b9SJerome Glisse /* Some production boards of m6 will report 0 1260*771fe6b9SJerome Glisse * if it's 8 MB 1261*771fe6b9SJerome Glisse */ 1262*771fe6b9SJerome Glisse if (rdev->mc.vram_size == 0) { 1263*771fe6b9SJerome Glisse rdev->mc.vram_size = 8192 * 1024; 1264*771fe6b9SJerome Glisse WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); 1265*771fe6b9SJerome Glisse } 1266*771fe6b9SJerome Glisse } 1267*771fe6b9SJerome Glisse 1268*771fe6b9SJerome Glisse rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); 1269*771fe6b9SJerome Glisse rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); 1270*771fe6b9SJerome Glisse if (rdev->mc.aper_size > rdev->mc.vram_size) { 1271*771fe6b9SJerome Glisse /* Why does some hw doesn't have CONFIG_MEMSIZE properly 1272*771fe6b9SJerome Glisse * setup ? */ 1273*771fe6b9SJerome Glisse rdev->mc.vram_size = rdev->mc.aper_size; 1274*771fe6b9SJerome Glisse WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); 1275*771fe6b9SJerome Glisse } 1276*771fe6b9SJerome Glisse } 1277*771fe6b9SJerome Glisse 1278*771fe6b9SJerome Glisse 1279*771fe6b9SJerome Glisse /* 1280*771fe6b9SJerome Glisse * Indirect registers accessor 1281*771fe6b9SJerome Glisse */ 1282*771fe6b9SJerome Glisse void r100_pll_errata_after_index(struct radeon_device *rdev) 1283*771fe6b9SJerome Glisse { 1284*771fe6b9SJerome Glisse if (!(rdev->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS)) { 1285*771fe6b9SJerome Glisse return; 1286*771fe6b9SJerome Glisse } 1287*771fe6b9SJerome Glisse (void)RREG32(RADEON_CLOCK_CNTL_DATA); 1288*771fe6b9SJerome Glisse (void)RREG32(RADEON_CRTC_GEN_CNTL); 1289*771fe6b9SJerome Glisse } 1290*771fe6b9SJerome Glisse 1291*771fe6b9SJerome Glisse static void r100_pll_errata_after_data(struct radeon_device *rdev) 1292*771fe6b9SJerome Glisse { 1293*771fe6b9SJerome Glisse /* This workarounds is necessary on RV100, RS100 and RS200 chips 1294*771fe6b9SJerome Glisse * or the chip could hang on a subsequent access 1295*771fe6b9SJerome Glisse */ 1296*771fe6b9SJerome Glisse if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) { 1297*771fe6b9SJerome Glisse udelay(5000); 1298*771fe6b9SJerome Glisse } 1299*771fe6b9SJerome Glisse 1300*771fe6b9SJerome Glisse /* This function is required to workaround a hardware bug in some (all?) 1301*771fe6b9SJerome Glisse * revisions of the R300. This workaround should be called after every 1302*771fe6b9SJerome Glisse * CLOCK_CNTL_INDEX register access. If not, register reads afterward 1303*771fe6b9SJerome Glisse * may not be correct. 1304*771fe6b9SJerome Glisse */ 1305*771fe6b9SJerome Glisse if (rdev->pll_errata & CHIP_ERRATA_R300_CG) { 1306*771fe6b9SJerome Glisse uint32_t save, tmp; 1307*771fe6b9SJerome Glisse 1308*771fe6b9SJerome Glisse save = RREG32(RADEON_CLOCK_CNTL_INDEX); 1309*771fe6b9SJerome Glisse tmp = save & ~(0x3f | RADEON_PLL_WR_EN); 1310*771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_INDEX, tmp); 1311*771fe6b9SJerome Glisse tmp = RREG32(RADEON_CLOCK_CNTL_DATA); 1312*771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_INDEX, save); 1313*771fe6b9SJerome Glisse } 1314*771fe6b9SJerome Glisse } 1315*771fe6b9SJerome Glisse 1316*771fe6b9SJerome Glisse uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg) 1317*771fe6b9SJerome Glisse { 1318*771fe6b9SJerome Glisse uint32_t data; 1319*771fe6b9SJerome Glisse 1320*771fe6b9SJerome Glisse WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f); 1321*771fe6b9SJerome Glisse r100_pll_errata_after_index(rdev); 1322*771fe6b9SJerome Glisse data = RREG32(RADEON_CLOCK_CNTL_DATA); 1323*771fe6b9SJerome Glisse r100_pll_errata_after_data(rdev); 1324*771fe6b9SJerome Glisse return data; 1325*771fe6b9SJerome Glisse } 1326*771fe6b9SJerome Glisse 1327*771fe6b9SJerome Glisse void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 1328*771fe6b9SJerome Glisse { 1329*771fe6b9SJerome Glisse WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN)); 1330*771fe6b9SJerome Glisse r100_pll_errata_after_index(rdev); 1331*771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_DATA, v); 1332*771fe6b9SJerome Glisse r100_pll_errata_after_data(rdev); 1333*771fe6b9SJerome Glisse } 1334*771fe6b9SJerome Glisse 1335*771fe6b9SJerome Glisse uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) 1336*771fe6b9SJerome Glisse { 1337*771fe6b9SJerome Glisse if (reg < 0x10000) 1338*771fe6b9SJerome Glisse return readl(((void __iomem *)rdev->rmmio) + reg); 1339*771fe6b9SJerome Glisse else { 1340*771fe6b9SJerome Glisse writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); 1341*771fe6b9SJerome Glisse return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); 1342*771fe6b9SJerome Glisse } 1343*771fe6b9SJerome Glisse } 1344*771fe6b9SJerome Glisse 1345*771fe6b9SJerome Glisse void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 1346*771fe6b9SJerome Glisse { 1347*771fe6b9SJerome Glisse if (reg < 0x10000) 1348*771fe6b9SJerome Glisse writel(v, ((void __iomem *)rdev->rmmio) + reg); 1349*771fe6b9SJerome Glisse else { 1350*771fe6b9SJerome Glisse writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); 1351*771fe6b9SJerome Glisse writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); 1352*771fe6b9SJerome Glisse } 1353*771fe6b9SJerome Glisse } 1354*771fe6b9SJerome Glisse 1355*771fe6b9SJerome Glisse /* 1356*771fe6b9SJerome Glisse * Debugfs info 1357*771fe6b9SJerome Glisse */ 1358*771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1359*771fe6b9SJerome Glisse static int r100_debugfs_rbbm_info(struct seq_file *m, void *data) 1360*771fe6b9SJerome Glisse { 1361*771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1362*771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1363*771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1364*771fe6b9SJerome Glisse uint32_t reg, value; 1365*771fe6b9SJerome Glisse unsigned i; 1366*771fe6b9SJerome Glisse 1367*771fe6b9SJerome Glisse seq_printf(m, "RBBM_STATUS 0x%08x\n", RREG32(RADEON_RBBM_STATUS)); 1368*771fe6b9SJerome Glisse seq_printf(m, "RBBM_CMDFIFO_STAT 0x%08x\n", RREG32(0xE7C)); 1369*771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1370*771fe6b9SJerome Glisse for (i = 0; i < 64; i++) { 1371*771fe6b9SJerome Glisse WREG32(RADEON_RBBM_CMDFIFO_ADDR, i | 0x100); 1372*771fe6b9SJerome Glisse reg = (RREG32(RADEON_RBBM_CMDFIFO_DATA) - 1) >> 2; 1373*771fe6b9SJerome Glisse WREG32(RADEON_RBBM_CMDFIFO_ADDR, i); 1374*771fe6b9SJerome Glisse value = RREG32(RADEON_RBBM_CMDFIFO_DATA); 1375*771fe6b9SJerome Glisse seq_printf(m, "[0x%03X] 0x%04X=0x%08X\n", i, reg, value); 1376*771fe6b9SJerome Glisse } 1377*771fe6b9SJerome Glisse return 0; 1378*771fe6b9SJerome Glisse } 1379*771fe6b9SJerome Glisse 1380*771fe6b9SJerome Glisse static int r100_debugfs_cp_ring_info(struct seq_file *m, void *data) 1381*771fe6b9SJerome Glisse { 1382*771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1383*771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1384*771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1385*771fe6b9SJerome Glisse uint32_t rdp, wdp; 1386*771fe6b9SJerome Glisse unsigned count, i, j; 1387*771fe6b9SJerome Glisse 1388*771fe6b9SJerome Glisse radeon_ring_free_size(rdev); 1389*771fe6b9SJerome Glisse rdp = RREG32(RADEON_CP_RB_RPTR); 1390*771fe6b9SJerome Glisse wdp = RREG32(RADEON_CP_RB_WPTR); 1391*771fe6b9SJerome Glisse count = (rdp + rdev->cp.ring_size - wdp) & rdev->cp.ptr_mask; 1392*771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1393*771fe6b9SJerome Glisse seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp); 1394*771fe6b9SJerome Glisse seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp); 1395*771fe6b9SJerome Glisse seq_printf(m, "%u free dwords in ring\n", rdev->cp.ring_free_dw); 1396*771fe6b9SJerome Glisse seq_printf(m, "%u dwords in ring\n", count); 1397*771fe6b9SJerome Glisse for (j = 0; j <= count; j++) { 1398*771fe6b9SJerome Glisse i = (rdp + j) & rdev->cp.ptr_mask; 1399*771fe6b9SJerome Glisse seq_printf(m, "r[%04d]=0x%08x\n", i, rdev->cp.ring[i]); 1400*771fe6b9SJerome Glisse } 1401*771fe6b9SJerome Glisse return 0; 1402*771fe6b9SJerome Glisse } 1403*771fe6b9SJerome Glisse 1404*771fe6b9SJerome Glisse 1405*771fe6b9SJerome Glisse static int r100_debugfs_cp_csq_fifo(struct seq_file *m, void *data) 1406*771fe6b9SJerome Glisse { 1407*771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1408*771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1409*771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1410*771fe6b9SJerome Glisse uint32_t csq_stat, csq2_stat, tmp; 1411*771fe6b9SJerome Glisse unsigned r_rptr, r_wptr, ib1_rptr, ib1_wptr, ib2_rptr, ib2_wptr; 1412*771fe6b9SJerome Glisse unsigned i; 1413*771fe6b9SJerome Glisse 1414*771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1415*771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ_MODE 0x%08x\n", RREG32(RADEON_CP_CSQ_MODE)); 1416*771fe6b9SJerome Glisse csq_stat = RREG32(RADEON_CP_CSQ_STAT); 1417*771fe6b9SJerome Glisse csq2_stat = RREG32(RADEON_CP_CSQ2_STAT); 1418*771fe6b9SJerome Glisse r_rptr = (csq_stat >> 0) & 0x3ff; 1419*771fe6b9SJerome Glisse r_wptr = (csq_stat >> 10) & 0x3ff; 1420*771fe6b9SJerome Glisse ib1_rptr = (csq_stat >> 20) & 0x3ff; 1421*771fe6b9SJerome Glisse ib1_wptr = (csq2_stat >> 0) & 0x3ff; 1422*771fe6b9SJerome Glisse ib2_rptr = (csq2_stat >> 10) & 0x3ff; 1423*771fe6b9SJerome Glisse ib2_wptr = (csq2_stat >> 20) & 0x3ff; 1424*771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ_STAT 0x%08x\n", csq_stat); 1425*771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ2_STAT 0x%08x\n", csq2_stat); 1426*771fe6b9SJerome Glisse seq_printf(m, "Ring rptr %u\n", r_rptr); 1427*771fe6b9SJerome Glisse seq_printf(m, "Ring wptr %u\n", r_wptr); 1428*771fe6b9SJerome Glisse seq_printf(m, "Indirect1 rptr %u\n", ib1_rptr); 1429*771fe6b9SJerome Glisse seq_printf(m, "Indirect1 wptr %u\n", ib1_wptr); 1430*771fe6b9SJerome Glisse seq_printf(m, "Indirect2 rptr %u\n", ib2_rptr); 1431*771fe6b9SJerome Glisse seq_printf(m, "Indirect2 wptr %u\n", ib2_wptr); 1432*771fe6b9SJerome Glisse /* FIXME: 0, 128, 640 depends on fifo setup see cp_init_kms 1433*771fe6b9SJerome Glisse * 128 = indirect1_start * 8 & 640 = indirect2_start * 8 */ 1434*771fe6b9SJerome Glisse seq_printf(m, "Ring fifo:\n"); 1435*771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 1436*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1437*771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1438*771fe6b9SJerome Glisse seq_printf(m, "rfifo[%04d]=0x%08X\n", i, tmp); 1439*771fe6b9SJerome Glisse } 1440*771fe6b9SJerome Glisse seq_printf(m, "Indirect1 fifo:\n"); 1441*771fe6b9SJerome Glisse for (i = 256; i <= 512; i++) { 1442*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1443*771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1444*771fe6b9SJerome Glisse seq_printf(m, "ib1fifo[%04d]=0x%08X\n", i, tmp); 1445*771fe6b9SJerome Glisse } 1446*771fe6b9SJerome Glisse seq_printf(m, "Indirect2 fifo:\n"); 1447*771fe6b9SJerome Glisse for (i = 640; i < ib1_wptr; i++) { 1448*771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1449*771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1450*771fe6b9SJerome Glisse seq_printf(m, "ib2fifo[%04d]=0x%08X\n", i, tmp); 1451*771fe6b9SJerome Glisse } 1452*771fe6b9SJerome Glisse return 0; 1453*771fe6b9SJerome Glisse } 1454*771fe6b9SJerome Glisse 1455*771fe6b9SJerome Glisse static int r100_debugfs_mc_info(struct seq_file *m, void *data) 1456*771fe6b9SJerome Glisse { 1457*771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1458*771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1459*771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1460*771fe6b9SJerome Glisse uint32_t tmp; 1461*771fe6b9SJerome Glisse 1462*771fe6b9SJerome Glisse tmp = RREG32(RADEON_CONFIG_MEMSIZE); 1463*771fe6b9SJerome Glisse seq_printf(m, "CONFIG_MEMSIZE 0x%08x\n", tmp); 1464*771fe6b9SJerome Glisse tmp = RREG32(RADEON_MC_FB_LOCATION); 1465*771fe6b9SJerome Glisse seq_printf(m, "MC_FB_LOCATION 0x%08x\n", tmp); 1466*771fe6b9SJerome Glisse tmp = RREG32(RADEON_BUS_CNTL); 1467*771fe6b9SJerome Glisse seq_printf(m, "BUS_CNTL 0x%08x\n", tmp); 1468*771fe6b9SJerome Glisse tmp = RREG32(RADEON_MC_AGP_LOCATION); 1469*771fe6b9SJerome Glisse seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp); 1470*771fe6b9SJerome Glisse tmp = RREG32(RADEON_AGP_BASE); 1471*771fe6b9SJerome Glisse seq_printf(m, "AGP_BASE 0x%08x\n", tmp); 1472*771fe6b9SJerome Glisse tmp = RREG32(RADEON_HOST_PATH_CNTL); 1473*771fe6b9SJerome Glisse seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp); 1474*771fe6b9SJerome Glisse tmp = RREG32(0x01D0); 1475*771fe6b9SJerome Glisse seq_printf(m, "AIC_CTRL 0x%08x\n", tmp); 1476*771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_LO_ADDR); 1477*771fe6b9SJerome Glisse seq_printf(m, "AIC_LO_ADDR 0x%08x\n", tmp); 1478*771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_HI_ADDR); 1479*771fe6b9SJerome Glisse seq_printf(m, "AIC_HI_ADDR 0x%08x\n", tmp); 1480*771fe6b9SJerome Glisse tmp = RREG32(0x01E4); 1481*771fe6b9SJerome Glisse seq_printf(m, "AIC_TLB_ADDR 0x%08x\n", tmp); 1482*771fe6b9SJerome Glisse return 0; 1483*771fe6b9SJerome Glisse } 1484*771fe6b9SJerome Glisse 1485*771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_rbbm_list[] = { 1486*771fe6b9SJerome Glisse {"r100_rbbm_info", r100_debugfs_rbbm_info, 0, NULL}, 1487*771fe6b9SJerome Glisse }; 1488*771fe6b9SJerome Glisse 1489*771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_cp_list[] = { 1490*771fe6b9SJerome Glisse {"r100_cp_ring_info", r100_debugfs_cp_ring_info, 0, NULL}, 1491*771fe6b9SJerome Glisse {"r100_cp_csq_fifo", r100_debugfs_cp_csq_fifo, 0, NULL}, 1492*771fe6b9SJerome Glisse }; 1493*771fe6b9SJerome Glisse 1494*771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_mc_info_list[] = { 1495*771fe6b9SJerome Glisse {"r100_mc_info", r100_debugfs_mc_info, 0, NULL}, 1496*771fe6b9SJerome Glisse }; 1497*771fe6b9SJerome Glisse #endif 1498*771fe6b9SJerome Glisse 1499*771fe6b9SJerome Glisse int r100_debugfs_rbbm_init(struct radeon_device *rdev) 1500*771fe6b9SJerome Glisse { 1501*771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1502*771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_rbbm_list, 1); 1503*771fe6b9SJerome Glisse #else 1504*771fe6b9SJerome Glisse return 0; 1505*771fe6b9SJerome Glisse #endif 1506*771fe6b9SJerome Glisse } 1507*771fe6b9SJerome Glisse 1508*771fe6b9SJerome Glisse int r100_debugfs_cp_init(struct radeon_device *rdev) 1509*771fe6b9SJerome Glisse { 1510*771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1511*771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_cp_list, 2); 1512*771fe6b9SJerome Glisse #else 1513*771fe6b9SJerome Glisse return 0; 1514*771fe6b9SJerome Glisse #endif 1515*771fe6b9SJerome Glisse } 1516*771fe6b9SJerome Glisse 1517*771fe6b9SJerome Glisse int r100_debugfs_mc_info_init(struct radeon_device *rdev) 1518*771fe6b9SJerome Glisse { 1519*771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1520*771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_mc_info_list, 1); 1521*771fe6b9SJerome Glisse #else 1522*771fe6b9SJerome Glisse return 0; 1523*771fe6b9SJerome Glisse #endif 1524*771fe6b9SJerome Glisse } 1525