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_reg.h" 33771fe6b9SJerome Glisse #include "radeon.h" 34*70967ab9SBen Hutchings #include <linux/firmware.h> 35*70967ab9SBen Hutchings #include <linux/platform_device.h> 36*70967ab9SBen Hutchings 37*70967ab9SBen Hutchings /* Firmware Names */ 38*70967ab9SBen Hutchings #define FIRMWARE_R100 "radeon/R100_cp.bin" 39*70967ab9SBen Hutchings #define FIRMWARE_R200 "radeon/R200_cp.bin" 40*70967ab9SBen Hutchings #define FIRMWARE_R300 "radeon/R300_cp.bin" 41*70967ab9SBen Hutchings #define FIRMWARE_R420 "radeon/R420_cp.bin" 42*70967ab9SBen Hutchings #define FIRMWARE_RS690 "radeon/RS690_cp.bin" 43*70967ab9SBen Hutchings #define FIRMWARE_RS600 "radeon/RS600_cp.bin" 44*70967ab9SBen Hutchings #define FIRMWARE_R520 "radeon/R520_cp.bin" 45*70967ab9SBen Hutchings 46*70967ab9SBen Hutchings MODULE_FIRMWARE(FIRMWARE_R100); 47*70967ab9SBen Hutchings MODULE_FIRMWARE(FIRMWARE_R200); 48*70967ab9SBen Hutchings MODULE_FIRMWARE(FIRMWARE_R300); 49*70967ab9SBen Hutchings MODULE_FIRMWARE(FIRMWARE_R420); 50*70967ab9SBen Hutchings MODULE_FIRMWARE(FIRMWARE_RS690); 51*70967ab9SBen Hutchings MODULE_FIRMWARE(FIRMWARE_RS600); 52*70967ab9SBen Hutchings MODULE_FIRMWARE(FIRMWARE_R520); 53771fe6b9SJerome Glisse 54771fe6b9SJerome Glisse /* This files gather functions specifics to: 55771fe6b9SJerome Glisse * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 56771fe6b9SJerome Glisse * 57771fe6b9SJerome Glisse * Some of these functions might be used by newer ASICs. 58771fe6b9SJerome Glisse */ 59771fe6b9SJerome Glisse void r100_hdp_reset(struct radeon_device *rdev); 60771fe6b9SJerome Glisse void r100_gpu_init(struct radeon_device *rdev); 61771fe6b9SJerome Glisse int r100_gui_wait_for_idle(struct radeon_device *rdev); 62771fe6b9SJerome Glisse int r100_mc_wait_for_idle(struct radeon_device *rdev); 63771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync(struct radeon_device *rdev); 64771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync2(struct radeon_device *rdev); 65771fe6b9SJerome Glisse int r100_debugfs_mc_info_init(struct radeon_device *rdev); 66771fe6b9SJerome Glisse 67771fe6b9SJerome Glisse 68771fe6b9SJerome Glisse /* 69771fe6b9SJerome Glisse * PCI GART 70771fe6b9SJerome Glisse */ 71771fe6b9SJerome Glisse void r100_pci_gart_tlb_flush(struct radeon_device *rdev) 72771fe6b9SJerome Glisse { 73771fe6b9SJerome Glisse /* TODO: can we do somethings here ? */ 74771fe6b9SJerome Glisse /* It seems hw only cache one entry so we should discard this 75771fe6b9SJerome Glisse * entry otherwise if first GPU GART read hit this entry it 76771fe6b9SJerome Glisse * could end up in wrong address. */ 77771fe6b9SJerome Glisse } 78771fe6b9SJerome Glisse 79771fe6b9SJerome Glisse int r100_pci_gart_enable(struct radeon_device *rdev) 80771fe6b9SJerome Glisse { 81771fe6b9SJerome Glisse uint32_t tmp; 82771fe6b9SJerome Glisse int r; 83771fe6b9SJerome Glisse 84771fe6b9SJerome Glisse /* Initialize common gart structure */ 85771fe6b9SJerome Glisse r = radeon_gart_init(rdev); 86771fe6b9SJerome Glisse if (r) { 87771fe6b9SJerome Glisse return r; 88771fe6b9SJerome Glisse } 89771fe6b9SJerome Glisse if (rdev->gart.table.ram.ptr == NULL) { 90771fe6b9SJerome Glisse rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; 91771fe6b9SJerome Glisse r = radeon_gart_table_ram_alloc(rdev); 92771fe6b9SJerome Glisse if (r) { 93771fe6b9SJerome Glisse return r; 94771fe6b9SJerome Glisse } 95771fe6b9SJerome Glisse } 96771fe6b9SJerome Glisse /* discard memory request outside of configured range */ 97771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; 98771fe6b9SJerome Glisse WREG32(RADEON_AIC_CNTL, tmp); 99771fe6b9SJerome Glisse /* set address range for PCI address translate */ 100771fe6b9SJerome Glisse WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location); 101771fe6b9SJerome Glisse tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; 102771fe6b9SJerome Glisse WREG32(RADEON_AIC_HI_ADDR, tmp); 103771fe6b9SJerome Glisse /* Enable bus mastering */ 104771fe6b9SJerome Glisse tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; 105771fe6b9SJerome Glisse WREG32(RADEON_BUS_CNTL, tmp); 106771fe6b9SJerome Glisse /* set PCI GART page-table base address */ 107771fe6b9SJerome Glisse WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr); 108771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN; 109771fe6b9SJerome Glisse WREG32(RADEON_AIC_CNTL, tmp); 110771fe6b9SJerome Glisse r100_pci_gart_tlb_flush(rdev); 111771fe6b9SJerome Glisse rdev->gart.ready = true; 112771fe6b9SJerome Glisse return 0; 113771fe6b9SJerome Glisse } 114771fe6b9SJerome Glisse 115771fe6b9SJerome Glisse void r100_pci_gart_disable(struct radeon_device *rdev) 116771fe6b9SJerome Glisse { 117771fe6b9SJerome Glisse uint32_t tmp; 118771fe6b9SJerome Glisse 119771fe6b9SJerome Glisse /* discard memory request outside of configured range */ 120771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; 121771fe6b9SJerome Glisse WREG32(RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN); 122771fe6b9SJerome Glisse WREG32(RADEON_AIC_LO_ADDR, 0); 123771fe6b9SJerome Glisse WREG32(RADEON_AIC_HI_ADDR, 0); 124771fe6b9SJerome Glisse } 125771fe6b9SJerome Glisse 126771fe6b9SJerome Glisse int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) 127771fe6b9SJerome Glisse { 128771fe6b9SJerome Glisse if (i < 0 || i > rdev->gart.num_gpu_pages) { 129771fe6b9SJerome Glisse return -EINVAL; 130771fe6b9SJerome Glisse } 131ed10f95dSDave Airlie rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr)); 132771fe6b9SJerome Glisse return 0; 133771fe6b9SJerome Glisse } 134771fe6b9SJerome Glisse 135771fe6b9SJerome Glisse int r100_gart_enable(struct radeon_device *rdev) 136771fe6b9SJerome Glisse { 137771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 138771fe6b9SJerome Glisse r100_pci_gart_disable(rdev); 139771fe6b9SJerome Glisse return 0; 140771fe6b9SJerome Glisse } 141771fe6b9SJerome Glisse return r100_pci_gart_enable(rdev); 142771fe6b9SJerome Glisse } 143771fe6b9SJerome Glisse 144771fe6b9SJerome Glisse 145771fe6b9SJerome Glisse /* 146771fe6b9SJerome Glisse * MC 147771fe6b9SJerome Glisse */ 148771fe6b9SJerome Glisse void r100_mc_disable_clients(struct radeon_device *rdev) 149771fe6b9SJerome Glisse { 150771fe6b9SJerome Glisse uint32_t ov0_scale_cntl, crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl; 151771fe6b9SJerome Glisse 152771fe6b9SJerome Glisse /* FIXME: is this function correct for rs100,rs200,rs300 ? */ 153771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 154771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 155771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 156771fe6b9SJerome Glisse } 157771fe6b9SJerome Glisse 158771fe6b9SJerome Glisse /* stop display and memory access */ 159771fe6b9SJerome Glisse ov0_scale_cntl = RREG32(RADEON_OV0_SCALE_CNTL); 160771fe6b9SJerome Glisse WREG32(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE); 161771fe6b9SJerome Glisse crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); 162771fe6b9SJerome Glisse WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS); 163771fe6b9SJerome Glisse crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); 164771fe6b9SJerome Glisse 165771fe6b9SJerome Glisse r100_gpu_wait_for_vsync(rdev); 166771fe6b9SJerome Glisse 167771fe6b9SJerome Glisse WREG32(RADEON_CRTC_GEN_CNTL, 168771fe6b9SJerome Glisse (crtc_gen_cntl & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) | 169771fe6b9SJerome Glisse RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN); 170771fe6b9SJerome Glisse 171771fe6b9SJerome Glisse if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 172771fe6b9SJerome Glisse crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 173771fe6b9SJerome Glisse 174771fe6b9SJerome Glisse r100_gpu_wait_for_vsync2(rdev); 175771fe6b9SJerome Glisse WREG32(RADEON_CRTC2_GEN_CNTL, 176771fe6b9SJerome Glisse (crtc2_gen_cntl & 177771fe6b9SJerome Glisse ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) | 178771fe6b9SJerome Glisse RADEON_CRTC2_DISP_REQ_EN_B); 179771fe6b9SJerome Glisse } 180771fe6b9SJerome Glisse 181771fe6b9SJerome Glisse udelay(500); 182771fe6b9SJerome Glisse } 183771fe6b9SJerome Glisse 184771fe6b9SJerome Glisse void r100_mc_setup(struct radeon_device *rdev) 185771fe6b9SJerome Glisse { 186771fe6b9SJerome Glisse uint32_t tmp; 187771fe6b9SJerome Glisse int r; 188771fe6b9SJerome Glisse 189771fe6b9SJerome Glisse r = r100_debugfs_mc_info_init(rdev); 190771fe6b9SJerome Glisse if (r) { 191771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for R100 MC !\n"); 192771fe6b9SJerome Glisse } 193771fe6b9SJerome Glisse /* Write VRAM size in case we are limiting it */ 1947a50f01aSDave Airlie WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 1957a50f01aSDave Airlie /* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM, 1967a50f01aSDave Airlie * if the aperture is 64MB but we have 32MB VRAM 1977a50f01aSDave Airlie * we report only 32MB VRAM but we have to set MC_FB_LOCATION 1987a50f01aSDave Airlie * to 64MB, otherwise the gpu accidentially dies */ 1997a50f01aSDave Airlie tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; 200771fe6b9SJerome Glisse tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); 201771fe6b9SJerome Glisse tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); 202771fe6b9SJerome Glisse WREG32(RADEON_MC_FB_LOCATION, tmp); 203771fe6b9SJerome Glisse 204771fe6b9SJerome Glisse /* Enable bus mastering */ 205771fe6b9SJerome Glisse tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; 206771fe6b9SJerome Glisse WREG32(RADEON_BUS_CNTL, tmp); 207771fe6b9SJerome Glisse 208771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 209771fe6b9SJerome Glisse tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; 210771fe6b9SJerome Glisse tmp = REG_SET(RADEON_MC_AGP_TOP, tmp >> 16); 211771fe6b9SJerome Glisse tmp |= REG_SET(RADEON_MC_AGP_START, rdev->mc.gtt_location >> 16); 212771fe6b9SJerome Glisse WREG32(RADEON_MC_AGP_LOCATION, tmp); 213771fe6b9SJerome Glisse WREG32(RADEON_AGP_BASE, rdev->mc.agp_base); 214771fe6b9SJerome Glisse } else { 215771fe6b9SJerome Glisse WREG32(RADEON_MC_AGP_LOCATION, 0x0FFFFFFF); 216771fe6b9SJerome Glisse WREG32(RADEON_AGP_BASE, 0); 217771fe6b9SJerome Glisse } 218771fe6b9SJerome Glisse 219771fe6b9SJerome Glisse tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; 220771fe6b9SJerome Glisse tmp |= (7 << 28); 221771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); 222771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 223771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp); 224771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 225771fe6b9SJerome Glisse } 226771fe6b9SJerome Glisse 227771fe6b9SJerome Glisse int r100_mc_init(struct radeon_device *rdev) 228771fe6b9SJerome Glisse { 229771fe6b9SJerome Glisse int r; 230771fe6b9SJerome Glisse 231771fe6b9SJerome Glisse if (r100_debugfs_rbbm_init(rdev)) { 232771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for RBBM !\n"); 233771fe6b9SJerome Glisse } 234771fe6b9SJerome Glisse 235771fe6b9SJerome Glisse r100_gpu_init(rdev); 236771fe6b9SJerome Glisse /* Disable gart which also disable out of gart access */ 237771fe6b9SJerome Glisse r100_pci_gart_disable(rdev); 238771fe6b9SJerome Glisse 239771fe6b9SJerome Glisse /* Setup GPU memory space */ 240771fe6b9SJerome Glisse rdev->mc.gtt_location = 0xFFFFFFFFUL; 241771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 242771fe6b9SJerome Glisse r = radeon_agp_init(rdev); 243771fe6b9SJerome Glisse if (r) { 244771fe6b9SJerome Glisse printk(KERN_WARNING "[drm] Disabling AGP\n"); 245771fe6b9SJerome Glisse rdev->flags &= ~RADEON_IS_AGP; 246771fe6b9SJerome Glisse rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; 247771fe6b9SJerome Glisse } else { 248771fe6b9SJerome Glisse rdev->mc.gtt_location = rdev->mc.agp_base; 249771fe6b9SJerome Glisse } 250771fe6b9SJerome Glisse } 251771fe6b9SJerome Glisse r = radeon_mc_setup(rdev); 252771fe6b9SJerome Glisse if (r) { 253771fe6b9SJerome Glisse return r; 254771fe6b9SJerome Glisse } 255771fe6b9SJerome Glisse 256771fe6b9SJerome Glisse r100_mc_disable_clients(rdev); 257771fe6b9SJerome Glisse if (r100_mc_wait_for_idle(rdev)) { 258771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait MC idle while " 259771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 260771fe6b9SJerome Glisse } 261771fe6b9SJerome Glisse 262771fe6b9SJerome Glisse r100_mc_setup(rdev); 263771fe6b9SJerome Glisse return 0; 264771fe6b9SJerome Glisse } 265771fe6b9SJerome Glisse 266771fe6b9SJerome Glisse void r100_mc_fini(struct radeon_device *rdev) 267771fe6b9SJerome Glisse { 268771fe6b9SJerome Glisse r100_pci_gart_disable(rdev); 269771fe6b9SJerome Glisse radeon_gart_table_ram_free(rdev); 270771fe6b9SJerome Glisse radeon_gart_fini(rdev); 271771fe6b9SJerome Glisse } 272771fe6b9SJerome Glisse 273771fe6b9SJerome Glisse 274771fe6b9SJerome Glisse /* 2757ed220d7SMichel Dänzer * Interrupts 2767ed220d7SMichel Dänzer */ 2777ed220d7SMichel Dänzer int r100_irq_set(struct radeon_device *rdev) 2787ed220d7SMichel Dänzer { 2797ed220d7SMichel Dänzer uint32_t tmp = 0; 2807ed220d7SMichel Dänzer 2817ed220d7SMichel Dänzer if (rdev->irq.sw_int) { 2827ed220d7SMichel Dänzer tmp |= RADEON_SW_INT_ENABLE; 2837ed220d7SMichel Dänzer } 2847ed220d7SMichel Dänzer if (rdev->irq.crtc_vblank_int[0]) { 2857ed220d7SMichel Dänzer tmp |= RADEON_CRTC_VBLANK_MASK; 2867ed220d7SMichel Dänzer } 2877ed220d7SMichel Dänzer if (rdev->irq.crtc_vblank_int[1]) { 2887ed220d7SMichel Dänzer tmp |= RADEON_CRTC2_VBLANK_MASK; 2897ed220d7SMichel Dänzer } 2907ed220d7SMichel Dänzer WREG32(RADEON_GEN_INT_CNTL, tmp); 2917ed220d7SMichel Dänzer return 0; 2927ed220d7SMichel Dänzer } 2937ed220d7SMichel Dänzer 2947ed220d7SMichel Dänzer static inline uint32_t r100_irq_ack(struct radeon_device *rdev) 2957ed220d7SMichel Dänzer { 2967ed220d7SMichel Dänzer uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); 2977ed220d7SMichel Dänzer uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | 2987ed220d7SMichel Dänzer RADEON_CRTC2_VBLANK_STAT; 2997ed220d7SMichel Dänzer 3007ed220d7SMichel Dänzer if (irqs) { 3017ed220d7SMichel Dänzer WREG32(RADEON_GEN_INT_STATUS, irqs); 3027ed220d7SMichel Dänzer } 3037ed220d7SMichel Dänzer return irqs & irq_mask; 3047ed220d7SMichel Dänzer } 3057ed220d7SMichel Dänzer 3067ed220d7SMichel Dänzer int r100_irq_process(struct radeon_device *rdev) 3077ed220d7SMichel Dänzer { 3087ed220d7SMichel Dänzer uint32_t status; 3097ed220d7SMichel Dänzer 3107ed220d7SMichel Dänzer status = r100_irq_ack(rdev); 3117ed220d7SMichel Dänzer if (!status) { 3127ed220d7SMichel Dänzer return IRQ_NONE; 3137ed220d7SMichel Dänzer } 3147ed220d7SMichel Dänzer while (status) { 3157ed220d7SMichel Dänzer /* SW interrupt */ 3167ed220d7SMichel Dänzer if (status & RADEON_SW_INT_TEST) { 3177ed220d7SMichel Dänzer radeon_fence_process(rdev); 3187ed220d7SMichel Dänzer } 3197ed220d7SMichel Dänzer /* Vertical blank interrupts */ 3207ed220d7SMichel Dänzer if (status & RADEON_CRTC_VBLANK_STAT) { 3217ed220d7SMichel Dänzer drm_handle_vblank(rdev->ddev, 0); 3227ed220d7SMichel Dänzer } 3237ed220d7SMichel Dänzer if (status & RADEON_CRTC2_VBLANK_STAT) { 3247ed220d7SMichel Dänzer drm_handle_vblank(rdev->ddev, 1); 3257ed220d7SMichel Dänzer } 3267ed220d7SMichel Dänzer status = r100_irq_ack(rdev); 3277ed220d7SMichel Dänzer } 3287ed220d7SMichel Dänzer return IRQ_HANDLED; 3297ed220d7SMichel Dänzer } 3307ed220d7SMichel Dänzer 3317ed220d7SMichel Dänzer u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc) 3327ed220d7SMichel Dänzer { 3337ed220d7SMichel Dänzer if (crtc == 0) 3347ed220d7SMichel Dänzer return RREG32(RADEON_CRTC_CRNT_FRAME); 3357ed220d7SMichel Dänzer else 3367ed220d7SMichel Dänzer return RREG32(RADEON_CRTC2_CRNT_FRAME); 3377ed220d7SMichel Dänzer } 3387ed220d7SMichel Dänzer 3397ed220d7SMichel Dänzer 3407ed220d7SMichel Dänzer /* 341771fe6b9SJerome Glisse * Fence emission 342771fe6b9SJerome Glisse */ 343771fe6b9SJerome Glisse void r100_fence_ring_emit(struct radeon_device *rdev, 344771fe6b9SJerome Glisse struct radeon_fence *fence) 345771fe6b9SJerome Glisse { 346771fe6b9SJerome Glisse /* Who ever call radeon_fence_emit should call ring_lock and ask 347771fe6b9SJerome Glisse * for enough space (today caller are ib schedule and buffer move) */ 348771fe6b9SJerome Glisse /* Wait until IDLE & CLEAN */ 349771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(0x1720, 0)); 350771fe6b9SJerome Glisse radeon_ring_write(rdev, (1 << 16) | (1 << 17)); 351771fe6b9SJerome Glisse /* Emit fence sequence & fire IRQ */ 352771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0)); 353771fe6b9SJerome Glisse radeon_ring_write(rdev, fence->seq); 354771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_GEN_INT_STATUS, 0)); 355771fe6b9SJerome Glisse radeon_ring_write(rdev, RADEON_SW_INT_FIRE); 356771fe6b9SJerome Glisse } 357771fe6b9SJerome Glisse 358771fe6b9SJerome Glisse 359771fe6b9SJerome Glisse /* 360771fe6b9SJerome Glisse * Writeback 361771fe6b9SJerome Glisse */ 362771fe6b9SJerome Glisse int r100_wb_init(struct radeon_device *rdev) 363771fe6b9SJerome Glisse { 364771fe6b9SJerome Glisse int r; 365771fe6b9SJerome Glisse 366771fe6b9SJerome Glisse if (rdev->wb.wb_obj == NULL) { 367771fe6b9SJerome Glisse r = radeon_object_create(rdev, NULL, 4096, 368771fe6b9SJerome Glisse true, 369771fe6b9SJerome Glisse RADEON_GEM_DOMAIN_GTT, 370771fe6b9SJerome Glisse false, &rdev->wb.wb_obj); 371771fe6b9SJerome Glisse if (r) { 372771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to create WB buffer (%d).\n", r); 373771fe6b9SJerome Glisse return r; 374771fe6b9SJerome Glisse } 375771fe6b9SJerome Glisse r = radeon_object_pin(rdev->wb.wb_obj, 376771fe6b9SJerome Glisse RADEON_GEM_DOMAIN_GTT, 377771fe6b9SJerome Glisse &rdev->wb.gpu_addr); 378771fe6b9SJerome Glisse if (r) { 379771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to pin WB buffer (%d).\n", r); 380771fe6b9SJerome Glisse return r; 381771fe6b9SJerome Glisse } 382771fe6b9SJerome Glisse r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); 383771fe6b9SJerome Glisse if (r) { 384771fe6b9SJerome Glisse DRM_ERROR("radeon: failed to map WB buffer (%d).\n", r); 385771fe6b9SJerome Glisse return r; 386771fe6b9SJerome Glisse } 387771fe6b9SJerome Glisse } 388771fe6b9SJerome Glisse WREG32(0x774, rdev->wb.gpu_addr); 389771fe6b9SJerome Glisse WREG32(0x70C, rdev->wb.gpu_addr + 1024); 390771fe6b9SJerome Glisse WREG32(0x770, 0xff); 391771fe6b9SJerome Glisse return 0; 392771fe6b9SJerome Glisse } 393771fe6b9SJerome Glisse 394771fe6b9SJerome Glisse void r100_wb_fini(struct radeon_device *rdev) 395771fe6b9SJerome Glisse { 396771fe6b9SJerome Glisse if (rdev->wb.wb_obj) { 397771fe6b9SJerome Glisse radeon_object_kunmap(rdev->wb.wb_obj); 398771fe6b9SJerome Glisse radeon_object_unpin(rdev->wb.wb_obj); 399771fe6b9SJerome Glisse radeon_object_unref(&rdev->wb.wb_obj); 400771fe6b9SJerome Glisse rdev->wb.wb = NULL; 401771fe6b9SJerome Glisse rdev->wb.wb_obj = NULL; 402771fe6b9SJerome Glisse } 403771fe6b9SJerome Glisse } 404771fe6b9SJerome Glisse 405771fe6b9SJerome Glisse int r100_copy_blit(struct radeon_device *rdev, 406771fe6b9SJerome Glisse uint64_t src_offset, 407771fe6b9SJerome Glisse uint64_t dst_offset, 408771fe6b9SJerome Glisse unsigned num_pages, 409771fe6b9SJerome Glisse struct radeon_fence *fence) 410771fe6b9SJerome Glisse { 411771fe6b9SJerome Glisse uint32_t cur_pages; 412771fe6b9SJerome Glisse uint32_t stride_bytes = PAGE_SIZE; 413771fe6b9SJerome Glisse uint32_t pitch; 414771fe6b9SJerome Glisse uint32_t stride_pixels; 415771fe6b9SJerome Glisse unsigned ndw; 416771fe6b9SJerome Glisse int num_loops; 417771fe6b9SJerome Glisse int r = 0; 418771fe6b9SJerome Glisse 419771fe6b9SJerome Glisse /* radeon limited to 16k stride */ 420771fe6b9SJerome Glisse stride_bytes &= 0x3fff; 421771fe6b9SJerome Glisse /* radeon pitch is /64 */ 422771fe6b9SJerome Glisse pitch = stride_bytes / 64; 423771fe6b9SJerome Glisse stride_pixels = stride_bytes / 4; 424771fe6b9SJerome Glisse num_loops = DIV_ROUND_UP(num_pages, 8191); 425771fe6b9SJerome Glisse 426771fe6b9SJerome Glisse /* Ask for enough room for blit + flush + fence */ 427771fe6b9SJerome Glisse ndw = 64 + (10 * num_loops); 428771fe6b9SJerome Glisse r = radeon_ring_lock(rdev, ndw); 429771fe6b9SJerome Glisse if (r) { 430771fe6b9SJerome Glisse DRM_ERROR("radeon: moving bo (%d) asking for %u dw.\n", r, ndw); 431771fe6b9SJerome Glisse return -EINVAL; 432771fe6b9SJerome Glisse } 433771fe6b9SJerome Glisse while (num_pages > 0) { 434771fe6b9SJerome Glisse cur_pages = num_pages; 435771fe6b9SJerome Glisse if (cur_pages > 8191) { 436771fe6b9SJerome Glisse cur_pages = 8191; 437771fe6b9SJerome Glisse } 438771fe6b9SJerome Glisse num_pages -= cur_pages; 439771fe6b9SJerome Glisse 440771fe6b9SJerome Glisse /* pages are in Y direction - height 441771fe6b9SJerome Glisse page width in X direction - width */ 442771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET3(PACKET3_BITBLT_MULTI, 8)); 443771fe6b9SJerome Glisse radeon_ring_write(rdev, 444771fe6b9SJerome Glisse RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 445771fe6b9SJerome Glisse RADEON_GMC_DST_PITCH_OFFSET_CNTL | 446771fe6b9SJerome Glisse RADEON_GMC_SRC_CLIPPING | 447771fe6b9SJerome Glisse RADEON_GMC_DST_CLIPPING | 448771fe6b9SJerome Glisse RADEON_GMC_BRUSH_NONE | 449771fe6b9SJerome Glisse (RADEON_COLOR_FORMAT_ARGB8888 << 8) | 450771fe6b9SJerome Glisse RADEON_GMC_SRC_DATATYPE_COLOR | 451771fe6b9SJerome Glisse RADEON_ROP3_S | 452771fe6b9SJerome Glisse RADEON_DP_SRC_SOURCE_MEMORY | 453771fe6b9SJerome Glisse RADEON_GMC_CLR_CMP_CNTL_DIS | 454771fe6b9SJerome Glisse RADEON_GMC_WR_MSK_DIS); 455771fe6b9SJerome Glisse radeon_ring_write(rdev, (pitch << 22) | (src_offset >> 10)); 456771fe6b9SJerome Glisse radeon_ring_write(rdev, (pitch << 22) | (dst_offset >> 10)); 457771fe6b9SJerome Glisse radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); 458771fe6b9SJerome Glisse radeon_ring_write(rdev, 0); 459771fe6b9SJerome Glisse radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); 460771fe6b9SJerome Glisse radeon_ring_write(rdev, num_pages); 461771fe6b9SJerome Glisse radeon_ring_write(rdev, num_pages); 462771fe6b9SJerome Glisse radeon_ring_write(rdev, cur_pages | (stride_pixels << 16)); 463771fe6b9SJerome Glisse } 464771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0)); 465771fe6b9SJerome Glisse radeon_ring_write(rdev, RADEON_RB2D_DC_FLUSH_ALL); 466771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); 467771fe6b9SJerome Glisse radeon_ring_write(rdev, 468771fe6b9SJerome Glisse RADEON_WAIT_2D_IDLECLEAN | 469771fe6b9SJerome Glisse RADEON_WAIT_HOST_IDLECLEAN | 470771fe6b9SJerome Glisse RADEON_WAIT_DMA_GUI_IDLE); 471771fe6b9SJerome Glisse if (fence) { 472771fe6b9SJerome Glisse r = radeon_fence_emit(rdev, fence); 473771fe6b9SJerome Glisse } 474771fe6b9SJerome Glisse radeon_ring_unlock_commit(rdev); 475771fe6b9SJerome Glisse return r; 476771fe6b9SJerome Glisse } 477771fe6b9SJerome Glisse 478771fe6b9SJerome Glisse 479771fe6b9SJerome Glisse /* 480771fe6b9SJerome Glisse * CP 481771fe6b9SJerome Glisse */ 482771fe6b9SJerome Glisse void r100_ring_start(struct radeon_device *rdev) 483771fe6b9SJerome Glisse { 484771fe6b9SJerome Glisse int r; 485771fe6b9SJerome Glisse 486771fe6b9SJerome Glisse r = radeon_ring_lock(rdev, 2); 487771fe6b9SJerome Glisse if (r) { 488771fe6b9SJerome Glisse return; 489771fe6b9SJerome Glisse } 490771fe6b9SJerome Glisse radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0)); 491771fe6b9SJerome Glisse radeon_ring_write(rdev, 492771fe6b9SJerome Glisse RADEON_ISYNC_ANY2D_IDLE3D | 493771fe6b9SJerome Glisse RADEON_ISYNC_ANY3D_IDLE2D | 494771fe6b9SJerome Glisse RADEON_ISYNC_WAIT_IDLEGUI | 495771fe6b9SJerome Glisse RADEON_ISYNC_CPSCRATCH_IDLEGUI); 496771fe6b9SJerome Glisse radeon_ring_unlock_commit(rdev); 497771fe6b9SJerome Glisse } 498771fe6b9SJerome Glisse 499*70967ab9SBen Hutchings 500*70967ab9SBen Hutchings /* Load the microcode for the CP */ 501*70967ab9SBen Hutchings static int r100_cp_init_microcode(struct radeon_device *rdev) 502771fe6b9SJerome Glisse { 503*70967ab9SBen Hutchings struct platform_device *pdev; 504*70967ab9SBen Hutchings const char *fw_name = NULL; 505*70967ab9SBen Hutchings int err; 506771fe6b9SJerome Glisse 507*70967ab9SBen Hutchings DRM_DEBUG("\n"); 508*70967ab9SBen Hutchings 509*70967ab9SBen Hutchings pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0); 510*70967ab9SBen Hutchings err = IS_ERR(pdev); 511*70967ab9SBen Hutchings if (err) { 512*70967ab9SBen Hutchings printk(KERN_ERR "radeon_cp: Failed to register firmware\n"); 513*70967ab9SBen Hutchings return -EINVAL; 514771fe6b9SJerome Glisse } 515771fe6b9SJerome Glisse if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) || 516771fe6b9SJerome Glisse (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) || 517771fe6b9SJerome Glisse (rdev->family == CHIP_RS200)) { 518771fe6b9SJerome Glisse DRM_INFO("Loading R100 Microcode\n"); 519*70967ab9SBen Hutchings fw_name = FIRMWARE_R100; 520771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R200) || 521771fe6b9SJerome Glisse (rdev->family == CHIP_RV250) || 522771fe6b9SJerome Glisse (rdev->family == CHIP_RV280) || 523771fe6b9SJerome Glisse (rdev->family == CHIP_RS300)) { 524771fe6b9SJerome Glisse DRM_INFO("Loading R200 Microcode\n"); 525*70967ab9SBen Hutchings fw_name = FIRMWARE_R200; 526771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R300) || 527771fe6b9SJerome Glisse (rdev->family == CHIP_R350) || 528771fe6b9SJerome Glisse (rdev->family == CHIP_RV350) || 529771fe6b9SJerome Glisse (rdev->family == CHIP_RV380) || 530771fe6b9SJerome Glisse (rdev->family == CHIP_RS400) || 531771fe6b9SJerome Glisse (rdev->family == CHIP_RS480)) { 532771fe6b9SJerome Glisse DRM_INFO("Loading R300 Microcode\n"); 533*70967ab9SBen Hutchings fw_name = FIRMWARE_R300; 534771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_R420) || 535771fe6b9SJerome Glisse (rdev->family == CHIP_R423) || 536771fe6b9SJerome Glisse (rdev->family == CHIP_RV410)) { 537771fe6b9SJerome Glisse DRM_INFO("Loading R400 Microcode\n"); 538*70967ab9SBen Hutchings fw_name = FIRMWARE_R420; 539771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_RS690) || 540771fe6b9SJerome Glisse (rdev->family == CHIP_RS740)) { 541771fe6b9SJerome Glisse DRM_INFO("Loading RS690/RS740 Microcode\n"); 542*70967ab9SBen Hutchings fw_name = FIRMWARE_RS690; 543771fe6b9SJerome Glisse } else if (rdev->family == CHIP_RS600) { 544771fe6b9SJerome Glisse DRM_INFO("Loading RS600 Microcode\n"); 545*70967ab9SBen Hutchings fw_name = FIRMWARE_RS600; 546771fe6b9SJerome Glisse } else if ((rdev->family == CHIP_RV515) || 547771fe6b9SJerome Glisse (rdev->family == CHIP_R520) || 548771fe6b9SJerome Glisse (rdev->family == CHIP_RV530) || 549771fe6b9SJerome Glisse (rdev->family == CHIP_R580) || 550771fe6b9SJerome Glisse (rdev->family == CHIP_RV560) || 551771fe6b9SJerome Glisse (rdev->family == CHIP_RV570)) { 552771fe6b9SJerome Glisse DRM_INFO("Loading R500 Microcode\n"); 553*70967ab9SBen Hutchings fw_name = FIRMWARE_R520; 554*70967ab9SBen Hutchings } 555*70967ab9SBen Hutchings 556*70967ab9SBen Hutchings err = request_firmware(&rdev->fw, fw_name, &pdev->dev); 557*70967ab9SBen Hutchings platform_device_unregister(pdev); 558*70967ab9SBen Hutchings if (err) { 559*70967ab9SBen Hutchings printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n", 560*70967ab9SBen Hutchings fw_name); 561*70967ab9SBen Hutchings } else if (rdev->fw->size % 8) { 562*70967ab9SBen Hutchings printk(KERN_ERR 563*70967ab9SBen Hutchings "radeon_cp: Bogus length %zu in firmware \"%s\"\n", 564*70967ab9SBen Hutchings rdev->fw->size, fw_name); 565*70967ab9SBen Hutchings err = -EINVAL; 566*70967ab9SBen Hutchings release_firmware(rdev->fw); 567*70967ab9SBen Hutchings rdev->fw = NULL; 568*70967ab9SBen Hutchings } 569*70967ab9SBen Hutchings return err; 570*70967ab9SBen Hutchings } 571*70967ab9SBen Hutchings static void r100_cp_load_microcode(struct radeon_device *rdev) 572*70967ab9SBen Hutchings { 573*70967ab9SBen Hutchings const __be32 *fw_data; 574*70967ab9SBen Hutchings int i, size; 575*70967ab9SBen Hutchings 576*70967ab9SBen Hutchings if (r100_gui_wait_for_idle(rdev)) { 577*70967ab9SBen Hutchings printk(KERN_WARNING "Failed to wait GUI idle while " 578*70967ab9SBen Hutchings "programming pipes. Bad things might happen.\n"); 579*70967ab9SBen Hutchings } 580*70967ab9SBen Hutchings 581*70967ab9SBen Hutchings if (rdev->fw) { 582*70967ab9SBen Hutchings size = rdev->fw->size / 4; 583*70967ab9SBen Hutchings fw_data = (const __be32 *)&rdev->fw->data[0]; 584*70967ab9SBen Hutchings WREG32(RADEON_CP_ME_RAM_ADDR, 0); 585*70967ab9SBen Hutchings for (i = 0; i < size; i += 2) { 586*70967ab9SBen Hutchings WREG32(RADEON_CP_ME_RAM_DATAH, 587*70967ab9SBen Hutchings be32_to_cpup(&fw_data[i])); 588*70967ab9SBen Hutchings WREG32(RADEON_CP_ME_RAM_DATAL, 589*70967ab9SBen Hutchings be32_to_cpup(&fw_data[i + 1])); 590771fe6b9SJerome Glisse } 591771fe6b9SJerome Glisse } 592771fe6b9SJerome Glisse } 593771fe6b9SJerome Glisse 594771fe6b9SJerome Glisse int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) 595771fe6b9SJerome Glisse { 596771fe6b9SJerome Glisse unsigned rb_bufsz; 597771fe6b9SJerome Glisse unsigned rb_blksz; 598771fe6b9SJerome Glisse unsigned max_fetch; 599771fe6b9SJerome Glisse unsigned pre_write_timer; 600771fe6b9SJerome Glisse unsigned pre_write_limit; 601771fe6b9SJerome Glisse unsigned indirect2_start; 602771fe6b9SJerome Glisse unsigned indirect1_start; 603771fe6b9SJerome Glisse uint32_t tmp; 604771fe6b9SJerome Glisse int r; 605771fe6b9SJerome Glisse 606771fe6b9SJerome Glisse if (r100_debugfs_cp_init(rdev)) { 607771fe6b9SJerome Glisse DRM_ERROR("Failed to register debugfs file for CP !\n"); 608771fe6b9SJerome Glisse } 609771fe6b9SJerome Glisse /* Reset CP */ 610771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_STAT); 611771fe6b9SJerome Glisse if ((tmp & (1 << 31))) { 612771fe6b9SJerome Glisse DRM_INFO("radeon: cp busy (0x%08X) resetting\n", tmp); 613771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 614771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 615771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP); 616771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_SOFT_RESET); 617771fe6b9SJerome Glisse mdelay(2); 618771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 619771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_SOFT_RESET); 620771fe6b9SJerome Glisse mdelay(2); 621771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_STAT); 622771fe6b9SJerome Glisse if ((tmp & (1 << 31))) { 623771fe6b9SJerome Glisse DRM_INFO("radeon: cp reset failed (0x%08X)\n", tmp); 624771fe6b9SJerome Glisse } 625771fe6b9SJerome Glisse } else { 626771fe6b9SJerome Glisse DRM_INFO("radeon: cp idle (0x%08X)\n", tmp); 627771fe6b9SJerome Glisse } 628*70967ab9SBen Hutchings 629*70967ab9SBen Hutchings if (!rdev->fw) { 630*70967ab9SBen Hutchings r = r100_cp_init_microcode(rdev); 631*70967ab9SBen Hutchings if (r) { 632*70967ab9SBen Hutchings DRM_ERROR("Failed to load firmware!\n"); 633*70967ab9SBen Hutchings return r; 634*70967ab9SBen Hutchings } 635*70967ab9SBen Hutchings } 636*70967ab9SBen Hutchings 637771fe6b9SJerome Glisse /* Align ring size */ 638771fe6b9SJerome Glisse rb_bufsz = drm_order(ring_size / 8); 639771fe6b9SJerome Glisse ring_size = (1 << (rb_bufsz + 1)) * 4; 640771fe6b9SJerome Glisse r100_cp_load_microcode(rdev); 641771fe6b9SJerome Glisse r = radeon_ring_init(rdev, ring_size); 642771fe6b9SJerome Glisse if (r) { 643771fe6b9SJerome Glisse return r; 644771fe6b9SJerome Glisse } 645771fe6b9SJerome Glisse /* Each time the cp read 1024 bytes (16 dword/quadword) update 646771fe6b9SJerome Glisse * the rptr copy in system ram */ 647771fe6b9SJerome Glisse rb_blksz = 9; 648771fe6b9SJerome Glisse /* cp will read 128bytes at a time (4 dwords) */ 649771fe6b9SJerome Glisse max_fetch = 1; 650771fe6b9SJerome Glisse rdev->cp.align_mask = 16 - 1; 651771fe6b9SJerome Glisse /* Write to CP_RB_WPTR will be delayed for pre_write_timer clocks */ 652771fe6b9SJerome Glisse pre_write_timer = 64; 653771fe6b9SJerome Glisse /* Force CP_RB_WPTR write if written more than one time before the 654771fe6b9SJerome Glisse * delay expire 655771fe6b9SJerome Glisse */ 656771fe6b9SJerome Glisse pre_write_limit = 0; 657771fe6b9SJerome Glisse /* Setup the cp cache like this (cache size is 96 dwords) : 658771fe6b9SJerome Glisse * RING 0 to 15 659771fe6b9SJerome Glisse * INDIRECT1 16 to 79 660771fe6b9SJerome Glisse * INDIRECT2 80 to 95 661771fe6b9SJerome Glisse * So ring cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) 662771fe6b9SJerome Glisse * indirect1 cache size is 64dwords (> (2 * max_fetch = 2 * 4dwords)) 663771fe6b9SJerome Glisse * indirect2 cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) 664771fe6b9SJerome Glisse * Idea being that most of the gpu cmd will be through indirect1 buffer 665771fe6b9SJerome Glisse * so it gets the bigger cache. 666771fe6b9SJerome Glisse */ 667771fe6b9SJerome Glisse indirect2_start = 80; 668771fe6b9SJerome Glisse indirect1_start = 16; 669771fe6b9SJerome Glisse /* cp setup */ 670771fe6b9SJerome Glisse WREG32(0x718, pre_write_timer | (pre_write_limit << 28)); 671771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, 6724e484e7dSMichel Dänzer #ifdef __BIG_ENDIAN 6734e484e7dSMichel Dänzer RADEON_BUF_SWAP_32BIT | 6744e484e7dSMichel Dänzer #endif 675771fe6b9SJerome Glisse REG_SET(RADEON_RB_BUFSZ, rb_bufsz) | 676771fe6b9SJerome Glisse REG_SET(RADEON_RB_BLKSZ, rb_blksz) | 677771fe6b9SJerome Glisse REG_SET(RADEON_MAX_FETCH, max_fetch) | 678771fe6b9SJerome Glisse RADEON_RB_NO_UPDATE); 679771fe6b9SJerome Glisse /* Set ring address */ 680771fe6b9SJerome Glisse DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr); 681771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr); 682771fe6b9SJerome Glisse /* Force read & write ptr to 0 */ 683771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_RB_CNTL); 684771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); 685771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_RPTR_WR, 0); 686771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_WPTR, 0); 687771fe6b9SJerome Glisse WREG32(RADEON_CP_RB_CNTL, tmp); 688771fe6b9SJerome Glisse udelay(10); 689771fe6b9SJerome Glisse rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); 690771fe6b9SJerome Glisse rdev->cp.wptr = RREG32(RADEON_CP_RB_WPTR); 691771fe6b9SJerome Glisse /* Set cp mode to bus mastering & enable cp*/ 692771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 693771fe6b9SJerome Glisse REG_SET(RADEON_INDIRECT2_START, indirect2_start) | 694771fe6b9SJerome Glisse REG_SET(RADEON_INDIRECT1_START, indirect1_start)); 695771fe6b9SJerome Glisse WREG32(0x718, 0); 696771fe6b9SJerome Glisse WREG32(0x744, 0x00004D4D); 697771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM); 698771fe6b9SJerome Glisse radeon_ring_start(rdev); 699771fe6b9SJerome Glisse r = radeon_ring_test(rdev); 700771fe6b9SJerome Glisse if (r) { 701771fe6b9SJerome Glisse DRM_ERROR("radeon: cp isn't working (%d).\n", r); 702771fe6b9SJerome Glisse return r; 703771fe6b9SJerome Glisse } 704771fe6b9SJerome Glisse rdev->cp.ready = true; 705771fe6b9SJerome Glisse return 0; 706771fe6b9SJerome Glisse } 707771fe6b9SJerome Glisse 708771fe6b9SJerome Glisse void r100_cp_fini(struct radeon_device *rdev) 709771fe6b9SJerome Glisse { 710771fe6b9SJerome Glisse /* Disable ring */ 711771fe6b9SJerome Glisse rdev->cp.ready = false; 712771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 713771fe6b9SJerome Glisse radeon_ring_fini(rdev); 714771fe6b9SJerome Glisse DRM_INFO("radeon: cp finalized\n"); 715771fe6b9SJerome Glisse } 716771fe6b9SJerome Glisse 717771fe6b9SJerome Glisse void r100_cp_disable(struct radeon_device *rdev) 718771fe6b9SJerome Glisse { 719771fe6b9SJerome Glisse /* Disable ring */ 720771fe6b9SJerome Glisse rdev->cp.ready = false; 721771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 722771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 723771fe6b9SJerome Glisse if (r100_gui_wait_for_idle(rdev)) { 724771fe6b9SJerome Glisse printk(KERN_WARNING "Failed to wait GUI idle while " 725771fe6b9SJerome Glisse "programming pipes. Bad things might happen.\n"); 726771fe6b9SJerome Glisse } 727771fe6b9SJerome Glisse } 728771fe6b9SJerome Glisse 729771fe6b9SJerome Glisse int r100_cp_reset(struct radeon_device *rdev) 730771fe6b9SJerome Glisse { 731771fe6b9SJerome Glisse uint32_t tmp; 732771fe6b9SJerome Glisse bool reinit_cp; 733771fe6b9SJerome Glisse int i; 734771fe6b9SJerome Glisse 735771fe6b9SJerome Glisse reinit_cp = rdev->cp.ready; 736771fe6b9SJerome Glisse rdev->cp.ready = false; 737771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_MODE, 0); 738771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_CNTL, 0); 739771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP); 740771fe6b9SJerome Glisse (void)RREG32(RADEON_RBBM_SOFT_RESET); 741771fe6b9SJerome Glisse udelay(200); 742771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 743771fe6b9SJerome Glisse /* Wait to prevent race in RBBM_STATUS */ 744771fe6b9SJerome Glisse mdelay(1); 745771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 746771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 747771fe6b9SJerome Glisse if (!(tmp & (1 << 16))) { 748771fe6b9SJerome Glisse DRM_INFO("CP reset succeed (RBBM_STATUS=0x%08X)\n", 749771fe6b9SJerome Glisse tmp); 750771fe6b9SJerome Glisse if (reinit_cp) { 751771fe6b9SJerome Glisse return r100_cp_init(rdev, rdev->cp.ring_size); 752771fe6b9SJerome Glisse } 753771fe6b9SJerome Glisse return 0; 754771fe6b9SJerome Glisse } 755771fe6b9SJerome Glisse DRM_UDELAY(1); 756771fe6b9SJerome Glisse } 757771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 758771fe6b9SJerome Glisse DRM_ERROR("Failed to reset CP (RBBM_STATUS=0x%08X)!\n", tmp); 759771fe6b9SJerome Glisse return -1; 760771fe6b9SJerome Glisse } 761771fe6b9SJerome Glisse 762771fe6b9SJerome Glisse 763771fe6b9SJerome Glisse /* 764771fe6b9SJerome Glisse * CS functions 765771fe6b9SJerome Glisse */ 766771fe6b9SJerome Glisse int r100_cs_parse_packet0(struct radeon_cs_parser *p, 767771fe6b9SJerome Glisse struct radeon_cs_packet *pkt, 768068a117cSJerome Glisse const unsigned *auth, unsigned n, 769771fe6b9SJerome Glisse radeon_packet0_check_t check) 770771fe6b9SJerome Glisse { 771771fe6b9SJerome Glisse unsigned reg; 772771fe6b9SJerome Glisse unsigned i, j, m; 773771fe6b9SJerome Glisse unsigned idx; 774771fe6b9SJerome Glisse int r; 775771fe6b9SJerome Glisse 776771fe6b9SJerome Glisse idx = pkt->idx + 1; 777771fe6b9SJerome Glisse reg = pkt->reg; 778068a117cSJerome Glisse /* Check that register fall into register range 779068a117cSJerome Glisse * determined by the number of entry (n) in the 780068a117cSJerome Glisse * safe register bitmap. 781068a117cSJerome Glisse */ 782771fe6b9SJerome Glisse if (pkt->one_reg_wr) { 783771fe6b9SJerome Glisse if ((reg >> 7) > n) { 784771fe6b9SJerome Glisse return -EINVAL; 785771fe6b9SJerome Glisse } 786771fe6b9SJerome Glisse } else { 787771fe6b9SJerome Glisse if (((reg + (pkt->count << 2)) >> 7) > n) { 788771fe6b9SJerome Glisse return -EINVAL; 789771fe6b9SJerome Glisse } 790771fe6b9SJerome Glisse } 791771fe6b9SJerome Glisse for (i = 0; i <= pkt->count; i++, idx++) { 792771fe6b9SJerome Glisse j = (reg >> 7); 793771fe6b9SJerome Glisse m = 1 << ((reg >> 2) & 31); 794771fe6b9SJerome Glisse if (auth[j] & m) { 795771fe6b9SJerome Glisse r = check(p, pkt, idx, reg); 796771fe6b9SJerome Glisse if (r) { 797771fe6b9SJerome Glisse return r; 798771fe6b9SJerome Glisse } 799771fe6b9SJerome Glisse } 800771fe6b9SJerome Glisse if (pkt->one_reg_wr) { 801771fe6b9SJerome Glisse if (!(auth[j] & m)) { 802771fe6b9SJerome Glisse break; 803771fe6b9SJerome Glisse } 804771fe6b9SJerome Glisse } else { 805771fe6b9SJerome Glisse reg += 4; 806771fe6b9SJerome Glisse } 807771fe6b9SJerome Glisse } 808771fe6b9SJerome Glisse return 0; 809771fe6b9SJerome Glisse } 810771fe6b9SJerome Glisse 811771fe6b9SJerome Glisse void r100_cs_dump_packet(struct radeon_cs_parser *p, 812771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 813771fe6b9SJerome Glisse { 814771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 815771fe6b9SJerome Glisse volatile uint32_t *ib; 816771fe6b9SJerome Glisse unsigned i; 817771fe6b9SJerome Glisse unsigned idx; 818771fe6b9SJerome Glisse 819771fe6b9SJerome Glisse ib = p->ib->ptr; 820771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 821771fe6b9SJerome Glisse idx = pkt->idx; 822771fe6b9SJerome Glisse for (i = 0; i <= (pkt->count + 1); i++, idx++) { 823771fe6b9SJerome Glisse DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]); 824771fe6b9SJerome Glisse } 825771fe6b9SJerome Glisse } 826771fe6b9SJerome Glisse 827771fe6b9SJerome Glisse /** 828771fe6b9SJerome Glisse * r100_cs_packet_parse() - parse cp packet and point ib index to next packet 829771fe6b9SJerome Glisse * @parser: parser structure holding parsing context. 830771fe6b9SJerome Glisse * @pkt: where to store packet informations 831771fe6b9SJerome Glisse * 832771fe6b9SJerome Glisse * Assume that chunk_ib_index is properly set. Will return -EINVAL 833771fe6b9SJerome Glisse * if packet is bigger than remaining ib size. or if packets is unknown. 834771fe6b9SJerome Glisse **/ 835771fe6b9SJerome Glisse int r100_cs_packet_parse(struct radeon_cs_parser *p, 836771fe6b9SJerome Glisse struct radeon_cs_packet *pkt, 837771fe6b9SJerome Glisse unsigned idx) 838771fe6b9SJerome Glisse { 839771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; 840fa99239cSRoel Kluin uint32_t header; 841771fe6b9SJerome Glisse 842771fe6b9SJerome Glisse if (idx >= ib_chunk->length_dw) { 843771fe6b9SJerome Glisse DRM_ERROR("Can not parse packet at %d after CS end %d !\n", 844771fe6b9SJerome Glisse idx, ib_chunk->length_dw); 845771fe6b9SJerome Glisse return -EINVAL; 846771fe6b9SJerome Glisse } 847fa99239cSRoel Kluin header = ib_chunk->kdata[idx]; 848771fe6b9SJerome Glisse pkt->idx = idx; 849771fe6b9SJerome Glisse pkt->type = CP_PACKET_GET_TYPE(header); 850771fe6b9SJerome Glisse pkt->count = CP_PACKET_GET_COUNT(header); 851771fe6b9SJerome Glisse switch (pkt->type) { 852771fe6b9SJerome Glisse case PACKET_TYPE0: 853771fe6b9SJerome Glisse pkt->reg = CP_PACKET0_GET_REG(header); 854771fe6b9SJerome Glisse pkt->one_reg_wr = CP_PACKET0_GET_ONE_REG_WR(header); 855771fe6b9SJerome Glisse break; 856771fe6b9SJerome Glisse case PACKET_TYPE3: 857771fe6b9SJerome Glisse pkt->opcode = CP_PACKET3_GET_OPCODE(header); 858771fe6b9SJerome Glisse break; 859771fe6b9SJerome Glisse case PACKET_TYPE2: 860771fe6b9SJerome Glisse pkt->count = -1; 861771fe6b9SJerome Glisse break; 862771fe6b9SJerome Glisse default: 863771fe6b9SJerome Glisse DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx); 864771fe6b9SJerome Glisse return -EINVAL; 865771fe6b9SJerome Glisse } 866771fe6b9SJerome Glisse if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) { 867771fe6b9SJerome Glisse DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n", 868771fe6b9SJerome Glisse pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw); 869771fe6b9SJerome Glisse return -EINVAL; 870771fe6b9SJerome Glisse } 871771fe6b9SJerome Glisse return 0; 872771fe6b9SJerome Glisse } 873771fe6b9SJerome Glisse 874771fe6b9SJerome Glisse /** 875531369e6SDave Airlie * r100_cs_packet_next_vline() - parse userspace VLINE packet 876531369e6SDave Airlie * @parser: parser structure holding parsing context. 877531369e6SDave Airlie * 878531369e6SDave Airlie * Userspace sends a special sequence for VLINE waits. 879531369e6SDave Airlie * PACKET0 - VLINE_START_END + value 880531369e6SDave Airlie * PACKET0 - WAIT_UNTIL +_value 881531369e6SDave Airlie * RELOC (P3) - crtc_id in reloc. 882531369e6SDave Airlie * 883531369e6SDave Airlie * This function parses this and relocates the VLINE START END 884531369e6SDave Airlie * and WAIT UNTIL packets to the correct crtc. 885531369e6SDave Airlie * It also detects a switched off crtc and nulls out the 886531369e6SDave Airlie * wait in that case. 887531369e6SDave Airlie */ 888531369e6SDave Airlie int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) 889531369e6SDave Airlie { 890531369e6SDave Airlie struct radeon_cs_chunk *ib_chunk; 891531369e6SDave Airlie struct drm_mode_object *obj; 892531369e6SDave Airlie struct drm_crtc *crtc; 893531369e6SDave Airlie struct radeon_crtc *radeon_crtc; 894531369e6SDave Airlie struct radeon_cs_packet p3reloc, waitreloc; 895531369e6SDave Airlie int crtc_id; 896531369e6SDave Airlie int r; 897531369e6SDave Airlie uint32_t header, h_idx, reg; 898531369e6SDave Airlie 899531369e6SDave Airlie ib_chunk = &p->chunks[p->chunk_ib_idx]; 900531369e6SDave Airlie 901531369e6SDave Airlie /* parse the wait until */ 902531369e6SDave Airlie r = r100_cs_packet_parse(p, &waitreloc, p->idx); 903531369e6SDave Airlie if (r) 904531369e6SDave Airlie return r; 905531369e6SDave Airlie 906531369e6SDave Airlie /* check its a wait until and only 1 count */ 907531369e6SDave Airlie if (waitreloc.reg != RADEON_WAIT_UNTIL || 908531369e6SDave Airlie waitreloc.count != 0) { 909531369e6SDave Airlie DRM_ERROR("vline wait had illegal wait until segment\n"); 910531369e6SDave Airlie r = -EINVAL; 911531369e6SDave Airlie return r; 912531369e6SDave Airlie } 913531369e6SDave Airlie 914531369e6SDave Airlie if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) { 915531369e6SDave Airlie DRM_ERROR("vline wait had illegal wait until\n"); 916531369e6SDave Airlie r = -EINVAL; 917531369e6SDave Airlie return r; 918531369e6SDave Airlie } 919531369e6SDave Airlie 920531369e6SDave Airlie /* jump over the NOP */ 921531369e6SDave Airlie r = r100_cs_packet_parse(p, &p3reloc, p->idx); 922531369e6SDave Airlie if (r) 923531369e6SDave Airlie return r; 924531369e6SDave Airlie 925531369e6SDave Airlie h_idx = p->idx - 2; 926531369e6SDave Airlie p->idx += waitreloc.count; 927531369e6SDave Airlie p->idx += p3reloc.count; 928531369e6SDave Airlie 929531369e6SDave Airlie header = ib_chunk->kdata[h_idx]; 930531369e6SDave Airlie crtc_id = ib_chunk->kdata[h_idx + 5]; 931531369e6SDave Airlie reg = ib_chunk->kdata[h_idx] >> 2; 932531369e6SDave Airlie mutex_lock(&p->rdev->ddev->mode_config.mutex); 933531369e6SDave Airlie obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); 934531369e6SDave Airlie if (!obj) { 935531369e6SDave Airlie DRM_ERROR("cannot find crtc %d\n", crtc_id); 936531369e6SDave Airlie r = -EINVAL; 937531369e6SDave Airlie goto out; 938531369e6SDave Airlie } 939531369e6SDave Airlie crtc = obj_to_crtc(obj); 940531369e6SDave Airlie radeon_crtc = to_radeon_crtc(crtc); 941531369e6SDave Airlie crtc_id = radeon_crtc->crtc_id; 942531369e6SDave Airlie 943531369e6SDave Airlie if (!crtc->enabled) { 944531369e6SDave Airlie /* if the CRTC isn't enabled - we need to nop out the wait until */ 945531369e6SDave Airlie ib_chunk->kdata[h_idx + 2] = PACKET2(0); 946531369e6SDave Airlie ib_chunk->kdata[h_idx + 3] = PACKET2(0); 947531369e6SDave Airlie } else if (crtc_id == 1) { 948531369e6SDave Airlie switch (reg) { 949531369e6SDave Airlie case AVIVO_D1MODE_VLINE_START_END: 950531369e6SDave Airlie header &= R300_CP_PACKET0_REG_MASK; 951531369e6SDave Airlie header |= AVIVO_D2MODE_VLINE_START_END >> 2; 952531369e6SDave Airlie break; 953531369e6SDave Airlie case RADEON_CRTC_GUI_TRIG_VLINE: 954531369e6SDave Airlie header &= R300_CP_PACKET0_REG_MASK; 955531369e6SDave Airlie header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2; 956531369e6SDave Airlie break; 957531369e6SDave Airlie default: 958531369e6SDave Airlie DRM_ERROR("unknown crtc reloc\n"); 959531369e6SDave Airlie r = -EINVAL; 960531369e6SDave Airlie goto out; 961531369e6SDave Airlie } 962531369e6SDave Airlie ib_chunk->kdata[h_idx] = header; 963531369e6SDave Airlie ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; 964531369e6SDave Airlie } 965531369e6SDave Airlie out: 966531369e6SDave Airlie mutex_unlock(&p->rdev->ddev->mode_config.mutex); 967531369e6SDave Airlie return r; 968531369e6SDave Airlie } 969531369e6SDave Airlie 970531369e6SDave Airlie /** 971771fe6b9SJerome Glisse * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 972771fe6b9SJerome Glisse * @parser: parser structure holding parsing context. 973771fe6b9SJerome Glisse * @data: pointer to relocation data 974771fe6b9SJerome Glisse * @offset_start: starting offset 975771fe6b9SJerome Glisse * @offset_mask: offset mask (to align start offset on) 976771fe6b9SJerome Glisse * @reloc: reloc informations 977771fe6b9SJerome Glisse * 978771fe6b9SJerome Glisse * Check next packet is relocation packet3, do bo validation and compute 979771fe6b9SJerome Glisse * GPU offset using the provided start. 980771fe6b9SJerome Glisse **/ 981771fe6b9SJerome Glisse int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, 982771fe6b9SJerome Glisse struct radeon_cs_reloc **cs_reloc) 983771fe6b9SJerome Glisse { 984771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 985771fe6b9SJerome Glisse struct radeon_cs_chunk *relocs_chunk; 986771fe6b9SJerome Glisse struct radeon_cs_packet p3reloc; 987771fe6b9SJerome Glisse unsigned idx; 988771fe6b9SJerome Glisse int r; 989771fe6b9SJerome Glisse 990771fe6b9SJerome Glisse if (p->chunk_relocs_idx == -1) { 991771fe6b9SJerome Glisse DRM_ERROR("No relocation chunk !\n"); 992771fe6b9SJerome Glisse return -EINVAL; 993771fe6b9SJerome Glisse } 994771fe6b9SJerome Glisse *cs_reloc = NULL; 995771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 996771fe6b9SJerome Glisse relocs_chunk = &p->chunks[p->chunk_relocs_idx]; 997771fe6b9SJerome Glisse r = r100_cs_packet_parse(p, &p3reloc, p->idx); 998771fe6b9SJerome Glisse if (r) { 999771fe6b9SJerome Glisse return r; 1000771fe6b9SJerome Glisse } 1001771fe6b9SJerome Glisse p->idx += p3reloc.count + 2; 1002771fe6b9SJerome Glisse if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { 1003771fe6b9SJerome Glisse DRM_ERROR("No packet3 for relocation for packet at %d.\n", 1004771fe6b9SJerome Glisse p3reloc.idx); 1005771fe6b9SJerome Glisse r100_cs_dump_packet(p, &p3reloc); 1006771fe6b9SJerome Glisse return -EINVAL; 1007771fe6b9SJerome Glisse } 1008771fe6b9SJerome Glisse idx = ib_chunk->kdata[p3reloc.idx + 1]; 1009771fe6b9SJerome Glisse if (idx >= relocs_chunk->length_dw) { 1010771fe6b9SJerome Glisse DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", 1011771fe6b9SJerome Glisse idx, relocs_chunk->length_dw); 1012771fe6b9SJerome Glisse r100_cs_dump_packet(p, &p3reloc); 1013771fe6b9SJerome Glisse return -EINVAL; 1014771fe6b9SJerome Glisse } 1015771fe6b9SJerome Glisse /* FIXME: we assume reloc size is 4 dwords */ 1016771fe6b9SJerome Glisse *cs_reloc = p->relocs_ptr[(idx / 4)]; 1017771fe6b9SJerome Glisse return 0; 1018771fe6b9SJerome Glisse } 1019771fe6b9SJerome Glisse 1020771fe6b9SJerome Glisse static int r100_packet0_check(struct radeon_cs_parser *p, 1021771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 1022771fe6b9SJerome Glisse { 1023771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 1024771fe6b9SJerome Glisse struct radeon_cs_reloc *reloc; 1025771fe6b9SJerome Glisse volatile uint32_t *ib; 1026771fe6b9SJerome Glisse uint32_t tmp; 1027771fe6b9SJerome Glisse unsigned reg; 1028771fe6b9SJerome Glisse unsigned i; 1029771fe6b9SJerome Glisse unsigned idx; 1030771fe6b9SJerome Glisse bool onereg; 1031771fe6b9SJerome Glisse int r; 1032e024e110SDave Airlie u32 tile_flags = 0; 1033771fe6b9SJerome Glisse 1034771fe6b9SJerome Glisse ib = p->ib->ptr; 1035771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 1036771fe6b9SJerome Glisse idx = pkt->idx + 1; 1037771fe6b9SJerome Glisse reg = pkt->reg; 1038771fe6b9SJerome Glisse onereg = false; 1039771fe6b9SJerome Glisse if (CP_PACKET0_GET_ONE_REG_WR(ib_chunk->kdata[pkt->idx])) { 1040771fe6b9SJerome Glisse onereg = true; 1041771fe6b9SJerome Glisse } 1042771fe6b9SJerome Glisse for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { 1043771fe6b9SJerome Glisse switch (reg) { 1044531369e6SDave Airlie case RADEON_CRTC_GUI_TRIG_VLINE: 1045531369e6SDave Airlie r = r100_cs_packet_parse_vline(p); 1046531369e6SDave Airlie if (r) { 1047531369e6SDave Airlie DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1048531369e6SDave Airlie idx, reg); 1049531369e6SDave Airlie r100_cs_dump_packet(p, pkt); 1050531369e6SDave Airlie return r; 1051531369e6SDave Airlie } 1052531369e6SDave Airlie break; 1053771fe6b9SJerome Glisse /* FIXME: only allow PACKET3 blit? easier to check for out of 1054771fe6b9SJerome Glisse * range access */ 1055771fe6b9SJerome Glisse case RADEON_DST_PITCH_OFFSET: 1056771fe6b9SJerome Glisse case RADEON_SRC_PITCH_OFFSET: 1057771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1058771fe6b9SJerome Glisse if (r) { 1059771fe6b9SJerome Glisse DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1060771fe6b9SJerome Glisse idx, reg); 1061771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1062771fe6b9SJerome Glisse return r; 1063771fe6b9SJerome Glisse } 1064771fe6b9SJerome Glisse tmp = ib_chunk->kdata[idx] & 0x003fffff; 1065771fe6b9SJerome Glisse tmp += (((u32)reloc->lobj.gpu_offset) >> 10); 1066e024e110SDave Airlie 1067e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) 1068e024e110SDave Airlie tile_flags |= RADEON_DST_TILE_MACRO; 1069e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { 1070e024e110SDave Airlie if (reg == RADEON_SRC_PITCH_OFFSET) { 1071e024e110SDave Airlie DRM_ERROR("Cannot src blit from microtiled surface\n"); 1072e024e110SDave Airlie r100_cs_dump_packet(p, pkt); 1073e024e110SDave Airlie return -EINVAL; 1074e024e110SDave Airlie } 1075e024e110SDave Airlie tile_flags |= RADEON_DST_TILE_MICRO; 1076e024e110SDave Airlie } 1077e024e110SDave Airlie 1078e024e110SDave Airlie tmp |= tile_flags; 1079e024e110SDave Airlie ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp; 1080771fe6b9SJerome Glisse break; 1081771fe6b9SJerome Glisse case RADEON_RB3D_DEPTHOFFSET: 1082771fe6b9SJerome Glisse case RADEON_RB3D_COLOROFFSET: 1083771fe6b9SJerome Glisse case R300_RB3D_COLOROFFSET0: 1084771fe6b9SJerome Glisse case R300_ZB_DEPTHOFFSET: 1085771fe6b9SJerome Glisse case R200_PP_TXOFFSET_0: 1086771fe6b9SJerome Glisse case R200_PP_TXOFFSET_1: 1087771fe6b9SJerome Glisse case R200_PP_TXOFFSET_2: 1088771fe6b9SJerome Glisse case R200_PP_TXOFFSET_3: 1089771fe6b9SJerome Glisse case R200_PP_TXOFFSET_4: 1090771fe6b9SJerome Glisse case R200_PP_TXOFFSET_5: 1091771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_0: 1092771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_1: 1093771fe6b9SJerome Glisse case RADEON_PP_TXOFFSET_2: 1094771fe6b9SJerome Glisse case R300_TX_OFFSET_0: 1095771fe6b9SJerome Glisse case R300_TX_OFFSET_0+4: 1096771fe6b9SJerome Glisse case R300_TX_OFFSET_0+8: 1097771fe6b9SJerome Glisse case R300_TX_OFFSET_0+12: 1098771fe6b9SJerome Glisse case R300_TX_OFFSET_0+16: 1099771fe6b9SJerome Glisse case R300_TX_OFFSET_0+20: 1100771fe6b9SJerome Glisse case R300_TX_OFFSET_0+24: 1101771fe6b9SJerome Glisse case R300_TX_OFFSET_0+28: 1102771fe6b9SJerome Glisse case R300_TX_OFFSET_0+32: 1103771fe6b9SJerome Glisse case R300_TX_OFFSET_0+36: 1104771fe6b9SJerome Glisse case R300_TX_OFFSET_0+40: 1105771fe6b9SJerome Glisse case R300_TX_OFFSET_0+44: 1106771fe6b9SJerome Glisse case R300_TX_OFFSET_0+48: 1107771fe6b9SJerome Glisse case R300_TX_OFFSET_0+52: 1108771fe6b9SJerome Glisse case R300_TX_OFFSET_0+56: 1109771fe6b9SJerome Glisse case R300_TX_OFFSET_0+60: 1110b995e433SDave Airlie /* rn50 has no 3D engine so fail on any 3d setup */ 1111b995e433SDave Airlie if (ASIC_IS_RN50(p->rdev)) { 1112b995e433SDave Airlie DRM_ERROR("attempt to use RN50 3D engine failed\n"); 1113b995e433SDave Airlie return -EINVAL; 1114b995e433SDave Airlie } 1115771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1116771fe6b9SJerome Glisse if (r) { 1117771fe6b9SJerome Glisse DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1118771fe6b9SJerome Glisse idx, reg); 1119771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1120771fe6b9SJerome Glisse return r; 1121771fe6b9SJerome Glisse } 1122771fe6b9SJerome Glisse ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); 1123771fe6b9SJerome Glisse break; 1124e024e110SDave Airlie case R300_RB3D_COLORPITCH0: 1125e024e110SDave Airlie case RADEON_RB3D_COLORPITCH: 1126e024e110SDave Airlie r = r100_cs_packet_next_reloc(p, &reloc); 1127e024e110SDave Airlie if (r) { 1128e024e110SDave Airlie DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1129e024e110SDave Airlie idx, reg); 1130e024e110SDave Airlie r100_cs_dump_packet(p, pkt); 1131e024e110SDave Airlie return r; 1132e024e110SDave Airlie } 1133e024e110SDave Airlie 1134e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) 1135e024e110SDave Airlie tile_flags |= RADEON_COLOR_TILE_ENABLE; 1136e024e110SDave Airlie if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) 1137e024e110SDave Airlie tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; 1138e024e110SDave Airlie 1139e024e110SDave Airlie tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); 1140e024e110SDave Airlie tmp |= tile_flags; 1141e024e110SDave Airlie ib[idx] = tmp; 1142e024e110SDave Airlie break; 1143771fe6b9SJerome Glisse default: 1144771fe6b9SJerome Glisse /* FIXME: we don't want to allow anyothers packet */ 1145771fe6b9SJerome Glisse break; 1146771fe6b9SJerome Glisse } 1147771fe6b9SJerome Glisse if (onereg) { 1148771fe6b9SJerome Glisse /* FIXME: forbid onereg write to register on relocate */ 1149771fe6b9SJerome Glisse break; 1150771fe6b9SJerome Glisse } 1151771fe6b9SJerome Glisse } 1152771fe6b9SJerome Glisse return 0; 1153771fe6b9SJerome Glisse } 1154771fe6b9SJerome Glisse 1155068a117cSJerome Glisse int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, 1156068a117cSJerome Glisse struct radeon_cs_packet *pkt, 1157068a117cSJerome Glisse struct radeon_object *robj) 1158068a117cSJerome Glisse { 1159068a117cSJerome Glisse struct radeon_cs_chunk *ib_chunk; 1160068a117cSJerome Glisse unsigned idx; 1161068a117cSJerome Glisse 1162068a117cSJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 1163068a117cSJerome Glisse idx = pkt->idx + 1; 1164068a117cSJerome Glisse if ((ib_chunk->kdata[idx+2] + 1) > radeon_object_size(robj)) { 1165068a117cSJerome Glisse DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER " 1166068a117cSJerome Glisse "(need %u have %lu) !\n", 1167068a117cSJerome Glisse ib_chunk->kdata[idx+2] + 1, 1168068a117cSJerome Glisse radeon_object_size(robj)); 1169068a117cSJerome Glisse return -EINVAL; 1170068a117cSJerome Glisse } 1171068a117cSJerome Glisse return 0; 1172068a117cSJerome Glisse } 1173068a117cSJerome Glisse 1174771fe6b9SJerome Glisse static int r100_packet3_check(struct radeon_cs_parser *p, 1175771fe6b9SJerome Glisse struct radeon_cs_packet *pkt) 1176771fe6b9SJerome Glisse { 1177771fe6b9SJerome Glisse struct radeon_cs_chunk *ib_chunk; 1178771fe6b9SJerome Glisse struct radeon_cs_reloc *reloc; 1179771fe6b9SJerome Glisse unsigned idx; 1180771fe6b9SJerome Glisse unsigned i, c; 1181771fe6b9SJerome Glisse volatile uint32_t *ib; 1182771fe6b9SJerome Glisse int r; 1183771fe6b9SJerome Glisse 1184771fe6b9SJerome Glisse ib = p->ib->ptr; 1185771fe6b9SJerome Glisse ib_chunk = &p->chunks[p->chunk_ib_idx]; 1186771fe6b9SJerome Glisse idx = pkt->idx + 1; 1187771fe6b9SJerome Glisse switch (pkt->opcode) { 1188771fe6b9SJerome Glisse case PACKET3_3D_LOAD_VBPNTR: 1189771fe6b9SJerome Glisse c = ib_chunk->kdata[idx++]; 1190771fe6b9SJerome Glisse for (i = 0; i < (c - 1); i += 2, idx += 3) { 1191771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1192771fe6b9SJerome Glisse if (r) { 1193771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 1194771fe6b9SJerome Glisse pkt->opcode); 1195771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1196771fe6b9SJerome Glisse return r; 1197771fe6b9SJerome Glisse } 1198771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1199771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1200771fe6b9SJerome Glisse if (r) { 1201771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 1202771fe6b9SJerome Glisse pkt->opcode); 1203771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1204771fe6b9SJerome Glisse return r; 1205771fe6b9SJerome Glisse } 1206771fe6b9SJerome Glisse ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset); 1207771fe6b9SJerome Glisse } 1208771fe6b9SJerome Glisse if (c & 1) { 1209771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1210771fe6b9SJerome Glisse if (r) { 1211771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", 1212771fe6b9SJerome Glisse pkt->opcode); 1213771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1214771fe6b9SJerome Glisse return r; 1215771fe6b9SJerome Glisse } 1216771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1217771fe6b9SJerome Glisse } 1218771fe6b9SJerome Glisse break; 1219771fe6b9SJerome Glisse case PACKET3_INDX_BUFFER: 1220771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1221771fe6b9SJerome Glisse if (r) { 1222771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 1223771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1224771fe6b9SJerome Glisse return r; 1225771fe6b9SJerome Glisse } 1226771fe6b9SJerome Glisse ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1227068a117cSJerome Glisse r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj); 1228068a117cSJerome Glisse if (r) { 1229068a117cSJerome Glisse return r; 1230068a117cSJerome Glisse } 1231771fe6b9SJerome Glisse break; 1232771fe6b9SJerome Glisse case 0x23: 1233771fe6b9SJerome Glisse /* FIXME: cleanup */ 1234771fe6b9SJerome Glisse /* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */ 1235771fe6b9SJerome Glisse r = r100_cs_packet_next_reloc(p, &reloc); 1236771fe6b9SJerome Glisse if (r) { 1237771fe6b9SJerome Glisse DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 1238771fe6b9SJerome Glisse r100_cs_dump_packet(p, pkt); 1239771fe6b9SJerome Glisse return r; 1240771fe6b9SJerome Glisse } 1241771fe6b9SJerome Glisse ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); 1242771fe6b9SJerome Glisse break; 1243771fe6b9SJerome Glisse case PACKET3_3D_DRAW_IMMD: 1244771fe6b9SJerome Glisse /* triggers drawing using in-packet vertex data */ 1245771fe6b9SJerome Glisse case PACKET3_3D_DRAW_IMMD_2: 1246771fe6b9SJerome Glisse /* triggers drawing using in-packet vertex data */ 1247771fe6b9SJerome Glisse case PACKET3_3D_DRAW_VBUF_2: 1248771fe6b9SJerome Glisse /* triggers drawing of vertex buffers setup elsewhere */ 1249771fe6b9SJerome Glisse case PACKET3_3D_DRAW_INDX_2: 1250771fe6b9SJerome Glisse /* triggers drawing using indices to vertex buffer */ 1251771fe6b9SJerome Glisse case PACKET3_3D_DRAW_VBUF: 1252771fe6b9SJerome Glisse /* triggers drawing of vertex buffers setup elsewhere */ 1253771fe6b9SJerome Glisse case PACKET3_3D_DRAW_INDX: 1254771fe6b9SJerome Glisse /* triggers drawing using indices to vertex buffer */ 1255771fe6b9SJerome Glisse case PACKET3_NOP: 1256771fe6b9SJerome Glisse break; 1257771fe6b9SJerome Glisse default: 1258771fe6b9SJerome Glisse DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); 1259771fe6b9SJerome Glisse return -EINVAL; 1260771fe6b9SJerome Glisse } 1261771fe6b9SJerome Glisse return 0; 1262771fe6b9SJerome Glisse } 1263771fe6b9SJerome Glisse 1264771fe6b9SJerome Glisse int r100_cs_parse(struct radeon_cs_parser *p) 1265771fe6b9SJerome Glisse { 1266771fe6b9SJerome Glisse struct radeon_cs_packet pkt; 1267771fe6b9SJerome Glisse int r; 1268771fe6b9SJerome Glisse 1269771fe6b9SJerome Glisse do { 1270771fe6b9SJerome Glisse r = r100_cs_packet_parse(p, &pkt, p->idx); 1271771fe6b9SJerome Glisse if (r) { 1272771fe6b9SJerome Glisse return r; 1273771fe6b9SJerome Glisse } 1274771fe6b9SJerome Glisse p->idx += pkt.count + 2; 1275771fe6b9SJerome Glisse switch (pkt.type) { 1276771fe6b9SJerome Glisse case PACKET_TYPE0: 1277771fe6b9SJerome Glisse r = r100_packet0_check(p, &pkt); 1278771fe6b9SJerome Glisse break; 1279771fe6b9SJerome Glisse case PACKET_TYPE2: 1280771fe6b9SJerome Glisse break; 1281771fe6b9SJerome Glisse case PACKET_TYPE3: 1282771fe6b9SJerome Glisse r = r100_packet3_check(p, &pkt); 1283771fe6b9SJerome Glisse break; 1284771fe6b9SJerome Glisse default: 1285771fe6b9SJerome Glisse DRM_ERROR("Unknown packet type %d !\n", 1286771fe6b9SJerome Glisse pkt.type); 1287771fe6b9SJerome Glisse return -EINVAL; 1288771fe6b9SJerome Glisse } 1289771fe6b9SJerome Glisse if (r) { 1290771fe6b9SJerome Glisse return r; 1291771fe6b9SJerome Glisse } 1292771fe6b9SJerome Glisse } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); 1293771fe6b9SJerome Glisse return 0; 1294771fe6b9SJerome Glisse } 1295771fe6b9SJerome Glisse 1296771fe6b9SJerome Glisse 1297771fe6b9SJerome Glisse /* 1298771fe6b9SJerome Glisse * Global GPU functions 1299771fe6b9SJerome Glisse */ 1300771fe6b9SJerome Glisse void r100_errata(struct radeon_device *rdev) 1301771fe6b9SJerome Glisse { 1302771fe6b9SJerome Glisse rdev->pll_errata = 0; 1303771fe6b9SJerome Glisse 1304771fe6b9SJerome Glisse if (rdev->family == CHIP_RV200 || rdev->family == CHIP_RS200) { 1305771fe6b9SJerome Glisse rdev->pll_errata |= CHIP_ERRATA_PLL_DUMMYREADS; 1306771fe6b9SJerome Glisse } 1307771fe6b9SJerome Glisse 1308771fe6b9SJerome Glisse if (rdev->family == CHIP_RV100 || 1309771fe6b9SJerome Glisse rdev->family == CHIP_RS100 || 1310771fe6b9SJerome Glisse rdev->family == CHIP_RS200) { 1311771fe6b9SJerome Glisse rdev->pll_errata |= CHIP_ERRATA_PLL_DELAY; 1312771fe6b9SJerome Glisse } 1313771fe6b9SJerome Glisse } 1314771fe6b9SJerome Glisse 1315771fe6b9SJerome Glisse /* Wait for vertical sync on primary CRTC */ 1316771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync(struct radeon_device *rdev) 1317771fe6b9SJerome Glisse { 1318771fe6b9SJerome Glisse uint32_t crtc_gen_cntl, tmp; 1319771fe6b9SJerome Glisse int i; 1320771fe6b9SJerome Glisse 1321771fe6b9SJerome Glisse crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); 1322771fe6b9SJerome Glisse if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || 1323771fe6b9SJerome Glisse !(crtc_gen_cntl & RADEON_CRTC_EN)) { 1324771fe6b9SJerome Glisse return; 1325771fe6b9SJerome Glisse } 1326771fe6b9SJerome Glisse /* Clear the CRTC_VBLANK_SAVE bit */ 1327771fe6b9SJerome Glisse WREG32(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); 1328771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1329771fe6b9SJerome Glisse tmp = RREG32(RADEON_CRTC_STATUS); 1330771fe6b9SJerome Glisse if (tmp & RADEON_CRTC_VBLANK_SAVE) { 1331771fe6b9SJerome Glisse return; 1332771fe6b9SJerome Glisse } 1333771fe6b9SJerome Glisse DRM_UDELAY(1); 1334771fe6b9SJerome Glisse } 1335771fe6b9SJerome Glisse } 1336771fe6b9SJerome Glisse 1337771fe6b9SJerome Glisse /* Wait for vertical sync on secondary CRTC */ 1338771fe6b9SJerome Glisse void r100_gpu_wait_for_vsync2(struct radeon_device *rdev) 1339771fe6b9SJerome Glisse { 1340771fe6b9SJerome Glisse uint32_t crtc2_gen_cntl, tmp; 1341771fe6b9SJerome Glisse int i; 1342771fe6b9SJerome Glisse 1343771fe6b9SJerome Glisse crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); 1344771fe6b9SJerome Glisse if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || 1345771fe6b9SJerome Glisse !(crtc2_gen_cntl & RADEON_CRTC2_EN)) 1346771fe6b9SJerome Glisse return; 1347771fe6b9SJerome Glisse 1348771fe6b9SJerome Glisse /* Clear the CRTC_VBLANK_SAVE bit */ 1349771fe6b9SJerome Glisse WREG32(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); 1350771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1351771fe6b9SJerome Glisse tmp = RREG32(RADEON_CRTC2_STATUS); 1352771fe6b9SJerome Glisse if (tmp & RADEON_CRTC2_VBLANK_SAVE) { 1353771fe6b9SJerome Glisse return; 1354771fe6b9SJerome Glisse } 1355771fe6b9SJerome Glisse DRM_UDELAY(1); 1356771fe6b9SJerome Glisse } 1357771fe6b9SJerome Glisse } 1358771fe6b9SJerome Glisse 1359771fe6b9SJerome Glisse int r100_rbbm_fifo_wait_for_entry(struct radeon_device *rdev, unsigned n) 1360771fe6b9SJerome Glisse { 1361771fe6b9SJerome Glisse unsigned i; 1362771fe6b9SJerome Glisse uint32_t tmp; 1363771fe6b9SJerome Glisse 1364771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1365771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; 1366771fe6b9SJerome Glisse if (tmp >= n) { 1367771fe6b9SJerome Glisse return 0; 1368771fe6b9SJerome Glisse } 1369771fe6b9SJerome Glisse DRM_UDELAY(1); 1370771fe6b9SJerome Glisse } 1371771fe6b9SJerome Glisse return -1; 1372771fe6b9SJerome Glisse } 1373771fe6b9SJerome Glisse 1374771fe6b9SJerome Glisse int r100_gui_wait_for_idle(struct radeon_device *rdev) 1375771fe6b9SJerome Glisse { 1376771fe6b9SJerome Glisse unsigned i; 1377771fe6b9SJerome Glisse uint32_t tmp; 1378771fe6b9SJerome Glisse 1379771fe6b9SJerome Glisse if (r100_rbbm_fifo_wait_for_entry(rdev, 64)) { 1380771fe6b9SJerome Glisse printk(KERN_WARNING "radeon: wait for empty RBBM fifo failed !" 1381771fe6b9SJerome Glisse " Bad things might happen.\n"); 1382771fe6b9SJerome Glisse } 1383771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1384771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1385771fe6b9SJerome Glisse if (!(tmp & (1 << 31))) { 1386771fe6b9SJerome Glisse return 0; 1387771fe6b9SJerome Glisse } 1388771fe6b9SJerome Glisse DRM_UDELAY(1); 1389771fe6b9SJerome Glisse } 1390771fe6b9SJerome Glisse return -1; 1391771fe6b9SJerome Glisse } 1392771fe6b9SJerome Glisse 1393771fe6b9SJerome Glisse int r100_mc_wait_for_idle(struct radeon_device *rdev) 1394771fe6b9SJerome Glisse { 1395771fe6b9SJerome Glisse unsigned i; 1396771fe6b9SJerome Glisse uint32_t tmp; 1397771fe6b9SJerome Glisse 1398771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1399771fe6b9SJerome Glisse /* read MC_STATUS */ 1400771fe6b9SJerome Glisse tmp = RREG32(0x0150); 1401771fe6b9SJerome Glisse if (tmp & (1 << 2)) { 1402771fe6b9SJerome Glisse return 0; 1403771fe6b9SJerome Glisse } 1404771fe6b9SJerome Glisse DRM_UDELAY(1); 1405771fe6b9SJerome Glisse } 1406771fe6b9SJerome Glisse return -1; 1407771fe6b9SJerome Glisse } 1408771fe6b9SJerome Glisse 1409771fe6b9SJerome Glisse void r100_gpu_init(struct radeon_device *rdev) 1410771fe6b9SJerome Glisse { 1411771fe6b9SJerome Glisse /* TODO: anythings to do here ? pipes ? */ 1412771fe6b9SJerome Glisse r100_hdp_reset(rdev); 1413771fe6b9SJerome Glisse } 1414771fe6b9SJerome Glisse 1415771fe6b9SJerome Glisse void r100_hdp_reset(struct radeon_device *rdev) 1416771fe6b9SJerome Glisse { 1417771fe6b9SJerome Glisse uint32_t tmp; 1418771fe6b9SJerome Glisse 1419771fe6b9SJerome Glisse tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; 1420771fe6b9SJerome Glisse tmp |= (7 << 28); 1421771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); 1422771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 1423771fe6b9SJerome Glisse udelay(200); 1424771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 1425771fe6b9SJerome Glisse WREG32(RADEON_HOST_PATH_CNTL, tmp); 1426771fe6b9SJerome Glisse (void)RREG32(RADEON_HOST_PATH_CNTL); 1427771fe6b9SJerome Glisse } 1428771fe6b9SJerome Glisse 1429771fe6b9SJerome Glisse int r100_rb2d_reset(struct radeon_device *rdev) 1430771fe6b9SJerome Glisse { 1431771fe6b9SJerome Glisse uint32_t tmp; 1432771fe6b9SJerome Glisse int i; 1433771fe6b9SJerome Glisse 1434771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_E2); 1435771fe6b9SJerome Glisse (void)RREG32(RADEON_RBBM_SOFT_RESET); 1436771fe6b9SJerome Glisse udelay(200); 1437771fe6b9SJerome Glisse WREG32(RADEON_RBBM_SOFT_RESET, 0); 1438771fe6b9SJerome Glisse /* Wait to prevent race in RBBM_STATUS */ 1439771fe6b9SJerome Glisse mdelay(1); 1440771fe6b9SJerome Glisse for (i = 0; i < rdev->usec_timeout; i++) { 1441771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1442771fe6b9SJerome Glisse if (!(tmp & (1 << 26))) { 1443771fe6b9SJerome Glisse DRM_INFO("RB2D reset succeed (RBBM_STATUS=0x%08X)\n", 1444771fe6b9SJerome Glisse tmp); 1445771fe6b9SJerome Glisse return 0; 1446771fe6b9SJerome Glisse } 1447771fe6b9SJerome Glisse DRM_UDELAY(1); 1448771fe6b9SJerome Glisse } 1449771fe6b9SJerome Glisse tmp = RREG32(RADEON_RBBM_STATUS); 1450771fe6b9SJerome Glisse DRM_ERROR("Failed to reset RB2D (RBBM_STATUS=0x%08X)!\n", tmp); 1451771fe6b9SJerome Glisse return -1; 1452771fe6b9SJerome Glisse } 1453771fe6b9SJerome Glisse 1454771fe6b9SJerome Glisse int r100_gpu_reset(struct radeon_device *rdev) 1455771fe6b9SJerome Glisse { 1456771fe6b9SJerome Glisse uint32_t status; 1457771fe6b9SJerome Glisse 1458771fe6b9SJerome Glisse /* reset order likely matter */ 1459771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1460771fe6b9SJerome Glisse /* reset HDP */ 1461771fe6b9SJerome Glisse r100_hdp_reset(rdev); 1462771fe6b9SJerome Glisse /* reset rb2d */ 1463771fe6b9SJerome Glisse if (status & ((1 << 17) | (1 << 18) | (1 << 27))) { 1464771fe6b9SJerome Glisse r100_rb2d_reset(rdev); 1465771fe6b9SJerome Glisse } 1466771fe6b9SJerome Glisse /* TODO: reset 3D engine */ 1467771fe6b9SJerome Glisse /* reset CP */ 1468771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1469771fe6b9SJerome Glisse if (status & (1 << 16)) { 1470771fe6b9SJerome Glisse r100_cp_reset(rdev); 1471771fe6b9SJerome Glisse } 1472771fe6b9SJerome Glisse /* Check if GPU is idle */ 1473771fe6b9SJerome Glisse status = RREG32(RADEON_RBBM_STATUS); 1474771fe6b9SJerome Glisse if (status & (1 << 31)) { 1475771fe6b9SJerome Glisse DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); 1476771fe6b9SJerome Glisse return -1; 1477771fe6b9SJerome Glisse } 1478771fe6b9SJerome Glisse DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status); 1479771fe6b9SJerome Glisse return 0; 1480771fe6b9SJerome Glisse } 1481771fe6b9SJerome Glisse 1482771fe6b9SJerome Glisse 1483771fe6b9SJerome Glisse /* 1484771fe6b9SJerome Glisse * VRAM info 1485771fe6b9SJerome Glisse */ 1486771fe6b9SJerome Glisse static void r100_vram_get_type(struct radeon_device *rdev) 1487771fe6b9SJerome Glisse { 1488771fe6b9SJerome Glisse uint32_t tmp; 1489771fe6b9SJerome Glisse 1490771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = false; 1491771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_IGP) 1492771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1493771fe6b9SJerome Glisse else if (RREG32(RADEON_MEM_SDRAM_MODE_REG) & RADEON_MEM_CFG_TYPE_DDR) 1494771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1495771fe6b9SJerome Glisse if ((rdev->family == CHIP_RV100) || 1496771fe6b9SJerome Glisse (rdev->family == CHIP_RS100) || 1497771fe6b9SJerome Glisse (rdev->family == CHIP_RS200)) { 1498771fe6b9SJerome Glisse tmp = RREG32(RADEON_MEM_CNTL); 1499771fe6b9SJerome Glisse if (tmp & RV100_HALF_MODE) { 1500771fe6b9SJerome Glisse rdev->mc.vram_width = 32; 1501771fe6b9SJerome Glisse } else { 1502771fe6b9SJerome Glisse rdev->mc.vram_width = 64; 1503771fe6b9SJerome Glisse } 1504771fe6b9SJerome Glisse if (rdev->flags & RADEON_SINGLE_CRTC) { 1505771fe6b9SJerome Glisse rdev->mc.vram_width /= 4; 1506771fe6b9SJerome Glisse rdev->mc.vram_is_ddr = true; 1507771fe6b9SJerome Glisse } 1508771fe6b9SJerome Glisse } else if (rdev->family <= CHIP_RV280) { 1509771fe6b9SJerome Glisse tmp = RREG32(RADEON_MEM_CNTL); 1510771fe6b9SJerome Glisse if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) { 1511771fe6b9SJerome Glisse rdev->mc.vram_width = 128; 1512771fe6b9SJerome Glisse } else { 1513771fe6b9SJerome Glisse rdev->mc.vram_width = 64; 1514771fe6b9SJerome Glisse } 1515771fe6b9SJerome Glisse } else { 1516771fe6b9SJerome Glisse /* newer IGPs */ 1517771fe6b9SJerome Glisse rdev->mc.vram_width = 128; 1518771fe6b9SJerome Glisse } 1519771fe6b9SJerome Glisse } 1520771fe6b9SJerome Glisse 15212a0f8918SDave Airlie static u32 r100_get_accessible_vram(struct radeon_device *rdev) 1522771fe6b9SJerome Glisse { 15232a0f8918SDave Airlie u32 aper_size; 15242a0f8918SDave Airlie u8 byte; 15252a0f8918SDave Airlie 15262a0f8918SDave Airlie aper_size = RREG32(RADEON_CONFIG_APER_SIZE); 15272a0f8918SDave Airlie 15282a0f8918SDave Airlie /* Set HDP_APER_CNTL only on cards that are known not to be broken, 15292a0f8918SDave Airlie * that is has the 2nd generation multifunction PCI interface 15302a0f8918SDave Airlie */ 15312a0f8918SDave Airlie if (rdev->family == CHIP_RV280 || 15322a0f8918SDave Airlie rdev->family >= CHIP_RV350) { 15332a0f8918SDave Airlie WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, 15342a0f8918SDave Airlie ~RADEON_HDP_APER_CNTL); 15352a0f8918SDave Airlie DRM_INFO("Generation 2 PCI interface, using max accessible memory\n"); 15362a0f8918SDave Airlie return aper_size * 2; 15372a0f8918SDave Airlie } 15382a0f8918SDave Airlie 15392a0f8918SDave Airlie /* Older cards have all sorts of funny issues to deal with. First 15402a0f8918SDave Airlie * check if it's a multifunction card by reading the PCI config 15412a0f8918SDave Airlie * header type... Limit those to one aperture size 15422a0f8918SDave Airlie */ 15432a0f8918SDave Airlie pci_read_config_byte(rdev->pdev, 0xe, &byte); 15442a0f8918SDave Airlie if (byte & 0x80) { 15452a0f8918SDave Airlie DRM_INFO("Generation 1 PCI interface in multifunction mode\n"); 15462a0f8918SDave Airlie DRM_INFO("Limiting VRAM to one aperture\n"); 15472a0f8918SDave Airlie return aper_size; 15482a0f8918SDave Airlie } 15492a0f8918SDave Airlie 15502a0f8918SDave Airlie /* Single function older card. We read HDP_APER_CNTL to see how the BIOS 15512a0f8918SDave Airlie * have set it up. We don't write this as it's broken on some ASICs but 15522a0f8918SDave Airlie * we expect the BIOS to have done the right thing (might be too optimistic...) 15532a0f8918SDave Airlie */ 15542a0f8918SDave Airlie if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) 15552a0f8918SDave Airlie return aper_size * 2; 15562a0f8918SDave Airlie return aper_size; 15572a0f8918SDave Airlie } 15582a0f8918SDave Airlie 15592a0f8918SDave Airlie void r100_vram_init_sizes(struct radeon_device *rdev) 15602a0f8918SDave Airlie { 15612a0f8918SDave Airlie u64 config_aper_size; 15622a0f8918SDave Airlie u32 accessible; 15632a0f8918SDave Airlie 15642a0f8918SDave Airlie config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); 1565771fe6b9SJerome Glisse 1566771fe6b9SJerome Glisse if (rdev->flags & RADEON_IS_IGP) { 1567771fe6b9SJerome Glisse uint32_t tom; 1568771fe6b9SJerome Glisse /* read NB_TOM to get the amount of ram stolen for the GPU */ 1569771fe6b9SJerome Glisse tom = RREG32(RADEON_NB_TOM); 15707a50f01aSDave Airlie rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); 15713e43d821SDave Airlie /* for IGPs we need to keep VRAM where it was put by the BIOS */ 15723e43d821SDave Airlie rdev->mc.vram_location = (tom & 0xffff) << 16; 15737a50f01aSDave Airlie WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 15747a50f01aSDave Airlie rdev->mc.mc_vram_size = rdev->mc.real_vram_size; 1575771fe6b9SJerome Glisse } else { 15767a50f01aSDave Airlie rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); 1577771fe6b9SJerome Glisse /* Some production boards of m6 will report 0 1578771fe6b9SJerome Glisse * if it's 8 MB 1579771fe6b9SJerome Glisse */ 15807a50f01aSDave Airlie if (rdev->mc.real_vram_size == 0) { 15817a50f01aSDave Airlie rdev->mc.real_vram_size = 8192 * 1024; 15827a50f01aSDave Airlie WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 1583771fe6b9SJerome Glisse } 15843e43d821SDave Airlie /* let driver place VRAM */ 15853e43d821SDave Airlie rdev->mc.vram_location = 0xFFFFFFFFUL; 15862a0f8918SDave Airlie /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - 15872a0f8918SDave Airlie * Novell bug 204882 + along with lots of ubuntu ones */ 15887a50f01aSDave Airlie if (config_aper_size > rdev->mc.real_vram_size) 15897a50f01aSDave Airlie rdev->mc.mc_vram_size = config_aper_size; 15907a50f01aSDave Airlie else 15917a50f01aSDave Airlie rdev->mc.mc_vram_size = rdev->mc.real_vram_size; 1592771fe6b9SJerome Glisse } 1593771fe6b9SJerome Glisse 15942a0f8918SDave Airlie /* work out accessible VRAM */ 15952a0f8918SDave Airlie accessible = r100_get_accessible_vram(rdev); 15962a0f8918SDave Airlie 1597771fe6b9SJerome Glisse rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); 1598771fe6b9SJerome Glisse rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); 15992a0f8918SDave Airlie 16002a0f8918SDave Airlie if (accessible > rdev->mc.aper_size) 16012a0f8918SDave Airlie accessible = rdev->mc.aper_size; 16022a0f8918SDave Airlie 16037a50f01aSDave Airlie if (rdev->mc.mc_vram_size > rdev->mc.aper_size) 16047a50f01aSDave Airlie rdev->mc.mc_vram_size = rdev->mc.aper_size; 16057a50f01aSDave Airlie 16067a50f01aSDave Airlie if (rdev->mc.real_vram_size > rdev->mc.aper_size) 16077a50f01aSDave Airlie rdev->mc.real_vram_size = rdev->mc.aper_size; 16082a0f8918SDave Airlie } 16092a0f8918SDave Airlie 16102a0f8918SDave Airlie void r100_vram_info(struct radeon_device *rdev) 16112a0f8918SDave Airlie { 16122a0f8918SDave Airlie r100_vram_get_type(rdev); 16132a0f8918SDave Airlie 16142a0f8918SDave Airlie r100_vram_init_sizes(rdev); 1615771fe6b9SJerome Glisse } 1616771fe6b9SJerome Glisse 1617771fe6b9SJerome Glisse 1618771fe6b9SJerome Glisse /* 1619771fe6b9SJerome Glisse * Indirect registers accessor 1620771fe6b9SJerome Glisse */ 1621771fe6b9SJerome Glisse void r100_pll_errata_after_index(struct radeon_device *rdev) 1622771fe6b9SJerome Glisse { 1623771fe6b9SJerome Glisse if (!(rdev->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS)) { 1624771fe6b9SJerome Glisse return; 1625771fe6b9SJerome Glisse } 1626771fe6b9SJerome Glisse (void)RREG32(RADEON_CLOCK_CNTL_DATA); 1627771fe6b9SJerome Glisse (void)RREG32(RADEON_CRTC_GEN_CNTL); 1628771fe6b9SJerome Glisse } 1629771fe6b9SJerome Glisse 1630771fe6b9SJerome Glisse static void r100_pll_errata_after_data(struct radeon_device *rdev) 1631771fe6b9SJerome Glisse { 1632771fe6b9SJerome Glisse /* This workarounds is necessary on RV100, RS100 and RS200 chips 1633771fe6b9SJerome Glisse * or the chip could hang on a subsequent access 1634771fe6b9SJerome Glisse */ 1635771fe6b9SJerome Glisse if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) { 1636771fe6b9SJerome Glisse udelay(5000); 1637771fe6b9SJerome Glisse } 1638771fe6b9SJerome Glisse 1639771fe6b9SJerome Glisse /* This function is required to workaround a hardware bug in some (all?) 1640771fe6b9SJerome Glisse * revisions of the R300. This workaround should be called after every 1641771fe6b9SJerome Glisse * CLOCK_CNTL_INDEX register access. If not, register reads afterward 1642771fe6b9SJerome Glisse * may not be correct. 1643771fe6b9SJerome Glisse */ 1644771fe6b9SJerome Glisse if (rdev->pll_errata & CHIP_ERRATA_R300_CG) { 1645771fe6b9SJerome Glisse uint32_t save, tmp; 1646771fe6b9SJerome Glisse 1647771fe6b9SJerome Glisse save = RREG32(RADEON_CLOCK_CNTL_INDEX); 1648771fe6b9SJerome Glisse tmp = save & ~(0x3f | RADEON_PLL_WR_EN); 1649771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_INDEX, tmp); 1650771fe6b9SJerome Glisse tmp = RREG32(RADEON_CLOCK_CNTL_DATA); 1651771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_INDEX, save); 1652771fe6b9SJerome Glisse } 1653771fe6b9SJerome Glisse } 1654771fe6b9SJerome Glisse 1655771fe6b9SJerome Glisse uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg) 1656771fe6b9SJerome Glisse { 1657771fe6b9SJerome Glisse uint32_t data; 1658771fe6b9SJerome Glisse 1659771fe6b9SJerome Glisse WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f); 1660771fe6b9SJerome Glisse r100_pll_errata_after_index(rdev); 1661771fe6b9SJerome Glisse data = RREG32(RADEON_CLOCK_CNTL_DATA); 1662771fe6b9SJerome Glisse r100_pll_errata_after_data(rdev); 1663771fe6b9SJerome Glisse return data; 1664771fe6b9SJerome Glisse } 1665771fe6b9SJerome Glisse 1666771fe6b9SJerome Glisse void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 1667771fe6b9SJerome Glisse { 1668771fe6b9SJerome Glisse WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN)); 1669771fe6b9SJerome Glisse r100_pll_errata_after_index(rdev); 1670771fe6b9SJerome Glisse WREG32(RADEON_CLOCK_CNTL_DATA, v); 1671771fe6b9SJerome Glisse r100_pll_errata_after_data(rdev); 1672771fe6b9SJerome Glisse } 1673771fe6b9SJerome Glisse 1674068a117cSJerome Glisse int r100_init(struct radeon_device *rdev) 1675068a117cSJerome Glisse { 1676068a117cSJerome Glisse return 0; 1677068a117cSJerome Glisse } 1678068a117cSJerome Glisse 1679771fe6b9SJerome Glisse /* 1680771fe6b9SJerome Glisse * Debugfs info 1681771fe6b9SJerome Glisse */ 1682771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1683771fe6b9SJerome Glisse static int r100_debugfs_rbbm_info(struct seq_file *m, void *data) 1684771fe6b9SJerome Glisse { 1685771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1686771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1687771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1688771fe6b9SJerome Glisse uint32_t reg, value; 1689771fe6b9SJerome Glisse unsigned i; 1690771fe6b9SJerome Glisse 1691771fe6b9SJerome Glisse seq_printf(m, "RBBM_STATUS 0x%08x\n", RREG32(RADEON_RBBM_STATUS)); 1692771fe6b9SJerome Glisse seq_printf(m, "RBBM_CMDFIFO_STAT 0x%08x\n", RREG32(0xE7C)); 1693771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1694771fe6b9SJerome Glisse for (i = 0; i < 64; i++) { 1695771fe6b9SJerome Glisse WREG32(RADEON_RBBM_CMDFIFO_ADDR, i | 0x100); 1696771fe6b9SJerome Glisse reg = (RREG32(RADEON_RBBM_CMDFIFO_DATA) - 1) >> 2; 1697771fe6b9SJerome Glisse WREG32(RADEON_RBBM_CMDFIFO_ADDR, i); 1698771fe6b9SJerome Glisse value = RREG32(RADEON_RBBM_CMDFIFO_DATA); 1699771fe6b9SJerome Glisse seq_printf(m, "[0x%03X] 0x%04X=0x%08X\n", i, reg, value); 1700771fe6b9SJerome Glisse } 1701771fe6b9SJerome Glisse return 0; 1702771fe6b9SJerome Glisse } 1703771fe6b9SJerome Glisse 1704771fe6b9SJerome Glisse static int r100_debugfs_cp_ring_info(struct seq_file *m, void *data) 1705771fe6b9SJerome Glisse { 1706771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1707771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1708771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1709771fe6b9SJerome Glisse uint32_t rdp, wdp; 1710771fe6b9SJerome Glisse unsigned count, i, j; 1711771fe6b9SJerome Glisse 1712771fe6b9SJerome Glisse radeon_ring_free_size(rdev); 1713771fe6b9SJerome Glisse rdp = RREG32(RADEON_CP_RB_RPTR); 1714771fe6b9SJerome Glisse wdp = RREG32(RADEON_CP_RB_WPTR); 1715771fe6b9SJerome Glisse count = (rdp + rdev->cp.ring_size - wdp) & rdev->cp.ptr_mask; 1716771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1717771fe6b9SJerome Glisse seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp); 1718771fe6b9SJerome Glisse seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp); 1719771fe6b9SJerome Glisse seq_printf(m, "%u free dwords in ring\n", rdev->cp.ring_free_dw); 1720771fe6b9SJerome Glisse seq_printf(m, "%u dwords in ring\n", count); 1721771fe6b9SJerome Glisse for (j = 0; j <= count; j++) { 1722771fe6b9SJerome Glisse i = (rdp + j) & rdev->cp.ptr_mask; 1723771fe6b9SJerome Glisse seq_printf(m, "r[%04d]=0x%08x\n", i, rdev->cp.ring[i]); 1724771fe6b9SJerome Glisse } 1725771fe6b9SJerome Glisse return 0; 1726771fe6b9SJerome Glisse } 1727771fe6b9SJerome Glisse 1728771fe6b9SJerome Glisse 1729771fe6b9SJerome Glisse static int r100_debugfs_cp_csq_fifo(struct seq_file *m, void *data) 1730771fe6b9SJerome Glisse { 1731771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1732771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1733771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1734771fe6b9SJerome Glisse uint32_t csq_stat, csq2_stat, tmp; 1735771fe6b9SJerome Glisse unsigned r_rptr, r_wptr, ib1_rptr, ib1_wptr, ib2_rptr, ib2_wptr; 1736771fe6b9SJerome Glisse unsigned i; 1737771fe6b9SJerome Glisse 1738771fe6b9SJerome Glisse seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 1739771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ_MODE 0x%08x\n", RREG32(RADEON_CP_CSQ_MODE)); 1740771fe6b9SJerome Glisse csq_stat = RREG32(RADEON_CP_CSQ_STAT); 1741771fe6b9SJerome Glisse csq2_stat = RREG32(RADEON_CP_CSQ2_STAT); 1742771fe6b9SJerome Glisse r_rptr = (csq_stat >> 0) & 0x3ff; 1743771fe6b9SJerome Glisse r_wptr = (csq_stat >> 10) & 0x3ff; 1744771fe6b9SJerome Glisse ib1_rptr = (csq_stat >> 20) & 0x3ff; 1745771fe6b9SJerome Glisse ib1_wptr = (csq2_stat >> 0) & 0x3ff; 1746771fe6b9SJerome Glisse ib2_rptr = (csq2_stat >> 10) & 0x3ff; 1747771fe6b9SJerome Glisse ib2_wptr = (csq2_stat >> 20) & 0x3ff; 1748771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ_STAT 0x%08x\n", csq_stat); 1749771fe6b9SJerome Glisse seq_printf(m, "CP_CSQ2_STAT 0x%08x\n", csq2_stat); 1750771fe6b9SJerome Glisse seq_printf(m, "Ring rptr %u\n", r_rptr); 1751771fe6b9SJerome Glisse seq_printf(m, "Ring wptr %u\n", r_wptr); 1752771fe6b9SJerome Glisse seq_printf(m, "Indirect1 rptr %u\n", ib1_rptr); 1753771fe6b9SJerome Glisse seq_printf(m, "Indirect1 wptr %u\n", ib1_wptr); 1754771fe6b9SJerome Glisse seq_printf(m, "Indirect2 rptr %u\n", ib2_rptr); 1755771fe6b9SJerome Glisse seq_printf(m, "Indirect2 wptr %u\n", ib2_wptr); 1756771fe6b9SJerome Glisse /* FIXME: 0, 128, 640 depends on fifo setup see cp_init_kms 1757771fe6b9SJerome Glisse * 128 = indirect1_start * 8 & 640 = indirect2_start * 8 */ 1758771fe6b9SJerome Glisse seq_printf(m, "Ring fifo:\n"); 1759771fe6b9SJerome Glisse for (i = 0; i < 256; i++) { 1760771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1761771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1762771fe6b9SJerome Glisse seq_printf(m, "rfifo[%04d]=0x%08X\n", i, tmp); 1763771fe6b9SJerome Glisse } 1764771fe6b9SJerome Glisse seq_printf(m, "Indirect1 fifo:\n"); 1765771fe6b9SJerome Glisse for (i = 256; i <= 512; i++) { 1766771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1767771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1768771fe6b9SJerome Glisse seq_printf(m, "ib1fifo[%04d]=0x%08X\n", i, tmp); 1769771fe6b9SJerome Glisse } 1770771fe6b9SJerome Glisse seq_printf(m, "Indirect2 fifo:\n"); 1771771fe6b9SJerome Glisse for (i = 640; i < ib1_wptr; i++) { 1772771fe6b9SJerome Glisse WREG32(RADEON_CP_CSQ_ADDR, i << 2); 1773771fe6b9SJerome Glisse tmp = RREG32(RADEON_CP_CSQ_DATA); 1774771fe6b9SJerome Glisse seq_printf(m, "ib2fifo[%04d]=0x%08X\n", i, tmp); 1775771fe6b9SJerome Glisse } 1776771fe6b9SJerome Glisse return 0; 1777771fe6b9SJerome Glisse } 1778771fe6b9SJerome Glisse 1779771fe6b9SJerome Glisse static int r100_debugfs_mc_info(struct seq_file *m, void *data) 1780771fe6b9SJerome Glisse { 1781771fe6b9SJerome Glisse struct drm_info_node *node = (struct drm_info_node *) m->private; 1782771fe6b9SJerome Glisse struct drm_device *dev = node->minor->dev; 1783771fe6b9SJerome Glisse struct radeon_device *rdev = dev->dev_private; 1784771fe6b9SJerome Glisse uint32_t tmp; 1785771fe6b9SJerome Glisse 1786771fe6b9SJerome Glisse tmp = RREG32(RADEON_CONFIG_MEMSIZE); 1787771fe6b9SJerome Glisse seq_printf(m, "CONFIG_MEMSIZE 0x%08x\n", tmp); 1788771fe6b9SJerome Glisse tmp = RREG32(RADEON_MC_FB_LOCATION); 1789771fe6b9SJerome Glisse seq_printf(m, "MC_FB_LOCATION 0x%08x\n", tmp); 1790771fe6b9SJerome Glisse tmp = RREG32(RADEON_BUS_CNTL); 1791771fe6b9SJerome Glisse seq_printf(m, "BUS_CNTL 0x%08x\n", tmp); 1792771fe6b9SJerome Glisse tmp = RREG32(RADEON_MC_AGP_LOCATION); 1793771fe6b9SJerome Glisse seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp); 1794771fe6b9SJerome Glisse tmp = RREG32(RADEON_AGP_BASE); 1795771fe6b9SJerome Glisse seq_printf(m, "AGP_BASE 0x%08x\n", tmp); 1796771fe6b9SJerome Glisse tmp = RREG32(RADEON_HOST_PATH_CNTL); 1797771fe6b9SJerome Glisse seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp); 1798771fe6b9SJerome Glisse tmp = RREG32(0x01D0); 1799771fe6b9SJerome Glisse seq_printf(m, "AIC_CTRL 0x%08x\n", tmp); 1800771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_LO_ADDR); 1801771fe6b9SJerome Glisse seq_printf(m, "AIC_LO_ADDR 0x%08x\n", tmp); 1802771fe6b9SJerome Glisse tmp = RREG32(RADEON_AIC_HI_ADDR); 1803771fe6b9SJerome Glisse seq_printf(m, "AIC_HI_ADDR 0x%08x\n", tmp); 1804771fe6b9SJerome Glisse tmp = RREG32(0x01E4); 1805771fe6b9SJerome Glisse seq_printf(m, "AIC_TLB_ADDR 0x%08x\n", tmp); 1806771fe6b9SJerome Glisse return 0; 1807771fe6b9SJerome Glisse } 1808771fe6b9SJerome Glisse 1809771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_rbbm_list[] = { 1810771fe6b9SJerome Glisse {"r100_rbbm_info", r100_debugfs_rbbm_info, 0, NULL}, 1811771fe6b9SJerome Glisse }; 1812771fe6b9SJerome Glisse 1813771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_cp_list[] = { 1814771fe6b9SJerome Glisse {"r100_cp_ring_info", r100_debugfs_cp_ring_info, 0, NULL}, 1815771fe6b9SJerome Glisse {"r100_cp_csq_fifo", r100_debugfs_cp_csq_fifo, 0, NULL}, 1816771fe6b9SJerome Glisse }; 1817771fe6b9SJerome Glisse 1818771fe6b9SJerome Glisse static struct drm_info_list r100_debugfs_mc_info_list[] = { 1819771fe6b9SJerome Glisse {"r100_mc_info", r100_debugfs_mc_info, 0, NULL}, 1820771fe6b9SJerome Glisse }; 1821771fe6b9SJerome Glisse #endif 1822771fe6b9SJerome Glisse 1823771fe6b9SJerome Glisse int r100_debugfs_rbbm_init(struct radeon_device *rdev) 1824771fe6b9SJerome Glisse { 1825771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1826771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_rbbm_list, 1); 1827771fe6b9SJerome Glisse #else 1828771fe6b9SJerome Glisse return 0; 1829771fe6b9SJerome Glisse #endif 1830771fe6b9SJerome Glisse } 1831771fe6b9SJerome Glisse 1832771fe6b9SJerome Glisse int r100_debugfs_cp_init(struct radeon_device *rdev) 1833771fe6b9SJerome Glisse { 1834771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1835771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_cp_list, 2); 1836771fe6b9SJerome Glisse #else 1837771fe6b9SJerome Glisse return 0; 1838771fe6b9SJerome Glisse #endif 1839771fe6b9SJerome Glisse } 1840771fe6b9SJerome Glisse 1841771fe6b9SJerome Glisse int r100_debugfs_mc_info_init(struct radeon_device *rdev) 1842771fe6b9SJerome Glisse { 1843771fe6b9SJerome Glisse #if defined(CONFIG_DEBUG_FS) 1844771fe6b9SJerome Glisse return radeon_debugfs_add_files(rdev, r100_debugfs_mc_info_list, 1); 1845771fe6b9SJerome Glisse #else 1846771fe6b9SJerome Glisse return 0; 1847771fe6b9SJerome Glisse #endif 1848771fe6b9SJerome Glisse } 1849e024e110SDave Airlie 1850e024e110SDave Airlie int r100_set_surface_reg(struct radeon_device *rdev, int reg, 1851e024e110SDave Airlie uint32_t tiling_flags, uint32_t pitch, 1852e024e110SDave Airlie uint32_t offset, uint32_t obj_size) 1853e024e110SDave Airlie { 1854e024e110SDave Airlie int surf_index = reg * 16; 1855e024e110SDave Airlie int flags = 0; 1856e024e110SDave Airlie 1857e024e110SDave Airlie /* r100/r200 divide by 16 */ 1858e024e110SDave Airlie if (rdev->family < CHIP_R300) 1859e024e110SDave Airlie flags = pitch / 16; 1860e024e110SDave Airlie else 1861e024e110SDave Airlie flags = pitch / 8; 1862e024e110SDave Airlie 1863e024e110SDave Airlie if (rdev->family <= CHIP_RS200) { 1864e024e110SDave Airlie if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) 1865e024e110SDave Airlie == (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) 1866e024e110SDave Airlie flags |= RADEON_SURF_TILE_COLOR_BOTH; 1867e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MACRO) 1868e024e110SDave Airlie flags |= RADEON_SURF_TILE_COLOR_MACRO; 1869e024e110SDave Airlie } else if (rdev->family <= CHIP_RV280) { 1870e024e110SDave Airlie if (tiling_flags & (RADEON_TILING_MACRO)) 1871e024e110SDave Airlie flags |= R200_SURF_TILE_COLOR_MACRO; 1872e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MICRO) 1873e024e110SDave Airlie flags |= R200_SURF_TILE_COLOR_MICRO; 1874e024e110SDave Airlie } else { 1875e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MACRO) 1876e024e110SDave Airlie flags |= R300_SURF_TILE_MACRO; 1877e024e110SDave Airlie if (tiling_flags & RADEON_TILING_MICRO) 1878e024e110SDave Airlie flags |= R300_SURF_TILE_MICRO; 1879e024e110SDave Airlie } 1880e024e110SDave Airlie 1881e024e110SDave Airlie DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1); 1882e024e110SDave Airlie WREG32(RADEON_SURFACE0_INFO + surf_index, flags); 1883e024e110SDave Airlie WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); 1884e024e110SDave Airlie WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1); 1885e024e110SDave Airlie return 0; 1886e024e110SDave Airlie } 1887e024e110SDave Airlie 1888e024e110SDave Airlie void r100_clear_surface_reg(struct radeon_device *rdev, int reg) 1889e024e110SDave Airlie { 1890e024e110SDave Airlie int surf_index = reg * 16; 1891e024e110SDave Airlie WREG32(RADEON_SURFACE0_INFO + surf_index, 0); 1892e024e110SDave Airlie } 1893c93bb85bSJerome Glisse 1894c93bb85bSJerome Glisse void r100_bandwidth_update(struct radeon_device *rdev) 1895c93bb85bSJerome Glisse { 1896c93bb85bSJerome Glisse fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; 1897c93bb85bSJerome Glisse fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; 1898c93bb85bSJerome Glisse fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; 1899c93bb85bSJerome Glisse uint32_t temp, data, mem_trcd, mem_trp, mem_tras; 1900c93bb85bSJerome Glisse fixed20_12 memtcas_ff[8] = { 1901c93bb85bSJerome Glisse fixed_init(1), 1902c93bb85bSJerome Glisse fixed_init(2), 1903c93bb85bSJerome Glisse fixed_init(3), 1904c93bb85bSJerome Glisse fixed_init(0), 1905c93bb85bSJerome Glisse fixed_init_half(1), 1906c93bb85bSJerome Glisse fixed_init_half(2), 1907c93bb85bSJerome Glisse fixed_init(0), 1908c93bb85bSJerome Glisse }; 1909c93bb85bSJerome Glisse fixed20_12 memtcas_rs480_ff[8] = { 1910c93bb85bSJerome Glisse fixed_init(0), 1911c93bb85bSJerome Glisse fixed_init(1), 1912c93bb85bSJerome Glisse fixed_init(2), 1913c93bb85bSJerome Glisse fixed_init(3), 1914c93bb85bSJerome Glisse fixed_init(0), 1915c93bb85bSJerome Glisse fixed_init_half(1), 1916c93bb85bSJerome Glisse fixed_init_half(2), 1917c93bb85bSJerome Glisse fixed_init_half(3), 1918c93bb85bSJerome Glisse }; 1919c93bb85bSJerome Glisse fixed20_12 memtcas2_ff[8] = { 1920c93bb85bSJerome Glisse fixed_init(0), 1921c93bb85bSJerome Glisse fixed_init(1), 1922c93bb85bSJerome Glisse fixed_init(2), 1923c93bb85bSJerome Glisse fixed_init(3), 1924c93bb85bSJerome Glisse fixed_init(4), 1925c93bb85bSJerome Glisse fixed_init(5), 1926c93bb85bSJerome Glisse fixed_init(6), 1927c93bb85bSJerome Glisse fixed_init(7), 1928c93bb85bSJerome Glisse }; 1929c93bb85bSJerome Glisse fixed20_12 memtrbs[8] = { 1930c93bb85bSJerome Glisse fixed_init(1), 1931c93bb85bSJerome Glisse fixed_init_half(1), 1932c93bb85bSJerome Glisse fixed_init(2), 1933c93bb85bSJerome Glisse fixed_init_half(2), 1934c93bb85bSJerome Glisse fixed_init(3), 1935c93bb85bSJerome Glisse fixed_init_half(3), 1936c93bb85bSJerome Glisse fixed_init(4), 1937c93bb85bSJerome Glisse fixed_init_half(4) 1938c93bb85bSJerome Glisse }; 1939c93bb85bSJerome Glisse fixed20_12 memtrbs_r4xx[8] = { 1940c93bb85bSJerome Glisse fixed_init(4), 1941c93bb85bSJerome Glisse fixed_init(5), 1942c93bb85bSJerome Glisse fixed_init(6), 1943c93bb85bSJerome Glisse fixed_init(7), 1944c93bb85bSJerome Glisse fixed_init(8), 1945c93bb85bSJerome Glisse fixed_init(9), 1946c93bb85bSJerome Glisse fixed_init(10), 1947c93bb85bSJerome Glisse fixed_init(11) 1948c93bb85bSJerome Glisse }; 1949c93bb85bSJerome Glisse fixed20_12 min_mem_eff; 1950c93bb85bSJerome Glisse fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; 1951c93bb85bSJerome Glisse fixed20_12 cur_latency_mclk, cur_latency_sclk; 1952c93bb85bSJerome Glisse fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, 1953c93bb85bSJerome Glisse disp_drain_rate2, read_return_rate; 1954c93bb85bSJerome Glisse fixed20_12 time_disp1_drop_priority; 1955c93bb85bSJerome Glisse int c; 1956c93bb85bSJerome Glisse int cur_size = 16; /* in octawords */ 1957c93bb85bSJerome Glisse int critical_point = 0, critical_point2; 1958c93bb85bSJerome Glisse /* uint32_t read_return_rate, time_disp1_drop_priority; */ 1959c93bb85bSJerome Glisse int stop_req, max_stop_req; 1960c93bb85bSJerome Glisse struct drm_display_mode *mode1 = NULL; 1961c93bb85bSJerome Glisse struct drm_display_mode *mode2 = NULL; 1962c93bb85bSJerome Glisse uint32_t pixel_bytes1 = 0; 1963c93bb85bSJerome Glisse uint32_t pixel_bytes2 = 0; 1964c93bb85bSJerome Glisse 1965c93bb85bSJerome Glisse if (rdev->mode_info.crtcs[0]->base.enabled) { 1966c93bb85bSJerome Glisse mode1 = &rdev->mode_info.crtcs[0]->base.mode; 1967c93bb85bSJerome Glisse pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; 1968c93bb85bSJerome Glisse } 1969c93bb85bSJerome Glisse if (rdev->mode_info.crtcs[1]->base.enabled) { 1970c93bb85bSJerome Glisse mode2 = &rdev->mode_info.crtcs[1]->base.mode; 1971c93bb85bSJerome Glisse pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; 1972c93bb85bSJerome Glisse } 1973c93bb85bSJerome Glisse 1974c93bb85bSJerome Glisse min_mem_eff.full = rfixed_const_8(0); 1975c93bb85bSJerome Glisse /* get modes */ 1976c93bb85bSJerome Glisse if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { 1977c93bb85bSJerome Glisse uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); 1978c93bb85bSJerome Glisse mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); 1979c93bb85bSJerome Glisse mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); 1980c93bb85bSJerome Glisse /* check crtc enables */ 1981c93bb85bSJerome Glisse if (mode2) 1982c93bb85bSJerome Glisse mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); 1983c93bb85bSJerome Glisse if (mode1) 1984c93bb85bSJerome Glisse mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); 1985c93bb85bSJerome Glisse WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); 1986c93bb85bSJerome Glisse } 1987c93bb85bSJerome Glisse 1988c93bb85bSJerome Glisse /* 1989c93bb85bSJerome Glisse * determine is there is enough bw for current mode 1990c93bb85bSJerome Glisse */ 1991c93bb85bSJerome Glisse mclk_ff.full = rfixed_const(rdev->clock.default_mclk); 1992c93bb85bSJerome Glisse temp_ff.full = rfixed_const(100); 1993c93bb85bSJerome Glisse mclk_ff.full = rfixed_div(mclk_ff, temp_ff); 1994c93bb85bSJerome Glisse sclk_ff.full = rfixed_const(rdev->clock.default_sclk); 1995c93bb85bSJerome Glisse sclk_ff.full = rfixed_div(sclk_ff, temp_ff); 1996c93bb85bSJerome Glisse 1997c93bb85bSJerome Glisse temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); 1998c93bb85bSJerome Glisse temp_ff.full = rfixed_const(temp); 1999c93bb85bSJerome Glisse mem_bw.full = rfixed_mul(mclk_ff, temp_ff); 2000c93bb85bSJerome Glisse 2001c93bb85bSJerome Glisse pix_clk.full = 0; 2002c93bb85bSJerome Glisse pix_clk2.full = 0; 2003c93bb85bSJerome Glisse peak_disp_bw.full = 0; 2004c93bb85bSJerome Glisse if (mode1) { 2005c93bb85bSJerome Glisse temp_ff.full = rfixed_const(1000); 2006c93bb85bSJerome Glisse pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ 2007c93bb85bSJerome Glisse pix_clk.full = rfixed_div(pix_clk, temp_ff); 2008c93bb85bSJerome Glisse temp_ff.full = rfixed_const(pixel_bytes1); 2009c93bb85bSJerome Glisse peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); 2010c93bb85bSJerome Glisse } 2011c93bb85bSJerome Glisse if (mode2) { 2012c93bb85bSJerome Glisse temp_ff.full = rfixed_const(1000); 2013c93bb85bSJerome Glisse pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ 2014c93bb85bSJerome Glisse pix_clk2.full = rfixed_div(pix_clk2, temp_ff); 2015c93bb85bSJerome Glisse temp_ff.full = rfixed_const(pixel_bytes2); 2016c93bb85bSJerome Glisse peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); 2017c93bb85bSJerome Glisse } 2018c93bb85bSJerome Glisse 2019c93bb85bSJerome Glisse mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); 2020c93bb85bSJerome Glisse if (peak_disp_bw.full >= mem_bw.full) { 2021c93bb85bSJerome Glisse DRM_ERROR("You may not have enough display bandwidth for current mode\n" 2022c93bb85bSJerome Glisse "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); 2023c93bb85bSJerome Glisse } 2024c93bb85bSJerome Glisse 2025c93bb85bSJerome Glisse /* Get values from the EXT_MEM_CNTL register...converting its contents. */ 2026c93bb85bSJerome Glisse temp = RREG32(RADEON_MEM_TIMING_CNTL); 2027c93bb85bSJerome Glisse if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ 2028c93bb85bSJerome Glisse mem_trcd = ((temp >> 2) & 0x3) + 1; 2029c93bb85bSJerome Glisse mem_trp = ((temp & 0x3)) + 1; 2030c93bb85bSJerome Glisse mem_tras = ((temp & 0x70) >> 4) + 1; 2031c93bb85bSJerome Glisse } else if (rdev->family == CHIP_R300 || 2032c93bb85bSJerome Glisse rdev->family == CHIP_R350) { /* r300, r350 */ 2033c93bb85bSJerome Glisse mem_trcd = (temp & 0x7) + 1; 2034c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0x7) + 1; 2035c93bb85bSJerome Glisse mem_tras = ((temp >> 11) & 0xf) + 4; 2036c93bb85bSJerome Glisse } else if (rdev->family == CHIP_RV350 || 2037c93bb85bSJerome Glisse rdev->family <= CHIP_RV380) { 2038c93bb85bSJerome Glisse /* rv3x0 */ 2039c93bb85bSJerome Glisse mem_trcd = (temp & 0x7) + 3; 2040c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0x7) + 3; 2041c93bb85bSJerome Glisse mem_tras = ((temp >> 11) & 0xf) + 6; 2042c93bb85bSJerome Glisse } else if (rdev->family == CHIP_R420 || 2043c93bb85bSJerome Glisse rdev->family == CHIP_R423 || 2044c93bb85bSJerome Glisse rdev->family == CHIP_RV410) { 2045c93bb85bSJerome Glisse /* r4xx */ 2046c93bb85bSJerome Glisse mem_trcd = (temp & 0xf) + 3; 2047c93bb85bSJerome Glisse if (mem_trcd > 15) 2048c93bb85bSJerome Glisse mem_trcd = 15; 2049c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0xf) + 3; 2050c93bb85bSJerome Glisse if (mem_trp > 15) 2051c93bb85bSJerome Glisse mem_trp = 15; 2052c93bb85bSJerome Glisse mem_tras = ((temp >> 12) & 0x1f) + 6; 2053c93bb85bSJerome Glisse if (mem_tras > 31) 2054c93bb85bSJerome Glisse mem_tras = 31; 2055c93bb85bSJerome Glisse } else { /* RV200, R200 */ 2056c93bb85bSJerome Glisse mem_trcd = (temp & 0x7) + 1; 2057c93bb85bSJerome Glisse mem_trp = ((temp >> 8) & 0x7) + 1; 2058c93bb85bSJerome Glisse mem_tras = ((temp >> 12) & 0xf) + 4; 2059c93bb85bSJerome Glisse } 2060c93bb85bSJerome Glisse /* convert to FF */ 2061c93bb85bSJerome Glisse trcd_ff.full = rfixed_const(mem_trcd); 2062c93bb85bSJerome Glisse trp_ff.full = rfixed_const(mem_trp); 2063c93bb85bSJerome Glisse tras_ff.full = rfixed_const(mem_tras); 2064c93bb85bSJerome Glisse 2065c93bb85bSJerome Glisse /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ 2066c93bb85bSJerome Glisse temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); 2067c93bb85bSJerome Glisse data = (temp & (7 << 20)) >> 20; 2068c93bb85bSJerome Glisse if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { 2069c93bb85bSJerome Glisse if (rdev->family == CHIP_RS480) /* don't think rs400 */ 2070c93bb85bSJerome Glisse tcas_ff = memtcas_rs480_ff[data]; 2071c93bb85bSJerome Glisse else 2072c93bb85bSJerome Glisse tcas_ff = memtcas_ff[data]; 2073c93bb85bSJerome Glisse } else 2074c93bb85bSJerome Glisse tcas_ff = memtcas2_ff[data]; 2075c93bb85bSJerome Glisse 2076c93bb85bSJerome Glisse if (rdev->family == CHIP_RS400 || 2077c93bb85bSJerome Glisse rdev->family == CHIP_RS480) { 2078c93bb85bSJerome Glisse /* extra cas latency stored in bits 23-25 0-4 clocks */ 2079c93bb85bSJerome Glisse data = (temp >> 23) & 0x7; 2080c93bb85bSJerome Glisse if (data < 5) 2081c93bb85bSJerome Glisse tcas_ff.full += rfixed_const(data); 2082c93bb85bSJerome Glisse } 2083c93bb85bSJerome Glisse 2084c93bb85bSJerome Glisse if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { 2085c93bb85bSJerome Glisse /* on the R300, Tcas is included in Trbs. 2086c93bb85bSJerome Glisse */ 2087c93bb85bSJerome Glisse temp = RREG32(RADEON_MEM_CNTL); 2088c93bb85bSJerome Glisse data = (R300_MEM_NUM_CHANNELS_MASK & temp); 2089c93bb85bSJerome Glisse if (data == 1) { 2090c93bb85bSJerome Glisse if (R300_MEM_USE_CD_CH_ONLY & temp) { 2091c93bb85bSJerome Glisse temp = RREG32(R300_MC_IND_INDEX); 2092c93bb85bSJerome Glisse temp &= ~R300_MC_IND_ADDR_MASK; 2093c93bb85bSJerome Glisse temp |= R300_MC_READ_CNTL_CD_mcind; 2094c93bb85bSJerome Glisse WREG32(R300_MC_IND_INDEX, temp); 2095c93bb85bSJerome Glisse temp = RREG32(R300_MC_IND_DATA); 2096c93bb85bSJerome Glisse data = (R300_MEM_RBS_POSITION_C_MASK & temp); 2097c93bb85bSJerome Glisse } else { 2098c93bb85bSJerome Glisse temp = RREG32(R300_MC_READ_CNTL_AB); 2099c93bb85bSJerome Glisse data = (R300_MEM_RBS_POSITION_A_MASK & temp); 2100c93bb85bSJerome Glisse } 2101c93bb85bSJerome Glisse } else { 2102c93bb85bSJerome Glisse temp = RREG32(R300_MC_READ_CNTL_AB); 2103c93bb85bSJerome Glisse data = (R300_MEM_RBS_POSITION_A_MASK & temp); 2104c93bb85bSJerome Glisse } 2105c93bb85bSJerome Glisse if (rdev->family == CHIP_RV410 || 2106c93bb85bSJerome Glisse rdev->family == CHIP_R420 || 2107c93bb85bSJerome Glisse rdev->family == CHIP_R423) 2108c93bb85bSJerome Glisse trbs_ff = memtrbs_r4xx[data]; 2109c93bb85bSJerome Glisse else 2110c93bb85bSJerome Glisse trbs_ff = memtrbs[data]; 2111c93bb85bSJerome Glisse tcas_ff.full += trbs_ff.full; 2112c93bb85bSJerome Glisse } 2113c93bb85bSJerome Glisse 2114c93bb85bSJerome Glisse sclk_eff_ff.full = sclk_ff.full; 2115c93bb85bSJerome Glisse 2116c93bb85bSJerome Glisse if (rdev->flags & RADEON_IS_AGP) { 2117c93bb85bSJerome Glisse fixed20_12 agpmode_ff; 2118c93bb85bSJerome Glisse agpmode_ff.full = rfixed_const(radeon_agpmode); 2119c93bb85bSJerome Glisse temp_ff.full = rfixed_const_666(16); 2120c93bb85bSJerome Glisse sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff); 2121c93bb85bSJerome Glisse } 2122c93bb85bSJerome Glisse /* TODO PCIE lanes may affect this - agpmode == 16?? */ 2123c93bb85bSJerome Glisse 2124c93bb85bSJerome Glisse if (ASIC_IS_R300(rdev)) { 2125c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(250); 2126c93bb85bSJerome Glisse } else { 2127c93bb85bSJerome Glisse if ((rdev->family == CHIP_RV100) || 2128c93bb85bSJerome Glisse rdev->flags & RADEON_IS_IGP) { 2129c93bb85bSJerome Glisse if (rdev->mc.vram_is_ddr) 2130c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(41); 2131c93bb85bSJerome Glisse else 2132c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(33); 2133c93bb85bSJerome Glisse } else { 2134c93bb85bSJerome Glisse if (rdev->mc.vram_width == 128) 2135c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(57); 2136c93bb85bSJerome Glisse else 2137c93bb85bSJerome Glisse sclk_delay_ff.full = rfixed_const(41); 2138c93bb85bSJerome Glisse } 2139c93bb85bSJerome Glisse } 2140c93bb85bSJerome Glisse 2141c93bb85bSJerome Glisse mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff); 2142c93bb85bSJerome Glisse 2143c93bb85bSJerome Glisse if (rdev->mc.vram_is_ddr) { 2144c93bb85bSJerome Glisse if (rdev->mc.vram_width == 32) { 2145c93bb85bSJerome Glisse k1.full = rfixed_const(40); 2146c93bb85bSJerome Glisse c = 3; 2147c93bb85bSJerome Glisse } else { 2148c93bb85bSJerome Glisse k1.full = rfixed_const(20); 2149c93bb85bSJerome Glisse c = 1; 2150c93bb85bSJerome Glisse } 2151c93bb85bSJerome Glisse } else { 2152c93bb85bSJerome Glisse k1.full = rfixed_const(40); 2153c93bb85bSJerome Glisse c = 3; 2154c93bb85bSJerome Glisse } 2155c93bb85bSJerome Glisse 2156c93bb85bSJerome Glisse temp_ff.full = rfixed_const(2); 2157c93bb85bSJerome Glisse mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff); 2158c93bb85bSJerome Glisse temp_ff.full = rfixed_const(c); 2159c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff); 2160c93bb85bSJerome Glisse temp_ff.full = rfixed_const(4); 2161c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff); 2162c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff); 2163c93bb85bSJerome Glisse mc_latency_mclk.full += k1.full; 2164c93bb85bSJerome Glisse 2165c93bb85bSJerome Glisse mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff); 2166c93bb85bSJerome Glisse mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff); 2167c93bb85bSJerome Glisse 2168c93bb85bSJerome Glisse /* 2169c93bb85bSJerome Glisse HW cursor time assuming worst case of full size colour cursor. 2170c93bb85bSJerome Glisse */ 2171c93bb85bSJerome Glisse temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); 2172c93bb85bSJerome Glisse temp_ff.full += trcd_ff.full; 2173c93bb85bSJerome Glisse if (temp_ff.full < tras_ff.full) 2174c93bb85bSJerome Glisse temp_ff.full = tras_ff.full; 2175c93bb85bSJerome Glisse cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff); 2176c93bb85bSJerome Glisse 2177c93bb85bSJerome Glisse temp_ff.full = rfixed_const(cur_size); 2178c93bb85bSJerome Glisse cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff); 2179c93bb85bSJerome Glisse /* 2180c93bb85bSJerome Glisse Find the total latency for the display data. 2181c93bb85bSJerome Glisse */ 2182c93bb85bSJerome Glisse disp_latency_overhead.full = rfixed_const(80); 2183c93bb85bSJerome Glisse disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff); 2184c93bb85bSJerome Glisse mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; 2185c93bb85bSJerome Glisse mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; 2186c93bb85bSJerome Glisse 2187c93bb85bSJerome Glisse if (mc_latency_mclk.full > mc_latency_sclk.full) 2188c93bb85bSJerome Glisse disp_latency.full = mc_latency_mclk.full; 2189c93bb85bSJerome Glisse else 2190c93bb85bSJerome Glisse disp_latency.full = mc_latency_sclk.full; 2191c93bb85bSJerome Glisse 2192c93bb85bSJerome Glisse /* setup Max GRPH_STOP_REQ default value */ 2193c93bb85bSJerome Glisse if (ASIC_IS_RV100(rdev)) 2194c93bb85bSJerome Glisse max_stop_req = 0x5c; 2195c93bb85bSJerome Glisse else 2196c93bb85bSJerome Glisse max_stop_req = 0x7c; 2197c93bb85bSJerome Glisse 2198c93bb85bSJerome Glisse if (mode1) { 2199c93bb85bSJerome Glisse /* CRTC1 2200c93bb85bSJerome Glisse Set GRPH_BUFFER_CNTL register using h/w defined optimal values. 2201c93bb85bSJerome Glisse GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] 2202c93bb85bSJerome Glisse */ 2203c93bb85bSJerome Glisse stop_req = mode1->hdisplay * pixel_bytes1 / 16; 2204c93bb85bSJerome Glisse 2205c93bb85bSJerome Glisse if (stop_req > max_stop_req) 2206c93bb85bSJerome Glisse stop_req = max_stop_req; 2207c93bb85bSJerome Glisse 2208c93bb85bSJerome Glisse /* 2209c93bb85bSJerome Glisse Find the drain rate of the display buffer. 2210c93bb85bSJerome Glisse */ 2211c93bb85bSJerome Glisse temp_ff.full = rfixed_const((16/pixel_bytes1)); 2212c93bb85bSJerome Glisse disp_drain_rate.full = rfixed_div(pix_clk, temp_ff); 2213c93bb85bSJerome Glisse 2214c93bb85bSJerome Glisse /* 2215c93bb85bSJerome Glisse Find the critical point of the display buffer. 2216c93bb85bSJerome Glisse */ 2217c93bb85bSJerome Glisse crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency); 2218c93bb85bSJerome Glisse crit_point_ff.full += rfixed_const_half(0); 2219c93bb85bSJerome Glisse 2220c93bb85bSJerome Glisse critical_point = rfixed_trunc(crit_point_ff); 2221c93bb85bSJerome Glisse 2222c93bb85bSJerome Glisse if (rdev->disp_priority == 2) { 2223c93bb85bSJerome Glisse critical_point = 0; 2224c93bb85bSJerome Glisse } 2225c93bb85bSJerome Glisse 2226c93bb85bSJerome Glisse /* 2227c93bb85bSJerome Glisse The critical point should never be above max_stop_req-4. Setting 2228c93bb85bSJerome Glisse GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. 2229c93bb85bSJerome Glisse */ 2230c93bb85bSJerome Glisse if (max_stop_req - critical_point < 4) 2231c93bb85bSJerome Glisse critical_point = 0; 2232c93bb85bSJerome Glisse 2233c93bb85bSJerome Glisse if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { 2234c93bb85bSJerome Glisse /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ 2235c93bb85bSJerome Glisse critical_point = 0x10; 2236c93bb85bSJerome Glisse } 2237c93bb85bSJerome Glisse 2238c93bb85bSJerome Glisse temp = RREG32(RADEON_GRPH_BUFFER_CNTL); 2239c93bb85bSJerome Glisse temp &= ~(RADEON_GRPH_STOP_REQ_MASK); 2240c93bb85bSJerome Glisse temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); 2241c93bb85bSJerome Glisse temp &= ~(RADEON_GRPH_START_REQ_MASK); 2242c93bb85bSJerome Glisse if ((rdev->family == CHIP_R350) && 2243c93bb85bSJerome Glisse (stop_req > 0x15)) { 2244c93bb85bSJerome Glisse stop_req -= 0x10; 2245c93bb85bSJerome Glisse } 2246c93bb85bSJerome Glisse temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); 2247c93bb85bSJerome Glisse temp |= RADEON_GRPH_BUFFER_SIZE; 2248c93bb85bSJerome Glisse temp &= ~(RADEON_GRPH_CRITICAL_CNTL | 2249c93bb85bSJerome Glisse RADEON_GRPH_CRITICAL_AT_SOF | 2250c93bb85bSJerome Glisse RADEON_GRPH_STOP_CNTL); 2251c93bb85bSJerome Glisse /* 2252c93bb85bSJerome Glisse Write the result into the register. 2253c93bb85bSJerome Glisse */ 2254c93bb85bSJerome Glisse WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | 2255c93bb85bSJerome Glisse (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); 2256c93bb85bSJerome Glisse 2257c93bb85bSJerome Glisse #if 0 2258c93bb85bSJerome Glisse if ((rdev->family == CHIP_RS400) || 2259c93bb85bSJerome Glisse (rdev->family == CHIP_RS480)) { 2260c93bb85bSJerome Glisse /* attempt to program RS400 disp regs correctly ??? */ 2261c93bb85bSJerome Glisse temp = RREG32(RS400_DISP1_REG_CNTL); 2262c93bb85bSJerome Glisse temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | 2263c93bb85bSJerome Glisse RS400_DISP1_STOP_REQ_LEVEL_MASK); 2264c93bb85bSJerome Glisse WREG32(RS400_DISP1_REQ_CNTL1, (temp | 2265c93bb85bSJerome Glisse (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | 2266c93bb85bSJerome Glisse (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); 2267c93bb85bSJerome Glisse temp = RREG32(RS400_DMIF_MEM_CNTL1); 2268c93bb85bSJerome Glisse temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | 2269c93bb85bSJerome Glisse RS400_DISP1_CRITICAL_POINT_STOP_MASK); 2270c93bb85bSJerome Glisse WREG32(RS400_DMIF_MEM_CNTL1, (temp | 2271c93bb85bSJerome Glisse (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | 2272c93bb85bSJerome Glisse (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); 2273c93bb85bSJerome Glisse } 2274c93bb85bSJerome Glisse #endif 2275c93bb85bSJerome Glisse 2276c93bb85bSJerome Glisse DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n", 2277c93bb85bSJerome Glisse /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ 2278c93bb85bSJerome Glisse (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); 2279c93bb85bSJerome Glisse } 2280c93bb85bSJerome Glisse 2281c93bb85bSJerome Glisse if (mode2) { 2282c93bb85bSJerome Glisse u32 grph2_cntl; 2283c93bb85bSJerome Glisse stop_req = mode2->hdisplay * pixel_bytes2 / 16; 2284c93bb85bSJerome Glisse 2285c93bb85bSJerome Glisse if (stop_req > max_stop_req) 2286c93bb85bSJerome Glisse stop_req = max_stop_req; 2287c93bb85bSJerome Glisse 2288c93bb85bSJerome Glisse /* 2289c93bb85bSJerome Glisse Find the drain rate of the display buffer. 2290c93bb85bSJerome Glisse */ 2291c93bb85bSJerome Glisse temp_ff.full = rfixed_const((16/pixel_bytes2)); 2292c93bb85bSJerome Glisse disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff); 2293c93bb85bSJerome Glisse 2294c93bb85bSJerome Glisse grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); 2295c93bb85bSJerome Glisse grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); 2296c93bb85bSJerome Glisse grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); 2297c93bb85bSJerome Glisse grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); 2298c93bb85bSJerome Glisse if ((rdev->family == CHIP_R350) && 2299c93bb85bSJerome Glisse (stop_req > 0x15)) { 2300c93bb85bSJerome Glisse stop_req -= 0x10; 2301c93bb85bSJerome Glisse } 2302c93bb85bSJerome Glisse grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); 2303c93bb85bSJerome Glisse grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; 2304c93bb85bSJerome Glisse grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | 2305c93bb85bSJerome Glisse RADEON_GRPH_CRITICAL_AT_SOF | 2306c93bb85bSJerome Glisse RADEON_GRPH_STOP_CNTL); 2307c93bb85bSJerome Glisse 2308c93bb85bSJerome Glisse if ((rdev->family == CHIP_RS100) || 2309c93bb85bSJerome Glisse (rdev->family == CHIP_RS200)) 2310c93bb85bSJerome Glisse critical_point2 = 0; 2311c93bb85bSJerome Glisse else { 2312c93bb85bSJerome Glisse temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; 2313c93bb85bSJerome Glisse temp_ff.full = rfixed_const(temp); 2314c93bb85bSJerome Glisse temp_ff.full = rfixed_mul(mclk_ff, temp_ff); 2315c93bb85bSJerome Glisse if (sclk_ff.full < temp_ff.full) 2316c93bb85bSJerome Glisse temp_ff.full = sclk_ff.full; 2317c93bb85bSJerome Glisse 2318c93bb85bSJerome Glisse read_return_rate.full = temp_ff.full; 2319c93bb85bSJerome Glisse 2320c93bb85bSJerome Glisse if (mode1) { 2321c93bb85bSJerome Glisse temp_ff.full = read_return_rate.full - disp_drain_rate.full; 2322c93bb85bSJerome Glisse time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff); 2323c93bb85bSJerome Glisse } else { 2324c93bb85bSJerome Glisse time_disp1_drop_priority.full = 0; 2325c93bb85bSJerome Glisse } 2326c93bb85bSJerome Glisse crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; 2327c93bb85bSJerome Glisse crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2); 2328c93bb85bSJerome Glisse crit_point_ff.full += rfixed_const_half(0); 2329c93bb85bSJerome Glisse 2330c93bb85bSJerome Glisse critical_point2 = rfixed_trunc(crit_point_ff); 2331c93bb85bSJerome Glisse 2332c93bb85bSJerome Glisse if (rdev->disp_priority == 2) { 2333c93bb85bSJerome Glisse critical_point2 = 0; 2334c93bb85bSJerome Glisse } 2335c93bb85bSJerome Glisse 2336c93bb85bSJerome Glisse if (max_stop_req - critical_point2 < 4) 2337c93bb85bSJerome Glisse critical_point2 = 0; 2338c93bb85bSJerome Glisse 2339c93bb85bSJerome Glisse } 2340c93bb85bSJerome Glisse 2341c93bb85bSJerome Glisse if (critical_point2 == 0 && rdev->family == CHIP_R300) { 2342c93bb85bSJerome Glisse /* some R300 cards have problem with this set to 0 */ 2343c93bb85bSJerome Glisse critical_point2 = 0x10; 2344c93bb85bSJerome Glisse } 2345c93bb85bSJerome Glisse 2346c93bb85bSJerome Glisse WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | 2347c93bb85bSJerome Glisse (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); 2348c93bb85bSJerome Glisse 2349c93bb85bSJerome Glisse if ((rdev->family == CHIP_RS400) || 2350c93bb85bSJerome Glisse (rdev->family == CHIP_RS480)) { 2351c93bb85bSJerome Glisse #if 0 2352c93bb85bSJerome Glisse /* attempt to program RS400 disp2 regs correctly ??? */ 2353c93bb85bSJerome Glisse temp = RREG32(RS400_DISP2_REQ_CNTL1); 2354c93bb85bSJerome Glisse temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | 2355c93bb85bSJerome Glisse RS400_DISP2_STOP_REQ_LEVEL_MASK); 2356c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL1, (temp | 2357c93bb85bSJerome Glisse (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | 2358c93bb85bSJerome Glisse (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); 2359c93bb85bSJerome Glisse temp = RREG32(RS400_DISP2_REQ_CNTL2); 2360c93bb85bSJerome Glisse temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | 2361c93bb85bSJerome Glisse RS400_DISP2_CRITICAL_POINT_STOP_MASK); 2362c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL2, (temp | 2363c93bb85bSJerome Glisse (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | 2364c93bb85bSJerome Glisse (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); 2365c93bb85bSJerome Glisse #endif 2366c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); 2367c93bb85bSJerome Glisse WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); 2368c93bb85bSJerome Glisse WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); 2369c93bb85bSJerome Glisse WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); 2370c93bb85bSJerome Glisse } 2371c93bb85bSJerome Glisse 2372c93bb85bSJerome Glisse DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n", 2373c93bb85bSJerome Glisse (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); 2374c93bb85bSJerome Glisse } 2375c93bb85bSJerome Glisse } 2376