1254885Sdumbbell/* 2254885Sdumbbell * Copyright 2008 Advanced Micro Devices, Inc. 3254885Sdumbbell * Copyright 2008 Red Hat Inc. 4254885Sdumbbell * Copyright 2009 Jerome Glisse. 5254885Sdumbbell * 6254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 7254885Sdumbbell * copy of this software and associated documentation files (the "Software"), 8254885Sdumbbell * to deal in the Software without restriction, including without limitation 9254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the 11254885Sdumbbell * Software is furnished to do so, subject to the following conditions: 12254885Sdumbbell * 13254885Sdumbbell * The above copyright notice and this permission notice shall be included in 14254885Sdumbbell * all copies or substantial portions of the Software. 15254885Sdumbbell * 16254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE. 23254885Sdumbbell * 24254885Sdumbbell * Authors: Dave Airlie 25254885Sdumbbell * Alex Deucher 26254885Sdumbbell * Jerome Glisse 27254885Sdumbbell */ 28254885Sdumbbell 29254885Sdumbbell#include <sys/cdefs.h> 30254885Sdumbbell__FBSDID("$FreeBSD$"); 31254885Sdumbbell 32254885Sdumbbell#include <dev/drm2/drmP.h> 33254885Sdumbbell#include <dev/drm2/drm_crtc_helper.h> 34254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h> 35254885Sdumbbell#include "radeon_reg.h" 36254885Sdumbbell#include "radeon.h" 37254885Sdumbbell#include "atom.h" 38254885Sdumbbell 39254885Sdumbbellstatic const char radeon_family_name[][16] = { 40254885Sdumbbell "R100", 41254885Sdumbbell "RV100", 42254885Sdumbbell "RS100", 43254885Sdumbbell "RV200", 44254885Sdumbbell "RS200", 45254885Sdumbbell "R200", 46254885Sdumbbell "RV250", 47254885Sdumbbell "RS300", 48254885Sdumbbell "RV280", 49254885Sdumbbell "R300", 50254885Sdumbbell "R350", 51254885Sdumbbell "RV350", 52254885Sdumbbell "RV380", 53254885Sdumbbell "R420", 54254885Sdumbbell "R423", 55254885Sdumbbell "RV410", 56254885Sdumbbell "RS400", 57254885Sdumbbell "RS480", 58254885Sdumbbell "RS600", 59254885Sdumbbell "RS690", 60254885Sdumbbell "RS740", 61254885Sdumbbell "RV515", 62254885Sdumbbell "R520", 63254885Sdumbbell "RV530", 64254885Sdumbbell "RV560", 65254885Sdumbbell "RV570", 66254885Sdumbbell "R580", 67254885Sdumbbell "R600", 68254885Sdumbbell "RV610", 69254885Sdumbbell "RV630", 70254885Sdumbbell "RV670", 71254885Sdumbbell "RV620", 72254885Sdumbbell "RV635", 73254885Sdumbbell "RS780", 74254885Sdumbbell "RS880", 75254885Sdumbbell "RV770", 76254885Sdumbbell "RV730", 77254885Sdumbbell "RV710", 78254885Sdumbbell "RV740", 79254885Sdumbbell "CEDAR", 80254885Sdumbbell "REDWOOD", 81254885Sdumbbell "JUNIPER", 82254885Sdumbbell "CYPRESS", 83254885Sdumbbell "HEMLOCK", 84254885Sdumbbell "PALM", 85254885Sdumbbell "SUMO", 86254885Sdumbbell "SUMO2", 87254885Sdumbbell "BARTS", 88254885Sdumbbell "TURKS", 89254885Sdumbbell "CAICOS", 90254885Sdumbbell "CAYMAN", 91254885Sdumbbell "ARUBA", 92254885Sdumbbell "TAHITI", 93254885Sdumbbell "PITCAIRN", 94254885Sdumbbell "VERDE", 95254885Sdumbbell "LAST", 96254885Sdumbbell}; 97254885Sdumbbell 98254885Sdumbbell/** 99254885Sdumbbell * radeon_surface_init - Clear GPU surface registers. 100254885Sdumbbell * 101254885Sdumbbell * @rdev: radeon_device pointer 102254885Sdumbbell * 103254885Sdumbbell * Clear GPU surface registers (r1xx-r5xx). 104254885Sdumbbell */ 105254885Sdumbbellvoid radeon_surface_init(struct radeon_device *rdev) 106254885Sdumbbell{ 107254885Sdumbbell /* FIXME: check this out */ 108254885Sdumbbell if (rdev->family < CHIP_R600) { 109254885Sdumbbell int i; 110254885Sdumbbell 111254885Sdumbbell for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) { 112254885Sdumbbell if (rdev->surface_regs[i].bo) 113254885Sdumbbell radeon_bo_get_surface_reg(rdev->surface_regs[i].bo); 114254885Sdumbbell else 115254885Sdumbbell radeon_clear_surface_reg(rdev, i); 116254885Sdumbbell } 117254885Sdumbbell /* enable surfaces */ 118254885Sdumbbell WREG32(RADEON_SURFACE_CNTL, 0); 119254885Sdumbbell } 120254885Sdumbbell} 121254885Sdumbbell 122254885Sdumbbell/* 123254885Sdumbbell * GPU scratch registers helpers function. 124254885Sdumbbell */ 125254885Sdumbbell/** 126254885Sdumbbell * radeon_scratch_init - Init scratch register driver information. 127254885Sdumbbell * 128254885Sdumbbell * @rdev: radeon_device pointer 129254885Sdumbbell * 130254885Sdumbbell * Init CP scratch register driver information (r1xx-r5xx) 131254885Sdumbbell */ 132254885Sdumbbellvoid radeon_scratch_init(struct radeon_device *rdev) 133254885Sdumbbell{ 134254885Sdumbbell int i; 135254885Sdumbbell 136254885Sdumbbell /* FIXME: check this out */ 137254885Sdumbbell if (rdev->family < CHIP_R300) { 138254885Sdumbbell rdev->scratch.num_reg = 5; 139254885Sdumbbell } else { 140254885Sdumbbell rdev->scratch.num_reg = 7; 141254885Sdumbbell } 142254885Sdumbbell rdev->scratch.reg_base = RADEON_SCRATCH_REG0; 143254885Sdumbbell for (i = 0; i < rdev->scratch.num_reg; i++) { 144254885Sdumbbell rdev->scratch.free[i] = true; 145254885Sdumbbell rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4); 146254885Sdumbbell } 147254885Sdumbbell} 148254885Sdumbbell 149254885Sdumbbell/** 150254885Sdumbbell * radeon_scratch_get - Allocate a scratch register 151254885Sdumbbell * 152254885Sdumbbell * @rdev: radeon_device pointer 153254885Sdumbbell * @reg: scratch register mmio offset 154254885Sdumbbell * 155254885Sdumbbell * Allocate a CP scratch register for use by the driver (all asics). 156254885Sdumbbell * Returns 0 on success or -EINVAL on failure. 157254885Sdumbbell */ 158254885Sdumbbellint radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) 159254885Sdumbbell{ 160254885Sdumbbell int i; 161254885Sdumbbell 162254885Sdumbbell for (i = 0; i < rdev->scratch.num_reg; i++) { 163254885Sdumbbell if (rdev->scratch.free[i]) { 164254885Sdumbbell rdev->scratch.free[i] = false; 165254885Sdumbbell *reg = rdev->scratch.reg[i]; 166254885Sdumbbell return 0; 167254885Sdumbbell } 168254885Sdumbbell } 169254885Sdumbbell return -EINVAL; 170254885Sdumbbell} 171254885Sdumbbell 172254885Sdumbbell/** 173254885Sdumbbell * radeon_scratch_free - Free a scratch register 174254885Sdumbbell * 175254885Sdumbbell * @rdev: radeon_device pointer 176254885Sdumbbell * @reg: scratch register mmio offset 177254885Sdumbbell * 178254885Sdumbbell * Free a CP scratch register allocated for use by the driver (all asics) 179254885Sdumbbell */ 180254885Sdumbbellvoid radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) 181254885Sdumbbell{ 182254885Sdumbbell int i; 183254885Sdumbbell 184254885Sdumbbell for (i = 0; i < rdev->scratch.num_reg; i++) { 185254885Sdumbbell if (rdev->scratch.reg[i] == reg) { 186254885Sdumbbell rdev->scratch.free[i] = true; 187254885Sdumbbell return; 188254885Sdumbbell } 189254885Sdumbbell } 190254885Sdumbbell} 191254885Sdumbbell 192254885Sdumbbell/* 193254885Sdumbbell * radeon_wb_*() 194254885Sdumbbell * Writeback is the the method by which the the GPU updates special pages 195254885Sdumbbell * in memory with the status of certain GPU events (fences, ring pointers, 196254885Sdumbbell * etc.). 197254885Sdumbbell */ 198254885Sdumbbell 199254885Sdumbbell/** 200254885Sdumbbell * radeon_wb_disable - Disable Writeback 201254885Sdumbbell * 202254885Sdumbbell * @rdev: radeon_device pointer 203254885Sdumbbell * 204254885Sdumbbell * Disables Writeback (all asics). Used for suspend. 205254885Sdumbbell */ 206254885Sdumbbellvoid radeon_wb_disable(struct radeon_device *rdev) 207254885Sdumbbell{ 208254885Sdumbbell int r; 209254885Sdumbbell 210254885Sdumbbell if (rdev->wb.wb_obj) { 211254885Sdumbbell r = radeon_bo_reserve(rdev->wb.wb_obj, false); 212254885Sdumbbell if (unlikely(r != 0)) 213254885Sdumbbell return; 214254885Sdumbbell radeon_bo_kunmap(rdev->wb.wb_obj); 215254885Sdumbbell radeon_bo_unpin(rdev->wb.wb_obj); 216254885Sdumbbell radeon_bo_unreserve(rdev->wb.wb_obj); 217254885Sdumbbell } 218254885Sdumbbell rdev->wb.enabled = false; 219254885Sdumbbell} 220254885Sdumbbell 221254885Sdumbbell/** 222254885Sdumbbell * radeon_wb_fini - Disable Writeback and free memory 223254885Sdumbbell * 224254885Sdumbbell * @rdev: radeon_device pointer 225254885Sdumbbell * 226254885Sdumbbell * Disables Writeback and frees the Writeback memory (all asics). 227254885Sdumbbell * Used at driver shutdown. 228254885Sdumbbell */ 229254885Sdumbbellvoid radeon_wb_fini(struct radeon_device *rdev) 230254885Sdumbbell{ 231254885Sdumbbell radeon_wb_disable(rdev); 232254885Sdumbbell if (rdev->wb.wb_obj) { 233254885Sdumbbell radeon_bo_unref(&rdev->wb.wb_obj); 234254885Sdumbbell rdev->wb.wb = NULL; 235254885Sdumbbell rdev->wb.wb_obj = NULL; 236254885Sdumbbell } 237254885Sdumbbell} 238254885Sdumbbell 239254885Sdumbbell/** 240254885Sdumbbell * radeon_wb_init- Init Writeback driver info and allocate memory 241254885Sdumbbell * 242254885Sdumbbell * @rdev: radeon_device pointer 243254885Sdumbbell * 244254885Sdumbbell * Disables Writeback and frees the Writeback memory (all asics). 245254885Sdumbbell * Used at driver startup. 246254885Sdumbbell * Returns 0 on success or an -error on failure. 247254885Sdumbbell */ 248254885Sdumbbellint radeon_wb_init(struct radeon_device *rdev) 249254885Sdumbbell{ 250254885Sdumbbell int r; 251282199Sdumbbell void *wb_ptr; /* FreeBSD: to please GCC 4.2. */ 252254885Sdumbbell 253254885Sdumbbell if (rdev->wb.wb_obj == NULL) { 254254885Sdumbbell r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, 255254885Sdumbbell RADEON_GEM_DOMAIN_GTT, NULL, &rdev->wb.wb_obj); 256254885Sdumbbell if (r) { 257254885Sdumbbell dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); 258254885Sdumbbell return r; 259254885Sdumbbell } 260254885Sdumbbell } 261254885Sdumbbell r = radeon_bo_reserve(rdev->wb.wb_obj, false); 262254885Sdumbbell if (unlikely(r != 0)) { 263254885Sdumbbell radeon_wb_fini(rdev); 264254885Sdumbbell return r; 265254885Sdumbbell } 266254885Sdumbbell r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, 267254885Sdumbbell &rdev->wb.gpu_addr); 268254885Sdumbbell if (r) { 269254885Sdumbbell radeon_bo_unreserve(rdev->wb.wb_obj); 270254885Sdumbbell dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r); 271254885Sdumbbell radeon_wb_fini(rdev); 272254885Sdumbbell return r; 273254885Sdumbbell } 274254885Sdumbbell wb_ptr = &rdev->wb.wb; 275254885Sdumbbell r = radeon_bo_kmap(rdev->wb.wb_obj, wb_ptr); 276254885Sdumbbell radeon_bo_unreserve(rdev->wb.wb_obj); 277254885Sdumbbell if (r) { 278254885Sdumbbell dev_warn(rdev->dev, "(%d) map WB bo failed\n", r); 279254885Sdumbbell radeon_wb_fini(rdev); 280254885Sdumbbell return r; 281254885Sdumbbell } 282254885Sdumbbell 283254885Sdumbbell /* clear wb memory */ 284254885Sdumbbell memset(*(void **)wb_ptr, 0, RADEON_GPU_PAGE_SIZE); 285254885Sdumbbell /* disable event_write fences */ 286254885Sdumbbell rdev->wb.use_event = false; 287254885Sdumbbell /* disabled via module param */ 288254885Sdumbbell if (radeon_no_wb == 1) { 289254885Sdumbbell rdev->wb.enabled = false; 290254885Sdumbbell } else { 291254885Sdumbbell if (rdev->flags & RADEON_IS_AGP) { 292254885Sdumbbell /* often unreliable on AGP */ 293254885Sdumbbell rdev->wb.enabled = false; 294254885Sdumbbell } else if (rdev->family < CHIP_R300) { 295254885Sdumbbell /* often unreliable on pre-r300 */ 296254885Sdumbbell rdev->wb.enabled = false; 297254885Sdumbbell } else { 298254885Sdumbbell rdev->wb.enabled = true; 299254885Sdumbbell /* event_write fences are only available on r600+ */ 300254885Sdumbbell if (rdev->family >= CHIP_R600) { 301254885Sdumbbell rdev->wb.use_event = true; 302254885Sdumbbell } 303254885Sdumbbell } 304254885Sdumbbell } 305254885Sdumbbell /* always use writeback/events on NI, APUs */ 306254885Sdumbbell if (rdev->family >= CHIP_PALM) { 307254885Sdumbbell rdev->wb.enabled = true; 308254885Sdumbbell rdev->wb.use_event = true; 309254885Sdumbbell } 310254885Sdumbbell 311254885Sdumbbell dev_info(rdev->dev, "WB %sabled\n", rdev->wb.enabled ? "en" : "dis"); 312254885Sdumbbell 313254885Sdumbbell return 0; 314254885Sdumbbell} 315254885Sdumbbell 316254885Sdumbbell/** 317254885Sdumbbell * radeon_vram_location - try to find VRAM location 318254885Sdumbbell * @rdev: radeon device structure holding all necessary informations 319254885Sdumbbell * @mc: memory controller structure holding memory informations 320254885Sdumbbell * @base: base address at which to put VRAM 321254885Sdumbbell * 322254885Sdumbbell * Function will place try to place VRAM at base address provided 323254885Sdumbbell * as parameter (which is so far either PCI aperture address or 324254885Sdumbbell * for IGP TOM base address). 325254885Sdumbbell * 326254885Sdumbbell * If there is not enough space to fit the unvisible VRAM in the 32bits 327254885Sdumbbell * address space then we limit the VRAM size to the aperture. 328254885Sdumbbell * 329254885Sdumbbell * If we are using AGP and if the AGP aperture doesn't allow us to have 330254885Sdumbbell * room for all the VRAM than we restrict the VRAM to the PCI aperture 331254885Sdumbbell * size and print a warning. 332254885Sdumbbell * 333254885Sdumbbell * This function will never fails, worst case are limiting VRAM. 334254885Sdumbbell * 335254885Sdumbbell * Note: GTT start, end, size should be initialized before calling this 336254885Sdumbbell * function on AGP platform. 337254885Sdumbbell * 338254885Sdumbbell * Note: We don't explicitly enforce VRAM start to be aligned on VRAM size, 339254885Sdumbbell * this shouldn't be a problem as we are using the PCI aperture as a reference. 340254885Sdumbbell * Otherwise this would be needed for rv280, all r3xx, and all r4xx, but 341254885Sdumbbell * not IGP. 342254885Sdumbbell * 343254885Sdumbbell * Note: we use mc_vram_size as on some board we need to program the mc to 344254885Sdumbbell * cover the whole aperture even if VRAM size is inferior to aperture size 345254885Sdumbbell * Novell bug 204882 + along with lots of ubuntu ones 346254885Sdumbbell * 347254885Sdumbbell * Note: when limiting vram it's safe to overwritte real_vram_size because 348254885Sdumbbell * we are not in case where real_vram_size is inferior to mc_vram_size (ie 349254885Sdumbbell * note afected by bogus hw of Novell bug 204882 + along with lots of ubuntu 350254885Sdumbbell * ones) 351254885Sdumbbell * 352254885Sdumbbell * Note: IGP TOM addr should be the same as the aperture addr, we don't 353254885Sdumbbell * explicitly check for that thought. 354254885Sdumbbell * 355254885Sdumbbell * FIXME: when reducing VRAM size align new size on power of 2. 356254885Sdumbbell */ 357254885Sdumbbellvoid radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base) 358254885Sdumbbell{ 359254885Sdumbbell uint64_t limit = (uint64_t)radeon_vram_limit << 20; 360254885Sdumbbell 361254885Sdumbbell mc->vram_start = base; 362254885Sdumbbell if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) { 363254885Sdumbbell dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); 364254885Sdumbbell mc->real_vram_size = mc->aper_size; 365254885Sdumbbell mc->mc_vram_size = mc->aper_size; 366254885Sdumbbell } 367254885Sdumbbell mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; 368254885Sdumbbell if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_start <= mc->gtt_end) { 369254885Sdumbbell dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); 370254885Sdumbbell mc->real_vram_size = mc->aper_size; 371254885Sdumbbell mc->mc_vram_size = mc->aper_size; 372254885Sdumbbell } 373254885Sdumbbell mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; 374254885Sdumbbell if (limit && limit < mc->real_vram_size) 375254885Sdumbbell mc->real_vram_size = limit; 376254885Sdumbbell dev_info(rdev->dev, "VRAM: %juM 0x%016jX - 0x%016jX (%juM used)\n", 377254885Sdumbbell (uintmax_t)mc->mc_vram_size >> 20, (uintmax_t)mc->vram_start, 378254885Sdumbbell (uintmax_t)mc->vram_end, (uintmax_t)mc->real_vram_size >> 20); 379254885Sdumbbell} 380254885Sdumbbell 381254885Sdumbbell/** 382254885Sdumbbell * radeon_gtt_location - try to find GTT location 383254885Sdumbbell * @rdev: radeon device structure holding all necessary informations 384254885Sdumbbell * @mc: memory controller structure holding memory informations 385254885Sdumbbell * 386254885Sdumbbell * Function will place try to place GTT before or after VRAM. 387254885Sdumbbell * 388254885Sdumbbell * If GTT size is bigger than space left then we ajust GTT size. 389254885Sdumbbell * Thus function will never fails. 390254885Sdumbbell * 391254885Sdumbbell * FIXME: when reducing GTT size align new size on power of 2. 392254885Sdumbbell */ 393254885Sdumbbellvoid radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) 394254885Sdumbbell{ 395254885Sdumbbell u64 size_af, size_bf; 396254885Sdumbbell 397254885Sdumbbell size_af = ((0xFFFFFFFF - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align; 398254885Sdumbbell size_bf = mc->vram_start & ~mc->gtt_base_align; 399254885Sdumbbell if (size_bf > size_af) { 400254885Sdumbbell if (mc->gtt_size > size_bf) { 401254885Sdumbbell dev_warn(rdev->dev, "limiting GTT\n"); 402254885Sdumbbell mc->gtt_size = size_bf; 403254885Sdumbbell } 404254885Sdumbbell mc->gtt_start = (mc->vram_start & ~mc->gtt_base_align) - mc->gtt_size; 405254885Sdumbbell } else { 406254885Sdumbbell if (mc->gtt_size > size_af) { 407254885Sdumbbell dev_warn(rdev->dev, "limiting GTT\n"); 408254885Sdumbbell mc->gtt_size = size_af; 409254885Sdumbbell } 410254885Sdumbbell mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align; 411254885Sdumbbell } 412254885Sdumbbell mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; 413254885Sdumbbell dev_info(rdev->dev, "GTT: %juM 0x%016jX - 0x%016jX\n", 414254885Sdumbbell (uintmax_t)mc->gtt_size >> 20, (uintmax_t)mc->gtt_start, (uintmax_t)mc->gtt_end); 415254885Sdumbbell} 416254885Sdumbbell 417254885Sdumbbell/* 418254885Sdumbbell * GPU helpers function. 419254885Sdumbbell */ 420254885Sdumbbell/** 421254885Sdumbbell * radeon_card_posted - check if the hw has already been initialized 422254885Sdumbbell * 423254885Sdumbbell * @rdev: radeon_device pointer 424254885Sdumbbell * 425254885Sdumbbell * Check if the asic has been initialized (all asics). 426254885Sdumbbell * Used at driver startup. 427254885Sdumbbell * Returns true if initialized or false if not. 428254885Sdumbbell */ 429254885Sdumbbellbool radeon_card_posted(struct radeon_device *rdev) 430254885Sdumbbell{ 431254885Sdumbbell uint32_t reg; 432254885Sdumbbell 433282199Sdumbbell#ifdef FREEBSD_WIP 434254885Sdumbbell if (efi_enabled(EFI_BOOT) && 435254885Sdumbbell rdev->dev->pci_subvendor == PCI_VENDOR_ID_APPLE) 436254885Sdumbbell return false; 437282199Sdumbbell#endif /* FREEBSD_WIP */ 438254885Sdumbbell 439254885Sdumbbell /* first check CRTCs */ 440254885Sdumbbell if (ASIC_IS_DCE41(rdev)) { 441254885Sdumbbell reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | 442254885Sdumbbell RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); 443254885Sdumbbell if (reg & EVERGREEN_CRTC_MASTER_EN) 444254885Sdumbbell return true; 445254885Sdumbbell } else if (ASIC_IS_DCE4(rdev)) { 446254885Sdumbbell reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | 447254885Sdumbbell RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | 448254885Sdumbbell RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | 449254885Sdumbbell RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) | 450254885Sdumbbell RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) | 451254885Sdumbbell RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); 452254885Sdumbbell if (reg & EVERGREEN_CRTC_MASTER_EN) 453254885Sdumbbell return true; 454254885Sdumbbell } else if (ASIC_IS_AVIVO(rdev)) { 455254885Sdumbbell reg = RREG32(AVIVO_D1CRTC_CONTROL) | 456254885Sdumbbell RREG32(AVIVO_D2CRTC_CONTROL); 457254885Sdumbbell if (reg & AVIVO_CRTC_EN) { 458254885Sdumbbell return true; 459254885Sdumbbell } 460254885Sdumbbell } else { 461254885Sdumbbell reg = RREG32(RADEON_CRTC_GEN_CNTL) | 462254885Sdumbbell RREG32(RADEON_CRTC2_GEN_CNTL); 463254885Sdumbbell if (reg & RADEON_CRTC_EN) { 464254885Sdumbbell return true; 465254885Sdumbbell } 466254885Sdumbbell } 467254885Sdumbbell 468254885Sdumbbell /* then check MEM_SIZE, in case the crtcs are off */ 469254885Sdumbbell if (rdev->family >= CHIP_R600) 470254885Sdumbbell reg = RREG32(R600_CONFIG_MEMSIZE); 471254885Sdumbbell else 472254885Sdumbbell reg = RREG32(RADEON_CONFIG_MEMSIZE); 473254885Sdumbbell 474254885Sdumbbell if (reg) 475254885Sdumbbell return true; 476254885Sdumbbell 477254885Sdumbbell return false; 478254885Sdumbbell 479254885Sdumbbell} 480254885Sdumbbell 481254885Sdumbbell/** 482254885Sdumbbell * radeon_update_bandwidth_info - update display bandwidth params 483254885Sdumbbell * 484254885Sdumbbell * @rdev: radeon_device pointer 485254885Sdumbbell * 486254885Sdumbbell * Used when sclk/mclk are switched or display modes are set. 487254885Sdumbbell * params are used to calculate display watermarks (all asics) 488254885Sdumbbell */ 489254885Sdumbbellvoid radeon_update_bandwidth_info(struct radeon_device *rdev) 490254885Sdumbbell{ 491254885Sdumbbell fixed20_12 a; 492254885Sdumbbell u32 sclk = rdev->pm.current_sclk; 493254885Sdumbbell u32 mclk = rdev->pm.current_mclk; 494254885Sdumbbell 495254885Sdumbbell /* sclk/mclk in Mhz */ 496254885Sdumbbell a.full = dfixed_const(100); 497254885Sdumbbell rdev->pm.sclk.full = dfixed_const(sclk); 498254885Sdumbbell rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); 499254885Sdumbbell rdev->pm.mclk.full = dfixed_const(mclk); 500254885Sdumbbell rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); 501254885Sdumbbell 502254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) { 503254885Sdumbbell a.full = dfixed_const(16); 504254885Sdumbbell /* core_bandwidth = sclk(Mhz) * 16 */ 505254885Sdumbbell rdev->pm.core_bandwidth.full = dfixed_div(rdev->pm.sclk, a); 506254885Sdumbbell } 507254885Sdumbbell} 508254885Sdumbbell 509254885Sdumbbell/** 510254885Sdumbbell * radeon_boot_test_post_card - check and possibly initialize the hw 511254885Sdumbbell * 512254885Sdumbbell * @rdev: radeon_device pointer 513254885Sdumbbell * 514254885Sdumbbell * Check if the asic is initialized and if not, attempt to initialize 515254885Sdumbbell * it (all asics). 516254885Sdumbbell * Returns true if initialized or false if not. 517254885Sdumbbell */ 518254885Sdumbbellbool radeon_boot_test_post_card(struct radeon_device *rdev) 519254885Sdumbbell{ 520254885Sdumbbell if (radeon_card_posted(rdev)) 521254885Sdumbbell return true; 522254885Sdumbbell 523254885Sdumbbell if (rdev->bios) { 524254885Sdumbbell DRM_INFO("GPU not posted. posting now...\n"); 525254885Sdumbbell if (rdev->is_atom_bios) 526254885Sdumbbell atom_asic_init(rdev->mode_info.atom_context); 527254885Sdumbbell else 528254885Sdumbbell radeon_combios_asic_init(rdev->ddev); 529254885Sdumbbell return true; 530254885Sdumbbell } else { 531254885Sdumbbell dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); 532254885Sdumbbell return false; 533254885Sdumbbell } 534254885Sdumbbell} 535254885Sdumbbell 536254885Sdumbbell/** 537254885Sdumbbell * radeon_dummy_page_init - init dummy page used by the driver 538254885Sdumbbell * 539254885Sdumbbell * @rdev: radeon_device pointer 540254885Sdumbbell * 541254885Sdumbbell * Allocate the dummy page used by the driver (all asics). 542254885Sdumbbell * This dummy page is used by the driver as a filler for gart entries 543254885Sdumbbell * when pages are taken out of the GART 544254885Sdumbbell * Returns 0 on sucess, -ENOMEM on failure. 545254885Sdumbbell */ 546254885Sdumbbellint radeon_dummy_page_init(struct radeon_device *rdev) 547254885Sdumbbell{ 548254885Sdumbbell if (rdev->dummy_page.dmah) 549254885Sdumbbell return 0; 550254885Sdumbbell rdev->dummy_page.dmah = drm_pci_alloc(rdev->ddev, 551282199Sdumbbell PAGE_SIZE, PAGE_SIZE, BUS_SPACE_MAXADDR_32BIT); 552254885Sdumbbell if (rdev->dummy_page.dmah == NULL) 553254885Sdumbbell return -ENOMEM; 554267042Smarius rdev->dummy_page.addr = rdev->dummy_page.dmah->busaddr; 555254885Sdumbbell return 0; 556254885Sdumbbell} 557254885Sdumbbell 558254885Sdumbbell/** 559254885Sdumbbell * radeon_dummy_page_fini - free dummy page used by the driver 560254885Sdumbbell * 561254885Sdumbbell * @rdev: radeon_device pointer 562254885Sdumbbell * 563254885Sdumbbell * Frees the dummy page used by the driver (all asics). 564254885Sdumbbell */ 565254885Sdumbbellvoid radeon_dummy_page_fini(struct radeon_device *rdev) 566254885Sdumbbell{ 567254885Sdumbbell if (rdev->dummy_page.dmah == NULL) 568254885Sdumbbell return; 569254885Sdumbbell drm_pci_free(rdev->ddev, rdev->dummy_page.dmah); 570254885Sdumbbell rdev->dummy_page.dmah = NULL; 571254885Sdumbbell rdev->dummy_page.addr = 0; 572254885Sdumbbell} 573254885Sdumbbell 574254885Sdumbbell 575254885Sdumbbell/* ATOM accessor methods */ 576254885Sdumbbell/* 577254885Sdumbbell * ATOM is an interpreted byte code stored in tables in the vbios. The 578254885Sdumbbell * driver registers callbacks to access registers and the interpreter 579254885Sdumbbell * in the driver parses the tables and executes then to program specific 580254885Sdumbbell * actions (set display modes, asic init, etc.). See radeon_atombios.c, 581254885Sdumbbell * atombios.h, and atom.c 582254885Sdumbbell */ 583254885Sdumbbell 584254885Sdumbbell/** 585254885Sdumbbell * cail_pll_read - read PLL register 586254885Sdumbbell * 587254885Sdumbbell * @info: atom card_info pointer 588254885Sdumbbell * @reg: PLL register offset 589254885Sdumbbell * 590254885Sdumbbell * Provides a PLL register accessor for the atom interpreter (r4xx+). 591254885Sdumbbell * Returns the value of the PLL register. 592254885Sdumbbell */ 593254885Sdumbbellstatic uint32_t cail_pll_read(struct card_info *info, uint32_t reg) 594254885Sdumbbell{ 595254885Sdumbbell struct radeon_device *rdev = info->dev->dev_private; 596254885Sdumbbell uint32_t r; 597254885Sdumbbell 598254885Sdumbbell r = rdev->pll_rreg(rdev, reg); 599254885Sdumbbell return r; 600254885Sdumbbell} 601254885Sdumbbell 602254885Sdumbbell/** 603254885Sdumbbell * cail_pll_write - write PLL register 604254885Sdumbbell * 605254885Sdumbbell * @info: atom card_info pointer 606254885Sdumbbell * @reg: PLL register offset 607254885Sdumbbell * @val: value to write to the pll register 608254885Sdumbbell * 609254885Sdumbbell * Provides a PLL register accessor for the atom interpreter (r4xx+). 610254885Sdumbbell */ 611254885Sdumbbellstatic void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) 612254885Sdumbbell{ 613254885Sdumbbell struct radeon_device *rdev = info->dev->dev_private; 614254885Sdumbbell 615254885Sdumbbell rdev->pll_wreg(rdev, reg, val); 616254885Sdumbbell} 617254885Sdumbbell 618254885Sdumbbell/** 619254885Sdumbbell * cail_mc_read - read MC (Memory Controller) register 620254885Sdumbbell * 621254885Sdumbbell * @info: atom card_info pointer 622254885Sdumbbell * @reg: MC register offset 623254885Sdumbbell * 624254885Sdumbbell * Provides an MC register accessor for the atom interpreter (r4xx+). 625254885Sdumbbell * Returns the value of the MC register. 626254885Sdumbbell */ 627254885Sdumbbellstatic uint32_t cail_mc_read(struct card_info *info, uint32_t reg) 628254885Sdumbbell{ 629254885Sdumbbell struct radeon_device *rdev = info->dev->dev_private; 630254885Sdumbbell uint32_t r; 631254885Sdumbbell 632254885Sdumbbell r = rdev->mc_rreg(rdev, reg); 633254885Sdumbbell return r; 634254885Sdumbbell} 635254885Sdumbbell 636254885Sdumbbell/** 637254885Sdumbbell * cail_mc_write - write MC (Memory Controller) register 638254885Sdumbbell * 639254885Sdumbbell * @info: atom card_info pointer 640254885Sdumbbell * @reg: MC register offset 641254885Sdumbbell * @val: value to write to the pll register 642254885Sdumbbell * 643254885Sdumbbell * Provides a MC register accessor for the atom interpreter (r4xx+). 644254885Sdumbbell */ 645254885Sdumbbellstatic void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) 646254885Sdumbbell{ 647254885Sdumbbell struct radeon_device *rdev = info->dev->dev_private; 648254885Sdumbbell 649254885Sdumbbell rdev->mc_wreg(rdev, reg, val); 650254885Sdumbbell} 651254885Sdumbbell 652254885Sdumbbell/** 653254885Sdumbbell * cail_reg_write - write MMIO register 654254885Sdumbbell * 655254885Sdumbbell * @info: atom card_info pointer 656254885Sdumbbell * @reg: MMIO register offset 657254885Sdumbbell * @val: value to write to the pll register 658254885Sdumbbell * 659254885Sdumbbell * Provides a MMIO register accessor for the atom interpreter (r4xx+). 660254885Sdumbbell */ 661254885Sdumbbellstatic void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) 662254885Sdumbbell{ 663254885Sdumbbell struct radeon_device *rdev = info->dev->dev_private; 664254885Sdumbbell 665254885Sdumbbell WREG32(reg*4, val); 666254885Sdumbbell} 667254885Sdumbbell 668254885Sdumbbell/** 669254885Sdumbbell * cail_reg_read - read MMIO register 670254885Sdumbbell * 671254885Sdumbbell * @info: atom card_info pointer 672254885Sdumbbell * @reg: MMIO register offset 673254885Sdumbbell * 674254885Sdumbbell * Provides an MMIO register accessor for the atom interpreter (r4xx+). 675254885Sdumbbell * Returns the value of the MMIO register. 676254885Sdumbbell */ 677254885Sdumbbellstatic uint32_t cail_reg_read(struct card_info *info, uint32_t reg) 678254885Sdumbbell{ 679254885Sdumbbell struct radeon_device *rdev = info->dev->dev_private; 680254885Sdumbbell uint32_t r; 681254885Sdumbbell 682254885Sdumbbell r = RREG32(reg*4); 683254885Sdumbbell return r; 684254885Sdumbbell} 685254885Sdumbbell 686254885Sdumbbell/** 687254885Sdumbbell * cail_ioreg_write - write IO register 688254885Sdumbbell * 689254885Sdumbbell * @info: atom card_info pointer 690254885Sdumbbell * @reg: IO register offset 691254885Sdumbbell * @val: value to write to the pll register 692254885Sdumbbell * 693254885Sdumbbell * Provides a IO register accessor for the atom interpreter (r4xx+). 694254885Sdumbbell */ 695254885Sdumbbellstatic void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) 696254885Sdumbbell{ 697254885Sdumbbell struct radeon_device *rdev = info->dev->dev_private; 698254885Sdumbbell 699254885Sdumbbell WREG32_IO(reg*4, val); 700254885Sdumbbell} 701254885Sdumbbell 702254885Sdumbbell/** 703254885Sdumbbell * cail_ioreg_read - read IO register 704254885Sdumbbell * 705254885Sdumbbell * @info: atom card_info pointer 706254885Sdumbbell * @reg: IO register offset 707254885Sdumbbell * 708254885Sdumbbell * Provides an IO register accessor for the atom interpreter (r4xx+). 709254885Sdumbbell * Returns the value of the IO register. 710254885Sdumbbell */ 711254885Sdumbbellstatic uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) 712254885Sdumbbell{ 713254885Sdumbbell struct radeon_device *rdev = info->dev->dev_private; 714254885Sdumbbell uint32_t r; 715254885Sdumbbell 716254885Sdumbbell r = RREG32_IO(reg*4); 717254885Sdumbbell return r; 718254885Sdumbbell} 719254885Sdumbbell 720254885Sdumbbell/** 721254885Sdumbbell * radeon_atombios_init - init the driver info and callbacks for atombios 722254885Sdumbbell * 723254885Sdumbbell * @rdev: radeon_device pointer 724254885Sdumbbell * 725254885Sdumbbell * Initializes the driver info and register access callbacks for the 726254885Sdumbbell * ATOM interpreter (r4xx+). 727254885Sdumbbell * Returns 0 on sucess, -ENOMEM on failure. 728254885Sdumbbell * Called at driver startup. 729254885Sdumbbell */ 730254885Sdumbbellint radeon_atombios_init(struct radeon_device *rdev) 731254885Sdumbbell{ 732254885Sdumbbell struct card_info *atom_card_info = 733254885Sdumbbell malloc(sizeof(struct card_info), 734282199Sdumbbell DRM_MEM_DRIVER, M_NOWAIT | M_ZERO); 735254885Sdumbbell 736254885Sdumbbell if (!atom_card_info) 737254885Sdumbbell return -ENOMEM; 738254885Sdumbbell 739254885Sdumbbell rdev->mode_info.atom_card_info = atom_card_info; 740254885Sdumbbell atom_card_info->dev = rdev->ddev; 741254885Sdumbbell atom_card_info->reg_read = cail_reg_read; 742254885Sdumbbell atom_card_info->reg_write = cail_reg_write; 743254885Sdumbbell /* needed for iio ops */ 744254885Sdumbbell if (rdev->rio_mem) { 745254885Sdumbbell atom_card_info->ioreg_read = cail_ioreg_read; 746254885Sdumbbell atom_card_info->ioreg_write = cail_ioreg_write; 747254885Sdumbbell } else { 748254885Sdumbbell DRM_ERROR("Unable to find PCI I/O BAR; using MMIO for ATOM IIO\n"); 749254885Sdumbbell atom_card_info->ioreg_read = cail_reg_read; 750254885Sdumbbell atom_card_info->ioreg_write = cail_reg_write; 751254885Sdumbbell } 752254885Sdumbbell atom_card_info->mc_read = cail_mc_read; 753254885Sdumbbell atom_card_info->mc_write = cail_mc_write; 754254885Sdumbbell atom_card_info->pll_read = cail_pll_read; 755254885Sdumbbell atom_card_info->pll_write = cail_pll_write; 756254885Sdumbbell 757254885Sdumbbell rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios); 758254885Sdumbbell sx_init(&rdev->mode_info.atom_context->mutex, 759254885Sdumbbell "drm__radeon_device__mode_info__atom_context__mutex"); 760254885Sdumbbell radeon_atom_initialize_bios_scratch_regs(rdev->ddev); 761254885Sdumbbell atom_allocate_fb_scratch(rdev->mode_info.atom_context); 762254885Sdumbbell return 0; 763254885Sdumbbell} 764254885Sdumbbell 765254885Sdumbbell/** 766254885Sdumbbell * radeon_atombios_fini - free the driver info and callbacks for atombios 767254885Sdumbbell * 768254885Sdumbbell * @rdev: radeon_device pointer 769254885Sdumbbell * 770254885Sdumbbell * Frees the driver info and register access callbacks for the ATOM 771254885Sdumbbell * interpreter (r4xx+). 772254885Sdumbbell * Called at driver shutdown. 773254885Sdumbbell */ 774254885Sdumbbellvoid radeon_atombios_fini(struct radeon_device *rdev) 775254885Sdumbbell{ 776254885Sdumbbell if (rdev->mode_info.atom_context) { 777254885Sdumbbell free(rdev->mode_info.atom_context->scratch, DRM_MEM_DRIVER); 778254885Sdumbbell atom_destroy(rdev->mode_info.atom_context); 779254885Sdumbbell } 780254885Sdumbbell free(rdev->mode_info.atom_card_info, DRM_MEM_DRIVER); 781254885Sdumbbell} 782254885Sdumbbell 783254885Sdumbbell/* COMBIOS */ 784254885Sdumbbell/* 785254885Sdumbbell * COMBIOS is the bios format prior to ATOM. It provides 786254885Sdumbbell * command tables similar to ATOM, but doesn't have a unified 787254885Sdumbbell * parser. See radeon_combios.c 788254885Sdumbbell */ 789254885Sdumbbell 790254885Sdumbbell/** 791254885Sdumbbell * radeon_combios_init - init the driver info for combios 792254885Sdumbbell * 793254885Sdumbbell * @rdev: radeon_device pointer 794254885Sdumbbell * 795254885Sdumbbell * Initializes the driver info for combios (r1xx-r3xx). 796254885Sdumbbell * Returns 0 on sucess. 797254885Sdumbbell * Called at driver startup. 798254885Sdumbbell */ 799254885Sdumbbellint radeon_combios_init(struct radeon_device *rdev) 800254885Sdumbbell{ 801254885Sdumbbell radeon_combios_initialize_bios_scratch_regs(rdev->ddev); 802254885Sdumbbell return 0; 803254885Sdumbbell} 804254885Sdumbbell 805254885Sdumbbell/** 806254885Sdumbbell * radeon_combios_fini - free the driver info for combios 807254885Sdumbbell * 808254885Sdumbbell * @rdev: radeon_device pointer 809254885Sdumbbell * 810254885Sdumbbell * Frees the driver info for combios (r1xx-r3xx). 811254885Sdumbbell * Called at driver shutdown. 812254885Sdumbbell */ 813254885Sdumbbellvoid radeon_combios_fini(struct radeon_device *rdev) 814254885Sdumbbell{ 815254885Sdumbbell} 816254885Sdumbbell 817282199Sdumbbell#ifdef FREEBSD_WIP 818254885Sdumbbell/* if we get transitioned to only one device, take VGA back */ 819254885Sdumbbell/** 820254885Sdumbbell * radeon_vga_set_decode - enable/disable vga decode 821254885Sdumbbell * 822254885Sdumbbell * @cookie: radeon_device pointer 823254885Sdumbbell * @state: enable/disable vga decode 824254885Sdumbbell * 825254885Sdumbbell * Enable/disable vga decode (all asics). 826254885Sdumbbell * Returns VGA resource flags. 827254885Sdumbbell */ 828254885Sdumbbellstatic unsigned int radeon_vga_set_decode(void *cookie, bool state) 829254885Sdumbbell{ 830254885Sdumbbell struct radeon_device *rdev = cookie; 831254885Sdumbbell radeon_vga_set_state(rdev, state); 832254885Sdumbbell if (state) 833254885Sdumbbell return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | 834254885Sdumbbell VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; 835254885Sdumbbell else 836254885Sdumbbell return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; 837254885Sdumbbell} 838282199Sdumbbell#endif /* FREEBSD_WIP */ 839254885Sdumbbell 840254885Sdumbbell/** 841254885Sdumbbell * radeon_check_pot_argument - check that argument is a power of two 842254885Sdumbbell * 843254885Sdumbbell * @arg: value to check 844254885Sdumbbell * 845254885Sdumbbell * Validates that a certain argument is a power of two (all asics). 846254885Sdumbbell * Returns true if argument is valid. 847254885Sdumbbell */ 848254885Sdumbbellstatic bool radeon_check_pot_argument(int arg) 849254885Sdumbbell{ 850254885Sdumbbell return (arg & (arg - 1)) == 0; 851254885Sdumbbell} 852254885Sdumbbell 853254885Sdumbbell/** 854254885Sdumbbell * radeon_check_arguments - validate module params 855254885Sdumbbell * 856254885Sdumbbell * @rdev: radeon_device pointer 857254885Sdumbbell * 858254885Sdumbbell * Validates certain module parameters and updates 859254885Sdumbbell * the associated values used by the driver (all asics). 860254885Sdumbbell */ 861254885Sdumbbellstatic void radeon_check_arguments(struct radeon_device *rdev) 862254885Sdumbbell{ 863254885Sdumbbell /* vramlimit must be a power of two */ 864254885Sdumbbell if (!radeon_check_pot_argument(radeon_vram_limit)) { 865254885Sdumbbell dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n", 866254885Sdumbbell radeon_vram_limit); 867254885Sdumbbell radeon_vram_limit = 0; 868254885Sdumbbell } 869254885Sdumbbell 870254885Sdumbbell /* gtt size must be power of two and greater or equal to 32M */ 871254885Sdumbbell if (radeon_gart_size < 32) { 872254885Sdumbbell dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n", 873254885Sdumbbell radeon_gart_size); 874254885Sdumbbell radeon_gart_size = 512; 875254885Sdumbbell 876254885Sdumbbell } else if (!radeon_check_pot_argument(radeon_gart_size)) { 877254885Sdumbbell dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", 878254885Sdumbbell radeon_gart_size); 879254885Sdumbbell radeon_gart_size = 512; 880254885Sdumbbell } 881254885Sdumbbell rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; 882254885Sdumbbell 883254885Sdumbbell /* AGP mode can only be -1, 1, 2, 4, 8 */ 884254885Sdumbbell switch (radeon_agpmode) { 885254885Sdumbbell case -1: 886254885Sdumbbell case 0: 887254885Sdumbbell case 1: 888254885Sdumbbell case 2: 889254885Sdumbbell case 4: 890254885Sdumbbell case 8: 891254885Sdumbbell break; 892254885Sdumbbell default: 893254885Sdumbbell dev_warn(rdev->dev, "invalid AGP mode %d (valid mode: " 894254885Sdumbbell "-1, 0, 1, 2, 4, 8)\n", radeon_agpmode); 895254885Sdumbbell radeon_agpmode = 0; 896254885Sdumbbell break; 897254885Sdumbbell } 898254885Sdumbbell} 899254885Sdumbbell 900254885Sdumbbell/** 901254885Sdumbbell * radeon_switcheroo_quirk_long_wakeup - return true if longer d3 delay is 902254885Sdumbbell * needed for waking up. 903254885Sdumbbell * 904254885Sdumbbell * @pdev: pci dev pointer 905254885Sdumbbell */ 906282199Sdumbbell#ifdef FREEBSD_WIP 907254885Sdumbbellstatic bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev) 908254885Sdumbbell{ 909254885Sdumbbell 910254885Sdumbbell /* 6600m in a macbook pro */ 911254885Sdumbbell if (pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && 912254885Sdumbbell pdev->subsystem_device == 0x00e2) { 913254885Sdumbbell printk(KERN_INFO "radeon: quirking longer d3 wakeup delay\n"); 914254885Sdumbbell return true; 915254885Sdumbbell } 916254885Sdumbbell 917254885Sdumbbell return false; 918254885Sdumbbell} 919282199Sdumbbell#endif /* FREEBSD_WIP */ 920254885Sdumbbell 921254885Sdumbbell/** 922254885Sdumbbell * radeon_switcheroo_set_state - set switcheroo state 923254885Sdumbbell * 924254885Sdumbbell * @pdev: pci dev pointer 925254885Sdumbbell * @state: vga switcheroo state 926254885Sdumbbell * 927254885Sdumbbell * Callback for the switcheroo driver. Suspends or resumes the 928254885Sdumbbell * the asics before or after it is powered up using ACPI methods. 929254885Sdumbbell */ 930282199Sdumbbell#ifdef FREEBSD_WIP 931254885Sdumbbellstatic void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) 932254885Sdumbbell{ 933254885Sdumbbell struct drm_device *dev = pci_get_drvdata(pdev); 934254885Sdumbbell pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; 935254885Sdumbbell if (state == VGA_SWITCHEROO_ON) { 936254885Sdumbbell unsigned d3_delay = dev->pdev->d3_delay; 937254885Sdumbbell 938254885Sdumbbell printk(KERN_INFO "radeon: switched on\n"); 939254885Sdumbbell /* don't suspend or resume card normally */ 940254885Sdumbbell dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; 941254885Sdumbbell 942254885Sdumbbell if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev)) 943254885Sdumbbell dev->pdev->d3_delay = 20; 944254885Sdumbbell 945254885Sdumbbell radeon_resume_kms(dev); 946254885Sdumbbell 947254885Sdumbbell dev->pdev->d3_delay = d3_delay; 948254885Sdumbbell 949254885Sdumbbell dev->switch_power_state = DRM_SWITCH_POWER_ON; 950254885Sdumbbell drm_kms_helper_poll_enable(dev); 951254885Sdumbbell } else { 952254885Sdumbbell printk(KERN_INFO "radeon: switched off\n"); 953254885Sdumbbell drm_kms_helper_poll_disable(dev); 954254885Sdumbbell dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; 955254885Sdumbbell radeon_suspend_kms(dev, pmm); 956254885Sdumbbell dev->switch_power_state = DRM_SWITCH_POWER_OFF; 957254885Sdumbbell } 958254885Sdumbbell} 959282199Sdumbbell#endif /* FREEBSD_WIP */ 960254885Sdumbbell 961254885Sdumbbell/** 962254885Sdumbbell * radeon_switcheroo_can_switch - see if switcheroo state can change 963254885Sdumbbell * 964254885Sdumbbell * @pdev: pci dev pointer 965254885Sdumbbell * 966254885Sdumbbell * Callback for the switcheroo driver. Check of the switcheroo 967254885Sdumbbell * state can be changed. 968254885Sdumbbell * Returns true if the state can be changed, false if not. 969254885Sdumbbell */ 970282199Sdumbbell#ifdef FREEBSD_WIP 971254885Sdumbbellstatic bool radeon_switcheroo_can_switch(struct pci_dev *pdev) 972254885Sdumbbell{ 973254885Sdumbbell struct drm_device *dev = pci_get_drvdata(pdev); 974254885Sdumbbell bool can_switch; 975254885Sdumbbell 976254885Sdumbbell spin_lock(&dev->count_lock); 977254885Sdumbbell can_switch = (dev->open_count == 0); 978254885Sdumbbell spin_unlock(&dev->count_lock); 979254885Sdumbbell return can_switch; 980254885Sdumbbell} 981254885Sdumbbell 982254885Sdumbbellstatic const struct vga_switcheroo_client_ops radeon_switcheroo_ops = { 983254885Sdumbbell .set_gpu_state = radeon_switcheroo_set_state, 984254885Sdumbbell .reprobe = NULL, 985254885Sdumbbell .can_switch = radeon_switcheroo_can_switch, 986254885Sdumbbell}; 987282199Sdumbbell#endif /* FREEBSD_WIP */ 988254885Sdumbbell 989254885Sdumbbell/** 990254885Sdumbbell * radeon_device_init - initialize the driver 991254885Sdumbbell * 992254885Sdumbbell * @rdev: radeon_device pointer 993254885Sdumbbell * @pdev: drm dev pointer 994254885Sdumbbell * @flags: driver flags 995254885Sdumbbell * 996254885Sdumbbell * Initializes the driver info and hw (all asics). 997254885Sdumbbell * Returns 0 for success or an error on failure. 998254885Sdumbbell * Called at driver startup. 999254885Sdumbbell */ 1000254885Sdumbbellint radeon_device_init(struct radeon_device *rdev, 1001254885Sdumbbell struct drm_device *ddev, 1002254885Sdumbbell uint32_t flags) 1003254885Sdumbbell{ 1004254885Sdumbbell int r, i; 1005254885Sdumbbell int dma_bits; 1006254885Sdumbbell 1007254885Sdumbbell rdev->shutdown = false; 1008282199Sdumbbell rdev->dev = ddev->dev; 1009254885Sdumbbell rdev->ddev = ddev; 1010254885Sdumbbell rdev->flags = flags; 1011254885Sdumbbell rdev->family = flags & RADEON_FAMILY_MASK; 1012254885Sdumbbell rdev->is_atom_bios = false; 1013254885Sdumbbell rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT; 1014254885Sdumbbell rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; 1015254885Sdumbbell rdev->accel_working = false; 1016254885Sdumbbell rdev->fictitious_range_registered = false; 1017275408Stijl rdev->fictitious_agp_range_registered = false; 1018254885Sdumbbell /* set up ring ids */ 1019254885Sdumbbell for (i = 0; i < RADEON_NUM_RINGS; i++) { 1020254885Sdumbbell rdev->ring[i].idx = i; 1021254885Sdumbbell } 1022254885Sdumbbell 1023254885Sdumbbell DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n", 1024254885Sdumbbell radeon_family_name[rdev->family], ddev->pci_vendor, ddev->pci_device, 1025254885Sdumbbell ddev->pci_subvendor, ddev->pci_subdevice); 1026254885Sdumbbell 1027254885Sdumbbell /* mutex initialization are all done here so we 1028254885Sdumbbell * can recall function without having locking issues */ 1029254885Sdumbbell sx_init(&rdev->ring_lock, "drm__radeon_device__ring_lock"); 1030254885Sdumbbell sx_init(&rdev->dc_hw_i2c_mutex, "drm__radeon_device__dc_hw_i2c_mutex"); 1031254885Sdumbbell atomic_set(&rdev->ih.lock, 0); 1032254885Sdumbbell sx_init(&rdev->gem.mutex, "drm__radeon_device__gem__mutex"); 1033254885Sdumbbell sx_init(&rdev->pm.mutex, "drm__radeon_device__pm__mutex"); 1034254885Sdumbbell sx_init(&rdev->gpu_clock_mutex, "drm__radeon_device__gpu_clock_mutex"); 1035254885Sdumbbell sx_init(&rdev->pm.mclk_lock, "drm__radeon_device__pm__mclk_lock"); 1036254885Sdumbbell sx_init(&rdev->exclusive_lock, "drm__radeon_device__exclusive_lock"); 1037254885Sdumbbell DRM_INIT_WAITQUEUE(&rdev->irq.vblank_queue); 1038254885Sdumbbell r = radeon_gem_init(rdev); 1039254885Sdumbbell if (r) 1040254885Sdumbbell return r; 1041254885Sdumbbell /* initialize vm here */ 1042254885Sdumbbell sx_init(&rdev->vm_manager.lock, "drm__radeon_device__vm_manager__lock"); 1043254885Sdumbbell /* Adjust VM size here. 1044254885Sdumbbell * Currently set to 4GB ((1 << 20) 4k pages). 1045254885Sdumbbell * Max GPUVM size for cayman and SI is 40 bits. 1046254885Sdumbbell */ 1047254885Sdumbbell rdev->vm_manager.max_pfn = 1 << 20; 1048254885Sdumbbell INIT_LIST_HEAD(&rdev->vm_manager.lru_vm); 1049254885Sdumbbell 1050254885Sdumbbell /* Set asic functions */ 1051254885Sdumbbell r = radeon_asic_init(rdev); 1052254885Sdumbbell if (r) 1053254885Sdumbbell return r; 1054254885Sdumbbell radeon_check_arguments(rdev); 1055254885Sdumbbell 1056254885Sdumbbell /* all of the newer IGP chips have an internal gart 1057254885Sdumbbell * However some rs4xx report as AGP, so remove that here. 1058254885Sdumbbell */ 1059254885Sdumbbell if ((rdev->family >= CHIP_RS400) && 1060254885Sdumbbell (rdev->flags & RADEON_IS_IGP)) { 1061254885Sdumbbell rdev->flags &= ~RADEON_IS_AGP; 1062254885Sdumbbell } 1063254885Sdumbbell 1064254885Sdumbbell if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) { 1065254885Sdumbbell radeon_agp_disable(rdev); 1066254885Sdumbbell } 1067254885Sdumbbell 1068254885Sdumbbell /* set DMA mask + need_dma32 flags. 1069254885Sdumbbell * PCIE - can handle 40-bits. 1070254885Sdumbbell * IGP - can handle 40-bits 1071254885Sdumbbell * AGP - generally dma32 is safest 1072254885Sdumbbell * PCI - dma32 for legacy pci gart, 40 bits on newer asics 1073254885Sdumbbell */ 1074254885Sdumbbell rdev->need_dma32 = false; 1075254885Sdumbbell if (rdev->flags & RADEON_IS_AGP) 1076254885Sdumbbell rdev->need_dma32 = true; 1077254885Sdumbbell if ((rdev->flags & RADEON_IS_PCI) && 1078254885Sdumbbell (rdev->family <= CHIP_RS740)) 1079254885Sdumbbell rdev->need_dma32 = true; 1080254885Sdumbbell 1081254885Sdumbbell dma_bits = rdev->need_dma32 ? 32 : 40; 1082282199Sdumbbell#ifdef FREEBSD_WIP 1083254885Sdumbbell r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); 1084254885Sdumbbell if (r) { 1085254885Sdumbbell rdev->need_dma32 = true; 1086254885Sdumbbell dma_bits = 32; 1087254885Sdumbbell printk(KERN_WARNING "radeon: No suitable DMA available.\n"); 1088254885Sdumbbell } 1089254885Sdumbbell r = pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); 1090254885Sdumbbell if (r) { 1091254885Sdumbbell pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); 1092254885Sdumbbell printk(KERN_WARNING "radeon: No coherent DMA available.\n"); 1093254885Sdumbbell } 1094282199Sdumbbell#endif /* FREEBSD_WIP */ 1095254885Sdumbbell 1096254885Sdumbbell /* Registers mapping */ 1097254885Sdumbbell /* TODO: block userspace mapping of io register */ 1098254885Sdumbbell DRM_SPININIT(&rdev->mmio_idx_lock, "drm__radeon_device__mmio_idx_lock"); 1099254885Sdumbbell rdev->rmmio_rid = PCIR_BAR(2); 1100254885Sdumbbell rdev->rmmio = bus_alloc_resource_any(rdev->dev, SYS_RES_MEMORY, 1101254885Sdumbbell &rdev->rmmio_rid, RF_ACTIVE | RF_SHAREABLE); 1102254885Sdumbbell if (rdev->rmmio == NULL) { 1103254885Sdumbbell return -ENOMEM; 1104254885Sdumbbell } 1105254885Sdumbbell rdev->rmmio_base = rman_get_start(rdev->rmmio); 1106254885Sdumbbell rdev->rmmio_size = rman_get_size(rdev->rmmio); 1107254885Sdumbbell DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base); 1108254885Sdumbbell DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size); 1109254885Sdumbbell 1110254885Sdumbbell /* io port mapping */ 1111254885Sdumbbell for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) { 1112254885Sdumbbell uint32_t data; 1113254885Sdumbbell 1114254885Sdumbbell data = pci_read_config(rdev->dev, PCIR_BAR(i), 4); 1115254885Sdumbbell if (PCI_BAR_IO(data)) { 1116254885Sdumbbell rdev->rio_rid = PCIR_BAR(i); 1117254885Sdumbbell rdev->rio_mem = bus_alloc_resource_any(rdev->dev, 1118254885Sdumbbell SYS_RES_IOPORT, &rdev->rio_rid, 1119254885Sdumbbell RF_ACTIVE | RF_SHAREABLE); 1120254885Sdumbbell break; 1121254885Sdumbbell } 1122254885Sdumbbell } 1123254885Sdumbbell if (rdev->rio_mem == NULL) 1124254885Sdumbbell DRM_ERROR("Unable to find PCI I/O BAR\n"); 1125254885Sdumbbell 1126254885Sdumbbell rdev->tq = taskqueue_create("radeonkms", M_WAITOK, 1127254885Sdumbbell taskqueue_thread_enqueue, &rdev->tq); 1128254885Sdumbbell taskqueue_start_threads(&rdev->tq, 1, PWAIT, "radeon taskq"); 1129254885Sdumbbell 1130282199Sdumbbell#ifdef FREEBSD_WIP 1131254885Sdumbbell /* if we have > 1 VGA cards, then disable the radeon VGA resources */ 1132254885Sdumbbell /* this will fail for cards that aren't VGA class devices, just 1133254885Sdumbbell * ignore it */ 1134254885Sdumbbell vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); 1135254885Sdumbbell vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops); 1136282199Sdumbbell#endif /* FREEBSD_WIP */ 1137254885Sdumbbell 1138254885Sdumbbell r = radeon_init(rdev); 1139254885Sdumbbell if (r) 1140254885Sdumbbell return r; 1141254885Sdumbbell 1142254885Sdumbbell r = radeon_ib_ring_tests(rdev); 1143254885Sdumbbell if (r) 1144254885Sdumbbell DRM_ERROR("ib ring test failed (%d).\n", r); 1145254885Sdumbbell 1146254885Sdumbbell if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { 1147254885Sdumbbell /* Acceleration not working on AGP card try again 1148254885Sdumbbell * with fallback to PCI or PCIE GART 1149254885Sdumbbell */ 1150254885Sdumbbell radeon_asic_reset(rdev); 1151254885Sdumbbell radeon_fini(rdev); 1152254885Sdumbbell radeon_agp_disable(rdev); 1153254885Sdumbbell r = radeon_init(rdev); 1154254885Sdumbbell if (r) 1155254885Sdumbbell return r; 1156254885Sdumbbell } 1157254885Sdumbbell 1158254885Sdumbbell DRM_INFO("%s: Taking over the fictitious range 0x%jx-0x%jx\n", 1159254885Sdumbbell __func__, (uintmax_t)rdev->mc.aper_base, 1160254885Sdumbbell (uintmax_t)rdev->mc.aper_base + rdev->mc.visible_vram_size); 1161254885Sdumbbell r = vm_phys_fictitious_reg_range( 1162254885Sdumbbell rdev->mc.aper_base, 1163254885Sdumbbell rdev->mc.aper_base + rdev->mc.visible_vram_size, 1164254885Sdumbbell VM_MEMATTR_WRITE_COMBINING); 1165254885Sdumbbell if (r != 0) { 1166254885Sdumbbell DRM_ERROR("Failed to register fictitious range " 1167254885Sdumbbell "0x%jx-0x%jx (%d).\n", (uintmax_t)rdev->mc.aper_base, 1168254885Sdumbbell (uintmax_t)rdev->mc.aper_base + rdev->mc.visible_vram_size, r); 1169254885Sdumbbell return (-r); 1170254885Sdumbbell } 1171254885Sdumbbell rdev->fictitious_range_registered = true; 1172275408Stijl#if __OS_HAS_AGP 1173275408Stijl if (rdev->flags & RADEON_IS_AGP) { 1174275408Stijl DRM_INFO("%s: Taking over the fictitious range 0x%jx-0x%jx\n", 1175275408Stijl __func__, (uintmax_t)rdev->mc.agp_base, 1176275408Stijl (uintmax_t)rdev->mc.agp_base + rdev->mc.gtt_size); 1177275408Stijl r = vm_phys_fictitious_reg_range( 1178275408Stijl rdev->mc.agp_base, 1179275408Stijl rdev->mc.agp_base + rdev->mc.gtt_size, 1180275408Stijl VM_MEMATTR_WRITE_COMBINING); 1181275408Stijl if (r != 0) { 1182275408Stijl DRM_ERROR("Failed to register fictitious range " 1183275408Stijl "0x%jx-0x%jx (%d).\n", (uintmax_t)rdev->mc.agp_base, 1184275408Stijl (uintmax_t)rdev->mc.agp_base + rdev->mc.gtt_size, r); 1185275408Stijl return (-r); 1186275408Stijl } 1187275408Stijl rdev->fictitious_agp_range_registered = true; 1188275408Stijl } 1189275408Stijl#endif 1190254885Sdumbbell 1191254885Sdumbbell if ((radeon_testing & 1)) { 1192254885Sdumbbell radeon_test_moves(rdev); 1193254885Sdumbbell } 1194254885Sdumbbell if ((radeon_testing & 2)) { 1195254885Sdumbbell radeon_test_syncing(rdev); 1196254885Sdumbbell } 1197254885Sdumbbell if (radeon_benchmarking) { 1198254885Sdumbbell radeon_benchmark(rdev, radeon_benchmarking); 1199254885Sdumbbell } 1200254885Sdumbbell return 0; 1201254885Sdumbbell} 1202254885Sdumbbell 1203282199Sdumbbell#ifdef FREEBSD_WIP 1204254885Sdumbbellstatic void radeon_debugfs_remove_files(struct radeon_device *rdev); 1205282199Sdumbbell#endif /* FREEBSD_WIP */ 1206254885Sdumbbell 1207254885Sdumbbell/** 1208254885Sdumbbell * radeon_device_fini - tear down the driver 1209254885Sdumbbell * 1210254885Sdumbbell * @rdev: radeon_device pointer 1211254885Sdumbbell * 1212254885Sdumbbell * Tear down the driver info (all asics). 1213254885Sdumbbell * Called at driver shutdown. 1214254885Sdumbbell */ 1215254885Sdumbbellvoid radeon_device_fini(struct radeon_device *rdev) 1216254885Sdumbbell{ 1217254885Sdumbbell DRM_INFO("radeon: finishing device.\n"); 1218254885Sdumbbell rdev->shutdown = true; 1219254885Sdumbbell /* evict vram memory */ 1220254885Sdumbbell radeon_bo_evict_vram(rdev); 1221254885Sdumbbell 1222254885Sdumbbell if (rdev->fictitious_range_registered) { 1223254885Sdumbbell vm_phys_fictitious_unreg_range( 1224254885Sdumbbell rdev->mc.aper_base, 1225254885Sdumbbell rdev->mc.aper_base + rdev->mc.visible_vram_size); 1226254885Sdumbbell } 1227275408Stijl#if __OS_HAS_AGP 1228275408Stijl if (rdev->fictitious_agp_range_registered) { 1229275408Stijl vm_phys_fictitious_unreg_range( 1230275408Stijl rdev->mc.agp_base, 1231275408Stijl rdev->mc.agp_base + rdev->mc.gtt_size); 1232275408Stijl } 1233275408Stijl#endif 1234254885Sdumbbell 1235254885Sdumbbell radeon_fini(rdev); 1236282199Sdumbbell#ifdef FREEBSD_WIP 1237254885Sdumbbell vga_switcheroo_unregister_client(rdev->pdev); 1238254885Sdumbbell vga_client_register(rdev->pdev, NULL, NULL, NULL); 1239282199Sdumbbell#endif /* FREEBSD_WIP */ 1240254885Sdumbbell 1241254885Sdumbbell if (rdev->tq != NULL) { 1242254885Sdumbbell taskqueue_free(rdev->tq); 1243254885Sdumbbell rdev->tq = NULL; 1244254885Sdumbbell } 1245254885Sdumbbell 1246254885Sdumbbell if (rdev->rio_mem) 1247254885Sdumbbell bus_release_resource(rdev->dev, SYS_RES_IOPORT, rdev->rio_rid, 1248254885Sdumbbell rdev->rio_mem); 1249254885Sdumbbell rdev->rio_mem = NULL; 1250254885Sdumbbell bus_release_resource(rdev->dev, SYS_RES_MEMORY, rdev->rmmio_rid, 1251254885Sdumbbell rdev->rmmio); 1252254885Sdumbbell rdev->rmmio = NULL; 1253282199Sdumbbell#ifdef FREEBSD_WIP 1254254885Sdumbbell radeon_debugfs_remove_files(rdev); 1255282199Sdumbbell#endif /* FREEBSD_WIP */ 1256254885Sdumbbell} 1257254885Sdumbbell 1258254885Sdumbbell 1259254885Sdumbbell/* 1260254885Sdumbbell * Suspend & resume. 1261254885Sdumbbell */ 1262254885Sdumbbell/** 1263254885Sdumbbell * radeon_suspend_kms - initiate device suspend 1264254885Sdumbbell * 1265254885Sdumbbell * @pdev: drm dev pointer 1266254885Sdumbbell * @state: suspend state 1267254885Sdumbbell * 1268254885Sdumbbell * Puts the hw in the suspend state (all asics). 1269254885Sdumbbell * Returns 0 for success or an error on failure. 1270254885Sdumbbell * Called at driver suspend. 1271254885Sdumbbell */ 1272254885Sdumbbellint radeon_suspend_kms(struct drm_device *dev) 1273254885Sdumbbell{ 1274254885Sdumbbell struct radeon_device *rdev; 1275254885Sdumbbell struct drm_crtc *crtc; 1276254885Sdumbbell struct drm_connector *connector; 1277254885Sdumbbell int i, r; 1278254885Sdumbbell bool force_completion = false; 1279254885Sdumbbell 1280254885Sdumbbell if (dev == NULL || dev->dev_private == NULL) { 1281254885Sdumbbell return -ENODEV; 1282254885Sdumbbell } 1283282199Sdumbbell#ifdef FREEBSD_WIP 1284254885Sdumbbell if (state.event == PM_EVENT_PRETHAW) { 1285254885Sdumbbell return 0; 1286254885Sdumbbell } 1287282199Sdumbbell#endif /* FREEBSD_WIP */ 1288254885Sdumbbell rdev = dev->dev_private; 1289254885Sdumbbell 1290254885Sdumbbell if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) 1291254885Sdumbbell return 0; 1292254885Sdumbbell 1293254885Sdumbbell drm_kms_helper_poll_disable(dev); 1294254885Sdumbbell 1295254885Sdumbbell /* turn off display hw */ 1296254885Sdumbbell list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1297254885Sdumbbell drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); 1298254885Sdumbbell } 1299254885Sdumbbell 1300254885Sdumbbell /* unpin the front buffers */ 1301254885Sdumbbell list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 1302254885Sdumbbell struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); 1303254885Sdumbbell struct radeon_bo *robj; 1304254885Sdumbbell 1305254885Sdumbbell if (rfb == NULL || rfb->obj == NULL) { 1306254885Sdumbbell continue; 1307254885Sdumbbell } 1308254885Sdumbbell robj = gem_to_radeon_bo(rfb->obj); 1309254885Sdumbbell /* don't unpin kernel fb objects */ 1310254885Sdumbbell if (!radeon_fbdev_robj_is_fb(rdev, robj)) { 1311254885Sdumbbell r = radeon_bo_reserve(robj, false); 1312254885Sdumbbell if (r == 0) { 1313254885Sdumbbell radeon_bo_unpin(robj); 1314254885Sdumbbell radeon_bo_unreserve(robj); 1315254885Sdumbbell } 1316254885Sdumbbell } 1317254885Sdumbbell } 1318254885Sdumbbell /* evict vram memory */ 1319254885Sdumbbell radeon_bo_evict_vram(rdev); 1320254885Sdumbbell 1321254885Sdumbbell sx_xlock(&rdev->ring_lock); 1322254885Sdumbbell /* wait for gpu to finish processing current batch */ 1323254885Sdumbbell for (i = 0; i < RADEON_NUM_RINGS; i++) { 1324254885Sdumbbell r = radeon_fence_wait_empty_locked(rdev, i); 1325254885Sdumbbell if (r) { 1326254885Sdumbbell /* delay GPU reset to resume */ 1327254885Sdumbbell force_completion = true; 1328254885Sdumbbell } 1329254885Sdumbbell } 1330254885Sdumbbell if (force_completion) { 1331254885Sdumbbell radeon_fence_driver_force_completion(rdev); 1332254885Sdumbbell } 1333254885Sdumbbell sx_xunlock(&rdev->ring_lock); 1334254885Sdumbbell 1335254885Sdumbbell radeon_save_bios_scratch_regs(rdev); 1336254885Sdumbbell 1337254885Sdumbbell radeon_pm_suspend(rdev); 1338254885Sdumbbell radeon_suspend(rdev); 1339254885Sdumbbell radeon_hpd_fini(rdev); 1340254885Sdumbbell /* evict remaining vram memory */ 1341254885Sdumbbell radeon_bo_evict_vram(rdev); 1342254885Sdumbbell 1343254885Sdumbbell radeon_agp_suspend(rdev); 1344254885Sdumbbell 1345282199Sdumbbell#ifdef FREEBSD_WIP 1346254885Sdumbbell if (state.event == PM_EVENT_SUSPEND) { 1347254885Sdumbbell /* Shut down the device */ 1348254885Sdumbbell pci_disable_device(dev->pdev); 1349254885Sdumbbell } 1350254885Sdumbbell console_lock(); 1351282199Sdumbbell#endif /* FREEBSD_WIP */ 1352254885Sdumbbell radeon_fbdev_set_suspend(rdev, 1); 1353282199Sdumbbell#ifdef FREEBSD_WIP 1354254885Sdumbbell console_unlock(); 1355282199Sdumbbell#endif /* FREEBSD_WIP */ 1356254885Sdumbbell return 0; 1357254885Sdumbbell} 1358254885Sdumbbell 1359254885Sdumbbell/** 1360254885Sdumbbell * radeon_resume_kms - initiate device resume 1361254885Sdumbbell * 1362254885Sdumbbell * @pdev: drm dev pointer 1363254885Sdumbbell * 1364254885Sdumbbell * Bring the hw back to operating state (all asics). 1365254885Sdumbbell * Returns 0 for success or an error on failure. 1366254885Sdumbbell * Called at driver resume. 1367254885Sdumbbell */ 1368254885Sdumbbellint radeon_resume_kms(struct drm_device *dev) 1369254885Sdumbbell{ 1370254885Sdumbbell struct drm_connector *connector; 1371254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 1372254885Sdumbbell int r; 1373254885Sdumbbell 1374254885Sdumbbell if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) 1375254885Sdumbbell return 0; 1376254885Sdumbbell 1377282199Sdumbbell#ifdef FREEBSD_WIP 1378254885Sdumbbell console_lock(); 1379254885Sdumbbell if (pci_enable_device(dev->pdev)) { 1380254885Sdumbbell console_unlock(); 1381254885Sdumbbell return -1; 1382254885Sdumbbell } 1383282199Sdumbbell#endif /* FREEBSD_WIP */ 1384254885Sdumbbell /* resume AGP if in use */ 1385254885Sdumbbell radeon_agp_resume(rdev); 1386254885Sdumbbell radeon_resume(rdev); 1387254885Sdumbbell 1388254885Sdumbbell r = radeon_ib_ring_tests(rdev); 1389254885Sdumbbell if (r) 1390254885Sdumbbell DRM_ERROR("ib ring test failed (%d).\n", r); 1391254885Sdumbbell 1392254885Sdumbbell radeon_pm_resume(rdev); 1393254885Sdumbbell radeon_restore_bios_scratch_regs(rdev); 1394254885Sdumbbell 1395254885Sdumbbell radeon_fbdev_set_suspend(rdev, 0); 1396282199Sdumbbell#ifdef FREEBSD_WIP 1397254885Sdumbbell console_unlock(); 1398282199Sdumbbell#endif /* FREEBSD_WIP */ 1399254885Sdumbbell 1400254885Sdumbbell /* init dig PHYs, disp eng pll */ 1401254885Sdumbbell if (rdev->is_atom_bios) { 1402254885Sdumbbell radeon_atom_encoder_init(rdev); 1403254885Sdumbbell radeon_atom_disp_eng_pll_init(rdev); 1404254885Sdumbbell /* turn on the BL */ 1405254885Sdumbbell if (rdev->mode_info.bl_encoder) { 1406254885Sdumbbell u8 bl_level = radeon_get_backlight_level(rdev, 1407254885Sdumbbell rdev->mode_info.bl_encoder); 1408254885Sdumbbell radeon_set_backlight_level(rdev, rdev->mode_info.bl_encoder, 1409254885Sdumbbell bl_level); 1410254885Sdumbbell } 1411254885Sdumbbell } 1412254885Sdumbbell /* reset hpd state */ 1413254885Sdumbbell radeon_hpd_init(rdev); 1414254885Sdumbbell /* blat the mode back in */ 1415254885Sdumbbell drm_helper_resume_force_mode(dev); 1416254885Sdumbbell /* turn on display hw */ 1417254885Sdumbbell list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1418254885Sdumbbell drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); 1419254885Sdumbbell } 1420254885Sdumbbell 1421254885Sdumbbell drm_kms_helper_poll_enable(dev); 1422254885Sdumbbell return 0; 1423254885Sdumbbell} 1424254885Sdumbbell 1425254885Sdumbbell/** 1426254885Sdumbbell * radeon_gpu_reset - reset the asic 1427254885Sdumbbell * 1428254885Sdumbbell * @rdev: radeon device pointer 1429254885Sdumbbell * 1430254885Sdumbbell * Attempt the reset the GPU if it has hung (all asics). 1431254885Sdumbbell * Returns 0 for success or an error on failure. 1432254885Sdumbbell */ 1433254885Sdumbbellint radeon_gpu_reset(struct radeon_device *rdev) 1434254885Sdumbbell{ 1435254885Sdumbbell unsigned ring_sizes[RADEON_NUM_RINGS]; 1436254885Sdumbbell uint32_t *ring_data[RADEON_NUM_RINGS]; 1437254885Sdumbbell 1438254885Sdumbbell bool saved = false; 1439254885Sdumbbell 1440254885Sdumbbell int i, r; 1441254885Sdumbbell int resched; 1442254885Sdumbbell 1443254885Sdumbbell sx_xlock(&rdev->exclusive_lock); 1444254885Sdumbbell radeon_save_bios_scratch_regs(rdev); 1445254885Sdumbbell /* block TTM */ 1446254885Sdumbbell resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); 1447254885Sdumbbell radeon_suspend(rdev); 1448254885Sdumbbell 1449254885Sdumbbell for (i = 0; i < RADEON_NUM_RINGS; ++i) { 1450254885Sdumbbell ring_sizes[i] = radeon_ring_backup(rdev, &rdev->ring[i], 1451254885Sdumbbell &ring_data[i]); 1452254885Sdumbbell if (ring_sizes[i]) { 1453254885Sdumbbell saved = true; 1454254885Sdumbbell dev_info(rdev->dev, "Saved %d dwords of commands " 1455254885Sdumbbell "on ring %d.\n", ring_sizes[i], i); 1456254885Sdumbbell } 1457254885Sdumbbell } 1458254885Sdumbbell 1459254885Sdumbbellretry: 1460254885Sdumbbell r = radeon_asic_reset(rdev); 1461254885Sdumbbell if (!r) { 1462254885Sdumbbell dev_info(rdev->dev, "GPU reset succeeded, trying to resume\n"); 1463254885Sdumbbell radeon_resume(rdev); 1464254885Sdumbbell } 1465254885Sdumbbell 1466254885Sdumbbell radeon_restore_bios_scratch_regs(rdev); 1467254885Sdumbbell 1468254885Sdumbbell if (!r) { 1469254885Sdumbbell for (i = 0; i < RADEON_NUM_RINGS; ++i) { 1470254885Sdumbbell radeon_ring_restore(rdev, &rdev->ring[i], 1471254885Sdumbbell ring_sizes[i], ring_data[i]); 1472254885Sdumbbell ring_sizes[i] = 0; 1473254885Sdumbbell ring_data[i] = NULL; 1474254885Sdumbbell } 1475254885Sdumbbell 1476254885Sdumbbell r = radeon_ib_ring_tests(rdev); 1477254885Sdumbbell if (r) { 1478254885Sdumbbell dev_err(rdev->dev, "ib ring test failed (%d).\n", r); 1479254885Sdumbbell if (saved) { 1480254885Sdumbbell saved = false; 1481254885Sdumbbell radeon_suspend(rdev); 1482254885Sdumbbell goto retry; 1483254885Sdumbbell } 1484254885Sdumbbell } 1485254885Sdumbbell } else { 1486254885Sdumbbell radeon_fence_driver_force_completion(rdev); 1487254885Sdumbbell for (i = 0; i < RADEON_NUM_RINGS; ++i) { 1488254885Sdumbbell free(ring_data[i], DRM_MEM_DRIVER); 1489254885Sdumbbell } 1490254885Sdumbbell } 1491254885Sdumbbell 1492254885Sdumbbell drm_helper_resume_force_mode(rdev->ddev); 1493254885Sdumbbell 1494254885Sdumbbell ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); 1495254885Sdumbbell if (r) { 1496254885Sdumbbell /* bad news, how to tell it to userspace ? */ 1497254885Sdumbbell dev_info(rdev->dev, "GPU reset failed\n"); 1498254885Sdumbbell } 1499254885Sdumbbell 1500254885Sdumbbell sx_xunlock(&rdev->exclusive_lock); 1501254885Sdumbbell return r; 1502254885Sdumbbell} 1503254885Sdumbbell 1504254885Sdumbbell 1505254885Sdumbbell/* 1506254885Sdumbbell * Debugfs 1507254885Sdumbbell */ 1508282199Sdumbbell#ifdef FREEBSD_WIP 1509254885Sdumbbellint radeon_debugfs_add_files(struct radeon_device *rdev, 1510254885Sdumbbell struct drm_info_list *files, 1511254885Sdumbbell unsigned nfiles) 1512254885Sdumbbell{ 1513254885Sdumbbell unsigned i; 1514254885Sdumbbell 1515254885Sdumbbell for (i = 0; i < rdev->debugfs_count; i++) { 1516254885Sdumbbell if (rdev->debugfs[i].files == files) { 1517254885Sdumbbell /* Already registered */ 1518254885Sdumbbell return 0; 1519254885Sdumbbell } 1520254885Sdumbbell } 1521254885Sdumbbell 1522254885Sdumbbell i = rdev->debugfs_count + 1; 1523254885Sdumbbell if (i > RADEON_DEBUGFS_MAX_COMPONENTS) { 1524254885Sdumbbell DRM_ERROR("Reached maximum number of debugfs components.\n"); 1525254885Sdumbbell DRM_ERROR("Report so we increase " 1526254885Sdumbbell "RADEON_DEBUGFS_MAX_COMPONENTS.\n"); 1527254885Sdumbbell return -EINVAL; 1528254885Sdumbbell } 1529254885Sdumbbell rdev->debugfs[rdev->debugfs_count].files = files; 1530254885Sdumbbell rdev->debugfs[rdev->debugfs_count].num_files = nfiles; 1531254885Sdumbbell rdev->debugfs_count = i; 1532254885Sdumbbell#if defined(CONFIG_DEBUG_FS) 1533254885Sdumbbell drm_debugfs_create_files(files, nfiles, 1534254885Sdumbbell rdev->ddev->control->debugfs_root, 1535254885Sdumbbell rdev->ddev->control); 1536254885Sdumbbell drm_debugfs_create_files(files, nfiles, 1537254885Sdumbbell rdev->ddev->primary->debugfs_root, 1538254885Sdumbbell rdev->ddev->primary); 1539254885Sdumbbell#endif 1540254885Sdumbbell return 0; 1541254885Sdumbbell} 1542254885Sdumbbell 1543254885Sdumbbellstatic void radeon_debugfs_remove_files(struct radeon_device *rdev) 1544254885Sdumbbell{ 1545254885Sdumbbell#if defined(CONFIG_DEBUG_FS) 1546254885Sdumbbell unsigned i; 1547254885Sdumbbell 1548254885Sdumbbell for (i = 0; i < rdev->debugfs_count; i++) { 1549254885Sdumbbell drm_debugfs_remove_files(rdev->debugfs[i].files, 1550254885Sdumbbell rdev->debugfs[i].num_files, 1551254885Sdumbbell rdev->ddev->control); 1552254885Sdumbbell drm_debugfs_remove_files(rdev->debugfs[i].files, 1553254885Sdumbbell rdev->debugfs[i].num_files, 1554254885Sdumbbell rdev->ddev->primary); 1555254885Sdumbbell } 1556254885Sdumbbell#endif 1557254885Sdumbbell} 1558254885Sdumbbell 1559254885Sdumbbell#if defined(CONFIG_DEBUG_FS) 1560254885Sdumbbellint radeon_debugfs_init(struct drm_minor *minor) 1561254885Sdumbbell{ 1562254885Sdumbbell return 0; 1563254885Sdumbbell} 1564254885Sdumbbell 1565254885Sdumbbellvoid radeon_debugfs_cleanup(struct drm_minor *minor) 1566254885Sdumbbell{ 1567254885Sdumbbell} 1568282199Sdumbbell#endif /* FREEBSD_WIP */ 1569254885Sdumbbell#endif 1570