/* * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Alexander von Gluck, kallisti5@unixzen.com * Axel Dörfler, axeld@pinc-software.de */ #include "gpu.h" #include #include "accelerant_protos.h" #include "accelerant.h" #include "atom.h" #include "bios.h" #include "pll.h" #include "utility.h" #undef TRACE #define TRACE_GPU #ifdef TRACE_GPU # define TRACE(x...) _sPrintf("radeon_hd: " x) #else # define TRACE(x...) ; #endif #define ERROR(x...) _sPrintf("radeon_hd: " x) status_t radeon_gpu_probe() { uint8 tableMajor; uint8 tableMinor; uint16 tableOffset; gInfo->displayClockFrequency = 0; gInfo->dpExternalClock = 0; int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); if (atom_parse_data_header(gAtomContext, index, NULL, &tableMajor, &tableMinor, &tableOffset) != B_OK) { ERROR("%s: Couldn't parse data header\n", __func__); return B_ERROR; } TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, tableMajor, tableMinor); union atomFirmwareInfo { ATOM_FIRMWARE_INFO info; ATOM_FIRMWARE_INFO_V1_2 info_12; ATOM_FIRMWARE_INFO_V1_3 info_13; ATOM_FIRMWARE_INFO_V1_4 info_14; ATOM_FIRMWARE_INFO_V2_1 info_21; ATOM_FIRMWARE_INFO_V2_2 info_22; }; union atomFirmwareInfo* firmwareInfo = (union atomFirmwareInfo*)(gAtomContext->bios + tableOffset); radeon_shared_info &info = *gInfo->shared_info; if (info.dceMajor >= 4) { gInfo->displayClockFrequency = B_LENDIAN_TO_HOST_INT32( firmwareInfo->info_21.ulDefaultDispEngineClkFreq); gInfo->displayClockFrequency *= 10; if (gInfo->displayClockFrequency == 0) { if (info.dceMajor == 5) gInfo->displayClockFrequency = 540000; else gInfo->displayClockFrequency = 600000; } gInfo->dpExternalClock = B_LENDIAN_TO_HOST_INT16( firmwareInfo->info_21.usUniphyDPModeExtClkFreq); gInfo->dpExternalClock *= 10; } gInfo->maximumPixelClock = B_LENDIAN_TO_HOST_INT16( firmwareInfo->info.usMaxPixelClock); gInfo->maximumPixelClock *= 10; if (gInfo->maximumPixelClock == 0) gInfo->maximumPixelClock = 400000; return B_OK; } status_t radeon_gpu_reset() { radeon_shared_info &info = *gInfo->shared_info; // Read GRBM Command Processor status if ((Read32(OUT, GRBM_STATUS) & GUI_ACTIVE) == 0) return B_ERROR; TRACE("%s: GPU software reset in progress...\n", __func__); // Halt memory controller struct gpu_state gpuState; radeon_gpu_mc_halt(&gpuState); if (radeon_gpu_mc_idlewait() != B_OK) ERROR("%s: Couldn't idle memory controller!\n", __func__); if (info.chipsetID < RADEON_CEDAR) { Write32(OUT, CP_ME_CNTL, CP_ME_HALT); // Disable Command Processor parsing / prefetching // Register busy masks for early Radeon HD cards // GRBM Command Processor Status uint32 grbmBusyMask = VC_BUSY; // Vertex Cache Busy grbmBusyMask |= VGT_BUSY_NO_DMA | VGT_BUSY; // Vertex Grouper Tessellator Busy grbmBusyMask |= TA03_BUSY; // unknown grbmBusyMask |= TC_BUSY; // Texture Cache Busy grbmBusyMask |= SX_BUSY; // Shader Export Busy grbmBusyMask |= SH_BUSY; // Sequencer Instruction Cache Busy grbmBusyMask |= SPI_BUSY; // Shader Processor Interpolator Busy grbmBusyMask |= SMX_BUSY; // Shader Memory Exchange grbmBusyMask |= SC_BUSY; // Scan Converter Busy grbmBusyMask |= PA_BUSY; // Primitive Assembler Busy grbmBusyMask |= DB_BUSY; // Depth Block Busy grbmBusyMask |= CR_BUSY; // unknown grbmBusyMask |= CB_BUSY; // Color Block Busy grbmBusyMask |= GUI_ACTIVE; // unknown (graphics pipeline active?) // GRBM Command Processor Detailed Status uint32 grbm2BusyMask = SPI0_BUSY | SPI1_BUSY | SPI2_BUSY | SPI3_BUSY; // Shader Processor Interpolator 0 - 3 Busy grbm2BusyMask |= TA0_BUSY | TA1_BUSY | TA2_BUSY | TA3_BUSY; // unknown 0 - 3 Busy grbm2BusyMask |= DB0_BUSY | DB1_BUSY | DB2_BUSY | DB3_BUSY; // Depth Block 0 - 3 Busy grbm2BusyMask |= CB0_BUSY | CB1_BUSY | CB2_BUSY | CB3_BUSY; // Color Block 0 - 3 Busy uint32 tmp; /* Check if any of the rendering block is busy and reset it */ if ((Read32(OUT, GRBM_STATUS) & grbmBusyMask) != 0 || (Read32(OUT, GRBM_STATUS2) & grbm2BusyMask) != 0) { tmp = SOFT_RESET_CR | SOFT_RESET_DB | SOFT_RESET_CB | SOFT_RESET_PA | SOFT_RESET_SC | SOFT_RESET_SMX | SOFT_RESET_SPI | SOFT_RESET_SX | SOFT_RESET_SH | SOFT_RESET_TC | SOFT_RESET_TA | SOFT_RESET_VC | SOFT_RESET_VGT; Write32(OUT, GRBM_SOFT_RESET, tmp); Read32(OUT, GRBM_SOFT_RESET); snooze(15000); Write32(OUT, GRBM_SOFT_RESET, 0); } // Reset CP tmp = SOFT_RESET_CP; Write32(OUT, GRBM_SOFT_RESET, tmp); Read32(OUT, GRBM_SOFT_RESET); snooze(15000); Write32(OUT, GRBM_SOFT_RESET, 0); // Let things settle snooze(1000); } else { // Evergreen and higher Write32(OUT, CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); // Disable Command Processor parsing / prefetching // reset the graphics pipeline components uint32 grbmReset = (SOFT_RESET_CP | SOFT_RESET_CB | SOFT_RESET_DB | SOFT_RESET_GDS | SOFT_RESET_PA | SOFT_RESET_SC | SOFT_RESET_SPI | SOFT_RESET_SH | SOFT_RESET_SX | SOFT_RESET_TC | SOFT_RESET_TA | SOFT_RESET_VGT | SOFT_RESET_IA); Write32(OUT, GRBM_SOFT_RESET, grbmReset); Read32(OUT, GRBM_SOFT_RESET); snooze(50); Write32(OUT, GRBM_SOFT_RESET, 0); Read32(OUT, GRBM_SOFT_RESET); snooze(50); } // Resume memory controller radeon_gpu_mc_resume(&gpuState); return B_OK; } status_t radeon_gpu_quirks() { radeon_shared_info &info = *gInfo->shared_info; // Fix PCIe power distribution issue for Polaris10 XT // aka "Card draws >75W from PCIe bus" if (info.chipsetID == RADEON_POLARIS10 && info.pciRev == 0xc7) { ERROR("%s: Applying Polaris10 power distribution fix.\n", __func__); radeon_gpu_i2c_cmd(0x10, 0x96, 0x1e, 0xdd); radeon_gpu_i2c_cmd(0x10, 0x96, 0x1f, 0xd0); } return B_OK; } status_t radeon_gpu_i2c_cmd(uint16 slaveAddr, uint16 lineNumber, uint8 offset, uint8 data) { TRACE("%s\n", __func__); PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args; memset(&args, 0, sizeof(args)); int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction); args.ucRegIndex = offset; args.lpI2CDataOut = data; args.ucFlag = HW_I2C_WRITE; args.ucI2CSpeed = TARGET_HW_I2C_CLOCK; args.ucTransBytes = 1; args.ucSlaveAddr = slaveAddr; args.ucLineNumber = lineNumber; atom_execute_table(gAtomContext, index, (uint32*)&args); return B_OK; } void radeon_gpu_mc_halt(gpu_state* gpuState) { // Backup current memory controller state gpuState->d1vgaControl = Read32(OUT, AVIVO_D1VGA_CONTROL); gpuState->d2vgaControl = Read32(OUT, AVIVO_D2VGA_CONTROL); gpuState->vgaRenderControl = Read32(OUT, AVIVO_VGA_RENDER_CONTROL); gpuState->vgaHdpControl = Read32(OUT, AVIVO_VGA_HDP_CONTROL); gpuState->d1crtcControl = Read32(OUT, AVIVO_D1CRTC_CONTROL); gpuState->d2crtcControl = Read32(OUT, AVIVO_D2CRTC_CONTROL); // halt all memory controller actions Write32(OUT, AVIVO_VGA_RENDER_CONTROL, 0); Write32(OUT, AVIVO_D1CRTC_UPDATE_LOCK, 1); Write32(OUT, AVIVO_D2CRTC_UPDATE_LOCK, 1); Write32(OUT, AVIVO_D1CRTC_CONTROL, 0); Write32(OUT, AVIVO_D2CRTC_CONTROL, 0); Write32(OUT, AVIVO_D1CRTC_UPDATE_LOCK, 0); Write32(OUT, AVIVO_D2CRTC_UPDATE_LOCK, 0); Write32(OUT, AVIVO_D1VGA_CONTROL, 0); Write32(OUT, AVIVO_D2VGA_CONTROL, 0); } void radeon_gpu_mc_resume(gpu_state* gpuState) { Write32(OUT, AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS, gInfo->fb.vramStart); Write32(OUT, AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS, gInfo->fb.vramStart); Write32(OUT, AVIVO_D2GRPH_PRIMARY_SURFACE_ADDRESS, gInfo->fb.vramStart); Write32(OUT, AVIVO_D2GRPH_SECONDARY_SURFACE_ADDRESS, gInfo->fb.vramStart); // TODO: Evergreen high surface addresses? Write32(OUT, AVIVO_VGA_MEMORY_BASE_ADDRESS, gInfo->fb.vramStart); // Unlock host access Write32(OUT, AVIVO_VGA_HDP_CONTROL, gpuState->vgaHdpControl); snooze(1); // Restore memory controller state Write32(OUT, AVIVO_D1VGA_CONTROL, gpuState->d1vgaControl); Write32(OUT, AVIVO_D2VGA_CONTROL, gpuState->d2vgaControl); Write32(OUT, AVIVO_D1CRTC_UPDATE_LOCK, 1); Write32(OUT, AVIVO_D2CRTC_UPDATE_LOCK, 1); Write32(OUT, AVIVO_D1CRTC_CONTROL, gpuState->d1crtcControl); Write32(OUT, AVIVO_D2CRTC_CONTROL, gpuState->d2crtcControl); Write32(OUT, AVIVO_D1CRTC_UPDATE_LOCK, 0); Write32(OUT, AVIVO_D2CRTC_UPDATE_LOCK, 0); Write32(OUT, AVIVO_VGA_RENDER_CONTROL, gpuState->vgaRenderControl); } status_t radeon_gpu_mc_idlewait() { uint32 idleStatus; uint32 busyBits = (VMC_BUSY | MCB_BUSY | MCDZ_BUSY | MCDY_BUSY | MCDX_BUSY | MCDW_BUSY); uint32 tryCount; // We give the gpu 0.5 seconds to become idle checking once every 500usec for (tryCount = 0; tryCount < 1000; tryCount++) { if (((idleStatus = Read32(MC, SRBM_STATUS)) & busyBits) == 0) return B_OK; snooze(500); } ERROR("%s: Couldn't idle SRBM!\n", __func__); bool state; state = (idleStatus & VMC_BUSY) != 0; TRACE("%s: VMC is %s\n", __func__, state ? "busy" : "idle"); state = (idleStatus & MCB_BUSY) != 0; TRACE("%s: MCB is %s\n", __func__, state ? "busy" : "idle"); state = (idleStatus & MCDZ_BUSY) != 0; TRACE("%s: MCDZ is %s\n", __func__, state ? "busy" : "idle"); state = (idleStatus & MCDY_BUSY) != 0; TRACE("%s: MCDY is %s\n", __func__, state ? "busy" : "idle"); state = (idleStatus & MCDX_BUSY) != 0; TRACE("%s: MCDX is %s\n", __func__, state ? "busy" : "idle"); state = (idleStatus & MCDW_BUSY) != 0; TRACE("%s: MCDW is %s\n", __func__, state ? "busy" : "idle"); return B_TIMED_OUT; } static status_t radeon_gpu_mc_setup_r600() { // HDP initialization uint32 i; uint32 j; for (i = 0, j = 0; i < 32; i++, j += 0x18) { Write32(OUT, (0x2c14 + j), 0x00000000); Write32(OUT, (0x2c18 + j), 0x00000000); Write32(OUT, (0x2c1c + j), 0x00000000); Write32(OUT, (0x2c20 + j), 0x00000000); Write32(OUT, (0x2c24 + j), 0x00000000); } Write32(OUT, R600_HDP_REG_COHERENCY_FLUSH_CNTL, 0); // idle the memory controller struct gpu_state gpuState; radeon_gpu_mc_halt(&gpuState); if (radeon_gpu_mc_idlewait() != B_OK) ERROR("%s: Modifying non-idle memory controller!\n", __func__); // TODO: Memory Controller AGP Write32(OUT, R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR, gInfo->fb.vramStart >> 12); Write32(OUT, R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, gInfo->fb.vramEnd >> 12); Write32(OUT, R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); uint32 tmp = ((gInfo->fb.vramEnd >> 24) & 0xFFFF) << 16; tmp |= ((gInfo->fb.vramStart >> 24) & 0xFFFF); Write32(OUT, R600_MC_VM_FB_LOCATION, tmp); Write32(OUT, R600_HDP_NONSURFACE_BASE, (gInfo->fb.vramStart >> 8)); Write32(OUT, R600_HDP_NONSURFACE_INFO, (2 << 7)); Write32(OUT, R600_HDP_NONSURFACE_SIZE, 0x3FFFFFFF); // is AGP? // Write32(OUT, R600_MC_VM_AGP_TOP, gInfo->fb.gartEnd >> 22); // Write32(OUT, R600_MC_VM_AGP_BOT, gInfo->fb.gartStart >> 22); // Write32(OUT, R600_MC_VM_AGP_BASE, gInfo->fb.agpBase >> 22); // else? Write32(OUT, R600_MC_VM_AGP_BASE, 0); Write32(OUT, R600_MC_VM_AGP_TOP, 0x0FFFFFFF); Write32(OUT, R600_MC_VM_AGP_BOT, 0x0FFFFFFF); if (radeon_gpu_mc_idlewait() != B_OK) ERROR("%s: Modifying non-idle memory controller!\n", __func__); radeon_gpu_mc_resume(&gpuState); // disable render control Write32(OUT, 0x000300, Read32(OUT, 0x000300) & 0xFFFCFFFF); return B_OK; } static status_t radeon_gpu_mc_setup_r700() { // HDP initialization uint32 i; uint32 j; for (i = 0, j = 0; i < 32; i++, j += 0x18) { Write32(OUT, (0x2c14 + j), 0x00000000); Write32(OUT, (0x2c18 + j), 0x00000000); Write32(OUT, (0x2c1c + j), 0x00000000); Write32(OUT, (0x2c20 + j), 0x00000000); Write32(OUT, (0x2c24 + j), 0x00000000); } // On r7xx read from HDP_DEBUG1 vs write HDP_REG_COHERENCY_FLUSH_CNTL Read32(OUT, R700_HDP_DEBUG1); // idle the memory controller struct gpu_state gpuState; radeon_gpu_mc_halt(&gpuState); if (radeon_gpu_mc_idlewait() != B_OK) ERROR("%s: Modifying non-idle memory controller!\n", __func__); Write32(OUT, AVIVO_VGA_HDP_CONTROL, AVIVO_VGA_MEMORY_DISABLE); // TODO: Memory Controller AGP Write32(OUT, R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR, gInfo->fb.vramStart >> 12); Write32(OUT, R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, gInfo->fb.vramEnd >> 12); Write32(OUT, R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); uint32 tmp = ((gInfo->fb.vramEnd >> 24) & 0xFFFF) << 16; tmp |= ((gInfo->fb.vramStart >> 24) & 0xFFFF); Write32(OUT, R700_MC_VM_FB_LOCATION, tmp); Write32(OUT, R700_HDP_NONSURFACE_BASE, (gInfo->fb.vramStart >> 8)); Write32(OUT, R700_HDP_NONSURFACE_INFO, (2 << 7)); Write32(OUT, R700_HDP_NONSURFACE_SIZE, 0x3FFFFFFF); // is AGP? // Write32(OUT, R700_MC_VM_AGP_TOP, gInfo->fb.gartEnd >> 22); // Write32(OUT, R700_MC_VM_AGP_BOT, gInfo->fb.gartStart >> 22); // Write32(OUT, R700_MC_VM_AGP_BASE, gInfo->fb.agpBase >> 22); // else? Write32(OUT, R700_MC_VM_AGP_BASE, 0); Write32(OUT, R700_MC_VM_AGP_TOP, 0x0FFFFFFF); Write32(OUT, R700_MC_VM_AGP_BOT, 0x0FFFFFFF); if (radeon_gpu_mc_idlewait() != B_OK) ERROR("%s: Modifying non-idle memory controller!\n", __func__); radeon_gpu_mc_resume(&gpuState); // disable render control Write32(OUT, 0x000300, Read32(OUT, 0x000300) & 0xFFFCFFFF); return B_OK; } static status_t radeon_gpu_mc_setup_evergreen() { // HDP initialization uint32 i; uint32 j; for (i = 0, j = 0; i < 32; i++, j += 0x18) { Write32(OUT, (0x2c14 + j), 0x00000000); Write32(OUT, (0x2c18 + j), 0x00000000); Write32(OUT, (0x2c1c + j), 0x00000000); Write32(OUT, (0x2c20 + j), 0x00000000); Write32(OUT, (0x2c24 + j), 0x00000000); } Write32(OUT, EVERGREEN_HDP_REG_COHERENCY_FLUSH_CNTL, 0); // idle the memory controller struct gpu_state gpuState; radeon_gpu_mc_halt(&gpuState); if (radeon_gpu_mc_idlewait() != B_OK) ERROR("%s: Modifying non-idle memory controller!\n", __func__); Write32(OUT, AVIVO_VGA_HDP_CONTROL, AVIVO_VGA_MEMORY_DISABLE); // TODO: Memory Controller AGP Write32(OUT, EVERGREEN_MC_VM_SYSTEM_APERTURE_LOW_ADDR, gInfo->fb.vramStart >> 12); Write32(OUT, EVERGREEN_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, gInfo->fb.vramEnd >> 12); Write32(OUT, EVERGREEN_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); radeon_shared_info &info = *gInfo->shared_info; if ((info.chipsetFlags & CHIP_IGP) != 0) { // Evergreen IGP Fusion uint32 tmp = Read32(OUT, EVERGREEN_MC_FUS_VM_FB_OFFSET) & 0x000FFFFF; tmp |= ((gInfo->fb.vramEnd >> 20) & 0xF) << 24; tmp |= ((gInfo->fb.vramStart >> 20) & 0xF) << 20; Write32(OUT, EVERGREEN_MC_FUS_VM_FB_OFFSET, tmp); } uint32 tmp = ((gInfo->fb.vramEnd >> 24) & 0xFFFF) << 16; tmp |= ((gInfo->fb.vramStart >> 24) & 0xFFFF); Write32(OUT, EVERGREEN_MC_VM_FB_LOCATION, tmp); Write32(OUT, EVERGREEN_HDP_NONSURFACE_BASE, (gInfo->fb.vramStart >> 8)); Write32(OUT, EVERGREEN_HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30)); Write32(OUT, EVERGREEN_HDP_NONSURFACE_SIZE, 0x3FFFFFFF); // is AGP? // Write32(OUT, EVERGREEN_MC_VM_AGP_TOP, gInfo->fb.gartEnd >> 16); // Write32(OUT, EVERGREEN_MC_VM_AGP_BOT, gInfo->fb.gartStart >> 16); // Write32(OUT, EVERGREEN_MC_VM_AGP_BASE, gInfo->fb.agpBase >> 22); // else? Write32(OUT, EVERGREEN_MC_VM_AGP_BASE, 0); Write32(OUT, EVERGREEN_MC_VM_AGP_TOP, 0x0FFFFFFF); Write32(OUT, EVERGREEN_MC_VM_AGP_BOT, 0x0FFFFFFF); if (radeon_gpu_mc_idlewait() != B_OK) ERROR("%s: Modifying non-idle memory controller!\n", __func__); radeon_gpu_mc_resume(&gpuState); // disable render control Write32(OUT, 0x000300, Read32(OUT, 0x000300) & 0xFFFCFFFF); return B_OK; } void radeon_gpu_mc_init() { radeon_shared_info &info = *gInfo->shared_info; uint32 fbVMLocationReg; if (info.chipsetID >= RADEON_CEDAR) { fbVMLocationReg = EVERGREEN_MC_VM_FB_LOCATION; } else if (info.chipsetID >= RADEON_RV770) { fbVMLocationReg = R700_MC_VM_FB_LOCATION; } else { fbVMLocationReg = R600_MC_VM_FB_LOCATION; } if (gInfo->shared_info->frame_buffer_size > 0) gInfo->fb.valid = true; // This is the card internal location. uint64 vramBase = 0; if ((info.chipsetFlags & CHIP_IGP) != 0) { vramBase = Read32(OUT, fbVMLocationReg) & 0xFFFF; vramBase <<= 24; } gInfo->fb.vramStart = vramBase; gInfo->fb.vramSize = (uint64)gInfo->shared_info->frame_buffer_size * 1024; gInfo->fb.vramEnd = (vramBase + gInfo->fb.vramSize) - 1; } status_t radeon_gpu_mc_setup() { radeon_shared_info &info = *gInfo->shared_info; radeon_gpu_mc_init(); // init video ram ranges for memory controler if (gInfo->fb.valid != true) { ERROR("%s: Memory Controller init failed.\n", __func__); return B_ERROR; } TRACE("%s: vramStart: 0x%" B_PRIX64 ", vramEnd: 0x%" B_PRIX64 "\n", __func__, gInfo->fb.vramStart, gInfo->fb.vramEnd); if (info.chipsetID >= RADEON_CAYMAN) return radeon_gpu_mc_setup_evergreen(); // also for ni else if (info.chipsetID >= RADEON_CEDAR) return radeon_gpu_mc_setup_evergreen(); else if (info.chipsetID >= RADEON_RV770) return radeon_gpu_mc_setup_r700(); else if (info.chipsetID >= RADEON_R600) return radeon_gpu_mc_setup_r600(); return B_ERROR; } status_t radeon_gpu_ring_setup() { TRACE("%s called\n", __func__); // init GFX ring queue gInfo->ringQueue[RADEON_QUEUE_TYPE_GFX_INDEX] = new RingQueue(1024 * 1024, RADEON_QUEUE_TYPE_GFX_INDEX); #if 0 // init IRQ ring queue (reverse of rendering/cp ring queue) gInfo->irqRingQueue = new IRQRingQueue(64 * 1024) #endif return B_OK; } status_t radeon_gpu_ring_boot(uint32 ringType) { TRACE("%s called\n", __func__); RingQueue* ring = gInfo->ringQueue[ringType]; if (ring == NULL) { ERROR("%s: Specified ring doesn't exist!\n", __func__); return B_ERROR; } // We don't execute this code until it's more complete. ERROR("%s: TODO\n", __func__); return B_OK; // TODO: Write initial ring PACKET3 STATE // *** r600_cp_init_ring_buffer // Reset command processor Write32(OUT, GRBM_SOFT_RESET, RADEON_SOFT_RESET_CP); Read32(OUT, GRBM_SOFT_RESET); snooze(15000); Write32(OUT, GRBM_SOFT_RESET, 0); // Set ring buffer size uint32 controlScratch = RB_NO_UPDATE | (compute_order(4096 / 8) << 8) // rptr_update_l2qw | compute_order(ring->GetSize() / 8); // size_l2qw #ifdef __BIG_ENDIAN controlScratch |= BUF_SWAP_32BIT; #endif Write32(OUT, CP_RB_CNTL, controlScratch); // Set delays and timeouts Write32(OUT, CP_SEM_WAIT_TIMER, 0); Write32(OUT, CP_RB_WPTR_DELAY, 0); // Enable RenderBuffer Reads controlScratch |= RB_RPTR_WR_ENA; Write32(OUT, CP_RB_CNTL, controlScratch); // Zero out command processor read and write pointers Write32(OUT, CP_RB_RPTR_WR, 0); Write32(OUT, CP_RB_WPTR, 0); #if 0 int ringPointer = 0; // TODO: AGP cards /* if (RADEON_IS_AGP) { ringPointer = dev_priv->ring_rptr->offset - dev->agp->base + dev_priv->gart_vm_start; } else { */ ringPointer = dev_priv->ring_rptr->offset - ((unsigned long) dev->sg->virtual) + dev_priv->gart_vm_start; Write32(OUT, CP_RB_RPTR_ADDR, (ringPointer & 0xfffffffc)); Write32(OUT, CP_RB_RPTR_ADDR_HI, upper_32_bits(ringPointer)); // Drop RPTR_WR_ENA and update CP RB Control controlScratch &= ~R600_RB_RPTR_WR_ENA; Write32(OUT, CP_RB_CNTL, controlScratch); #endif #if 0 // Update command processor pointer int commandPointer = 0; // TODO: AGP cards /* if (RADEON_IS_AGP) { commandPointer = (dev_priv->cp_ring->offset - dev->agp->base + dev_priv->gart_vm_start); } */ commandPointer = (dev_priv->cp_ring->offset - (unsigned long)dev->sg->virtual + dev_priv->gart_vm_start); #endif #if 0 Write32(OUT, CP_RB_BASE, commandPointer >> 8); Write32(OUT, CP_ME_CNTL, 0xff); Write32(OUT, CP_DEBUG, (1 << 27) | (1 << 28)); #endif #if 0 // Initialize scratch register pointer. // This wil lcause the scratch register values to be wtitten // to memory whenever they are updated. uint64 scratchAddr = Read32(OUT, CP_RB_RPTR_ADDR) & 0xFFFFFFFC; scratchAddr |= ((uint64)Read32(OUT, CP_RB_RPTR_ADDR_HI)) << 32; scratchAddr += R600_SCRATCH_REG_OFFSET; scratchAddr >>= 8; scratchAddr &= 0xffffffff; Write32(OUT, R600_SCRATCH_ADDR, (uint32)scratchAddr); Write32(OUT, R600_SCRATCH_UMSK, 0x7); #endif #if 0 // Enable bus mastering radeon_enable_bm(dev_priv); radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(0), 0); Write32(OUT, R600_LAST_FRAME_REG, 0); radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(1), 0); Write32(OUT, R600_LAST_DISPATCH_REG, 0); radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(2), 0); Write32(OUT, R600_LAST_CLEAR_REG, 0); #endif // Reset sarea? #if 0 master_priv = file_priv->master->driver_priv; if (master_priv->sarea_priv) { master_priv->sarea_priv->last_frame = 0; master_priv->sarea_priv->last_dispatch = 0; master_priv->sarea_priv->last_clear = 0; } r600_do_wait_for_idle(dev_priv); #endif return B_OK; } status_t radeon_gpu_ss_control(pll_info* pll, bool enable) { TRACE("%s called\n", __func__); radeon_shared_info &info = *gInfo->shared_info; uint32 ssControl; if (info.chipsetID >= RADEON_CEDAR) { switch (pll->id) { case ATOM_PPLL1: // PLL1 ssControl = Read32(OUT, EVERGREEN_P1PLL_SS_CNTL); if (enable) ssControl |= EVERGREEN_PxPLL_SS_EN; else ssControl &= ~EVERGREEN_PxPLL_SS_EN; Write32(OUT, EVERGREEN_P1PLL_SS_CNTL, ssControl); break; case ATOM_PPLL2: // PLL2 ssControl = Read32(OUT, EVERGREEN_P2PLL_SS_CNTL); if (enable) ssControl |= EVERGREEN_PxPLL_SS_EN; else ssControl &= ~EVERGREEN_PxPLL_SS_EN; Write32(OUT, EVERGREEN_P2PLL_SS_CNTL, ssControl); break; } // DCPLL, no action return B_OK; } else if (info.chipsetID >= RADEON_RS600) { switch (pll->id) { case ATOM_PPLL1: // PLL1 ssControl = Read32(OUT, AVIVO_P1PLL_INT_SS_CNTL); if (enable) ssControl |= 1; else ssControl &= ~1; Write32(OUT, AVIVO_P1PLL_INT_SS_CNTL, ssControl); break; case ATOM_PPLL2: // PLL2 ssControl = Read32(OUT, AVIVO_P2PLL_INT_SS_CNTL); if (enable) ssControl |= 1; else ssControl &= ~1; Write32(OUT, AVIVO_P2PLL_INT_SS_CNTL, ssControl); break; } // DCPLL, no action return B_OK; } return B_ERROR; }