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 */ 1767a50f01aSDave Airlie WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 1777a50f01aSDave Airlie /* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM, 1787a50f01aSDave Airlie * if the aperture is 64MB but we have 32MB VRAM 1797a50f01aSDave Airlie * we report only 32MB VRAM but we have to set MC_FB_LOCATION 1807a50f01aSDave Airlie * to 64MB, otherwise the gpu accidentially dies */ 1817a50f01aSDave 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 /* 257*7ed220d7SMichel Dänzer * Interrupts 258*7ed220d7SMichel Dänzer */ 259*7ed220d7SMichel Dänzer int r100_irq_set(struct radeon_device *rdev) 260*7ed220d7SMichel Dänzer { 261*7ed220d7SMichel Dänzer uint32_t tmp = 0; 262*7ed220d7SMichel Dänzer 263*7ed220d7SMichel Dänzer if (rdev->irq.sw_int) { 264*7ed220d7SMichel Dänzer tmp |= RADEON_SW_INT_ENABLE; 265*7ed220d7SMichel Dänzer } 266*7ed220d7SMichel Dänzer if (rdev->irq.crtc_vblank_int[0]) { 267*7ed220d7SMichel Dänzer tmp |= RADEON_CRTC_VBLANK_MASK; 268*7ed220d7SMichel Dänzer } 269*7ed220d7SMichel Dänzer if (rdev->irq.crtc_vblank_int[1]) { 270*7ed220d7SMichel Dänzer tmp |= RADEON_CRTC2_VBLANK_MASK; 271*7ed220d7SMichel Dänzer } 272*7ed220d7SMichel Dänzer WREG32(RADEON_GEN_INT_CNTL, tmp); 273*7ed220d7SMichel Dänzer return 0; 274*7ed220d7SMichel Dänzer } 275*7ed220d7SMichel Dänzer 276*7ed220d7SMichel Dänzer static inline uint32_t r100_irq_ack(struct radeon_device *rdev) 277*7ed220d7SMichel Dänzer { 278*7ed220d7SMichel Dänzer uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); 279*7ed220d7SMichel Dänzer uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | 280*7ed220d7SMichel Dänzer RADEON_CRTC2_VBLANK_STAT; 281*7ed220d7SMichel Dänzer 282*7ed220d7SMichel Dänzer if (irqs) { 283*7ed220d7SMichel Dänzer WREG32(RADEON_GEN_INT_STATUS, irqs); 284*7ed220d7SMichel Dänzer } 285*7ed220d7SMichel Dänzer return irqs & irq_mask; 286*7ed220d7SMichel Dänzer } 287*7ed220d7SMichel Dänzer 288*7ed220d7SMichel Dänzer int r100_irq_process(struct radeon_device *rdev) 289*7ed220d7SMichel Dänzer { 290*7ed220d7SMichel Dänzer uint32_t status; 291*7ed220d7SMichel Dänzer 292*7ed220d7SMichel Dänzer status = r100_irq_ack(rdev); 293*7ed220d7SMichel Dänzer if (!status) { 294*7ed220d7SMichel Dänzer return IRQ_NONE; 295*7ed220d7SMichel Dänzer } 296*7ed220d7SMichel Dänzer while (status) { 297*7ed220d7SMichel Dänzer /* SW interrupt */ 298*7ed220d7SMichel Dänzer if (status & RADEON_SW_INT_TEST) { 299*7ed220d7SMichel Dänzer radeon_fence_process(rdev); 300*7ed220d7SMichel Dänzer } 301*7ed220d7SMichel Dänzer /* Vertical blank interrupts */ 302*7ed220d7SMichel Dänzer if (status & RADEON_CRTC_VBLANK_STAT) { 303*7ed220d7SMichel Dänzer drm_handle_vblank(rdev->ddev, 0); 304*7ed220d7SMichel Dänzer } 305*7ed220d7SMichel Dänzer if (status & RADEON_CRTC2_VBLANK_STAT) { 306*7ed220d7SMichel Dänzer drm_handle_vblank(rdev->ddev, 1); 307*7ed220d7SMichel Dänzer } 308*7ed220d7SMichel Dänzer status = r100_irq_ack(rdev); 309*7ed220d7SMichel Dänzer } 310*7ed220d7SMichel Dänzer return IRQ_HANDLED; 311*7ed220d7SMichel Dänzer } 312*7ed220d7SMichel Dänzer 313*7ed220d7SMichel Dänzer u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc) 314*7ed220d7SMichel Dänzer { 315*7ed220d7SMichel Dänzer if (crtc == 0) 316*7ed220d7SMichel Dänzer return RREG32(RADEON_CRTC_CRNT_FRAME); 317*7ed220d7SMichel Dänzer else 318*7ed220d7SMichel Dänzer return RREG32(RADEON_CRTC2_CRNT_FRAME); 319*7ed220d7SMichel Dänzer } 320*7ed220d7SMichel Dänzer 321*7ed220d7SMichel Dänzer 322*7ed220d7SMichel Dänzer /* 323771fe6b9SJerome Glisse * Fence emission 324771fe6b9SJerome Glisse */ 325771fe6b9SJerome Glisse void r100_fence_ring_emit(struct radeon_device *rdev, 326771fe6b9SJerome Glisse struct radeon_fence *fence) 327771fe6b9SJerome Glisse { 328771fe6b9SJerome Glisse /* Who ever call radeon_fence_emit should call ring_lock and ask 329771fe6b9SJerome Glisse * for enough space (today caller are ib schedule and buffer move) */ 330771fe6b9SJerome Glisse /* Wait until IDLE & CLEAN */ 331771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(0x1720, 0)); 332771fe6b9SJerome Glisse radeon_ring_write(rdev, (1 << 16) | (1 << 17)); 333771fe6b9SJerome Glisse /* Emit fence sequence & fire IRQ */ 334771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0)); 335771fe6b9SJerome Glisse radeon_ring_write(rdev, fence->seq); 336771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_GEN_INT_STATUS, 0)); 337771fe6b9SJerome Glisse radeon_ring_write(rdev, RADEON_SW_INT_FIRE); 338771fe6b9SJerome Glisse } 339771fe6b9SJerome Glisse 340771fe6b9SJerome Glisse 341771fe6b9SJerome Glisse /* 342771fe6b9SJerome Glisse * Writeback 343771fe6b9SJerome Glisse */ 344771fe6b9SJerome Glisse int r100_wb_init(struct radeon_device *rdev) 345771fe6b9SJerome Glisse { 346771fe6b9SJerome Glisse int r; 347771fe6b9SJerome Glisse 348771fe6b9SJerome Glisse if (rdev->wb.wb_obj == NULL) { 349771fe6b9SJerome Glisse r = radeon_object_create(rdev, NULL, 4096, 350771fe6b9SJerome Glisse true, 351771fe6b9SJerome Glisse RADEON_GEM_DOMAIN_GTT, 352771fe6b9SJerome Glisse false, &rdev->wb.wb_obj); 353771fe6b9SJerome Glisse if (r) { 354771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to create WB buffer (%d).\n", r); 355771fe6b9SJerome Glisse return r; 356771fe6b9SJerome Glisse } 357771fe6b9SJerome Glisse r = radeon_object_pin(rdev->wb.wb_obj, 358771fe6b9SJerome Glisse RADEON_GEM_DOMAIN_GTT, 359771fe6b9SJerome Glisse &rdev->wb.gpu_addr); 360771fe6b9SJerome Glisse if (r) { 361771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to pin WB buffer (%d).\n", r); 362771fe6b9SJerome Glisse return r; 363771fe6b9SJerome Glisse } 364771fe6b9SJerome Glisse r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); 365771fe6b9SJerome Glisse if (r) { 366771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to map WB buffer (%d).\n", r); 367771fe6b9SJerome Glisse return r; 368771fe6b9SJerome Glisse } 369771fe6b9SJerome Glisse } 370771fe6b9SJerome Glisse WREG32(0x774, rdev->wb.gpu_addr); 371771fe6b9SJerome Glisse WREG32(0x70C, rdev->wb.gpu_addr + 1024); 372771fe6b9SJerome Glisse WREG32(0x770, 0xff); 373771fe6b9SJerome Glisse return 0; 374771fe6b9SJerome Glisse } 375771fe6b9SJerome Glisse 376771fe6b9SJerome Glisse void r100_wb_fini(struct radeon_device *rdev) 377771fe6b9SJerome Glisse { 378771fe6b9SJerome Glisse if (rdev->wb.wb_obj) { 379771fe6b9SJerome Glisse radeon_object_kunmap(rdev->wb.wb_obj); 380771fe6b9SJerome Glisse radeon_object_unpin(rdev->wb.wb_obj); 381771fe6b9SJerome Glisse radeon_object_unref(&rdev->wb.wb_obj); 382771fe6b9SJerome Glisse rdev->wb.wb = NULL; 383771fe6b9SJerome Glisse rdev->wb.wb_obj = NULL; 384771fe6b9SJerome Glisse } 385771fe6b9SJerome Glisse } 386771fe6b9SJerome Glisse 387771fe6b9SJerome Glisse int r100_copy_blit(struct radeon_device *rdev, 388771fe6b9SJerome Glisse uint64_t src_offset, 389771fe6b9SJerome Glisse uint64_t dst_offset, 390771fe6b9SJerome Glisse unsigned num_pages, 391771fe6b9SJerome Glisse struct radeon_fence *fence) 392771fe6b9SJerome Glisse { 393771fe6b9SJerome Glisse uint32_t cur_pages; 394771fe6b9SJerome Glisse uint32_t stride_bytes = PAGE_SIZE; 395771fe6b9SJerome Glisse uint32_t pitch; 396771fe6b9SJerome Glisse uint32_t stride_pixels; 397771fe6b9SJerome Glisse unsigned ndw; 398771fe6b9SJerome Glisse int num_loops; 399771fe6b9SJerome Glisse int r = 0; 400771fe6b9SJerome Glisse 401771fe6b9SJerome Glisse /* radeon limited to 16k stride */ 402771fe6b9SJerome Glisse stride_bytes &= 0x3fff; 403771fe6b9SJerome Glisse /* radeon pitch is /64 */ 404771fe6b9SJerome Glisse pitch = stride_bytes / 64; 405771fe6b9SJerome Glisse stride_pixels = stride_bytes / 4; 406771fe6b9SJerome Glisse num_loops = DIV_ROUND_UP(num_pages, 8191); 407771fe6b9SJerome Glisse 408771fe6b9SJerome Glisse /* Ask for enough room for blit + flush + fence */ 409771fe6b9SJerome Glisse ndw = 64 + (10 * num_loops); 410771fe6b9SJerome Glisse r = radeon_ring_lock(rdev, ndw); 411771fe6b9SJerome Glisse if (r) { 412771fe6b9SJerome Glisse DRM_ERROR("radeon: moving bo (%d) asking for %u dw.\n", r, ndw); 413771fe6b9SJerome Glisse return -EINVAL; 414771fe6b9SJerome Glisse } 415771fe6b9SJerome Glisse while (num_pages > 0) { 416771fe6b9SJerome Glisse cur_pages = num_pages; 417771fe6b9SJerome Glisse if (cur_pages > 8191) { 418771fe6b9SJerome Glisse cur_pages = 8191; 419771fe6b9SJerome Glisse } 420771fe6b9SJerome Glisse num_pages -= cur_pages; 421771fe6b9SJerome Glisse 422771fe6b9SJerome Glisse /* pages are in Y direction - height 423771fe6b9SJerome Glisse page width in X direction - width */ 424771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET3(PACKET3_BITBLT_MULTI, 8)); 425771fe6b9SJerome Glisse radeon_ring_write(rdev, 426771fe6b9SJerome Glisse RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 427771fe6b9SJerome Glisse RADEON_GMC_DST_PITCH_OFFSET_CNTL | 428771fe6b9SJerome Glisse RADEON_GMC_SRC_CLIPPING | 429771fe6b9SJerome Glisse RADEON_GMC_DST_CLIPPING | 430771fe6b9SJerome Glisse RADEON_GMC_BRUSH_NONE | 431771fe6b9SJerome Glisse (RADEON_COLOR_FORMAT_ARGB8888 << 8) | 432771fe6b9SJerome Glisse RADEON_GMC_SRC_DATATYPE_COLOR | 433771fe6b9SJerome Glisse RADEON_ROP3_S | 434771fe6b9SJerome Glisse RADEON_DP_SRC_SOURCE_MEMORY | 435771fe6b9SJerome Glisse RADEON_GMC_CLR_CMP_CNTL_DIS | 436771fe6b9SJerome Glisse RADEON_GMC_WR_MSK_DIS); 437771fe6b9SJerome Glisse radeon_ring_write(rdev, (pitch << 22) | (src_offset >> 10)); 438771fe6b9SJerome Glisse radeon_ring_write(rdev, (pitch << 22) | (dst_offset >> 10)); 439771fe6b9SJerome Glisse radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); 440771fe6b9SJerome Glisse radeon_ring_write(rdev, 0); 441771fe6b9SJerome Glisse radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); 442771fe6b9SJerome Glisse radeon_ring_write(rdev, num_pages); 443771fe6b9SJerome Glisse radeon_ring_write(rdev, num_pages); 444771fe6b9SJerome Glisse radeon_ring_write(rdev, cur_pages | (stride_pixels << 16)); 445771fe6b9SJerome Glisse } 446771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0)); 447771fe6b9SJerome Glisse radeon_ring_write(rdev, RADEON_RB2D_DC_FLUSH_ALL); 448771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); 449771fe6b9SJerome Glisse radeon_ring_write(rdev, 450771fe6b9SJerome Glisse RADEON_WAIT_2D_IDLECLEAN | 451771fe6b9SJerome Glisse RADEON_WAIT_HOST_IDLECLEAN | 452771fe6b9SJerome Glisse RADEON_WAIT_DMA_GUI_IDLE); 453771fe6b9SJerome Glisse if (fence) { 454771fe6b9SJerome Glisse r = radeon_fence_emit(rdev, fence); 455771fe6b9SJerome Glisse } 456771fe6b9SJerome Glisse radeon_ring_unlock_commit(rdev); 457771fe6b9SJerome Glisse return r; 458771fe6b9SJerome Glisse } 459771fe6b9SJerome Glisse 460771fe6b9SJerome Glisse 461771fe6b9SJerome Glisse /* 462771fe6b9SJerome Glisse * CP 463771fe6b9SJerome Glisse */ 464771fe6b9SJerome Glisse void r100_ring_start(struct radeon_device *rdev) 465771fe6b9SJerome Glisse { 466771fe6b9SJerome Glisse int r; 467771fe6b9SJerome Glisse 468771fe6b9SJerome Glisse r = radeon_ring_lock(rdev, 2); 469771fe6b9SJerome Glisse if (r) { 470771fe6b9SJerome Glisse return; 471771fe6b9SJerome Glisse } 472771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0)); 473771fe6b9SJerome Glisse radeon_ring_write(rdev, 474771fe6b9SJerome Glisse RADEON_ISYNC_ANY2D_IDLE3D | 475771fe6b9SJerome Glisse RADEON_ISYNC_ANY3D_IDLE2D | 476771fe6b9SJerome Glisse RADEON_ISYNC_WAIT_IDLEGUI | 477771fe6b9SJerome Glisse RADEON_ISYNC_CPSCRATCH_IDLEGUI); 478771fe6b9SJerome Glisse radeon_ring_unlock_commit(rdev); 479771fe6b9SJerome Glisse } 480771fe6b9SJerome Glisse 481771fe6b9SJerome Glisse static void r100_cp_load_microcode(struct radeon_device *rdev) 482771fe6b9SJerome Glisse { 483771fe6b9SJerome Glisse int i; 484771fe6b9SJerome Glisse 485771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 486771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 487771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 488771fe6b9SJerome Glisse } 489771fe6b9SJerome Glisse 490771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_ADDR, 0); 491771fe6b9SJerome Glisse if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) || 492771fe6b9SJerome Glisse (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) || 493771fe6b9SJerome Glisse (rdev->family == CHIP_RS200)) { 494771fe6b9SJerome Glisse DRM_INFO("Loading R100 Microcode\n"); 495771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 496771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R100_cp_microcode[i][1]); 497771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R100_cp_microcode[i][0]); 498771fe6b9SJerome Glisse } 499771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R200) || 500771fe6b9SJerome Glisse (rdev->family == CHIP_RV250) || 501771fe6b9SJerome Glisse (rdev->family == CHIP_RV280) || 502771fe6b9SJerome Glisse (rdev->family == CHIP_RS300)) { 503771fe6b9SJerome Glisse DRM_INFO("Loading R200 Microcode\n"); 504771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 505771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R200_cp_microcode[i][1]); 506771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R200_cp_microcode[i][0]); 507771fe6b9SJerome Glisse } 508771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R300) || 509771fe6b9SJerome Glisse (rdev->family == CHIP_R350) || 510771fe6b9SJerome Glisse (rdev->family == CHIP_RV350) || 511771fe6b9SJerome Glisse (rdev->family == CHIP_RV380) || 512771fe6b9SJerome Glisse (rdev->family == CHIP_RS400) || 513771fe6b9SJerome Glisse (rdev->family == CHIP_RS480)) { 514771fe6b9SJerome Glisse DRM_INFO("Loading R300 Microcode\n"); 515771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 516771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R300_cp_microcode[i][1]); 517771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R300_cp_microcode[i][0]); 518771fe6b9SJerome Glisse } 519771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R420) || 520771fe6b9SJerome Glisse (rdev->family == CHIP_R423) || 521771fe6b9SJerome Glisse (rdev->family == CHIP_RV410)) { 522771fe6b9SJerome Glisse DRM_INFO("Loading R400 Microcode\n"); 523771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 524771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R420_cp_microcode[i][1]); 525771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R420_cp_microcode[i][0]); 526771fe6b9SJerome Glisse } 527771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_RS690) || 528771fe6b9SJerome Glisse (rdev->family == CHIP_RS740)) { 529771fe6b9SJerome Glisse DRM_INFO("Loading RS690/RS740 Microcode\n"); 530771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 531771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, RS690_cp_microcode[i][1]); 532771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, RS690_cp_microcode[i][0]); 533771fe6b9SJerome Glisse } 534771fe6b9SJerome Glisse } else if (rdev->family == CHIP_RS600) { 535771fe6b9SJerome Glisse DRM_INFO("Loading RS600 Microcode\n"); 536771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 537771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, RS600_cp_microcode[i][1]); 538771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, RS600_cp_microcode[i][0]); 539771fe6b9SJerome Glisse } 540771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_RV515) || 541771fe6b9SJerome Glisse (rdev->family == CHIP_R520) || 542771fe6b9SJerome Glisse (rdev->family == CHIP_RV530) || 543771fe6b9SJerome Glisse (rdev->family == CHIP_R580) || 544771fe6b9SJerome Glisse (rdev->family == CHIP_RV560) || 545771fe6b9SJerome Glisse (rdev->family == CHIP_RV570)) { 546771fe6b9SJerome Glisse DRM_INFO("Loading R500 Microcode\n"); 547771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 548771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAH, R520_cp_microcode[i][1]); 549771fe6b9SJerome Glisse WREG32(RADEON_CP_ME_RAM_DATAL, R520_cp_microcode[i][0]); 550771fe6b9SJerome Glisse } 551771fe6b9SJerome Glisse } 552771fe6b9SJerome Glisse } 553771fe6b9SJerome Glisse 554771fe6b9SJerome Glisse int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) 555771fe6b9SJerome Glisse { 556771fe6b9SJerome Glisse unsigned rb_bufsz; 557771fe6b9SJerome Glisse unsigned rb_blksz; 558771fe6b9SJerome Glisse unsigned max_fetch; 559771fe6b9SJerome Glisse unsigned pre_write_timer; 560771fe6b9SJerome Glisse unsigned pre_write_limit; 561771fe6b9SJerome Glisse unsigned indirect2_start; 562771fe6b9SJerome Glisse unsigned indirect1_start; 563771fe6b9SJerome Glisse uint32_t tmp; 564771fe6b9SJerome Glisse int r; 565771fe6b9SJerome Glisse 566771fe6b9SJerome Glisse if (r100_debugfs_cp_init(rdev)) { 567771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for CP !\n"); 568771fe6b9SJerome Glisse } 569771fe6b9SJerome Glisse /* Reset CP */ 570771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_STAT); 571771fe6b9SJerome Glisse if ((tmp & (1 << 31))) { 572771fe6b9SJerome Glisse DRM_INFO("radeon: cp busy (0x%08X) resetting\n", tmp); 573771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 574771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 575771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP); 576771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_SOFT_RESET); 577771fe6b9SJerome Glisse mdelay(2); 578771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 579771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_SOFT_RESET); 580771fe6b9SJerome Glisse mdelay(2); 581771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_STAT); 582771fe6b9SJerome Glisse if ((tmp & (1 << 31))) { 583771fe6b9SJerome Glisse DRM_INFO("radeon: cp reset failed (0x%08X)\n", tmp); 584771fe6b9SJerome Glisse } 585771fe6b9SJerome Glisse } else { 586771fe6b9SJerome Glisse DRM_INFO("radeon: cp idle (0x%08X)\n", tmp); 587771fe6b9SJerome Glisse } 588771fe6b9SJerome Glisse /* Align ring size */ 589771fe6b9SJerome Glisse rb_bufsz = drm_order(ring_size / 8); 590771fe6b9SJerome Glisse ring_size = (1 << (rb_bufsz + 1)) * 4; 591771fe6b9SJerome Glisse r100_cp_load_microcode(rdev); 592771fe6b9SJerome Glisse r = radeon_ring_init(rdev, ring_size); 593771fe6b9SJerome Glisse if (r) { 594771fe6b9SJerome Glisse return r; 595771fe6b9SJerome Glisse } 596771fe6b9SJerome Glisse /* Each time the cp read 1024 bytes (16 dword/quadword) update 597771fe6b9SJerome Glisse * the rptr copy in system ram */ 598771fe6b9SJerome Glisse rb_blksz = 9; 599771fe6b9SJerome Glisse /* cp will read 128bytes at a time (4 dwords) */ 600771fe6b9SJerome Glisse max_fetch = 1; 601771fe6b9SJerome Glisse rdev->cp.align_mask = 16 - 1; 602771fe6b9SJerome Glisse /* Write to CP_RB_WPTR will be delayed for pre_write_timer clocks */ 603771fe6b9SJerome Glisse pre_write_timer = 64; 604771fe6b9SJerome Glisse /* Force CP_RB_WPTR write if written more than one time before the 605771fe6b9SJerome Glisse * delay expire 606771fe6b9SJerome Glisse */ 607771fe6b9SJerome Glisse pre_write_limit = 0; 608771fe6b9SJerome Glisse /* Setup the cp cache like this (cache size is 96 dwords) : 609771fe6b9SJerome Glisse * RING 0 to 15 610771fe6b9SJerome Glisse * INDIRECT1 16 to 79 611771fe6b9SJerome Glisse * INDIRECT2 80 to 95 612771fe6b9SJerome Glisse * So ring cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) 613771fe6b9SJerome Glisse * indirect1 cache size is 64dwords (> (2 * max_fetch = 2 * 4dwords)) 614771fe6b9SJerome Glisse * indirect2 cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) 615771fe6b9SJerome Glisse * Idea being that most of the gpu cmd will be through indirect1 buffer 616771fe6b9SJerome Glisse * so it gets the bigger cache. 617771fe6b9SJerome Glisse */ 618771fe6b9SJerome Glisse indirect2_start = 80; 619771fe6b9SJerome Glisse indirect1_start = 16; 620771fe6b9SJerome Glisse /* cp setup */ 621771fe6b9SJerome Glisse WREG32(0x718, pre_write_timer | (pre_write_limit << 28)); 622771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, 6234e484e7dSMichel Dänzer #ifdef __BIG_ENDIAN 6244e484e7dSMichel Dänzer RADEON_BUF_SWAP_32BIT | 6254e484e7dSMichel Dänzer #endif 626771fe6b9SJerome Glisse REG_SET(RADEON_RB_BUFSZ, rb_bufsz) | 627771fe6b9SJerome Glisse REG_SET(RADEON_RB_BLKSZ, rb_blksz) | 628771fe6b9SJerome Glisse REG_SET(RADEON_MAX_FETCH, max_fetch) | 629771fe6b9SJerome Glisse RADEON_RB_NO_UPDATE); 630771fe6b9SJerome Glisse /* Set ring address */ 631771fe6b9SJerome Glisse DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr); 632771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr); 633771fe6b9SJerome Glisse /* Force read & write ptr to 0 */ 634771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_RB_CNTL); 635771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); 636771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_RPTR_WR, 0); 637771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_WPTR, 0); 638771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, tmp); 639771fe6b9SJerome Glisse udelay(10); 640771fe6b9SJerome Glisse rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); 641771fe6b9SJerome Glisse rdev->cp.wptr = RREG32(RADEON_CP_RB_WPTR); 642771fe6b9SJerome Glisse /* Set cp mode to bus mastering & enable cp*/ 643771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 644771fe6b9SJerome Glisse REG_SET(RADEON_INDIRECT2_START, indirect2_start) | 645771fe6b9SJerome Glisse REG_SET(RADEON_INDIRECT1_START, indirect1_start)); 646771fe6b9SJerome Glisse WREG32(0x718, 0); 647771fe6b9SJerome Glisse WREG32(0x744, 0x00004D4D); 648771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM); 649771fe6b9SJerome Glisse radeon_ring_start(rdev); 650771fe6b9SJerome Glisse r = radeon_ring_test(rdev); 651771fe6b9SJerome Glisse if (r) { 652771fe6b9SJerome Glisse DRM_ERROR("radeon: cp isn't working (%d).\n", r); 653771fe6b9SJerome Glisse return r; 654771fe6b9SJerome Glisse } 655771fe6b9SJerome Glisse rdev->cp.ready = true; 656771fe6b9SJerome Glisse return 0; 657771fe6b9SJerome Glisse } 658771fe6b9SJerome Glisse 659771fe6b9SJerome Glisse void r100_cp_fini(struct radeon_device *rdev) 660771fe6b9SJerome Glisse { 661771fe6b9SJerome Glisse /* Disable ring */ 662771fe6b9SJerome Glisse rdev->cp.ready = false; 663771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 664771fe6b9SJerome Glisse radeon_ring_fini(rdev); 665771fe6b9SJerome Glisse DRM_INFO("radeon: cp finalized\n"); 666771fe6b9SJerome Glisse } 667771fe6b9SJerome Glisse 668771fe6b9SJerome Glisse void r100_cp_disable(struct radeon_device *rdev) 669771fe6b9SJerome Glisse { 670771fe6b9SJerome Glisse /* Disable ring */ 671771fe6b9SJerome Glisse rdev->cp.ready = false; 672771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 673771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 674771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 675771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 676771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 677771fe6b9SJerome Glisse } 678771fe6b9SJerome Glisse } 679771fe6b9SJerome Glisse 680771fe6b9SJerome Glisse int r100_cp_reset(struct radeon_device *rdev) 681771fe6b9SJerome Glisse { 682771fe6b9SJerome Glisse uint32_t tmp; 683771fe6b9SJerome Glisse bool reinit_cp; 684771fe6b9SJerome Glisse int i; 685771fe6b9SJerome Glisse 686771fe6b9SJerome Glisse reinit_cp = rdev->cp.ready; 687771fe6b9SJerome Glisse rdev->cp.ready = false; 688771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 689771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 690771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP); 691771fe6b9SJerome Glisse (void)RREG32(RADEON_RBBM_SOFT_RESET); 692771fe6b9SJerome Glisse udelay(200); 693771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 694771fe6b9SJerome Glisse /* Wait to prevent race in RBBM_STATUS */ 695771fe6b9SJerome Glisse mdelay(1); 696771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 697771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 698771fe6b9SJerome Glisse if (!(tmp & (1 << 16))) { 699771fe6b9SJerome Glisse DRM_INFO("CP reset succeed (RBBM_STATUS=0x%08X)\n", 700771fe6b9SJerome Glisse tmp); 701771fe6b9SJerome Glisse if (reinit_cp) { 702771fe6b9SJerome Glisse return r100_cp_init(rdev, rdev->cp.ring_size); 703771fe6b9SJerome Glisse } 704771fe6b9SJerome Glisse return 0; 705771fe6b9SJerome Glisse } 706771fe6b9SJerome Glisse DRM_UDELAY(1); 707771fe6b9SJerome Glisse } 708771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 709771fe6b9SJerome Glisse DRM_ERROR("Failed to reset CP (RBBM_STATUS=0x%08X)!\n", tmp); 710771fe6b9SJerome Glisse return -1; 711771fe6b9SJerome Glisse } 712771fe6b9SJerome Glisse 713771fe6b9SJerome Glisse 714771fe6b9SJerome Glisse /* 715771fe6b9SJerome Glisse * CS functions 716771fe6b9SJerome Glisse */ 717771fe6b9SJerome Glisse int r100_cs_parse_packet0(struct radeon_cs_parser *p, 718771fe6b9SJerome Glisse struct radeon_cs_packet *pkt, 719068a117cSJerome Glisse const unsigned *auth, unsigned n, 720771fe6b9SJerome Glisse radeon_packet0_check_t check) 721771fe6b9SJerome Glisse { 722771fe6b9SJerome Glisse unsigned reg; 723771fe6b9SJerome Glisse unsigned i, j, m; 724771fe6b9SJerome Glisse unsigned idx; 725771fe6b9SJerome Glisse int r; 726771fe6b9SJerome Glisse 727771fe6b9SJerome Glisse idx = pkt->idx + 1; 728771fe6b9SJerome Glisse reg = pkt->reg; 729068a117cSJerome Glisse /* Check that register fall into register range 730068a117cSJerome Glisse * determined by the number of entry (n) in the 731068a117cSJerome Glisse * safe register bitmap. 732068a117cSJerome Glisse */ 733771fe6b9SJerome Glisse if (pkt->one_reg_wr) { 734771fe6b9SJerome Glisse if ((reg >> 7) > n) { 735771fe6b9SJerome Glisse return -EINVAL; 736771fe6b9SJerome Glisse } 737771fe6b9SJerome Glisse } else { 738771fe6b9SJerome Glisse if (((reg + (pkt->count << 2)) >> 7) > n) { 739771fe6b9SJerome Glisse return -EINVAL; 740771fe6b9SJerome Glisse } 741771fe6b9SJerome Glisse } 742771fe6b9SJerome Glisse for (i = 0; i <= pkt->count; i++, idx++) { 743771fe6b9SJerome Glisse j = (reg >> 7); 744771fe6b9SJerome Glisse m = 1 << ((reg >> 2) & 31); 745771fe6b9SJerome Glisse if (auth[j] & m) { 746771fe6b9SJerome Glisse r = check(p, pkt, idx, reg); 747771fe6b9SJerome Glisse if (r) { 748771fe6b9SJerome Glisse return r; 749771fe6b9SJerome Glisse } 750771fe6b9SJerome Glisse } 751771fe6b9SJerome Glisse if (pkt->one_reg_wr) { 752771fe6b9SJerome Glisse if (!(auth[j] & m)) { 753771fe6b9SJerome Glisse break; 754771fe6b9SJerome Glisse } 755771fe6b9SJerome Glisse } else { 756771fe6b9SJerome Glisse reg += 4; 757771fe6b9SJerome Glisse } 758771fe6b9SJerome Glisse } 759771fe6b9SJerome Glisse return 0; 760771fe6b9SJerome Glisse } 761771fe6b9SJerome Glisse 762771fe6b9SJerome Glisse void r100_cs_dump_packet(struct radeon_cs_parser *p, 763771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 764771fe6b9SJerome Glisse { 765771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 766771fe6b9SJerome Glisse volatile uint32_t *ib; 767771fe6b9SJerome Glisse unsigned i; 768771fe6b9SJerome Glisse unsigned idx; 769771fe6b9SJerome Glisse 770771fe6b9SJerome Glisse ib = p->ib->ptr; 771771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 772771fe6b9SJerome Glisse idx = pkt->idx; 773771fe6b9SJerome Glisse for (i = 0; i <= (pkt->count + 1); i++, idx++) { 774771fe6b9SJerome Glisse DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]); 775771fe6b9SJerome Glisse } 776771fe6b9SJerome Glisse } 777771fe6b9SJerome Glisse 778771fe6b9SJerome Glisse /** 779771fe6b9SJerome Glisse * r100_cs_packet_parse() - parse cp packet and point ib index to next packet 780771fe6b9SJerome Glisse * @parser: parser structure holding parsing context. 781771fe6b9SJerome Glisse * @pkt: where to store packet informations 782771fe6b9SJerome Glisse * 783771fe6b9SJerome Glisse * Assume that chunk_ib_index is properly set. Will return -EINVAL 784771fe6b9SJerome Glisse * if packet is bigger than remaining ib size. or if packets is unknown. 785771fe6b9SJerome Glisse **/ 786771fe6b9SJerome Glisse int r100_cs_packet_parse(struct radeon_cs_parser *p, 787771fe6b9SJerome Glisse struct radeon_cs_packet *pkt, 788771fe6b9SJerome Glisse unsigned idx) 789771fe6b9SJerome Glisse { 790771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; 791fa99239cSRoel Kluin uint32_t header; 792771fe6b9SJerome Glisse 793771fe6b9SJerome Glisse if (idx >= ib_chunk->length_dw) { 794771fe6b9SJerome Glisse DRM_ERROR("Can not parse packet at %d after CS end %d !\n", 795771fe6b9SJerome Glisse idx, ib_chunk->length_dw); 796771fe6b9SJerome Glisse return -EINVAL; 797771fe6b9SJerome Glisse } 798fa99239cSRoel Kluin header = ib_chunk->kdata[idx]; 799771fe6b9SJerome Glisse pkt->idx = idx; 800771fe6b9SJerome Glisse pkt->type = CP_PACKET_GET_TYPE(header); 801771fe6b9SJerome Glisse pkt->count = CP_PACKET_GET_COUNT(header); 802771fe6b9SJerome Glisse switch (pkt->type) { 803771fe6b9SJerome Glisse case PACKET_TYPE0: 804771fe6b9SJerome Glisse pkt->reg = CP_PACKET0_GET_REG(header); 805771fe6b9SJerome Glisse pkt->one_reg_wr = CP_PACKET0_GET_ONE_REG_WR(header); 806771fe6b9SJerome Glisse break; 807771fe6b9SJerome Glisse case PACKET_TYPE3: 808771fe6b9SJerome Glisse pkt->opcode = CP_PACKET3_GET_OPCODE(header); 809771fe6b9SJerome Glisse break; 810771fe6b9SJerome Glisse case PACKET_TYPE2: 811771fe6b9SJerome Glisse pkt->count = -1; 812771fe6b9SJerome Glisse break; 813771fe6b9SJerome Glisse default: 814771fe6b9SJerome Glisse DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx); 815771fe6b9SJerome Glisse return -EINVAL; 816771fe6b9SJerome Glisse } 817771fe6b9SJerome Glisse if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) { 818771fe6b9SJerome Glisse DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n", 819771fe6b9SJerome Glisse pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw); 820771fe6b9SJerome Glisse return -EINVAL; 821771fe6b9SJerome Glisse } 822771fe6b9SJerome Glisse return 0; 823771fe6b9SJerome Glisse } 824771fe6b9SJerome Glisse 825771fe6b9SJerome Glisse /** 826531369e6SDave Airlie * r100_cs_packet_next_vline() - parse userspace VLINE packet 827531369e6SDave Airlie * @parser: parser structure holding parsing context. 828531369e6SDave Airlie * 829531369e6SDave Airlie * Userspace sends a special sequence for VLINE waits. 830531369e6SDave Airlie * PACKET0 - VLINE_START_END + value 831531369e6SDave Airlie * PACKET0 - WAIT_UNTIL +_value 832531369e6SDave Airlie * RELOC (P3) - crtc_id in reloc. 833531369e6SDave Airlie * 834531369e6SDave Airlie * This function parses this and relocates the VLINE START END 835531369e6SDave Airlie * and WAIT UNTIL packets to the correct crtc. 836531369e6SDave Airlie * It also detects a switched off crtc and nulls out the 837531369e6SDave Airlie * wait in that case. 838531369e6SDave Airlie */ 839531369e6SDave Airlie int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) 840531369e6SDave Airlie { 841531369e6SDave Airlie struct radeon_cs_chunk *ib_chunk; 842531369e6SDave Airlie struct drm_mode_object *obj; 843531369e6SDave Airlie struct drm_crtc *crtc; 844531369e6SDave Airlie struct radeon_crtc *radeon_crtc; 845531369e6SDave Airlie struct radeon_cs_packet p3reloc, waitreloc; 846531369e6SDave Airlie int crtc_id; 847531369e6SDave Airlie int r; 848531369e6SDave Airlie uint32_t header, h_idx, reg; 849531369e6SDave Airlie 850531369e6SDave Airlie ib_chunk = &p->chunks[p->chunk_ib_idx]; 851531369e6SDave Airlie 852531369e6SDave Airlie /* parse the wait until */ 853531369e6SDave Airlie r = r100_cs_packet_parse(p, &waitreloc, p->idx); 854531369e6SDave Airlie if (r) 855531369e6SDave Airlie return r; 856531369e6SDave Airlie 857531369e6SDave Airlie /* check its a wait until and only 1 count */ 858531369e6SDave Airlie if (waitreloc.reg != RADEON_WAIT_UNTIL || 859531369e6SDave Airlie waitreloc.count != 0) { 860531369e6SDave Airlie DRM_ERROR("vline wait had illegal wait until segment\n"); 861531369e6SDave Airlie r = -EINVAL; 862531369e6SDave Airlie return r; 863531369e6SDave Airlie } 864531369e6SDave Airlie 865531369e6SDave Airlie if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) { 866531369e6SDave Airlie DRM_ERROR("vline wait had illegal wait until\n"); 867531369e6SDave Airlie r = -EINVAL; 868531369e6SDave Airlie return r; 869531369e6SDave Airlie } 870531369e6SDave Airlie 871531369e6SDave Airlie /* jump over the NOP */ 872531369e6SDave Airlie r = r100_cs_packet_parse(p, &p3reloc, p->idx); 873531369e6SDave Airlie if (r) 874531369e6SDave Airlie return r; 875531369e6SDave Airlie 876531369e6SDave Airlie h_idx = p->idx - 2; 877531369e6SDave Airlie p->idx += waitreloc.count; 878531369e6SDave Airlie p->idx += p3reloc.count; 879531369e6SDave Airlie 880531369e6SDave Airlie header = ib_chunk->kdata[h_idx]; 881531369e6SDave Airlie crtc_id = ib_chunk->kdata[h_idx + 5]; 882531369e6SDave Airlie reg = ib_chunk->kdata[h_idx] >> 2; 883531369e6SDave Airlie mutex_lock(&p->rdev->ddev->mode_config.mutex); 884531369e6SDave Airlie obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); 885531369e6SDave Airlie if (!obj) { 886531369e6SDave Airlie DRM_ERROR("cannot find crtc %d\n", crtc_id); 887531369e6SDave Airlie r = -EINVAL; 888531369e6SDave Airlie goto out; 889531369e6SDave Airlie } 890531369e6SDave Airlie crtc = obj_to_crtc(obj); 891531369e6SDave Airlie radeon_crtc = to_radeon_crtc(crtc); 892531369e6SDave Airlie crtc_id = radeon_crtc->crtc_id; 893531369e6SDave Airlie 894531369e6SDave Airlie if (!crtc->enabled) { 895531369e6SDave Airlie /* if the CRTC isn't enabled - we need to nop out the wait until */ 896531369e6SDave Airlie ib_chunk->kdata[h_idx + 2] = PACKET2(0); 897531369e6SDave Airlie ib_chunk->kdata[h_idx + 3] = PACKET2(0); 898531369e6SDave Airlie } else if (crtc_id == 1) { 899531369e6SDave Airlie switch (reg) { 900531369e6SDave Airlie case AVIVO_D1MODE_VLINE_START_END: 901531369e6SDave Airlie header &= R300_CP_PACKET0_REG_MASK; 902531369e6SDave Airlie header |= AVIVO_D2MODE_VLINE_START_END >> 2; 903531369e6SDave Airlie break; 904531369e6SDave Airlie case RADEON_CRTC_GUI_TRIG_VLINE: 905531369e6SDave Airlie header &= R300_CP_PACKET0_REG_MASK; 906531369e6SDave Airlie header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2; 907531369e6SDave Airlie break; 908531369e6SDave Airlie default: 909531369e6SDave Airlie DRM_ERROR("unknown crtc reloc\n"); 910531369e6SDave Airlie r = -EINVAL; 911531369e6SDave Airlie goto out; 912531369e6SDave Airlie } 913531369e6SDave Airlie ib_chunk->kdata[h_idx] = header; 914531369e6SDave Airlie ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; 915531369e6SDave Airlie } 916531369e6SDave Airlie out: 917531369e6SDave Airlie mutex_unlock(&p->rdev->ddev->mode_config.mutex); 918531369e6SDave Airlie return r; 919531369e6SDave Airlie } 920531369e6SDave Airlie 921531369e6SDave Airlie /** 922771fe6b9SJerome Glisse * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 923771fe6b9SJerome Glisse * @parser: parser structure holding parsing context. 924771fe6b9SJerome Glisse * @data: pointer to relocation data 925771fe6b9SJerome Glisse * @offset_start: starting offset 926771fe6b9SJerome Glisse * @offset_mask: offset mask (to align start offset on) 927771fe6b9SJerome Glisse * @reloc: reloc informations 928771fe6b9SJerome Glisse * 929771fe6b9SJerome Glisse * Check next packet is relocation packet3, do bo validation and compute 930771fe6b9SJerome Glisse * GPU offset using the provided start. 931771fe6b9SJerome Glisse **/ 932771fe6b9SJerome Glisse int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, 933771fe6b9SJerome Glisse struct radeon_cs_reloc **cs_reloc) 934771fe6b9SJerome Glisse { 935771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 936771fe6b9SJerome Glisse struct radeon_cs_chunk *relocs_chunk; 937771fe6b9SJerome Glisse struct radeon_cs_packet p3reloc; 938771fe6b9SJerome Glisse unsigned idx; 939771fe6b9SJerome Glisse int r; 940771fe6b9SJerome Glisse 941771fe6b9SJerome Glisse if (p->chunk_relocs_idx == -1) { 942771fe6b9SJerome Glisse DRM_ERROR("No relocation chunk !\n"); 943771fe6b9SJerome Glisse return -EINVAL; 944771fe6b9SJerome Glisse } 945771fe6b9SJerome Glisse *cs_reloc = NULL; 946771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 947771fe6b9SJerome Glisse relocs_chunk = &p->chunks[p->chunk_relocs_idx]; 948771fe6b9SJerome Glisse r = r100_cs_packet_parse(p, &p3reloc, p->idx); 949771fe6b9SJerome Glisse if (r) { 950771fe6b9SJerome Glisse return r; 951771fe6b9SJerome Glisse } 952771fe6b9SJerome Glisse p->idx += p3reloc.count + 2; 953771fe6b9SJerome Glisse if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { 954771fe6b9SJerome Glisse DRM_ERROR("No packet3 for relocation for packet at %d.\n", 955771fe6b9SJerome Glisse p3reloc.idx); 956771fe6b9SJerome Glisse r100_cs_dump_packet(p, &p3reloc); 957771fe6b9SJerome Glisse return -EINVAL; 958771fe6b9SJerome Glisse } 959771fe6b9SJerome Glisse idx = ib_chunk->kdata[p3reloc.idx + 1]; 960771fe6b9SJerome Glisse if (idx >= relocs_chunk->length_dw) { 961771fe6b9SJerome Glisse DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", 962771fe6b9SJerome Glisse idx, relocs_chunk->length_dw); 963771fe6b9SJerome Glisse r100_cs_dump_packet(p, &p3reloc); 964771fe6b9SJerome Glisse return -EINVAL; 965771fe6b9SJerome Glisse } 966771fe6b9SJerome Glisse /* FIXME: we assume reloc size is 4 dwords */ 967771fe6b9SJerome Glisse *cs_reloc = p->relocs_ptr[(idx / 4)]; 968771fe6b9SJerome Glisse return 0; 969771fe6b9SJerome Glisse } 970771fe6b9SJerome Glisse 971771fe6b9SJerome Glisse static int r100_packet0_check(struct radeon_cs_parser *p, 972771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 973771fe6b9SJerome Glisse { 974771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 975771fe6b9SJerome Glisse struct radeon_cs_reloc *reloc; 976771fe6b9SJerome Glisse volatile uint32_t *ib; 977771fe6b9SJerome Glisse uint32_t tmp; 978771fe6b9SJerome Glisse unsigned reg; 979771fe6b9SJerome Glisse unsigned i; 980771fe6b9SJerome Glisse unsigned idx; 981771fe6b9SJerome Glisse bool onereg; 982771fe6b9SJerome Glisse int r; 983e024e110SDave Airlie u32 tile_flags = 0; 984771fe6b9SJerome Glisse 985771fe6b9SJerome Glisse ib = p->ib->ptr; 986771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 987771fe6b9SJerome Glisse idx = pkt->idx + 1; 988771fe6b9SJerome Glisse reg = pkt->reg; 989771fe6b9SJerome Glisse onereg = false; 990771fe6b9SJerome Glisse if (CP_PACKET0_GET_ONE_REG_WR(ib_chunk->kdata[pkt->idx])) { 991771fe6b9SJerome Glisse onereg = true; 992771fe6b9SJerome Glisse } 993771fe6b9SJerome Glisse for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { 994771fe6b9SJerome Glisse switch (reg) { 995531369e6SDave Airlie case RADEON_CRTC_GUI_TRIG_VLINE: 996531369e6SDave Airlie r = r100_cs_packet_parse_vline(p); 997531369e6SDave Airlie if (r) { 998531369e6SDave Airlie DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 999531369e6SDave Airlie idx, reg); 1000531369e6SDave Airlie r100_cs_dump_packet(p, pkt); 1001531369e6SDave Airlie return r; 1002531369e6SDave Airlie } 1003531369e6SDave Airlie break; 1004771fe6b9SJerome Glisse /* FIXME: only allow PACKET3 blit? easier to check for out of 1005771fe6b9SJerome Glisse * range access */ 1006771fe6b9SJerome Glisse case RADEON_DST_PITCH_OFFSET: 1007771fe6b9SJerome Glisse case RADEON_SRC_PITCH_OFFSET: 1008771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1009771fe6b9SJerome Glisse if (r) { 1010771fe6b9SJerome Glisse DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1011771fe6b9SJerome Glisse idx, reg); 1012771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1013771fe6b9SJerome Glisse return r; 1014771fe6b9SJerome Glisse } 1015771fe6b9SJerome Glisse tmp = ib_chunk->kdata[idx] & 0x003fffff; 1016771fe6b9SJerome Glisse tmp += (((u32)reloc->lobj.gpu_offset) >> 10); 1017e024e110SDave Airlie 1018e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) 1019e024e110SDave Airlie tile_flags |= RADEON_DST_TILE_MACRO; 1020e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { 1021e024e110SDave Airlie if (reg == RADEON_SRC_PITCH_OFFSET) { 1022e024e110SDave Airlie DRM_ERROR("Cannot src blit from microtiled surface\n"); 1023e024e110SDave Airlie r100_cs_dump_packet(p, pkt); 1024e024e110SDave Airlie return -EINVAL; 1025e024e110SDave Airlie } 1026e024e110SDave Airlie tile_flags |= RADEON_DST_TILE_MICRO; 1027e024e110SDave Airlie } 1028e024e110SDave Airlie 1029e024e110SDave Airlie tmp |= tile_flags; 1030e024e110SDave Airlie ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp; 1031771fe6b9SJerome Glisse break; 1032771fe6b9SJerome Glisse case RADEON_RB3D_DEPTHOFFSET: 1033771fe6b9SJerome Glisse case RADEON_RB3D_COLOROFFSET: 1034771fe6b9SJerome Glisse case R300_RB3D_COLOROFFSET0: 1035771fe6b9SJerome Glisse case R300_ZB_DEPTHOFFSET: 1036771fe6b9SJerome Glisse case R200_PP_TXOFFSET_0: 1037771fe6b9SJerome Glisse case R200_PP_TXOFFSET_1: 1038771fe6b9SJerome Glisse case R200_PP_TXOFFSET_2: 1039771fe6b9SJerome Glisse case R200_PP_TXOFFSET_3: 1040771fe6b9SJerome Glisse case R200_PP_TXOFFSET_4: 1041771fe6b9SJerome Glisse case R200_PP_TXOFFSET_5: 1042771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_0: 1043771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_1: 1044771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_2: 1045771fe6b9SJerome Glisse case R300_TX_OFFSET_0: 1046771fe6b9SJerome Glisse case R300_TX_OFFSET_0+4: 1047771fe6b9SJerome Glisse case R300_TX_OFFSET_0+8: 1048771fe6b9SJerome Glisse case R300_TX_OFFSET_0+12: 1049771fe6b9SJerome Glisse case R300_TX_OFFSET_0+16: 1050771fe6b9SJerome Glisse case R300_TX_OFFSET_0+20: 1051771fe6b9SJerome Glisse case R300_TX_OFFSET_0+24: 1052771fe6b9SJerome Glisse case R300_TX_OFFSET_0+28: 1053771fe6b9SJerome Glisse case R300_TX_OFFSET_0+32: 1054771fe6b9SJerome Glisse case R300_TX_OFFSET_0+36: 1055771fe6b9SJerome Glisse case R300_TX_OFFSET_0+40: 1056771fe6b9SJerome Glisse case R300_TX_OFFSET_0+44: 1057771fe6b9SJerome Glisse case R300_TX_OFFSET_0+48: 1058771fe6b9SJerome Glisse case R300_TX_OFFSET_0+52: 1059771fe6b9SJerome Glisse case R300_TX_OFFSET_0+56: 1060771fe6b9SJerome Glisse case R300_TX_OFFSET_0+60: 1061b995e433SDave Airlie /* rn50 has no 3D engine so fail on any 3d setup */ 1062b995e433SDave Airlie if (ASIC_IS_RN50(p->rdev)) { 1063b995e433SDave Airlie DRM_ERROR("attempt to use RN50 3D engine failed\n"); 1064b995e433SDave Airlie return -EINVAL; 1065b995e433SDave Airlie } 1066771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1067771fe6b9SJerome Glisse if (r) { 1068771fe6b9SJerome Glisse DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1069771fe6b9SJerome Glisse idx, reg); 1070771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1071771fe6b9SJerome Glisse return r; 1072771fe6b9SJerome Glisse } 1073771fe6b9SJerome Glisse ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); 1074771fe6b9SJerome Glisse break; 1075e024e110SDave Airlie case R300_RB3D_COLORPITCH0: 1076e024e110SDave Airlie case RADEON_RB3D_COLORPITCH: 1077e024e110SDave Airlie r = r100_cs_packet_next_reloc(p, &reloc); 1078e024e110SDave Airlie if (r) { 1079e024e110SDave Airlie DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1080e024e110SDave Airlie idx, reg); 1081e024e110SDave Airlie r100_cs_dump_packet(p, pkt); 1082e024e110SDave Airlie return r; 1083e024e110SDave Airlie } 1084e024e110SDave Airlie 1085e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) 1086e024e110SDave Airlie tile_flags |= RADEON_COLOR_TILE_ENABLE; 1087e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) 1088e024e110SDave Airlie tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; 1089e024e110SDave Airlie 1090e024e110SDave Airlie tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); 1091e024e110SDave Airlie tmp |= tile_flags; 1092e024e110SDave Airlie ib[idx] = tmp; 1093e024e110SDave Airlie break; 1094771fe6b9SJerome Glisse default: 1095771fe6b9SJerome Glisse /* FIXME: we don't want to allow anyothers packet */ 1096771fe6b9SJerome Glisse break; 1097771fe6b9SJerome Glisse } 1098771fe6b9SJerome Glisse if (onereg) { 1099771fe6b9SJerome Glisse /* FIXME: forbid onereg write to register on relocate */ 1100771fe6b9SJerome Glisse break; 1101771fe6b9SJerome Glisse } 1102771fe6b9SJerome Glisse } 1103771fe6b9SJerome Glisse return 0; 1104771fe6b9SJerome Glisse } 1105771fe6b9SJerome Glisse 1106068a117cSJerome Glisse int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, 1107068a117cSJerome Glisse struct radeon_cs_packet *pkt, 1108068a117cSJerome Glisse struct radeon_object *robj) 1109068a117cSJerome Glisse { 1110068a117cSJerome Glisse struct radeon_cs_chunk *ib_chunk; 1111068a117cSJerome Glisse unsigned idx; 1112068a117cSJerome Glisse 1113068a117cSJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 1114068a117cSJerome Glisse idx = pkt->idx + 1; 1115068a117cSJerome Glisse if ((ib_chunk->kdata[idx+2] + 1) > radeon_object_size(robj)) { 1116068a117cSJerome Glisse DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER " 1117068a117cSJerome Glisse "(need %u have %lu) !\n", 1118068a117cSJerome Glisse ib_chunk->kdata[idx+2] + 1, 1119068a117cSJerome Glisse radeon_object_size(robj)); 1120068a117cSJerome Glisse return -EINVAL; 1121068a117cSJerome Glisse } 1122068a117cSJerome Glisse return 0; 1123068a117cSJerome Glisse } 1124068a117cSJerome Glisse 1125771fe6b9SJerome Glisse static int r100_packet3_check(struct radeon_cs_parser *p, 1126771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 1127771fe6b9SJerome Glisse { 1128771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 1129771fe6b9SJerome Glisse struct radeon_cs_reloc *reloc; 1130771fe6b9SJerome Glisse unsigned idx; 1131771fe6b9SJerome Glisse unsigned i, c; 1132771fe6b9SJerome Glisse volatile uint32_t *ib; 1133771fe6b9SJerome Glisse int r; 1134771fe6b9SJerome Glisse 1135771fe6b9SJerome Glisse ib = p->ib->ptr; 1136771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 1137771fe6b9SJerome Glisse idx = pkt->idx + 1; 1138771fe6b9SJerome Glisse switch (pkt->opcode) { 1139771fe6b9SJerome Glisse case PACKET3_3D_LOAD_VBPNTR: 1140771fe6b9SJerome Glisse c = ib_chunk->kdata[idx++]; 1141771fe6b9SJerome Glisse for (i = 0; i < (c - 1); i += 2, idx += 3) { 1142771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1143771fe6b9SJerome Glisse if (r) { 1144771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 1145771fe6b9SJerome Glisse pkt->opcode); 1146771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1147771fe6b9SJerome Glisse return r; 1148771fe6b9SJerome Glisse } 1149771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1150771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1151771fe6b9SJerome Glisse if (r) { 1152771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 1153771fe6b9SJerome Glisse pkt->opcode); 1154771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1155771fe6b9SJerome Glisse return r; 1156771fe6b9SJerome Glisse } 1157771fe6b9SJerome Glisse ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset); 1158771fe6b9SJerome Glisse } 1159771fe6b9SJerome Glisse if (c & 1) { 1160771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1161771fe6b9SJerome Glisse if (r) { 1162771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 1163771fe6b9SJerome Glisse pkt->opcode); 1164771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1165771fe6b9SJerome Glisse return r; 1166771fe6b9SJerome Glisse } 1167771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1168771fe6b9SJerome Glisse } 1169771fe6b9SJerome Glisse break; 1170771fe6b9SJerome Glisse case PACKET3_INDX_BUFFER: 1171771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1172771fe6b9SJerome Glisse if (r) { 1173771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 1174771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1175771fe6b9SJerome Glisse return r; 1176771fe6b9SJerome Glisse } 1177771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1178068a117cSJerome Glisse r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj); 1179068a117cSJerome Glisse if (r) { 1180068a117cSJerome Glisse return r; 1181068a117cSJerome Glisse } 1182771fe6b9SJerome Glisse break; 1183771fe6b9SJerome Glisse case 0x23: 1184771fe6b9SJerome Glisse /* FIXME: cleanup */ 1185771fe6b9SJerome Glisse /* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */ 1186771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1187771fe6b9SJerome Glisse if (r) { 1188771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 1189771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1190771fe6b9SJerome Glisse return r; 1191771fe6b9SJerome Glisse } 1192771fe6b9SJerome Glisse ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); 1193771fe6b9SJerome Glisse break; 1194771fe6b9SJerome Glisse case PACKET3_3D_DRAW_IMMD: 1195771fe6b9SJerome Glisse /* triggers drawing using in-packet vertex data */ 1196771fe6b9SJerome Glisse case PACKET3_3D_DRAW_IMMD_2: 1197771fe6b9SJerome Glisse /* triggers drawing using in-packet vertex data */ 1198771fe6b9SJerome Glisse case PACKET3_3D_DRAW_VBUF_2: 1199771fe6b9SJerome Glisse /* triggers drawing of vertex buffers setup elsewhere */ 1200771fe6b9SJerome Glisse case PACKET3_3D_DRAW_INDX_2: 1201771fe6b9SJerome Glisse /* triggers drawing using indices to vertex buffer */ 1202771fe6b9SJerome Glisse case PACKET3_3D_DRAW_VBUF: 1203771fe6b9SJerome Glisse /* triggers drawing of vertex buffers setup elsewhere */ 1204771fe6b9SJerome Glisse case PACKET3_3D_DRAW_INDX: 1205771fe6b9SJerome Glisse /* triggers drawing using indices to vertex buffer */ 1206771fe6b9SJerome Glisse case PACKET3_NOP: 1207771fe6b9SJerome Glisse break; 1208771fe6b9SJerome Glisse default: 1209771fe6b9SJerome Glisse DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); 1210771fe6b9SJerome Glisse return -EINVAL; 1211771fe6b9SJerome Glisse } 1212771fe6b9SJerome Glisse return 0; 1213771fe6b9SJerome Glisse } 1214771fe6b9SJerome Glisse 1215771fe6b9SJerome Glisse int r100_cs_parse(struct radeon_cs_parser *p) 1216771fe6b9SJerome Glisse { 1217771fe6b9SJerome Glisse struct radeon_cs_packet pkt; 1218771fe6b9SJerome Glisse int r; 1219771fe6b9SJerome Glisse 1220771fe6b9SJerome Glisse do { 1221771fe6b9SJerome Glisse r = r100_cs_packet_parse(p, &pkt, p->idx); 1222771fe6b9SJerome Glisse if (r) { 1223771fe6b9SJerome Glisse return r; 1224771fe6b9SJerome Glisse } 1225771fe6b9SJerome Glisse p->idx += pkt.count + 2; 1226771fe6b9SJerome Glisse switch (pkt.type) { 1227771fe6b9SJerome Glisse case PACKET_TYPE0: 1228771fe6b9SJerome Glisse r = r100_packet0_check(p, &pkt); 1229771fe6b9SJerome Glisse break; 1230771fe6b9SJerome Glisse case PACKET_TYPE2: 1231771fe6b9SJerome Glisse break; 1232771fe6b9SJerome Glisse case PACKET_TYPE3: 1233771fe6b9SJerome Glisse r = r100_packet3_check(p, &pkt); 1234771fe6b9SJerome Glisse break; 1235771fe6b9SJerome Glisse default: 1236771fe6b9SJerome Glisse DRM_ERROR("Unknown packet type %d !\n", 1237771fe6b9SJerome Glisse pkt.type); 1238771fe6b9SJerome Glisse return -EINVAL; 1239771fe6b9SJerome Glisse } 1240771fe6b9SJerome Glisse if (r) { 1241771fe6b9SJerome Glisse return r; 1242771fe6b9SJerome Glisse } 1243771fe6b9SJerome Glisse } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); 1244771fe6b9SJerome Glisse return 0; 1245771fe6b9SJerome Glisse } 1246771fe6b9SJerome Glisse 1247771fe6b9SJerome Glisse 1248771fe6b9SJerome Glisse /* 1249771fe6b9SJerome Glisse * Global GPU functions 1250771fe6b9SJerome Glisse */ 1251771fe6b9SJerome Glisse void r100_errata(struct radeon_device *rdev) 1252771fe6b9SJerome Glisse { 1253771fe6b9SJerome Glisse rdev->pll_errata = 0; 1254771fe6b9SJerome Glisse 1255771fe6b9SJerome Glisse if (rdev->family == CHIP_RV200 || rdev->family == CHIP_RS200) { 1256771fe6b9SJerome Glisse rdev->pll_errata |= CHIP_ERRATA_PLL_DUMMYREADS; 1257771fe6b9SJerome Glisse } 1258771fe6b9SJerome Glisse 1259771fe6b9SJerome Glisse if (rdev->family == CHIP_RV100 || 1260771fe6b9SJerome Glisse rdev->family == CHIP_RS100 || 1261771fe6b9SJerome Glisse rdev->family == CHIP_RS200) { 1262771fe6b9SJerome Glisse rdev->pll_errata |= CHIP_ERRATA_PLL_DELAY; 1263771fe6b9SJerome Glisse } 1264771fe6b9SJerome Glisse } 1265771fe6b9SJerome Glisse 1266771fe6b9SJerome Glisse /* Wait for vertical sync on primary CRTC */ 1267771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync(struct radeon_device *rdev) 1268771fe6b9SJerome Glisse { 1269771fe6b9SJerome Glisse uint32_t crtc_gen_cntl, tmp; 1270771fe6b9SJerome Glisse int i; 1271771fe6b9SJerome Glisse 1272771fe6b9SJerome Glisse crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); 1273771fe6b9SJerome Glisse if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || 1274771fe6b9SJerome Glisse !(crtc_gen_cntl & RADEON_CRTC_EN)) { 1275771fe6b9SJerome Glisse return; 1276771fe6b9SJerome Glisse } 1277771fe6b9SJerome Glisse /* Clear the CRTC_VBLANK_SAVE bit */ 1278771fe6b9SJerome Glisse WREG32(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); 1279771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1280771fe6b9SJerome Glisse tmp = RREG32(RADEON_CRTC_STATUS); 1281771fe6b9SJerome Glisse if (tmp & RADEON_CRTC_VBLANK_SAVE) { 1282771fe6b9SJerome Glisse return; 1283771fe6b9SJerome Glisse } 1284771fe6b9SJerome Glisse DRM_UDELAY(1); 1285771fe6b9SJerome Glisse } 1286771fe6b9SJerome Glisse } 1287771fe6b9SJerome Glisse 1288771fe6b9SJerome Glisse /* Wait for vertical sync on secondary CRTC */ 1289771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync2(struct radeon_device *rdev) 1290771fe6b9SJerome Glisse { 1291771fe6b9SJerome Glisse uint32_t crtc2_gen_cntl, tmp; 1292771fe6b9SJerome Glisse int i; 1293771fe6b9SJerome Glisse 1294771fe6b9SJerome Glisse crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 1295771fe6b9SJerome Glisse if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || 1296771fe6b9SJerome Glisse !(crtc2_gen_cntl & RADEON_CRTC2_EN)) 1297771fe6b9SJerome Glisse return; 1298771fe6b9SJerome Glisse 1299771fe6b9SJerome Glisse /* Clear the CRTC_VBLANK_SAVE bit */ 1300771fe6b9SJerome Glisse WREG32(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); 1301771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1302771fe6b9SJerome Glisse tmp = RREG32(RADEON_CRTC2_STATUS); 1303771fe6b9SJerome Glisse if (tmp & RADEON_CRTC2_VBLANK_SAVE) { 1304771fe6b9SJerome Glisse return; 1305771fe6b9SJerome Glisse } 1306771fe6b9SJerome Glisse DRM_UDELAY(1); 1307771fe6b9SJerome Glisse } 1308771fe6b9SJerome Glisse } 1309771fe6b9SJerome Glisse 1310771fe6b9SJerome Glisse int r100_rbbm_fifo_wait_for_entry(struct radeon_device *rdev, unsigned n) 1311771fe6b9SJerome Glisse { 1312771fe6b9SJerome Glisse unsigned i; 1313771fe6b9SJerome Glisse uint32_t tmp; 1314771fe6b9SJerome Glisse 1315771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1316771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; 1317771fe6b9SJerome Glisse if (tmp >= n) { 1318771fe6b9SJerome Glisse return 0; 1319771fe6b9SJerome Glisse } 1320771fe6b9SJerome Glisse DRM_UDELAY(1); 1321771fe6b9SJerome Glisse } 1322771fe6b9SJerome Glisse return -1; 1323771fe6b9SJerome Glisse } 1324771fe6b9SJerome Glisse 1325771fe6b9SJerome Glisse int r100_gui_wait_for_idle(struct radeon_device *rdev) 1326771fe6b9SJerome Glisse { 1327771fe6b9SJerome Glisse unsigned i; 1328771fe6b9SJerome Glisse uint32_t tmp; 1329771fe6b9SJerome Glisse 1330771fe6b9SJerome Glisse if (r100_rbbm_fifo_wait_for_entry(rdev, 64)) { 1331771fe6b9SJerome Glisse printk(KERN_WARNING "radeon: wait for empty RBBM fifo failed !" 1332771fe6b9SJerome Glisse " Bad things might happen.\n"); 1333771fe6b9SJerome Glisse } 1334771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1335771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1336771fe6b9SJerome Glisse if (!(tmp & (1 << 31))) { 1337771fe6b9SJerome Glisse return 0; 1338771fe6b9SJerome Glisse } 1339771fe6b9SJerome Glisse DRM_UDELAY(1); 1340771fe6b9SJerome Glisse } 1341771fe6b9SJerome Glisse return -1; 1342771fe6b9SJerome Glisse } 1343771fe6b9SJerome Glisse 1344771fe6b9SJerome Glisse int r100_mc_wait_for_idle(struct radeon_device *rdev) 1345771fe6b9SJerome Glisse { 1346771fe6b9SJerome Glisse unsigned i; 1347771fe6b9SJerome Glisse uint32_t tmp; 1348771fe6b9SJerome Glisse 1349771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1350771fe6b9SJerome Glisse /* read MC_STATUS */ 1351771fe6b9SJerome Glisse tmp = RREG32(0x0150); 1352771fe6b9SJerome Glisse if (tmp & (1 << 2)) { 1353771fe6b9SJerome Glisse return 0; 1354771fe6b9SJerome Glisse } 1355771fe6b9SJerome Glisse DRM_UDELAY(1); 1356771fe6b9SJerome Glisse } 1357771fe6b9SJerome Glisse return -1; 1358771fe6b9SJerome Glisse } 1359771fe6b9SJerome Glisse 1360771fe6b9SJerome Glisse void r100_gpu_init(struct radeon_device *rdev) 1361771fe6b9SJerome Glisse { 1362771fe6b9SJerome Glisse /* TODO: anythings to do here ? pipes ? */ 1363771fe6b9SJerome Glisse r100_hdp_reset(rdev); 1364771fe6b9SJerome Glisse } 1365771fe6b9SJerome Glisse 1366771fe6b9SJerome Glisse void r100_hdp_reset(struct radeon_device *rdev) 1367771fe6b9SJerome Glisse { 1368771fe6b9SJerome Glisse uint32_t tmp; 1369771fe6b9SJerome Glisse 1370771fe6b9SJerome Glisse tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; 1371771fe6b9SJerome Glisse tmp |= (7 << 28); 1372771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); 1373771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 1374771fe6b9SJerome Glisse udelay(200); 1375771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 1376771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp); 1377771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 1378771fe6b9SJerome Glisse } 1379771fe6b9SJerome Glisse 1380771fe6b9SJerome Glisse int r100_rb2d_reset(struct radeon_device *rdev) 1381771fe6b9SJerome Glisse { 1382771fe6b9SJerome Glisse uint32_t tmp; 1383771fe6b9SJerome Glisse int i; 1384771fe6b9SJerome Glisse 1385771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_E2); 1386771fe6b9SJerome Glisse (void)RREG32(RADEON_RBBM_SOFT_RESET); 1387771fe6b9SJerome Glisse udelay(200); 1388771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 1389771fe6b9SJerome Glisse /* Wait to prevent race in RBBM_STATUS */ 1390771fe6b9SJerome Glisse mdelay(1); 1391771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1392771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1393771fe6b9SJerome Glisse if (!(tmp & (1 << 26))) { 1394771fe6b9SJerome Glisse DRM_INFO("RB2D reset succeed (RBBM_STATUS=0x%08X)\n", 1395771fe6b9SJerome Glisse tmp); 1396771fe6b9SJerome Glisse return 0; 1397771fe6b9SJerome Glisse } 1398771fe6b9SJerome Glisse DRM_UDELAY(1); 1399771fe6b9SJerome Glisse } 1400771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1401771fe6b9SJerome Glisse DRM_ERROR("Failed to reset RB2D (RBBM_STATUS=0x%08X)!\n", tmp); 1402771fe6b9SJerome Glisse return -1; 1403771fe6b9SJerome Glisse } 1404771fe6b9SJerome Glisse 1405771fe6b9SJerome Glisse int r100_gpu_reset(struct radeon_device *rdev) 1406771fe6b9SJerome Glisse { 1407771fe6b9SJerome Glisse uint32_t status; 1408771fe6b9SJerome Glisse 1409771fe6b9SJerome Glisse /* reset order likely matter */ 1410771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1411771fe6b9SJerome Glisse /* reset HDP */ 1412771fe6b9SJerome Glisse r100_hdp_reset(rdev); 1413771fe6b9SJerome Glisse /* reset rb2d */ 1414771fe6b9SJerome Glisse if (status & ((1 << 17) | (1 << 18) | (1 << 27))) { 1415771fe6b9SJerome Glisse r100_rb2d_reset(rdev); 1416771fe6b9SJerome Glisse } 1417771fe6b9SJerome Glisse /* TODO: reset 3D engine */ 1418771fe6b9SJerome Glisse /* reset CP */ 1419771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1420771fe6b9SJerome Glisse if (status & (1 << 16)) { 1421771fe6b9SJerome Glisse r100_cp_reset(rdev); 1422771fe6b9SJerome Glisse } 1423771fe6b9SJerome Glisse /* Check if GPU is idle */ 1424771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1425771fe6b9SJerome Glisse if (status & (1 << 31)) { 1426771fe6b9SJerome Glisse DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); 1427771fe6b9SJerome Glisse return -1; 1428771fe6b9SJerome Glisse } 1429771fe6b9SJerome Glisse DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status); 1430771fe6b9SJerome Glisse return 0; 1431771fe6b9SJerome Glisse } 1432771fe6b9SJerome Glisse 1433771fe6b9SJerome Glisse 1434771fe6b9SJerome Glisse /* 1435771fe6b9SJerome Glisse * VRAM info 1436771fe6b9SJerome Glisse */ 1437771fe6b9SJerome Glisse static void r100_vram_get_type(struct radeon_device *rdev) 1438771fe6b9SJerome Glisse { 1439771fe6b9SJerome Glisse uint32_t tmp; 1440771fe6b9SJerome Glisse 1441771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = false; 1442771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_IGP) 1443771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1444771fe6b9SJerome Glisse else if (RREG32(RADEON_MEM_SDRAM_MODE_REG) & RADEON_MEM_CFG_TYPE_DDR) 1445771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1446771fe6b9SJerome Glisse if ((rdev->family == CHIP_RV100) || 1447771fe6b9SJerome Glisse (rdev->family == CHIP_RS100) || 1448771fe6b9SJerome Glisse (rdev->family == CHIP_RS200)) { 1449771fe6b9SJerome Glisse tmp = RREG32(RADEON_MEM_CNTL); 1450771fe6b9SJerome Glisse if (tmp & RV100_HALF_MODE) { 1451771fe6b9SJerome Glisse rdev->mc.vram_width = 32; 1452771fe6b9SJerome Glisse } else { 1453771fe6b9SJerome Glisse rdev->mc.vram_width = 64; 1454771fe6b9SJerome Glisse } 1455771fe6b9SJerome Glisse if (rdev->flags & RADEON_SINGLE_CRTC) { 1456771fe6b9SJerome Glisse rdev->mc.vram_width /= 4; 1457771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1458771fe6b9SJerome Glisse } 1459771fe6b9SJerome Glisse } else if (rdev->family <= CHIP_RV280) { 1460771fe6b9SJerome Glisse tmp = RREG32(RADEON_MEM_CNTL); 1461771fe6b9SJerome Glisse if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) { 1462771fe6b9SJerome Glisse rdev->mc.vram_width = 128; 1463771fe6b9SJerome Glisse } else { 1464771fe6b9SJerome Glisse rdev->mc.vram_width = 64; 1465771fe6b9SJerome Glisse } 1466771fe6b9SJerome Glisse } else { 1467771fe6b9SJerome Glisse /* newer IGPs */ 1468771fe6b9SJerome Glisse rdev->mc.vram_width = 128; 1469771fe6b9SJerome Glisse } 1470771fe6b9SJerome Glisse } 1471771fe6b9SJerome Glisse 14722a0f8918SDave Airlie static u32 r100_get_accessible_vram(struct radeon_device *rdev) 1473771fe6b9SJerome Glisse { 14742a0f8918SDave Airlie u32 aper_size; 14752a0f8918SDave Airlie u8 byte; 14762a0f8918SDave Airlie 14772a0f8918SDave Airlie aper_size = RREG32(RADEON_CONFIG_APER_SIZE); 14782a0f8918SDave Airlie 14792a0f8918SDave Airlie /* Set HDP_APER_CNTL only on cards that are known not to be broken, 14802a0f8918SDave Airlie * that is has the 2nd generation multifunction PCI interface 14812a0f8918SDave Airlie */ 14822a0f8918SDave Airlie if (rdev->family == CHIP_RV280 || 14832a0f8918SDave Airlie rdev->family >= CHIP_RV350) { 14842a0f8918SDave Airlie WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, 14852a0f8918SDave Airlie ~RADEON_HDP_APER_CNTL); 14862a0f8918SDave Airlie DRM_INFO("Generation 2 PCI interface, using max accessible memory\n"); 14872a0f8918SDave Airlie return aper_size * 2; 14882a0f8918SDave Airlie } 14892a0f8918SDave Airlie 14902a0f8918SDave Airlie /* Older cards have all sorts of funny issues to deal with. First 14912a0f8918SDave Airlie * check if it's a multifunction card by reading the PCI config 14922a0f8918SDave Airlie * header type... Limit those to one aperture size 14932a0f8918SDave Airlie */ 14942a0f8918SDave Airlie pci_read_config_byte(rdev->pdev, 0xe, &byte); 14952a0f8918SDave Airlie if (byte & 0x80) { 14962a0f8918SDave Airlie DRM_INFO("Generation 1 PCI interface in multifunction mode\n"); 14972a0f8918SDave Airlie DRM_INFO("Limiting VRAM to one aperture\n"); 14982a0f8918SDave Airlie return aper_size; 14992a0f8918SDave Airlie } 15002a0f8918SDave Airlie 15012a0f8918SDave Airlie /* Single function older card. We read HDP_APER_CNTL to see how the BIOS 15022a0f8918SDave Airlie * have set it up. We don't write this as it's broken on some ASICs but 15032a0f8918SDave Airlie * we expect the BIOS to have done the right thing (might be too optimistic...) 15042a0f8918SDave Airlie */ 15052a0f8918SDave Airlie if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) 15062a0f8918SDave Airlie return aper_size * 2; 15072a0f8918SDave Airlie return aper_size; 15082a0f8918SDave Airlie } 15092a0f8918SDave Airlie 15102a0f8918SDave Airlie void r100_vram_init_sizes(struct radeon_device *rdev) 15112a0f8918SDave Airlie { 15122a0f8918SDave Airlie u64 config_aper_size; 15132a0f8918SDave Airlie u32 accessible; 15142a0f8918SDave Airlie 15152a0f8918SDave Airlie config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); 1516771fe6b9SJerome Glisse 1517771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_IGP) { 1518771fe6b9SJerome Glisse uint32_t tom; 1519771fe6b9SJerome Glisse /* read NB_TOM to get the amount of ram stolen for the GPU */ 1520771fe6b9SJerome Glisse tom = RREG32(RADEON_NB_TOM); 15217a50f01aSDave Airlie rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); 15223e43d821SDave Airlie /* for IGPs we need to keep VRAM where it was put by the BIOS */ 15233e43d821SDave Airlie rdev->mc.vram_location = (tom & 0xffff) << 16; 15247a50f01aSDave Airlie WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 15257a50f01aSDave Airlie rdev->mc.mc_vram_size = rdev->mc.real_vram_size; 1526771fe6b9SJerome Glisse } else { 15277a50f01aSDave Airlie rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); 1528771fe6b9SJerome Glisse /* Some production boards of m6 will report 0 1529771fe6b9SJerome Glisse * if it's 8 MB 1530771fe6b9SJerome Glisse */ 15317a50f01aSDave Airlie if (rdev->mc.real_vram_size == 0) { 15327a50f01aSDave Airlie rdev->mc.real_vram_size = 8192 * 1024; 15337a50f01aSDave Airlie WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 1534771fe6b9SJerome Glisse } 15353e43d821SDave Airlie /* let driver place VRAM */ 15363e43d821SDave Airlie rdev->mc.vram_location = 0xFFFFFFFFUL; 15372a0f8918SDave Airlie /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - 15382a0f8918SDave Airlie * Novell bug 204882 + along with lots of ubuntu ones */ 15397a50f01aSDave Airlie if (config_aper_size > rdev->mc.real_vram_size) 15407a50f01aSDave Airlie rdev->mc.mc_vram_size = config_aper_size; 15417a50f01aSDave Airlie else 15427a50f01aSDave Airlie rdev->mc.mc_vram_size = rdev->mc.real_vram_size; 1543771fe6b9SJerome Glisse } 1544771fe6b9SJerome Glisse 15452a0f8918SDave Airlie /* work out accessible VRAM */ 15462a0f8918SDave Airlie accessible = r100_get_accessible_vram(rdev); 15472a0f8918SDave Airlie 1548771fe6b9SJerome Glisse rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); 1549771fe6b9SJerome Glisse rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); 15502a0f8918SDave Airlie 15512a0f8918SDave Airlie if (accessible > rdev->mc.aper_size) 15522a0f8918SDave Airlie accessible = rdev->mc.aper_size; 15532a0f8918SDave Airlie 15547a50f01aSDave Airlie if (rdev->mc.mc_vram_size > rdev->mc.aper_size) 15557a50f01aSDave Airlie rdev->mc.mc_vram_size = rdev->mc.aper_size; 15567a50f01aSDave Airlie 15577a50f01aSDave Airlie if (rdev->mc.real_vram_size > rdev->mc.aper_size) 15587a50f01aSDave Airlie rdev->mc.real_vram_size = rdev->mc.aper_size; 15592a0f8918SDave Airlie } 15602a0f8918SDave Airlie 15612a0f8918SDave Airlie void r100_vram_info(struct radeon_device *rdev) 15622a0f8918SDave Airlie { 15632a0f8918SDave Airlie r100_vram_get_type(rdev); 15642a0f8918SDave Airlie 15652a0f8918SDave Airlie r100_vram_init_sizes(rdev); 1566771fe6b9SJerome Glisse } 1567771fe6b9SJerome Glisse 1568771fe6b9SJerome Glisse 1569771fe6b9SJerome Glisse /* 1570771fe6b9SJerome Glisse * Indirect registers accessor 1571771fe6b9SJerome Glisse */ 1572771fe6b9SJerome Glisse void r100_pll_errata_after_index(struct radeon_device *rdev) 1573771fe6b9SJerome Glisse { 1574771fe6b9SJerome Glisse if (!(rdev->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS)) { 1575771fe6b9SJerome Glisse return; 1576771fe6b9SJerome Glisse } 1577771fe6b9SJerome Glisse (void)RREG32(RADEON_CLOCK_CNTL_DATA); 1578771fe6b9SJerome Glisse (void)RREG32(RADEON_CRTC_GEN_CNTL); 1579771fe6b9SJerome Glisse } 1580771fe6b9SJerome Glisse 1581771fe6b9SJerome Glisse static void r100_pll_errata_after_data(struct radeon_device *rdev) 1582771fe6b9SJerome Glisse { 1583771fe6b9SJerome Glisse /* This workarounds is necessary on RV100, RS100 and RS200 chips 1584771fe6b9SJerome Glisse * or the chip could hang on a subsequent access 1585771fe6b9SJerome Glisse */ 1586771fe6b9SJerome Glisse if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) { 1587771fe6b9SJerome Glisse udelay(5000); 1588771fe6b9SJerome Glisse } 1589771fe6b9SJerome Glisse 1590771fe6b9SJerome Glisse /* This function is required to workaround a hardware bug in some (all?) 1591771fe6b9SJerome Glisse * revisions of the R300. This workaround should be called after every 1592771fe6b9SJerome Glisse * CLOCK_CNTL_INDEX register access. If not, register reads afterward 1593771fe6b9SJerome Glisse * may not be correct. 1594771fe6b9SJerome Glisse */ 1595771fe6b9SJerome Glisse if (rdev->pll_errata & CHIP_ERRATA_R300_CG) { 1596771fe6b9SJerome Glisse uint32_t save, tmp; 1597771fe6b9SJerome Glisse 1598771fe6b9SJerome Glisse save = RREG32(RADEON_CLOCK_CNTL_INDEX); 1599771fe6b9SJerome Glisse tmp = save & ~(0x3f | RADEON_PLL_WR_EN); 1600771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_INDEX, tmp); 1601771fe6b9SJerome Glisse tmp = RREG32(RADEON_CLOCK_CNTL_DATA); 1602771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_INDEX, save); 1603771fe6b9SJerome Glisse } 1604771fe6b9SJerome Glisse } 1605771fe6b9SJerome Glisse 1606771fe6b9SJerome Glisse uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg) 1607771fe6b9SJerome Glisse { 1608771fe6b9SJerome Glisse uint32_t data; 1609771fe6b9SJerome Glisse 1610771fe6b9SJerome Glisse WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f); 1611771fe6b9SJerome Glisse r100_pll_errata_after_index(rdev); 1612771fe6b9SJerome Glisse data = RREG32(RADEON_CLOCK_CNTL_DATA); 1613771fe6b9SJerome Glisse r100_pll_errata_after_data(rdev); 1614771fe6b9SJerome Glisse return data; 1615771fe6b9SJerome Glisse } 1616771fe6b9SJerome Glisse 1617771fe6b9SJerome Glisse void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 1618771fe6b9SJerome Glisse { 1619771fe6b9SJerome Glisse WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN)); 1620771fe6b9SJerome Glisse r100_pll_errata_after_index(rdev); 1621771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_DATA, v); 1622771fe6b9SJerome Glisse r100_pll_errata_after_data(rdev); 1623771fe6b9SJerome Glisse } 1624771fe6b9SJerome Glisse 1625771fe6b9SJerome Glisse uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) 1626771fe6b9SJerome Glisse { 1627771fe6b9SJerome Glisse if (reg < 0x10000) 1628771fe6b9SJerome Glisse return readl(((void __iomem *)rdev->rmmio) + reg); 1629771fe6b9SJerome Glisse else { 1630771fe6b9SJerome Glisse writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); 1631771fe6b9SJerome Glisse return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); 1632771fe6b9SJerome Glisse } 1633771fe6b9SJerome Glisse } 1634771fe6b9SJerome Glisse 1635771fe6b9SJerome Glisse void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 1636771fe6b9SJerome Glisse { 1637771fe6b9SJerome Glisse if (reg < 0x10000) 1638771fe6b9SJerome Glisse writel(v, ((void __iomem *)rdev->rmmio) + reg); 1639771fe6b9SJerome Glisse else { 1640771fe6b9SJerome Glisse writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); 1641771fe6b9SJerome Glisse writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); 1642771fe6b9SJerome Glisse } 1643771fe6b9SJerome Glisse } 1644771fe6b9SJerome Glisse 1645068a117cSJerome Glisse int r100_init(struct radeon_device *rdev) 1646068a117cSJerome Glisse { 1647068a117cSJerome Glisse return 0; 1648068a117cSJerome Glisse } 1649068a117cSJerome Glisse 1650771fe6b9SJerome Glisse /* 1651771fe6b9SJerome Glisse * Debugfs info 1652771fe6b9SJerome Glisse */ 1653771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1654771fe6b9SJerome Glisse static int r100_debugfs_rbbm_info(struct seq_file *m, void *data) 1655771fe6b9SJerome Glisse { 1656771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1657771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1658771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1659771fe6b9SJerome Glisse uint32_t reg, value; 1660771fe6b9SJerome Glisse unsigned i; 1661771fe6b9SJerome Glisse 1662771fe6b9SJerome Glisse seq_printf(m, "RBBM_STATUS 0x%08x\n", RREG32(RADEON_RBBM_STATUS)); 1663771fe6b9SJerome Glisse seq_printf(m, "RBBM_CMDFIFO_STAT 0x%08x\n", RREG32(0xE7C)); 1664771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1665771fe6b9SJerome Glisse for (i = 0; i < 64; i++) { 1666771fe6b9SJerome Glisse WREG32(RADEON_RBBM_CMDFIFO_ADDR, i | 0x100); 1667771fe6b9SJerome Glisse reg = (RREG32(RADEON_RBBM_CMDFIFO_DATA) - 1) >> 2; 1668771fe6b9SJerome Glisse WREG32(RADEON_RBBM_CMDFIFO_ADDR, i); 1669771fe6b9SJerome Glisse value = RREG32(RADEON_RBBM_CMDFIFO_DATA); 1670771fe6b9SJerome Glisse seq_printf(m, "[0x%03X] 0x%04X=0x%08X\n", i, reg, value); 1671771fe6b9SJerome Glisse } 1672771fe6b9SJerome Glisse return 0; 1673771fe6b9SJerome Glisse } 1674771fe6b9SJerome Glisse 1675771fe6b9SJerome Glisse static int r100_debugfs_cp_ring_info(struct seq_file *m, void *data) 1676771fe6b9SJerome Glisse { 1677771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1678771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1679771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1680771fe6b9SJerome Glisse uint32_t rdp, wdp; 1681771fe6b9SJerome Glisse unsigned count, i, j; 1682771fe6b9SJerome Glisse 1683771fe6b9SJerome Glisse radeon_ring_free_size(rdev); 1684771fe6b9SJerome Glisse rdp = RREG32(RADEON_CP_RB_RPTR); 1685771fe6b9SJerome Glisse wdp = RREG32(RADEON_CP_RB_WPTR); 1686771fe6b9SJerome Glisse count = (rdp + rdev->cp.ring_size - wdp) & rdev->cp.ptr_mask; 1687771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1688771fe6b9SJerome Glisse seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp); 1689771fe6b9SJerome Glisse seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp); 1690771fe6b9SJerome Glisse seq_printf(m, "%u free dwords in ring\n", rdev->cp.ring_free_dw); 1691771fe6b9SJerome Glisse seq_printf(m, "%u dwords in ring\n", count); 1692771fe6b9SJerome Glisse for (j = 0; j <= count; j++) { 1693771fe6b9SJerome Glisse i = (rdp + j) & rdev->cp.ptr_mask; 1694771fe6b9SJerome Glisse seq_printf(m, "r[%04d]=0x%08x\n", i, rdev->cp.ring[i]); 1695771fe6b9SJerome Glisse } 1696771fe6b9SJerome Glisse return 0; 1697771fe6b9SJerome Glisse } 1698771fe6b9SJerome Glisse 1699771fe6b9SJerome Glisse 1700771fe6b9SJerome Glisse static int r100_debugfs_cp_csq_fifo(struct seq_file *m, void *data) 1701771fe6b9SJerome Glisse { 1702771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1703771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1704771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1705771fe6b9SJerome Glisse uint32_t csq_stat, csq2_stat, tmp; 1706771fe6b9SJerome Glisse unsigned r_rptr, r_wptr, ib1_rptr, ib1_wptr, ib2_rptr, ib2_wptr; 1707771fe6b9SJerome Glisse unsigned i; 1708771fe6b9SJerome Glisse 1709771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1710771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ_MODE 0x%08x\n", RREG32(RADEON_CP_CSQ_MODE)); 1711771fe6b9SJerome Glisse csq_stat = RREG32(RADEON_CP_CSQ_STAT); 1712771fe6b9SJerome Glisse csq2_stat = RREG32(RADEON_CP_CSQ2_STAT); 1713771fe6b9SJerome Glisse r_rptr = (csq_stat >> 0) & 0x3ff; 1714771fe6b9SJerome Glisse r_wptr = (csq_stat >> 10) & 0x3ff; 1715771fe6b9SJerome Glisse ib1_rptr = (csq_stat >> 20) & 0x3ff; 1716771fe6b9SJerome Glisse ib1_wptr = (csq2_stat >> 0) & 0x3ff; 1717771fe6b9SJerome Glisse ib2_rptr = (csq2_stat >> 10) & 0x3ff; 1718771fe6b9SJerome Glisse ib2_wptr = (csq2_stat >> 20) & 0x3ff; 1719771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ_STAT 0x%08x\n", csq_stat); 1720771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ2_STAT 0x%08x\n", csq2_stat); 1721771fe6b9SJerome Glisse seq_printf(m, "Ring rptr %u\n", r_rptr); 1722771fe6b9SJerome Glisse seq_printf(m, "Ring wptr %u\n", r_wptr); 1723771fe6b9SJerome Glisse seq_printf(m, "Indirect1 rptr %u\n", ib1_rptr); 1724771fe6b9SJerome Glisse seq_printf(m, "Indirect1 wptr %u\n", ib1_wptr); 1725771fe6b9SJerome Glisse seq_printf(m, "Indirect2 rptr %u\n", ib2_rptr); 1726771fe6b9SJerome Glisse seq_printf(m, "Indirect2 wptr %u\n", ib2_wptr); 1727771fe6b9SJerome Glisse /* FIXME: 0, 128, 640 depends on fifo setup see cp_init_kms 1728771fe6b9SJerome Glisse * 128 = indirect1_start * 8 & 640 = indirect2_start * 8 */ 1729771fe6b9SJerome Glisse seq_printf(m, "Ring fifo:\n"); 1730771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 1731771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1732771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1733771fe6b9SJerome Glisse seq_printf(m, "rfifo[%04d]=0x%08X\n", i, tmp); 1734771fe6b9SJerome Glisse } 1735771fe6b9SJerome Glisse seq_printf(m, "Indirect1 fifo:\n"); 1736771fe6b9SJerome Glisse for (i = 256; i <= 512; i++) { 1737771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1738771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1739771fe6b9SJerome Glisse seq_printf(m, "ib1fifo[%04d]=0x%08X\n", i, tmp); 1740771fe6b9SJerome Glisse } 1741771fe6b9SJerome Glisse seq_printf(m, "Indirect2 fifo:\n"); 1742771fe6b9SJerome Glisse for (i = 640; i < ib1_wptr; i++) { 1743771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1744771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1745771fe6b9SJerome Glisse seq_printf(m, "ib2fifo[%04d]=0x%08X\n", i, tmp); 1746771fe6b9SJerome Glisse } 1747771fe6b9SJerome Glisse return 0; 1748771fe6b9SJerome Glisse } 1749771fe6b9SJerome Glisse 1750771fe6b9SJerome Glisse static int r100_debugfs_mc_info(struct seq_file *m, void *data) 1751771fe6b9SJerome Glisse { 1752771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1753771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1754771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1755771fe6b9SJerome Glisse uint32_t tmp; 1756771fe6b9SJerome Glisse 1757771fe6b9SJerome Glisse tmp = RREG32(RADEON_CONFIG_MEMSIZE); 1758771fe6b9SJerome Glisse seq_printf(m, "CONFIG_MEMSIZE 0x%08x\n", tmp); 1759771fe6b9SJerome Glisse tmp = RREG32(RADEON_MC_FB_LOCATION); 1760771fe6b9SJerome Glisse seq_printf(m, "MC_FB_LOCATION 0x%08x\n", tmp); 1761771fe6b9SJerome Glisse tmp = RREG32(RADEON_BUS_CNTL); 1762771fe6b9SJerome Glisse seq_printf(m, "BUS_CNTL 0x%08x\n", tmp); 1763771fe6b9SJerome Glisse tmp = RREG32(RADEON_MC_AGP_LOCATION); 1764771fe6b9SJerome Glisse seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp); 1765771fe6b9SJerome Glisse tmp = RREG32(RADEON_AGP_BASE); 1766771fe6b9SJerome Glisse seq_printf(m, "AGP_BASE 0x%08x\n", tmp); 1767771fe6b9SJerome Glisse tmp = RREG32(RADEON_HOST_PATH_CNTL); 1768771fe6b9SJerome Glisse seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp); 1769771fe6b9SJerome Glisse tmp = RREG32(0x01D0); 1770771fe6b9SJerome Glisse seq_printf(m, "AIC_CTRL 0x%08x\n", tmp); 1771771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_LO_ADDR); 1772771fe6b9SJerome Glisse seq_printf(m, "AIC_LO_ADDR 0x%08x\n", tmp); 1773771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_HI_ADDR); 1774771fe6b9SJerome Glisse seq_printf(m, "AIC_HI_ADDR 0x%08x\n", tmp); 1775771fe6b9SJerome Glisse tmp = RREG32(0x01E4); 1776771fe6b9SJerome Glisse seq_printf(m, "AIC_TLB_ADDR 0x%08x\n", tmp); 1777771fe6b9SJerome Glisse return 0; 1778771fe6b9SJerome Glisse } 1779771fe6b9SJerome Glisse 1780771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_rbbm_list[] = { 1781771fe6b9SJerome Glisse {"r100_rbbm_info", r100_debugfs_rbbm_info, 0, NULL}, 1782771fe6b9SJerome Glisse }; 1783771fe6b9SJerome Glisse 1784771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_cp_list[] = { 1785771fe6b9SJerome Glisse {"r100_cp_ring_info", r100_debugfs_cp_ring_info, 0, NULL}, 1786771fe6b9SJerome Glisse {"r100_cp_csq_fifo", r100_debugfs_cp_csq_fifo, 0, NULL}, 1787771fe6b9SJerome Glisse }; 1788771fe6b9SJerome Glisse 1789771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_mc_info_list[] = { 1790771fe6b9SJerome Glisse {"r100_mc_info", r100_debugfs_mc_info, 0, NULL}, 1791771fe6b9SJerome Glisse }; 1792771fe6b9SJerome Glisse #endif 1793771fe6b9SJerome Glisse 1794771fe6b9SJerome Glisse int r100_debugfs_rbbm_init(struct radeon_device *rdev) 1795771fe6b9SJerome Glisse { 1796771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1797771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_rbbm_list, 1); 1798771fe6b9SJerome Glisse #else 1799771fe6b9SJerome Glisse return 0; 1800771fe6b9SJerome Glisse #endif 1801771fe6b9SJerome Glisse } 1802771fe6b9SJerome Glisse 1803771fe6b9SJerome Glisse int r100_debugfs_cp_init(struct radeon_device *rdev) 1804771fe6b9SJerome Glisse { 1805771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1806771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_cp_list, 2); 1807771fe6b9SJerome Glisse #else 1808771fe6b9SJerome Glisse return 0; 1809771fe6b9SJerome Glisse #endif 1810771fe6b9SJerome Glisse } 1811771fe6b9SJerome Glisse 1812771fe6b9SJerome Glisse int r100_debugfs_mc_info_init(struct radeon_device *rdev) 1813771fe6b9SJerome Glisse { 1814771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1815771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_mc_info_list, 1); 1816771fe6b9SJerome Glisse #else 1817771fe6b9SJerome Glisse return 0; 1818771fe6b9SJerome Glisse #endif 1819771fe6b9SJerome Glisse } 1820e024e110SDave Airlie 1821e024e110SDave Airlie int r100_set_surface_reg(struct radeon_device *rdev, int reg, 1822e024e110SDave Airlie uint32_t tiling_flags, uint32_t pitch, 1823e024e110SDave Airlie uint32_t offset, uint32_t obj_size) 1824e024e110SDave Airlie { 1825e024e110SDave Airlie int surf_index = reg * 16; 1826e024e110SDave Airlie int flags = 0; 1827e024e110SDave Airlie 1828e024e110SDave Airlie /* r100/r200 divide by 16 */ 1829e024e110SDave Airlie if (rdev->family < CHIP_R300) 1830e024e110SDave Airlie flags = pitch / 16; 1831e024e110SDave Airlie else 1832e024e110SDave Airlie flags = pitch / 8; 1833e024e110SDave Airlie 1834e024e110SDave Airlie if (rdev->family <= CHIP_RS200) { 1835e024e110SDave Airlie if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) 1836e024e110SDave Airlie == (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) 1837e024e110SDave Airlie flags |= RADEON_SURF_TILE_COLOR_BOTH; 1838e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MACRO) 1839e024e110SDave Airlie flags |= RADEON_SURF_TILE_COLOR_MACRO; 1840e024e110SDave Airlie } else if (rdev->family <= CHIP_RV280) { 1841e024e110SDave Airlie if (tiling_flags & (RADEON_TILING_MACRO)) 1842e024e110SDave Airlie flags |= R200_SURF_TILE_COLOR_MACRO; 1843e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MICRO) 1844e024e110SDave Airlie flags |= R200_SURF_TILE_COLOR_MICRO; 1845e024e110SDave Airlie } else { 1846e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MACRO) 1847e024e110SDave Airlie flags |= R300_SURF_TILE_MACRO; 1848e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MICRO) 1849e024e110SDave Airlie flags |= R300_SURF_TILE_MICRO; 1850e024e110SDave Airlie } 1851e024e110SDave Airlie 1852e024e110SDave Airlie DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1); 1853e024e110SDave Airlie WREG32(RADEON_SURFACE0_INFO + surf_index, flags); 1854e024e110SDave Airlie WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); 1855e024e110SDave Airlie WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1); 1856e024e110SDave Airlie return 0; 1857e024e110SDave Airlie } 1858e024e110SDave Airlie 1859e024e110SDave Airlie void r100_clear_surface_reg(struct radeon_device *rdev, int reg) 1860e024e110SDave Airlie { 1861e024e110SDave Airlie int surf_index = reg * 16; 1862e024e110SDave Airlie WREG32(RADEON_SURFACE0_INFO + surf_index, 0); 1863e024e110SDave Airlie } 1864c93bb85bSJerome Glisse 1865c93bb85bSJerome Glisse void r100_bandwidth_update(struct radeon_device *rdev) 1866c93bb85bSJerome Glisse { 1867c93bb85bSJerome Glisse fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; 1868c93bb85bSJerome Glisse fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; 1869c93bb85bSJerome Glisse fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; 1870c93bb85bSJerome Glisse uint32_t temp, data, mem_trcd, mem_trp, mem_tras; 1871c93bb85bSJerome Glisse fixed20_12 memtcas_ff[8] = { 1872c93bb85bSJerome Glisse fixed_init(1), 1873c93bb85bSJerome Glisse fixed_init(2), 1874c93bb85bSJerome Glisse fixed_init(3), 1875c93bb85bSJerome Glisse fixed_init(0), 1876c93bb85bSJerome Glisse fixed_init_half(1), 1877c93bb85bSJerome Glisse fixed_init_half(2), 1878c93bb85bSJerome Glisse fixed_init(0), 1879c93bb85bSJerome Glisse }; 1880c93bb85bSJerome Glisse fixed20_12 memtcas_rs480_ff[8] = { 1881c93bb85bSJerome Glisse fixed_init(0), 1882c93bb85bSJerome Glisse fixed_init(1), 1883c93bb85bSJerome Glisse fixed_init(2), 1884c93bb85bSJerome Glisse fixed_init(3), 1885c93bb85bSJerome Glisse fixed_init(0), 1886c93bb85bSJerome Glisse fixed_init_half(1), 1887c93bb85bSJerome Glisse fixed_init_half(2), 1888c93bb85bSJerome Glisse fixed_init_half(3), 1889c93bb85bSJerome Glisse }; 1890c93bb85bSJerome Glisse fixed20_12 memtcas2_ff[8] = { 1891c93bb85bSJerome Glisse fixed_init(0), 1892c93bb85bSJerome Glisse fixed_init(1), 1893c93bb85bSJerome Glisse fixed_init(2), 1894c93bb85bSJerome Glisse fixed_init(3), 1895c93bb85bSJerome Glisse fixed_init(4), 1896c93bb85bSJerome Glisse fixed_init(5), 1897c93bb85bSJerome Glisse fixed_init(6), 1898c93bb85bSJerome Glisse fixed_init(7), 1899c93bb85bSJerome Glisse }; 1900c93bb85bSJerome Glisse fixed20_12 memtrbs[8] = { 1901c93bb85bSJerome Glisse fixed_init(1), 1902c93bb85bSJerome Glisse fixed_init_half(1), 1903c93bb85bSJerome Glisse fixed_init(2), 1904c93bb85bSJerome Glisse fixed_init_half(2), 1905c93bb85bSJerome Glisse fixed_init(3), 1906c93bb85bSJerome Glisse fixed_init_half(3), 1907c93bb85bSJerome Glisse fixed_init(4), 1908c93bb85bSJerome Glisse fixed_init_half(4) 1909c93bb85bSJerome Glisse }; 1910c93bb85bSJerome Glisse fixed20_12 memtrbs_r4xx[8] = { 1911c93bb85bSJerome Glisse fixed_init(4), 1912c93bb85bSJerome Glisse fixed_init(5), 1913c93bb85bSJerome Glisse fixed_init(6), 1914c93bb85bSJerome Glisse fixed_init(7), 1915c93bb85bSJerome Glisse fixed_init(8), 1916c93bb85bSJerome Glisse fixed_init(9), 1917c93bb85bSJerome Glisse fixed_init(10), 1918c93bb85bSJerome Glisse fixed_init(11) 1919c93bb85bSJerome Glisse }; 1920c93bb85bSJerome Glisse fixed20_12 min_mem_eff; 1921c93bb85bSJerome Glisse fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; 1922c93bb85bSJerome Glisse fixed20_12 cur_latency_mclk, cur_latency_sclk; 1923c93bb85bSJerome Glisse fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, 1924c93bb85bSJerome Glisse disp_drain_rate2, read_return_rate; 1925c93bb85bSJerome Glisse fixed20_12 time_disp1_drop_priority; 1926c93bb85bSJerome Glisse int c; 1927c93bb85bSJerome Glisse int cur_size = 16; /* in octawords */ 1928c93bb85bSJerome Glisse int critical_point = 0, critical_point2; 1929c93bb85bSJerome Glisse /* uint32_t read_return_rate, time_disp1_drop_priority; */ 1930c93bb85bSJerome Glisse int stop_req, max_stop_req; 1931c93bb85bSJerome Glisse struct drm_display_mode *mode1 = NULL; 1932c93bb85bSJerome Glisse struct drm_display_mode *mode2 = NULL; 1933c93bb85bSJerome Glisse uint32_t pixel_bytes1 = 0; 1934c93bb85bSJerome Glisse uint32_t pixel_bytes2 = 0; 1935c93bb85bSJerome Glisse 1936c93bb85bSJerome Glisse if (rdev->mode_info.crtcs[0]->base.enabled) { 1937c93bb85bSJerome Glisse mode1 = &rdev->mode_info.crtcs[0]->base.mode; 1938c93bb85bSJerome Glisse pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; 1939c93bb85bSJerome Glisse } 1940c93bb85bSJerome Glisse if (rdev->mode_info.crtcs[1]->base.enabled) { 1941c93bb85bSJerome Glisse mode2 = &rdev->mode_info.crtcs[1]->base.mode; 1942c93bb85bSJerome Glisse pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; 1943c93bb85bSJerome Glisse } 1944c93bb85bSJerome Glisse 1945c93bb85bSJerome Glisse min_mem_eff.full = rfixed_const_8(0); 1946c93bb85bSJerome Glisse /* get modes */ 1947c93bb85bSJerome Glisse if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { 1948c93bb85bSJerome Glisse uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); 1949c93bb85bSJerome Glisse mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); 1950c93bb85bSJerome Glisse mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); 1951c93bb85bSJerome Glisse /* check crtc enables */ 1952c93bb85bSJerome Glisse if (mode2) 1953c93bb85bSJerome Glisse mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); 1954c93bb85bSJerome Glisse if (mode1) 1955c93bb85bSJerome Glisse mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); 1956c93bb85bSJerome Glisse WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); 1957c93bb85bSJerome Glisse } 1958c93bb85bSJerome Glisse 1959c93bb85bSJerome Glisse /* 1960c93bb85bSJerome Glisse * determine is there is enough bw for current mode 1961c93bb85bSJerome Glisse */ 1962c93bb85bSJerome Glisse mclk_ff.full = rfixed_const(rdev->clock.default_mclk); 1963c93bb85bSJerome Glisse temp_ff.full = rfixed_const(100); 1964c93bb85bSJerome Glisse mclk_ff.full = rfixed_div(mclk_ff, temp_ff); 1965c93bb85bSJerome Glisse sclk_ff.full = rfixed_const(rdev->clock.default_sclk); 1966c93bb85bSJerome Glisse sclk_ff.full = rfixed_div(sclk_ff, temp_ff); 1967c93bb85bSJerome Glisse 1968c93bb85bSJerome Glisse temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); 1969c93bb85bSJerome Glisse temp_ff.full = rfixed_const(temp); 1970c93bb85bSJerome Glisse mem_bw.full = rfixed_mul(mclk_ff, temp_ff); 1971c93bb85bSJerome Glisse 1972c93bb85bSJerome Glisse pix_clk.full = 0; 1973c93bb85bSJerome Glisse pix_clk2.full = 0; 1974c93bb85bSJerome Glisse peak_disp_bw.full = 0; 1975c93bb85bSJerome Glisse if (mode1) { 1976c93bb85bSJerome Glisse temp_ff.full = rfixed_const(1000); 1977c93bb85bSJerome Glisse pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ 1978c93bb85bSJerome Glisse pix_clk.full = rfixed_div(pix_clk, temp_ff); 1979c93bb85bSJerome Glisse temp_ff.full = rfixed_const(pixel_bytes1); 1980c93bb85bSJerome Glisse peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); 1981c93bb85bSJerome Glisse } 1982c93bb85bSJerome Glisse if (mode2) { 1983c93bb85bSJerome Glisse temp_ff.full = rfixed_const(1000); 1984c93bb85bSJerome Glisse pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ 1985c93bb85bSJerome Glisse pix_clk2.full = rfixed_div(pix_clk2, temp_ff); 1986c93bb85bSJerome Glisse temp_ff.full = rfixed_const(pixel_bytes2); 1987c93bb85bSJerome Glisse peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); 1988c93bb85bSJerome Glisse } 1989c93bb85bSJerome Glisse 1990c93bb85bSJerome Glisse mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); 1991c93bb85bSJerome Glisse if (peak_disp_bw.full >= mem_bw.full) { 1992c93bb85bSJerome Glisse DRM_ERROR("You may not have enough display bandwidth for current mode\n" 1993c93bb85bSJerome Glisse "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); 1994c93bb85bSJerome Glisse } 1995c93bb85bSJerome Glisse 1996c93bb85bSJerome Glisse /* Get values from the EXT_MEM_CNTL register...converting its contents. */ 1997c93bb85bSJerome Glisse temp = RREG32(RADEON_MEM_TIMING_CNTL); 1998c93bb85bSJerome Glisse if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ 1999c93bb85bSJerome Glisse mem_trcd = ((temp >> 2) & 0x3) + 1; 2000c93bb85bSJerome Glisse mem_trp = ((temp & 0x3)) + 1; 2001c93bb85bSJerome Glisse mem_tras = ((temp & 0x70) >> 4) + 1; 2002c93bb85bSJerome Glisse } else if (rdev->family == CHIP_R300 || 2003c93bb85bSJerome Glisse rdev->family == CHIP_R350) { /* r300, r350 */ 2004c93bb85bSJerome Glisse mem_trcd = (temp & 0x7) + 1; 2005c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0x7) + 1; 2006c93bb85bSJerome Glisse mem_tras = ((temp >> 11) & 0xf) + 4; 2007c93bb85bSJerome Glisse } else if (rdev->family == CHIP_RV350 || 2008c93bb85bSJerome Glisse rdev->family <= CHIP_RV380) { 2009c93bb85bSJerome Glisse /* rv3x0 */ 2010c93bb85bSJerome Glisse mem_trcd = (temp & 0x7) + 3; 2011c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0x7) + 3; 2012c93bb85bSJerome Glisse mem_tras = ((temp >> 11) & 0xf) + 6; 2013c93bb85bSJerome Glisse } else if (rdev->family == CHIP_R420 || 2014c93bb85bSJerome Glisse rdev->family == CHIP_R423 || 2015c93bb85bSJerome Glisse rdev->family == CHIP_RV410) { 2016c93bb85bSJerome Glisse /* r4xx */ 2017c93bb85bSJerome Glisse mem_trcd = (temp & 0xf) + 3; 2018c93bb85bSJerome Glisse if (mem_trcd > 15) 2019c93bb85bSJerome Glisse mem_trcd = 15; 2020c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0xf) + 3; 2021c93bb85bSJerome Glisse if (mem_trp > 15) 2022c93bb85bSJerome Glisse mem_trp = 15; 2023c93bb85bSJerome Glisse mem_tras = ((temp >> 12) & 0x1f) + 6; 2024c93bb85bSJerome Glisse if (mem_tras > 31) 2025c93bb85bSJerome Glisse mem_tras = 31; 2026c93bb85bSJerome Glisse } else { /* RV200, R200 */ 2027c93bb85bSJerome Glisse mem_trcd = (temp & 0x7) + 1; 2028c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0x7) + 1; 2029c93bb85bSJerome Glisse mem_tras = ((temp >> 12) & 0xf) + 4; 2030c93bb85bSJerome Glisse } 2031c93bb85bSJerome Glisse /* convert to FF */ 2032c93bb85bSJerome Glisse trcd_ff.full = rfixed_const(mem_trcd); 2033c93bb85bSJerome Glisse trp_ff.full = rfixed_const(mem_trp); 2034c93bb85bSJerome Glisse tras_ff.full = rfixed_const(mem_tras); 2035c93bb85bSJerome Glisse 2036c93bb85bSJerome Glisse /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ 2037c93bb85bSJerome Glisse temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); 2038c93bb85bSJerome Glisse data = (temp & (7 << 20)) >> 20; 2039c93bb85bSJerome Glisse if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { 2040c93bb85bSJerome Glisse if (rdev->family == CHIP_RS480) /* don't think rs400 */ 2041c93bb85bSJerome Glisse tcas_ff = memtcas_rs480_ff[data]; 2042c93bb85bSJerome Glisse else 2043c93bb85bSJerome Glisse tcas_ff = memtcas_ff[data]; 2044c93bb85bSJerome Glisse } else 2045c93bb85bSJerome Glisse tcas_ff = memtcas2_ff[data]; 2046c93bb85bSJerome Glisse 2047c93bb85bSJerome Glisse if (rdev->family == CHIP_RS400 || 2048c93bb85bSJerome Glisse rdev->family == CHIP_RS480) { 2049c93bb85bSJerome Glisse /* extra cas latency stored in bits 23-25 0-4 clocks */ 2050c93bb85bSJerome Glisse data = (temp >> 23) & 0x7; 2051c93bb85bSJerome Glisse if (data < 5) 2052c93bb85bSJerome Glisse tcas_ff.full += rfixed_const(data); 2053c93bb85bSJerome Glisse } 2054c93bb85bSJerome Glisse 2055c93bb85bSJerome Glisse if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { 2056c93bb85bSJerome Glisse /* on the R300, Tcas is included in Trbs. 2057c93bb85bSJerome Glisse */ 2058c93bb85bSJerome Glisse temp = RREG32(RADEON_MEM_CNTL); 2059c93bb85bSJerome Glisse data = (R300_MEM_NUM_CHANNELS_MASK & temp); 2060c93bb85bSJerome Glisse if (data == 1) { 2061c93bb85bSJerome Glisse if (R300_MEM_USE_CD_CH_ONLY & temp) { 2062c93bb85bSJerome Glisse temp = RREG32(R300_MC_IND_INDEX); 2063c93bb85bSJerome Glisse temp &= ~R300_MC_IND_ADDR_MASK; 2064c93bb85bSJerome Glisse temp |= R300_MC_READ_CNTL_CD_mcind; 2065c93bb85bSJerome Glisse WREG32(R300_MC_IND_INDEX, temp); 2066c93bb85bSJerome Glisse temp = RREG32(R300_MC_IND_DATA); 2067c93bb85bSJerome Glisse data = (R300_MEM_RBS_POSITION_C_MASK & temp); 2068c93bb85bSJerome Glisse } else { 2069c93bb85bSJerome Glisse temp = RREG32(R300_MC_READ_CNTL_AB); 2070c93bb85bSJerome Glisse data = (R300_MEM_RBS_POSITION_A_MASK & temp); 2071c93bb85bSJerome Glisse } 2072c93bb85bSJerome Glisse } else { 2073c93bb85bSJerome Glisse temp = RREG32(R300_MC_READ_CNTL_AB); 2074c93bb85bSJerome Glisse data = (R300_MEM_RBS_POSITION_A_MASK & temp); 2075c93bb85bSJerome Glisse } 2076c93bb85bSJerome Glisse if (rdev->family == CHIP_RV410 || 2077c93bb85bSJerome Glisse rdev->family == CHIP_R420 || 2078c93bb85bSJerome Glisse rdev->family == CHIP_R423) 2079c93bb85bSJerome Glisse trbs_ff = memtrbs_r4xx[data]; 2080c93bb85bSJerome Glisse else 2081c93bb85bSJerome Glisse trbs_ff = memtrbs[data]; 2082c93bb85bSJerome Glisse tcas_ff.full += trbs_ff.full; 2083c93bb85bSJerome Glisse } 2084c93bb85bSJerome Glisse 2085c93bb85bSJerome Glisse sclk_eff_ff.full = sclk_ff.full; 2086c93bb85bSJerome Glisse 2087c93bb85bSJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 2088c93bb85bSJerome Glisse fixed20_12 agpmode_ff; 2089c93bb85bSJerome Glisse agpmode_ff.full = rfixed_const(radeon_agpmode); 2090c93bb85bSJerome Glisse temp_ff.full = rfixed_const_666(16); 2091c93bb85bSJerome Glisse sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff); 2092c93bb85bSJerome Glisse } 2093c93bb85bSJerome Glisse /* TODO PCIE lanes may affect this - agpmode == 16?? */ 2094c93bb85bSJerome Glisse 2095c93bb85bSJerome Glisse if (ASIC_IS_R300(rdev)) { 2096c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(250); 2097c93bb85bSJerome Glisse } else { 2098c93bb85bSJerome Glisse if ((rdev->family == CHIP_RV100) || 2099c93bb85bSJerome Glisse rdev->flags & RADEON_IS_IGP) { 2100c93bb85bSJerome Glisse if (rdev->mc.vram_is_ddr) 2101c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(41); 2102c93bb85bSJerome Glisse else 2103c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(33); 2104c93bb85bSJerome Glisse } else { 2105c93bb85bSJerome Glisse if (rdev->mc.vram_width == 128) 2106c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(57); 2107c93bb85bSJerome Glisse else 2108c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(41); 2109c93bb85bSJerome Glisse } 2110c93bb85bSJerome Glisse } 2111c93bb85bSJerome Glisse 2112c93bb85bSJerome Glisse mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff); 2113c93bb85bSJerome Glisse 2114c93bb85bSJerome Glisse if (rdev->mc.vram_is_ddr) { 2115c93bb85bSJerome Glisse if (rdev->mc.vram_width == 32) { 2116c93bb85bSJerome Glisse k1.full = rfixed_const(40); 2117c93bb85bSJerome Glisse c = 3; 2118c93bb85bSJerome Glisse } else { 2119c93bb85bSJerome Glisse k1.full = rfixed_const(20); 2120c93bb85bSJerome Glisse c = 1; 2121c93bb85bSJerome Glisse } 2122c93bb85bSJerome Glisse } else { 2123c93bb85bSJerome Glisse k1.full = rfixed_const(40); 2124c93bb85bSJerome Glisse c = 3; 2125c93bb85bSJerome Glisse } 2126c93bb85bSJerome Glisse 2127c93bb85bSJerome Glisse temp_ff.full = rfixed_const(2); 2128c93bb85bSJerome Glisse mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff); 2129c93bb85bSJerome Glisse temp_ff.full = rfixed_const(c); 2130c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff); 2131c93bb85bSJerome Glisse temp_ff.full = rfixed_const(4); 2132c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff); 2133c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff); 2134c93bb85bSJerome Glisse mc_latency_mclk.full += k1.full; 2135c93bb85bSJerome Glisse 2136c93bb85bSJerome Glisse mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff); 2137c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff); 2138c93bb85bSJerome Glisse 2139c93bb85bSJerome Glisse /* 2140c93bb85bSJerome Glisse HW cursor time assuming worst case of full size colour cursor. 2141c93bb85bSJerome Glisse */ 2142c93bb85bSJerome Glisse temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); 2143c93bb85bSJerome Glisse temp_ff.full += trcd_ff.full; 2144c93bb85bSJerome Glisse if (temp_ff.full < tras_ff.full) 2145c93bb85bSJerome Glisse temp_ff.full = tras_ff.full; 2146c93bb85bSJerome Glisse cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff); 2147c93bb85bSJerome Glisse 2148c93bb85bSJerome Glisse temp_ff.full = rfixed_const(cur_size); 2149c93bb85bSJerome Glisse cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff); 2150c93bb85bSJerome Glisse /* 2151c93bb85bSJerome Glisse Find the total latency for the display data. 2152c93bb85bSJerome Glisse */ 2153c93bb85bSJerome Glisse disp_latency_overhead.full = rfixed_const(80); 2154c93bb85bSJerome Glisse disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff); 2155c93bb85bSJerome Glisse mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; 2156c93bb85bSJerome Glisse mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; 2157c93bb85bSJerome Glisse 2158c93bb85bSJerome Glisse if (mc_latency_mclk.full > mc_latency_sclk.full) 2159c93bb85bSJerome Glisse disp_latency.full = mc_latency_mclk.full; 2160c93bb85bSJerome Glisse else 2161c93bb85bSJerome Glisse disp_latency.full = mc_latency_sclk.full; 2162c93bb85bSJerome Glisse 2163c93bb85bSJerome Glisse /* setup Max GRPH_STOP_REQ default value */ 2164c93bb85bSJerome Glisse if (ASIC_IS_RV100(rdev)) 2165c93bb85bSJerome Glisse max_stop_req = 0x5c; 2166c93bb85bSJerome Glisse else 2167c93bb85bSJerome Glisse max_stop_req = 0x7c; 2168c93bb85bSJerome Glisse 2169c93bb85bSJerome Glisse if (mode1) { 2170c93bb85bSJerome Glisse /* CRTC1 2171c93bb85bSJerome Glisse Set GRPH_BUFFER_CNTL register using h/w defined optimal values. 2172c93bb85bSJerome Glisse GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] 2173c93bb85bSJerome Glisse */ 2174c93bb85bSJerome Glisse stop_req = mode1->hdisplay * pixel_bytes1 / 16; 2175c93bb85bSJerome Glisse 2176c93bb85bSJerome Glisse if (stop_req > max_stop_req) 2177c93bb85bSJerome Glisse stop_req = max_stop_req; 2178c93bb85bSJerome Glisse 2179c93bb85bSJerome Glisse /* 2180c93bb85bSJerome Glisse Find the drain rate of the display buffer. 2181c93bb85bSJerome Glisse */ 2182c93bb85bSJerome Glisse temp_ff.full = rfixed_const((16/pixel_bytes1)); 2183c93bb85bSJerome Glisse disp_drain_rate.full = rfixed_div(pix_clk, temp_ff); 2184c93bb85bSJerome Glisse 2185c93bb85bSJerome Glisse /* 2186c93bb85bSJerome Glisse Find the critical point of the display buffer. 2187c93bb85bSJerome Glisse */ 2188c93bb85bSJerome Glisse crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency); 2189c93bb85bSJerome Glisse crit_point_ff.full += rfixed_const_half(0); 2190c93bb85bSJerome Glisse 2191c93bb85bSJerome Glisse critical_point = rfixed_trunc(crit_point_ff); 2192c93bb85bSJerome Glisse 2193c93bb85bSJerome Glisse if (rdev->disp_priority == 2) { 2194c93bb85bSJerome Glisse critical_point = 0; 2195c93bb85bSJerome Glisse } 2196c93bb85bSJerome Glisse 2197c93bb85bSJerome Glisse /* 2198c93bb85bSJerome Glisse The critical point should never be above max_stop_req-4. Setting 2199c93bb85bSJerome Glisse GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. 2200c93bb85bSJerome Glisse */ 2201c93bb85bSJerome Glisse if (max_stop_req - critical_point < 4) 2202c93bb85bSJerome Glisse critical_point = 0; 2203c93bb85bSJerome Glisse 2204c93bb85bSJerome Glisse if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { 2205c93bb85bSJerome Glisse /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ 2206c93bb85bSJerome Glisse critical_point = 0x10; 2207c93bb85bSJerome Glisse } 2208c93bb85bSJerome Glisse 2209c93bb85bSJerome Glisse temp = RREG32(RADEON_GRPH_BUFFER_CNTL); 2210c93bb85bSJerome Glisse temp &= ~(RADEON_GRPH_STOP_REQ_MASK); 2211c93bb85bSJerome Glisse temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); 2212c93bb85bSJerome Glisse temp &= ~(RADEON_GRPH_START_REQ_MASK); 2213c93bb85bSJerome Glisse if ((rdev->family == CHIP_R350) && 2214c93bb85bSJerome Glisse (stop_req > 0x15)) { 2215c93bb85bSJerome Glisse stop_req -= 0x10; 2216c93bb85bSJerome Glisse } 2217c93bb85bSJerome Glisse temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); 2218c93bb85bSJerome Glisse temp |= RADEON_GRPH_BUFFER_SIZE; 2219c93bb85bSJerome Glisse temp &= ~(RADEON_GRPH_CRITICAL_CNTL | 2220c93bb85bSJerome Glisse RADEON_GRPH_CRITICAL_AT_SOF | 2221c93bb85bSJerome Glisse RADEON_GRPH_STOP_CNTL); 2222c93bb85bSJerome Glisse /* 2223c93bb85bSJerome Glisse Write the result into the register. 2224c93bb85bSJerome Glisse */ 2225c93bb85bSJerome Glisse WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | 2226c93bb85bSJerome Glisse (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); 2227c93bb85bSJerome Glisse 2228c93bb85bSJerome Glisse #if 0 2229c93bb85bSJerome Glisse if ((rdev->family == CHIP_RS400) || 2230c93bb85bSJerome Glisse (rdev->family == CHIP_RS480)) { 2231c93bb85bSJerome Glisse /* attempt to program RS400 disp regs correctly ??? */ 2232c93bb85bSJerome Glisse temp = RREG32(RS400_DISP1_REG_CNTL); 2233c93bb85bSJerome Glisse temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | 2234c93bb85bSJerome Glisse RS400_DISP1_STOP_REQ_LEVEL_MASK); 2235c93bb85bSJerome Glisse WREG32(RS400_DISP1_REQ_CNTL1, (temp | 2236c93bb85bSJerome Glisse (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | 2237c93bb85bSJerome Glisse (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); 2238c93bb85bSJerome Glisse temp = RREG32(RS400_DMIF_MEM_CNTL1); 2239c93bb85bSJerome Glisse temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | 2240c93bb85bSJerome Glisse RS400_DISP1_CRITICAL_POINT_STOP_MASK); 2241c93bb85bSJerome Glisse WREG32(RS400_DMIF_MEM_CNTL1, (temp | 2242c93bb85bSJerome Glisse (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | 2243c93bb85bSJerome Glisse (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); 2244c93bb85bSJerome Glisse } 2245c93bb85bSJerome Glisse #endif 2246c93bb85bSJerome Glisse 2247c93bb85bSJerome Glisse DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n", 2248c93bb85bSJerome Glisse /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ 2249c93bb85bSJerome Glisse (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); 2250c93bb85bSJerome Glisse } 2251c93bb85bSJerome Glisse 2252c93bb85bSJerome Glisse if (mode2) { 2253c93bb85bSJerome Glisse u32 grph2_cntl; 2254c93bb85bSJerome Glisse stop_req = mode2->hdisplay * pixel_bytes2 / 16; 2255c93bb85bSJerome Glisse 2256c93bb85bSJerome Glisse if (stop_req > max_stop_req) 2257c93bb85bSJerome Glisse stop_req = max_stop_req; 2258c93bb85bSJerome Glisse 2259c93bb85bSJerome Glisse /* 2260c93bb85bSJerome Glisse Find the drain rate of the display buffer. 2261c93bb85bSJerome Glisse */ 2262c93bb85bSJerome Glisse temp_ff.full = rfixed_const((16/pixel_bytes2)); 2263c93bb85bSJerome Glisse disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff); 2264c93bb85bSJerome Glisse 2265c93bb85bSJerome Glisse grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); 2266c93bb85bSJerome Glisse grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); 2267c93bb85bSJerome Glisse grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); 2268c93bb85bSJerome Glisse grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); 2269c93bb85bSJerome Glisse if ((rdev->family == CHIP_R350) && 2270c93bb85bSJerome Glisse (stop_req > 0x15)) { 2271c93bb85bSJerome Glisse stop_req -= 0x10; 2272c93bb85bSJerome Glisse } 2273c93bb85bSJerome Glisse grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); 2274c93bb85bSJerome Glisse grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; 2275c93bb85bSJerome Glisse grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | 2276c93bb85bSJerome Glisse RADEON_GRPH_CRITICAL_AT_SOF | 2277c93bb85bSJerome Glisse RADEON_GRPH_STOP_CNTL); 2278c93bb85bSJerome Glisse 2279c93bb85bSJerome Glisse if ((rdev->family == CHIP_RS100) || 2280c93bb85bSJerome Glisse (rdev->family == CHIP_RS200)) 2281c93bb85bSJerome Glisse critical_point2 = 0; 2282c93bb85bSJerome Glisse else { 2283c93bb85bSJerome Glisse temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; 2284c93bb85bSJerome Glisse temp_ff.full = rfixed_const(temp); 2285c93bb85bSJerome Glisse temp_ff.full = rfixed_mul(mclk_ff, temp_ff); 2286c93bb85bSJerome Glisse if (sclk_ff.full < temp_ff.full) 2287c93bb85bSJerome Glisse temp_ff.full = sclk_ff.full; 2288c93bb85bSJerome Glisse 2289c93bb85bSJerome Glisse read_return_rate.full = temp_ff.full; 2290c93bb85bSJerome Glisse 2291c93bb85bSJerome Glisse if (mode1) { 2292c93bb85bSJerome Glisse temp_ff.full = read_return_rate.full - disp_drain_rate.full; 2293c93bb85bSJerome Glisse time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff); 2294c93bb85bSJerome Glisse } else { 2295c93bb85bSJerome Glisse time_disp1_drop_priority.full = 0; 2296c93bb85bSJerome Glisse } 2297c93bb85bSJerome Glisse crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; 2298c93bb85bSJerome Glisse crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2); 2299c93bb85bSJerome Glisse crit_point_ff.full += rfixed_const_half(0); 2300c93bb85bSJerome Glisse 2301c93bb85bSJerome Glisse critical_point2 = rfixed_trunc(crit_point_ff); 2302c93bb85bSJerome Glisse 2303c93bb85bSJerome Glisse if (rdev->disp_priority == 2) { 2304c93bb85bSJerome Glisse critical_point2 = 0; 2305c93bb85bSJerome Glisse } 2306c93bb85bSJerome Glisse 2307c93bb85bSJerome Glisse if (max_stop_req - critical_point2 < 4) 2308c93bb85bSJerome Glisse critical_point2 = 0; 2309c93bb85bSJerome Glisse 2310c93bb85bSJerome Glisse } 2311c93bb85bSJerome Glisse 2312c93bb85bSJerome Glisse if (critical_point2 == 0 && rdev->family == CHIP_R300) { 2313c93bb85bSJerome Glisse /* some R300 cards have problem with this set to 0 */ 2314c93bb85bSJerome Glisse critical_point2 = 0x10; 2315c93bb85bSJerome Glisse } 2316c93bb85bSJerome Glisse 2317c93bb85bSJerome Glisse WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | 2318c93bb85bSJerome Glisse (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); 2319c93bb85bSJerome Glisse 2320c93bb85bSJerome Glisse if ((rdev->family == CHIP_RS400) || 2321c93bb85bSJerome Glisse (rdev->family == CHIP_RS480)) { 2322c93bb85bSJerome Glisse #if 0 2323c93bb85bSJerome Glisse /* attempt to program RS400 disp2 regs correctly ??? */ 2324c93bb85bSJerome Glisse temp = RREG32(RS400_DISP2_REQ_CNTL1); 2325c93bb85bSJerome Glisse temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | 2326c93bb85bSJerome Glisse RS400_DISP2_STOP_REQ_LEVEL_MASK); 2327c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL1, (temp | 2328c93bb85bSJerome Glisse (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | 2329c93bb85bSJerome Glisse (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); 2330c93bb85bSJerome Glisse temp = RREG32(RS400_DISP2_REQ_CNTL2); 2331c93bb85bSJerome Glisse temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | 2332c93bb85bSJerome Glisse RS400_DISP2_CRITICAL_POINT_STOP_MASK); 2333c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL2, (temp | 2334c93bb85bSJerome Glisse (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | 2335c93bb85bSJerome Glisse (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); 2336c93bb85bSJerome Glisse #endif 2337c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); 2338c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); 2339c93bb85bSJerome Glisse WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); 2340c93bb85bSJerome Glisse WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); 2341c93bb85bSJerome Glisse } 2342c93bb85bSJerome Glisse 2343c93bb85bSJerome Glisse DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n", 2344c93bb85bSJerome Glisse (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); 2345c93bb85bSJerome Glisse } 2346c93bb85bSJerome Glisse } 2347