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: releng/10.3/sys/dev/drm2/radeon/rs690.c 282199 2015-04-28 19:35:05Z dumbbell $"); 31254885Sdumbbell 32254885Sdumbbell#include <dev/drm2/drmP.h> 33254885Sdumbbell#include "radeon.h" 34254885Sdumbbell#include "radeon_asic.h" 35254885Sdumbbell#include "atom.h" 36254885Sdumbbell#include "rs690d.h" 37254885Sdumbbell 38254885Sdumbbellint rs690_mc_wait_for_idle(struct radeon_device *rdev) 39254885Sdumbbell{ 40254885Sdumbbell unsigned i; 41254885Sdumbbell uint32_t tmp; 42254885Sdumbbell 43254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 44254885Sdumbbell /* read MC_STATUS */ 45254885Sdumbbell tmp = RREG32_MC(R_000090_MC_SYSTEM_STATUS); 46254885Sdumbbell if (G_000090_MC_SYSTEM_IDLE(tmp)) 47254885Sdumbbell return 0; 48282199Sdumbbell udelay(1); 49254885Sdumbbell } 50254885Sdumbbell return -1; 51254885Sdumbbell} 52254885Sdumbbell 53254885Sdumbbellstatic void rs690_gpu_init(struct radeon_device *rdev) 54254885Sdumbbell{ 55254885Sdumbbell /* FIXME: is this correct ? */ 56254885Sdumbbell r420_pipes_init(rdev); 57254885Sdumbbell if (rs690_mc_wait_for_idle(rdev)) { 58254885Sdumbbell DRM_ERROR("Failed to wait MC idle while " 59254885Sdumbbell "programming pipes. Bad things might happen.\n"); 60254885Sdumbbell } 61254885Sdumbbell} 62254885Sdumbbell 63254885Sdumbbellunion igp_info { 64254885Sdumbbell struct _ATOM_INTEGRATED_SYSTEM_INFO info; 65254885Sdumbbell struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_v2; 66254885Sdumbbell}; 67254885Sdumbbell 68254885Sdumbbellvoid rs690_pm_info(struct radeon_device *rdev) 69254885Sdumbbell{ 70254885Sdumbbell int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); 71254885Sdumbbell union igp_info *info; 72254885Sdumbbell uint16_t data_offset; 73254885Sdumbbell uint8_t frev, crev; 74254885Sdumbbell fixed20_12 tmp; 75254885Sdumbbell 76254885Sdumbbell if (atom_parse_data_header(rdev->mode_info.atom_context, index, NULL, 77254885Sdumbbell &frev, &crev, &data_offset)) { 78254885Sdumbbell info = (union igp_info *)((uintptr_t)rdev->mode_info.atom_context->bios + data_offset); 79254885Sdumbbell 80254885Sdumbbell /* Get various system informations from bios */ 81254885Sdumbbell switch (crev) { 82254885Sdumbbell case 1: 83254885Sdumbbell tmp.full = dfixed_const(100); 84254885Sdumbbell rdev->pm.igp_sideport_mclk.full = dfixed_const(le32_to_cpu(info->info.ulBootUpMemoryClock)); 85254885Sdumbbell rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp); 86254885Sdumbbell if (le16_to_cpu(info->info.usK8MemoryClock)) 87254885Sdumbbell rdev->pm.igp_system_mclk.full = dfixed_const(le16_to_cpu(info->info.usK8MemoryClock)); 88254885Sdumbbell else if (rdev->clock.default_mclk) { 89254885Sdumbbell rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk); 90254885Sdumbbell rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp); 91254885Sdumbbell } else 92254885Sdumbbell rdev->pm.igp_system_mclk.full = dfixed_const(400); 93254885Sdumbbell rdev->pm.igp_ht_link_clk.full = dfixed_const(le16_to_cpu(info->info.usFSBClock)); 94254885Sdumbbell rdev->pm.igp_ht_link_width.full = dfixed_const(info->info.ucHTLinkWidth); 95254885Sdumbbell break; 96254885Sdumbbell case 2: 97254885Sdumbbell tmp.full = dfixed_const(100); 98254885Sdumbbell rdev->pm.igp_sideport_mclk.full = dfixed_const(le32_to_cpu(info->info_v2.ulBootUpSidePortClock)); 99254885Sdumbbell rdev->pm.igp_sideport_mclk.full = dfixed_div(rdev->pm.igp_sideport_mclk, tmp); 100254885Sdumbbell if (le32_to_cpu(info->info_v2.ulBootUpUMAClock)) 101254885Sdumbbell rdev->pm.igp_system_mclk.full = dfixed_const(le32_to_cpu(info->info_v2.ulBootUpUMAClock)); 102254885Sdumbbell else if (rdev->clock.default_mclk) 103254885Sdumbbell rdev->pm.igp_system_mclk.full = dfixed_const(rdev->clock.default_mclk); 104254885Sdumbbell else 105254885Sdumbbell rdev->pm.igp_system_mclk.full = dfixed_const(66700); 106254885Sdumbbell rdev->pm.igp_system_mclk.full = dfixed_div(rdev->pm.igp_system_mclk, tmp); 107254885Sdumbbell rdev->pm.igp_ht_link_clk.full = dfixed_const(le32_to_cpu(info->info_v2.ulHTLinkFreq)); 108254885Sdumbbell rdev->pm.igp_ht_link_clk.full = dfixed_div(rdev->pm.igp_ht_link_clk, tmp); 109254885Sdumbbell rdev->pm.igp_ht_link_width.full = dfixed_const(le16_to_cpu(info->info_v2.usMinHTLinkWidth)); 110254885Sdumbbell break; 111254885Sdumbbell default: 112254885Sdumbbell /* We assume the slower possible clock ie worst case */ 113254885Sdumbbell rdev->pm.igp_sideport_mclk.full = dfixed_const(200); 114254885Sdumbbell rdev->pm.igp_system_mclk.full = dfixed_const(200); 115254885Sdumbbell rdev->pm.igp_ht_link_clk.full = dfixed_const(1000); 116254885Sdumbbell rdev->pm.igp_ht_link_width.full = dfixed_const(8); 117254885Sdumbbell DRM_ERROR("No integrated system info for your GPU, using safe default\n"); 118254885Sdumbbell break; 119254885Sdumbbell } 120254885Sdumbbell } else { 121254885Sdumbbell /* We assume the slower possible clock ie worst case */ 122254885Sdumbbell rdev->pm.igp_sideport_mclk.full = dfixed_const(200); 123254885Sdumbbell rdev->pm.igp_system_mclk.full = dfixed_const(200); 124254885Sdumbbell rdev->pm.igp_ht_link_clk.full = dfixed_const(1000); 125254885Sdumbbell rdev->pm.igp_ht_link_width.full = dfixed_const(8); 126254885Sdumbbell DRM_ERROR("No integrated system info for your GPU, using safe default\n"); 127254885Sdumbbell } 128254885Sdumbbell /* Compute various bandwidth */ 129254885Sdumbbell /* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4 */ 130254885Sdumbbell tmp.full = dfixed_const(4); 131254885Sdumbbell rdev->pm.k8_bandwidth.full = dfixed_mul(rdev->pm.igp_system_mclk, tmp); 132254885Sdumbbell /* ht_bandwidth = ht_clk * 2 * ht_width / 8 * 0.8 133254885Sdumbbell * = ht_clk * ht_width / 5 134254885Sdumbbell */ 135254885Sdumbbell tmp.full = dfixed_const(5); 136254885Sdumbbell rdev->pm.ht_bandwidth.full = dfixed_mul(rdev->pm.igp_ht_link_clk, 137254885Sdumbbell rdev->pm.igp_ht_link_width); 138254885Sdumbbell rdev->pm.ht_bandwidth.full = dfixed_div(rdev->pm.ht_bandwidth, tmp); 139254885Sdumbbell if (tmp.full < rdev->pm.max_bandwidth.full) { 140254885Sdumbbell /* HT link is a limiting factor */ 141254885Sdumbbell rdev->pm.max_bandwidth.full = tmp.full; 142254885Sdumbbell } 143254885Sdumbbell /* sideport_bandwidth = (sideport_clk / 2) * 2 * 2 * 0.7 144254885Sdumbbell * = (sideport_clk * 14) / 10 145254885Sdumbbell */ 146254885Sdumbbell tmp.full = dfixed_const(14); 147254885Sdumbbell rdev->pm.sideport_bandwidth.full = dfixed_mul(rdev->pm.igp_sideport_mclk, tmp); 148254885Sdumbbell tmp.full = dfixed_const(10); 149254885Sdumbbell rdev->pm.sideport_bandwidth.full = dfixed_div(rdev->pm.sideport_bandwidth, tmp); 150254885Sdumbbell} 151254885Sdumbbell 152254885Sdumbbellstatic void rs690_mc_init(struct radeon_device *rdev) 153254885Sdumbbell{ 154254885Sdumbbell u64 base; 155254885Sdumbbell 156254885Sdumbbell rs400_gart_adjust_size(rdev); 157254885Sdumbbell rdev->mc.vram_is_ddr = true; 158254885Sdumbbell rdev->mc.vram_width = 128; 159254885Sdumbbell rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); 160254885Sdumbbell rdev->mc.mc_vram_size = rdev->mc.real_vram_size; 161254885Sdumbbell rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); 162254885Sdumbbell rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); 163254885Sdumbbell rdev->mc.visible_vram_size = rdev->mc.aper_size; 164254885Sdumbbell base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); 165254885Sdumbbell base = G_000100_MC_FB_START(base) << 16; 166254885Sdumbbell rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); 167254885Sdumbbell rs690_pm_info(rdev); 168254885Sdumbbell radeon_vram_location(rdev, &rdev->mc, base); 169254885Sdumbbell rdev->mc.gtt_base_align = rdev->mc.gtt_size - 1; 170254885Sdumbbell radeon_gtt_location(rdev, &rdev->mc); 171254885Sdumbbell radeon_update_bandwidth_info(rdev); 172254885Sdumbbell} 173254885Sdumbbell 174254885Sdumbbellvoid rs690_line_buffer_adjust(struct radeon_device *rdev, 175254885Sdumbbell struct drm_display_mode *mode1, 176254885Sdumbbell struct drm_display_mode *mode2) 177254885Sdumbbell{ 178254885Sdumbbell u32 tmp; 179254885Sdumbbell 180254885Sdumbbell /* 181254885Sdumbbell * Line Buffer Setup 182254885Sdumbbell * There is a single line buffer shared by both display controllers. 183254885Sdumbbell * R_006520_DC_LB_MEMORY_SPLIT controls how that line buffer is shared between 184254885Sdumbbell * the display controllers. The paritioning can either be done 185254885Sdumbbell * manually or via one of four preset allocations specified in bits 1:0: 186254885Sdumbbell * 0 - line buffer is divided in half and shared between crtc 187254885Sdumbbell * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4 188254885Sdumbbell * 2 - D1 gets the whole buffer 189254885Sdumbbell * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4 190254885Sdumbbell * Setting bit 2 of R_006520_DC_LB_MEMORY_SPLIT controls switches to manual 191254885Sdumbbell * allocation mode. In manual allocation mode, D1 always starts at 0, 192254885Sdumbbell * D1 end/2 is specified in bits 14:4; D2 allocation follows D1. 193254885Sdumbbell */ 194254885Sdumbbell tmp = RREG32(R_006520_DC_LB_MEMORY_SPLIT) & C_006520_DC_LB_MEMORY_SPLIT; 195254885Sdumbbell tmp &= ~C_006520_DC_LB_MEMORY_SPLIT_MODE; 196254885Sdumbbell /* auto */ 197254885Sdumbbell if (mode1 && mode2) { 198254885Sdumbbell if (mode1->hdisplay > mode2->hdisplay) { 199254885Sdumbbell if (mode1->hdisplay > 2560) 200254885Sdumbbell tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q; 201254885Sdumbbell else 202254885Sdumbbell tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; 203254885Sdumbbell } else if (mode2->hdisplay > mode1->hdisplay) { 204254885Sdumbbell if (mode2->hdisplay > 2560) 205254885Sdumbbell tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; 206254885Sdumbbell else 207254885Sdumbbell tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; 208254885Sdumbbell } else 209254885Sdumbbell tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; 210254885Sdumbbell } else if (mode1) { 211254885Sdumbbell tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_ONLY; 212254885Sdumbbell } else if (mode2) { 213254885Sdumbbell tmp |= V_006520_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; 214254885Sdumbbell } 215254885Sdumbbell WREG32(R_006520_DC_LB_MEMORY_SPLIT, tmp); 216254885Sdumbbell} 217254885Sdumbbell 218254885Sdumbbellstruct rs690_watermark { 219254885Sdumbbell u32 lb_request_fifo_depth; 220254885Sdumbbell fixed20_12 num_line_pair; 221254885Sdumbbell fixed20_12 estimated_width; 222254885Sdumbbell fixed20_12 worst_case_latency; 223254885Sdumbbell fixed20_12 consumption_rate; 224254885Sdumbbell fixed20_12 active_time; 225254885Sdumbbell fixed20_12 dbpp; 226254885Sdumbbell fixed20_12 priority_mark_max; 227254885Sdumbbell fixed20_12 priority_mark; 228254885Sdumbbell fixed20_12 sclk; 229254885Sdumbbell}; 230254885Sdumbbell 231254885Sdumbbellstatic void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, 232254885Sdumbbell struct radeon_crtc *crtc, 233254885Sdumbbell struct rs690_watermark *wm) 234254885Sdumbbell{ 235254885Sdumbbell struct drm_display_mode *mode = &crtc->base.mode; 236254885Sdumbbell fixed20_12 a, b, c; 237254885Sdumbbell fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; 238254885Sdumbbell fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; 239254885Sdumbbell 240254885Sdumbbell if (!crtc->base.enabled) { 241254885Sdumbbell /* FIXME: wouldn't it better to set priority mark to maximum */ 242254885Sdumbbell wm->lb_request_fifo_depth = 4; 243254885Sdumbbell return; 244254885Sdumbbell } 245254885Sdumbbell 246254885Sdumbbell if (crtc->vsc.full > dfixed_const(2)) 247254885Sdumbbell wm->num_line_pair.full = dfixed_const(2); 248254885Sdumbbell else 249254885Sdumbbell wm->num_line_pair.full = dfixed_const(1); 250254885Sdumbbell 251254885Sdumbbell b.full = dfixed_const(mode->crtc_hdisplay); 252254885Sdumbbell c.full = dfixed_const(256); 253254885Sdumbbell a.full = dfixed_div(b, c); 254254885Sdumbbell request_fifo_depth.full = dfixed_mul(a, wm->num_line_pair); 255254885Sdumbbell request_fifo_depth.full = dfixed_ceil(request_fifo_depth); 256254885Sdumbbell if (a.full < dfixed_const(4)) { 257254885Sdumbbell wm->lb_request_fifo_depth = 4; 258254885Sdumbbell } else { 259254885Sdumbbell wm->lb_request_fifo_depth = dfixed_trunc(request_fifo_depth); 260254885Sdumbbell } 261254885Sdumbbell 262254885Sdumbbell /* Determine consumption rate 263254885Sdumbbell * pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000) 264254885Sdumbbell * vtaps = number of vertical taps, 265254885Sdumbbell * vsc = vertical scaling ratio, defined as source/destination 266254885Sdumbbell * hsc = horizontal scaling ration, defined as source/destination 267254885Sdumbbell */ 268254885Sdumbbell a.full = dfixed_const(mode->clock); 269254885Sdumbbell b.full = dfixed_const(1000); 270254885Sdumbbell a.full = dfixed_div(a, b); 271254885Sdumbbell pclk.full = dfixed_div(b, a); 272254885Sdumbbell if (crtc->rmx_type != RMX_OFF) { 273254885Sdumbbell b.full = dfixed_const(2); 274254885Sdumbbell if (crtc->vsc.full > b.full) 275254885Sdumbbell b.full = crtc->vsc.full; 276254885Sdumbbell b.full = dfixed_mul(b, crtc->hsc); 277254885Sdumbbell c.full = dfixed_const(2); 278254885Sdumbbell b.full = dfixed_div(b, c); 279254885Sdumbbell consumption_time.full = dfixed_div(pclk, b); 280254885Sdumbbell } else { 281254885Sdumbbell consumption_time.full = pclk.full; 282254885Sdumbbell } 283254885Sdumbbell a.full = dfixed_const(1); 284254885Sdumbbell wm->consumption_rate.full = dfixed_div(a, consumption_time); 285254885Sdumbbell 286254885Sdumbbell 287254885Sdumbbell /* Determine line time 288254885Sdumbbell * LineTime = total time for one line of displayhtotal 289254885Sdumbbell * LineTime = total number of horizontal pixels 290254885Sdumbbell * pclk = pixel clock period(ns) 291254885Sdumbbell */ 292254885Sdumbbell a.full = dfixed_const(crtc->base.mode.crtc_htotal); 293254885Sdumbbell line_time.full = dfixed_mul(a, pclk); 294254885Sdumbbell 295254885Sdumbbell /* Determine active time 296254885Sdumbbell * ActiveTime = time of active region of display within one line, 297254885Sdumbbell * hactive = total number of horizontal active pixels 298254885Sdumbbell * htotal = total number of horizontal pixels 299254885Sdumbbell */ 300254885Sdumbbell a.full = dfixed_const(crtc->base.mode.crtc_htotal); 301254885Sdumbbell b.full = dfixed_const(crtc->base.mode.crtc_hdisplay); 302254885Sdumbbell wm->active_time.full = dfixed_mul(line_time, b); 303254885Sdumbbell wm->active_time.full = dfixed_div(wm->active_time, a); 304254885Sdumbbell 305254885Sdumbbell /* Maximun bandwidth is the minimun bandwidth of all component */ 306254885Sdumbbell rdev->pm.max_bandwidth = rdev->pm.core_bandwidth; 307254885Sdumbbell if (rdev->mc.igp_sideport_enabled) { 308254885Sdumbbell if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full && 309254885Sdumbbell rdev->pm.sideport_bandwidth.full) 310254885Sdumbbell rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth; 311269790Ssbruno read_delay_latency.full = dfixed_const(370 * 800); 312269790Ssbruno a.full = dfixed_const(1000); 313269790Ssbruno b.full = dfixed_div(rdev->pm.igp_sideport_mclk, a); 314269790Ssbruno read_delay_latency.full = dfixed_div(read_delay_latency, b); 315269790Ssbruno read_delay_latency.full = dfixed_mul(read_delay_latency, a); 316254885Sdumbbell } else { 317254885Sdumbbell if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full && 318254885Sdumbbell rdev->pm.k8_bandwidth.full) 319254885Sdumbbell rdev->pm.max_bandwidth = rdev->pm.k8_bandwidth; 320254885Sdumbbell if (rdev->pm.max_bandwidth.full > rdev->pm.ht_bandwidth.full && 321254885Sdumbbell rdev->pm.ht_bandwidth.full) 322254885Sdumbbell rdev->pm.max_bandwidth = rdev->pm.ht_bandwidth; 323254885Sdumbbell read_delay_latency.full = dfixed_const(5000); 324254885Sdumbbell } 325254885Sdumbbell 326254885Sdumbbell /* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */ 327254885Sdumbbell a.full = dfixed_const(16); 328254885Sdumbbell rdev->pm.sclk.full = dfixed_mul(rdev->pm.max_bandwidth, a); 329254885Sdumbbell a.full = dfixed_const(1000); 330254885Sdumbbell rdev->pm.sclk.full = dfixed_div(a, rdev->pm.sclk); 331254885Sdumbbell /* Determine chunk time 332254885Sdumbbell * ChunkTime = the time it takes the DCP to send one chunk of data 333254885Sdumbbell * to the LB which consists of pipeline delay and inter chunk gap 334254885Sdumbbell * sclk = system clock(ns) 335254885Sdumbbell */ 336254885Sdumbbell a.full = dfixed_const(256 * 13); 337254885Sdumbbell chunk_time.full = dfixed_mul(rdev->pm.sclk, a); 338254885Sdumbbell a.full = dfixed_const(10); 339254885Sdumbbell chunk_time.full = dfixed_div(chunk_time, a); 340254885Sdumbbell 341254885Sdumbbell /* Determine the worst case latency 342254885Sdumbbell * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines) 343254885Sdumbbell * WorstCaseLatency = worst case time from urgent to when the MC starts 344254885Sdumbbell * to return data 345254885Sdumbbell * READ_DELAY_IDLE_MAX = constant of 1us 346254885Sdumbbell * ChunkTime = time it takes the DCP to send one chunk of data to the LB 347254885Sdumbbell * which consists of pipeline delay and inter chunk gap 348254885Sdumbbell */ 349254885Sdumbbell if (dfixed_trunc(wm->num_line_pair) > 1) { 350254885Sdumbbell a.full = dfixed_const(3); 351254885Sdumbbell wm->worst_case_latency.full = dfixed_mul(a, chunk_time); 352254885Sdumbbell wm->worst_case_latency.full += read_delay_latency.full; 353254885Sdumbbell } else { 354254885Sdumbbell a.full = dfixed_const(2); 355254885Sdumbbell wm->worst_case_latency.full = dfixed_mul(a, chunk_time); 356254885Sdumbbell wm->worst_case_latency.full += read_delay_latency.full; 357254885Sdumbbell } 358254885Sdumbbell 359254885Sdumbbell /* Determine the tolerable latency 360254885Sdumbbell * TolerableLatency = Any given request has only 1 line time 361254885Sdumbbell * for the data to be returned 362254885Sdumbbell * LBRequestFifoDepth = Number of chunk requests the LB can 363254885Sdumbbell * put into the request FIFO for a display 364254885Sdumbbell * LineTime = total time for one line of display 365254885Sdumbbell * ChunkTime = the time it takes the DCP to send one chunk 366254885Sdumbbell * of data to the LB which consists of 367254885Sdumbbell * pipeline delay and inter chunk gap 368254885Sdumbbell */ 369254885Sdumbbell if ((2+wm->lb_request_fifo_depth) >= dfixed_trunc(request_fifo_depth)) { 370254885Sdumbbell tolerable_latency.full = line_time.full; 371254885Sdumbbell } else { 372254885Sdumbbell tolerable_latency.full = dfixed_const(wm->lb_request_fifo_depth - 2); 373254885Sdumbbell tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full; 374254885Sdumbbell tolerable_latency.full = dfixed_mul(tolerable_latency, chunk_time); 375254885Sdumbbell tolerable_latency.full = line_time.full - tolerable_latency.full; 376254885Sdumbbell } 377254885Sdumbbell /* We assume worst case 32bits (4 bytes) */ 378254885Sdumbbell wm->dbpp.full = dfixed_const(4 * 8); 379254885Sdumbbell 380254885Sdumbbell /* Determine the maximum priority mark 381254885Sdumbbell * width = viewport width in pixels 382254885Sdumbbell */ 383254885Sdumbbell a.full = dfixed_const(16); 384254885Sdumbbell wm->priority_mark_max.full = dfixed_const(crtc->base.mode.crtc_hdisplay); 385254885Sdumbbell wm->priority_mark_max.full = dfixed_div(wm->priority_mark_max, a); 386254885Sdumbbell wm->priority_mark_max.full = dfixed_ceil(wm->priority_mark_max); 387254885Sdumbbell 388254885Sdumbbell /* Determine estimated width */ 389254885Sdumbbell estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; 390254885Sdumbbell estimated_width.full = dfixed_div(estimated_width, consumption_time); 391254885Sdumbbell if (dfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { 392254885Sdumbbell wm->priority_mark.full = dfixed_const(10); 393254885Sdumbbell } else { 394254885Sdumbbell a.full = dfixed_const(16); 395254885Sdumbbell wm->priority_mark.full = dfixed_div(estimated_width, a); 396254885Sdumbbell wm->priority_mark.full = dfixed_ceil(wm->priority_mark); 397254885Sdumbbell wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; 398254885Sdumbbell } 399254885Sdumbbell} 400254885Sdumbbell 401254885Sdumbbellvoid rs690_bandwidth_update(struct radeon_device *rdev) 402254885Sdumbbell{ 403254885Sdumbbell struct drm_display_mode *mode0 = NULL; 404254885Sdumbbell struct drm_display_mode *mode1 = NULL; 405254885Sdumbbell struct rs690_watermark wm0; 406254885Sdumbbell struct rs690_watermark wm1; 407254885Sdumbbell u32 tmp; 408254885Sdumbbell u32 d1mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1); 409254885Sdumbbell u32 d2mode_priority_a_cnt = S_006548_D1MODE_PRIORITY_A_OFF(1); 410254885Sdumbbell fixed20_12 priority_mark02, priority_mark12, fill_rate; 411254885Sdumbbell fixed20_12 a, b; 412254885Sdumbbell 413254885Sdumbbell radeon_update_display_priority(rdev); 414254885Sdumbbell 415254885Sdumbbell if (rdev->mode_info.crtcs[0]->base.enabled) 416254885Sdumbbell mode0 = &rdev->mode_info.crtcs[0]->base.mode; 417254885Sdumbbell if (rdev->mode_info.crtcs[1]->base.enabled) 418254885Sdumbbell mode1 = &rdev->mode_info.crtcs[1]->base.mode; 419254885Sdumbbell /* 420254885Sdumbbell * Set display0/1 priority up in the memory controller for 421254885Sdumbbell * modes if the user specifies HIGH for displaypriority 422254885Sdumbbell * option. 423254885Sdumbbell */ 424254885Sdumbbell if ((rdev->disp_priority == 2) && 425254885Sdumbbell ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740))) { 426254885Sdumbbell tmp = RREG32_MC(R_000104_MC_INIT_MISC_LAT_TIMER); 427254885Sdumbbell tmp &= C_000104_MC_DISP0R_INIT_LAT; 428254885Sdumbbell tmp &= C_000104_MC_DISP1R_INIT_LAT; 429254885Sdumbbell if (mode0) 430254885Sdumbbell tmp |= S_000104_MC_DISP0R_INIT_LAT(1); 431254885Sdumbbell if (mode1) 432254885Sdumbbell tmp |= S_000104_MC_DISP1R_INIT_LAT(1); 433254885Sdumbbell WREG32_MC(R_000104_MC_INIT_MISC_LAT_TIMER, tmp); 434254885Sdumbbell } 435254885Sdumbbell rs690_line_buffer_adjust(rdev, mode0, mode1); 436254885Sdumbbell 437254885Sdumbbell if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) 438254885Sdumbbell WREG32(R_006C9C_DCP_CONTROL, 0); 439254885Sdumbbell if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880)) 440254885Sdumbbell WREG32(R_006C9C_DCP_CONTROL, 2); 441254885Sdumbbell 442254885Sdumbbell rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0); 443254885Sdumbbell rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1); 444254885Sdumbbell 445254885Sdumbbell tmp = (wm0.lb_request_fifo_depth - 1); 446254885Sdumbbell tmp |= (wm1.lb_request_fifo_depth - 1) << 16; 447254885Sdumbbell WREG32(R_006D58_LB_MAX_REQ_OUTSTANDING, tmp); 448254885Sdumbbell 449254885Sdumbbell if (mode0 && mode1) { 450254885Sdumbbell if (dfixed_trunc(wm0.dbpp) > 64) 451254885Sdumbbell a.full = dfixed_mul(wm0.dbpp, wm0.num_line_pair); 452254885Sdumbbell else 453254885Sdumbbell a.full = wm0.num_line_pair.full; 454254885Sdumbbell if (dfixed_trunc(wm1.dbpp) > 64) 455254885Sdumbbell b.full = dfixed_mul(wm1.dbpp, wm1.num_line_pair); 456254885Sdumbbell else 457254885Sdumbbell b.full = wm1.num_line_pair.full; 458254885Sdumbbell a.full += b.full; 459254885Sdumbbell fill_rate.full = dfixed_div(wm0.sclk, a); 460254885Sdumbbell if (wm0.consumption_rate.full > fill_rate.full) { 461254885Sdumbbell b.full = wm0.consumption_rate.full - fill_rate.full; 462254885Sdumbbell b.full = dfixed_mul(b, wm0.active_time); 463254885Sdumbbell a.full = dfixed_mul(wm0.worst_case_latency, 464254885Sdumbbell wm0.consumption_rate); 465254885Sdumbbell a.full = a.full + b.full; 466254885Sdumbbell b.full = dfixed_const(16 * 1000); 467254885Sdumbbell priority_mark02.full = dfixed_div(a, b); 468254885Sdumbbell } else { 469254885Sdumbbell a.full = dfixed_mul(wm0.worst_case_latency, 470254885Sdumbbell wm0.consumption_rate); 471254885Sdumbbell b.full = dfixed_const(16 * 1000); 472254885Sdumbbell priority_mark02.full = dfixed_div(a, b); 473254885Sdumbbell } 474254885Sdumbbell if (wm1.consumption_rate.full > fill_rate.full) { 475254885Sdumbbell b.full = wm1.consumption_rate.full - fill_rate.full; 476254885Sdumbbell b.full = dfixed_mul(b, wm1.active_time); 477254885Sdumbbell a.full = dfixed_mul(wm1.worst_case_latency, 478254885Sdumbbell wm1.consumption_rate); 479254885Sdumbbell a.full = a.full + b.full; 480254885Sdumbbell b.full = dfixed_const(16 * 1000); 481254885Sdumbbell priority_mark12.full = dfixed_div(a, b); 482254885Sdumbbell } else { 483254885Sdumbbell a.full = dfixed_mul(wm1.worst_case_latency, 484254885Sdumbbell wm1.consumption_rate); 485254885Sdumbbell b.full = dfixed_const(16 * 1000); 486254885Sdumbbell priority_mark12.full = dfixed_div(a, b); 487254885Sdumbbell } 488254885Sdumbbell if (wm0.priority_mark.full > priority_mark02.full) 489254885Sdumbbell priority_mark02.full = wm0.priority_mark.full; 490254885Sdumbbell if (wm0.priority_mark_max.full > priority_mark02.full) 491254885Sdumbbell priority_mark02.full = wm0.priority_mark_max.full; 492254885Sdumbbell if (wm1.priority_mark.full > priority_mark12.full) 493254885Sdumbbell priority_mark12.full = wm1.priority_mark.full; 494254885Sdumbbell if (wm1.priority_mark_max.full > priority_mark12.full) 495254885Sdumbbell priority_mark12.full = wm1.priority_mark_max.full; 496254885Sdumbbell d1mode_priority_a_cnt = dfixed_trunc(priority_mark02); 497254885Sdumbbell d2mode_priority_a_cnt = dfixed_trunc(priority_mark12); 498254885Sdumbbell if (rdev->disp_priority == 2) { 499254885Sdumbbell d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1); 500254885Sdumbbell d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1); 501254885Sdumbbell } 502254885Sdumbbell } else if (mode0) { 503254885Sdumbbell if (dfixed_trunc(wm0.dbpp) > 64) 504254885Sdumbbell a.full = dfixed_mul(wm0.dbpp, wm0.num_line_pair); 505254885Sdumbbell else 506254885Sdumbbell a.full = wm0.num_line_pair.full; 507254885Sdumbbell fill_rate.full = dfixed_div(wm0.sclk, a); 508254885Sdumbbell if (wm0.consumption_rate.full > fill_rate.full) { 509254885Sdumbbell b.full = wm0.consumption_rate.full - fill_rate.full; 510254885Sdumbbell b.full = dfixed_mul(b, wm0.active_time); 511254885Sdumbbell a.full = dfixed_mul(wm0.worst_case_latency, 512254885Sdumbbell wm0.consumption_rate); 513254885Sdumbbell a.full = a.full + b.full; 514254885Sdumbbell b.full = dfixed_const(16 * 1000); 515254885Sdumbbell priority_mark02.full = dfixed_div(a, b); 516254885Sdumbbell } else { 517254885Sdumbbell a.full = dfixed_mul(wm0.worst_case_latency, 518254885Sdumbbell wm0.consumption_rate); 519254885Sdumbbell b.full = dfixed_const(16 * 1000); 520254885Sdumbbell priority_mark02.full = dfixed_div(a, b); 521254885Sdumbbell } 522254885Sdumbbell if (wm0.priority_mark.full > priority_mark02.full) 523254885Sdumbbell priority_mark02.full = wm0.priority_mark.full; 524254885Sdumbbell if (wm0.priority_mark_max.full > priority_mark02.full) 525254885Sdumbbell priority_mark02.full = wm0.priority_mark_max.full; 526254885Sdumbbell d1mode_priority_a_cnt = dfixed_trunc(priority_mark02); 527254885Sdumbbell if (rdev->disp_priority == 2) 528254885Sdumbbell d1mode_priority_a_cnt |= S_006548_D1MODE_PRIORITY_A_ALWAYS_ON(1); 529254885Sdumbbell } else if (mode1) { 530254885Sdumbbell if (dfixed_trunc(wm1.dbpp) > 64) 531254885Sdumbbell a.full = dfixed_mul(wm1.dbpp, wm1.num_line_pair); 532254885Sdumbbell else 533254885Sdumbbell a.full = wm1.num_line_pair.full; 534254885Sdumbbell fill_rate.full = dfixed_div(wm1.sclk, a); 535254885Sdumbbell if (wm1.consumption_rate.full > fill_rate.full) { 536254885Sdumbbell b.full = wm1.consumption_rate.full - fill_rate.full; 537254885Sdumbbell b.full = dfixed_mul(b, wm1.active_time); 538254885Sdumbbell a.full = dfixed_mul(wm1.worst_case_latency, 539254885Sdumbbell wm1.consumption_rate); 540254885Sdumbbell a.full = a.full + b.full; 541254885Sdumbbell b.full = dfixed_const(16 * 1000); 542254885Sdumbbell priority_mark12.full = dfixed_div(a, b); 543254885Sdumbbell } else { 544254885Sdumbbell a.full = dfixed_mul(wm1.worst_case_latency, 545254885Sdumbbell wm1.consumption_rate); 546254885Sdumbbell b.full = dfixed_const(16 * 1000); 547254885Sdumbbell priority_mark12.full = dfixed_div(a, b); 548254885Sdumbbell } 549254885Sdumbbell if (wm1.priority_mark.full > priority_mark12.full) 550254885Sdumbbell priority_mark12.full = wm1.priority_mark.full; 551254885Sdumbbell if (wm1.priority_mark_max.full > priority_mark12.full) 552254885Sdumbbell priority_mark12.full = wm1.priority_mark_max.full; 553254885Sdumbbell d2mode_priority_a_cnt = dfixed_trunc(priority_mark12); 554254885Sdumbbell if (rdev->disp_priority == 2) 555254885Sdumbbell d2mode_priority_a_cnt |= S_006D48_D2MODE_PRIORITY_A_ALWAYS_ON(1); 556254885Sdumbbell } 557254885Sdumbbell 558254885Sdumbbell WREG32(R_006548_D1MODE_PRIORITY_A_CNT, d1mode_priority_a_cnt); 559254885Sdumbbell WREG32(R_00654C_D1MODE_PRIORITY_B_CNT, d1mode_priority_a_cnt); 560254885Sdumbbell WREG32(R_006D48_D2MODE_PRIORITY_A_CNT, d2mode_priority_a_cnt); 561254885Sdumbbell WREG32(R_006D4C_D2MODE_PRIORITY_B_CNT, d2mode_priority_a_cnt); 562254885Sdumbbell} 563254885Sdumbbell 564254885Sdumbbelluint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg) 565254885Sdumbbell{ 566254885Sdumbbell uint32_t r; 567254885Sdumbbell 568254885Sdumbbell WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg)); 569254885Sdumbbell r = RREG32(R_00007C_MC_DATA); 570254885Sdumbbell WREG32(R_000078_MC_INDEX, ~C_000078_MC_IND_ADDR); 571254885Sdumbbell return r; 572254885Sdumbbell} 573254885Sdumbbell 574254885Sdumbbellvoid rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 575254885Sdumbbell{ 576254885Sdumbbell WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg) | 577254885Sdumbbell S_000078_MC_IND_WR_EN(1)); 578254885Sdumbbell WREG32(R_00007C_MC_DATA, v); 579254885Sdumbbell WREG32(R_000078_MC_INDEX, 0x7F); 580254885Sdumbbell} 581254885Sdumbbell 582254885Sdumbbellstatic void rs690_mc_program(struct radeon_device *rdev) 583254885Sdumbbell{ 584254885Sdumbbell struct rv515_mc_save save; 585254885Sdumbbell 586254885Sdumbbell /* Stops all mc clients */ 587254885Sdumbbell rv515_mc_stop(rdev, &save); 588254885Sdumbbell 589254885Sdumbbell /* Wait for mc idle */ 590254885Sdumbbell if (rs690_mc_wait_for_idle(rdev)) 591254885Sdumbbell dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); 592254885Sdumbbell /* Program MC, should be a 32bits limited address space */ 593254885Sdumbbell WREG32_MC(R_000100_MCCFG_FB_LOCATION, 594254885Sdumbbell S_000100_MC_FB_START(rdev->mc.vram_start >> 16) | 595254885Sdumbbell S_000100_MC_FB_TOP(rdev->mc.vram_end >> 16)); 596254885Sdumbbell WREG32(R_000134_HDP_FB_LOCATION, 597254885Sdumbbell S_000134_HDP_FB_START(rdev->mc.vram_start >> 16)); 598254885Sdumbbell 599254885Sdumbbell rv515_mc_resume(rdev, &save); 600254885Sdumbbell} 601254885Sdumbbell 602254885Sdumbbellstatic int rs690_startup(struct radeon_device *rdev) 603254885Sdumbbell{ 604254885Sdumbbell int r; 605254885Sdumbbell 606254885Sdumbbell rs690_mc_program(rdev); 607254885Sdumbbell /* Resume clock */ 608254885Sdumbbell rv515_clock_startup(rdev); 609254885Sdumbbell /* Initialize GPU configuration (# pipes, ...) */ 610254885Sdumbbell rs690_gpu_init(rdev); 611254885Sdumbbell /* Initialize GART (initialize after TTM so we can allocate 612254885Sdumbbell * memory through TTM but finalize after TTM) */ 613254885Sdumbbell r = rs400_gart_enable(rdev); 614254885Sdumbbell if (r) 615254885Sdumbbell return r; 616254885Sdumbbell 617254885Sdumbbell /* allocate wb buffer */ 618254885Sdumbbell r = radeon_wb_init(rdev); 619254885Sdumbbell if (r) 620254885Sdumbbell return r; 621254885Sdumbbell 622254885Sdumbbell r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); 623254885Sdumbbell if (r) { 624254885Sdumbbell dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 625254885Sdumbbell return r; 626254885Sdumbbell } 627254885Sdumbbell 628254885Sdumbbell /* Enable IRQ */ 629254885Sdumbbell rs600_irq_set(rdev); 630254885Sdumbbell rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); 631254885Sdumbbell /* 1M ring buffer */ 632254885Sdumbbell r = r100_cp_init(rdev, 1024 * 1024); 633254885Sdumbbell if (r) { 634254885Sdumbbell dev_err(rdev->dev, "failed initializing CP (%d).\n", r); 635254885Sdumbbell return r; 636254885Sdumbbell } 637254885Sdumbbell 638254885Sdumbbell r = radeon_ib_pool_init(rdev); 639254885Sdumbbell if (r) { 640254885Sdumbbell dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 641254885Sdumbbell return r; 642254885Sdumbbell } 643254885Sdumbbell 644254885Sdumbbell r = r600_audio_init(rdev); 645254885Sdumbbell if (r) { 646254885Sdumbbell dev_err(rdev->dev, "failed initializing audio\n"); 647254885Sdumbbell return r; 648254885Sdumbbell } 649254885Sdumbbell 650254885Sdumbbell return 0; 651254885Sdumbbell} 652254885Sdumbbell 653254885Sdumbbellint rs690_resume(struct radeon_device *rdev) 654254885Sdumbbell{ 655254885Sdumbbell int r; 656254885Sdumbbell 657254885Sdumbbell /* Make sur GART are not working */ 658254885Sdumbbell rs400_gart_disable(rdev); 659254885Sdumbbell /* Resume clock before doing reset */ 660254885Sdumbbell rv515_clock_startup(rdev); 661254885Sdumbbell /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 662254885Sdumbbell if (radeon_asic_reset(rdev)) { 663254885Sdumbbell dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 664254885Sdumbbell RREG32(R_000E40_RBBM_STATUS), 665254885Sdumbbell RREG32(R_0007C0_CP_STAT)); 666254885Sdumbbell } 667254885Sdumbbell /* post */ 668254885Sdumbbell atom_asic_init(rdev->mode_info.atom_context); 669254885Sdumbbell /* Resume clock after posting */ 670254885Sdumbbell rv515_clock_startup(rdev); 671254885Sdumbbell /* Initialize surface registers */ 672254885Sdumbbell radeon_surface_init(rdev); 673254885Sdumbbell 674254885Sdumbbell rdev->accel_working = true; 675254885Sdumbbell r = rs690_startup(rdev); 676254885Sdumbbell if (r) { 677254885Sdumbbell rdev->accel_working = false; 678254885Sdumbbell } 679254885Sdumbbell return r; 680254885Sdumbbell} 681254885Sdumbbell 682254885Sdumbbellint rs690_suspend(struct radeon_device *rdev) 683254885Sdumbbell{ 684254885Sdumbbell r600_audio_fini(rdev); 685254885Sdumbbell r100_cp_disable(rdev); 686254885Sdumbbell radeon_wb_disable(rdev); 687254885Sdumbbell rs600_irq_disable(rdev); 688254885Sdumbbell rs400_gart_disable(rdev); 689254885Sdumbbell return 0; 690254885Sdumbbell} 691254885Sdumbbell 692254885Sdumbbellvoid rs690_fini(struct radeon_device *rdev) 693254885Sdumbbell{ 694254885Sdumbbell r600_audio_fini(rdev); 695254885Sdumbbell r100_cp_fini(rdev); 696254885Sdumbbell radeon_wb_fini(rdev); 697254885Sdumbbell radeon_ib_pool_fini(rdev); 698254885Sdumbbell radeon_gem_fini(rdev); 699254885Sdumbbell rs400_gart_fini(rdev); 700254885Sdumbbell radeon_irq_kms_fini(rdev); 701254885Sdumbbell radeon_fence_driver_fini(rdev); 702254885Sdumbbell radeon_bo_fini(rdev); 703254885Sdumbbell radeon_atombios_fini(rdev); 704254885Sdumbbell free(rdev->bios, DRM_MEM_DRIVER); 705254885Sdumbbell rdev->bios = NULL; 706254885Sdumbbell} 707254885Sdumbbell 708254885Sdumbbellint rs690_init(struct radeon_device *rdev) 709254885Sdumbbell{ 710254885Sdumbbell int r; 711254885Sdumbbell 712254885Sdumbbell /* Disable VGA */ 713254885Sdumbbell rv515_vga_render_disable(rdev); 714254885Sdumbbell /* Initialize scratch registers */ 715254885Sdumbbell radeon_scratch_init(rdev); 716254885Sdumbbell /* Initialize surface registers */ 717254885Sdumbbell radeon_surface_init(rdev); 718254885Sdumbbell /* restore some register to sane defaults */ 719254885Sdumbbell r100_restore_sanity(rdev); 720254885Sdumbbell /* TODO: disable VGA need to use VGA request */ 721254885Sdumbbell /* BIOS*/ 722254885Sdumbbell if (!radeon_get_bios(rdev)) { 723254885Sdumbbell if (ASIC_IS_AVIVO(rdev)) 724254885Sdumbbell return -EINVAL; 725254885Sdumbbell } 726254885Sdumbbell if (rdev->is_atom_bios) { 727254885Sdumbbell r = radeon_atombios_init(rdev); 728254885Sdumbbell if (r) 729254885Sdumbbell return r; 730254885Sdumbbell } else { 731254885Sdumbbell dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n"); 732254885Sdumbbell return -EINVAL; 733254885Sdumbbell } 734254885Sdumbbell /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 735254885Sdumbbell if (radeon_asic_reset(rdev)) { 736254885Sdumbbell dev_warn(rdev->dev, 737254885Sdumbbell "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 738254885Sdumbbell RREG32(R_000E40_RBBM_STATUS), 739254885Sdumbbell RREG32(R_0007C0_CP_STAT)); 740254885Sdumbbell } 741254885Sdumbbell /* check if cards are posted or not */ 742254885Sdumbbell if (radeon_boot_test_post_card(rdev) == false) 743254885Sdumbbell return -EINVAL; 744254885Sdumbbell 745254885Sdumbbell /* Initialize clocks */ 746254885Sdumbbell radeon_get_clock_info(rdev->ddev); 747254885Sdumbbell /* initialize memory controller */ 748254885Sdumbbell rs690_mc_init(rdev); 749254885Sdumbbell rv515_debugfs(rdev); 750254885Sdumbbell /* Fence driver */ 751254885Sdumbbell r = radeon_fence_driver_init(rdev); 752254885Sdumbbell if (r) 753254885Sdumbbell return r; 754254885Sdumbbell r = radeon_irq_kms_init(rdev); 755254885Sdumbbell if (r) 756254885Sdumbbell return r; 757254885Sdumbbell /* Memory manager */ 758254885Sdumbbell r = radeon_bo_init(rdev); 759254885Sdumbbell if (r) 760254885Sdumbbell return r; 761254885Sdumbbell r = rs400_gart_init(rdev); 762254885Sdumbbell if (r) 763254885Sdumbbell return r; 764254885Sdumbbell rs600_set_safe_registers(rdev); 765254885Sdumbbell 766254885Sdumbbell rdev->accel_working = true; 767254885Sdumbbell r = rs690_startup(rdev); 768254885Sdumbbell if (r) { 769254885Sdumbbell /* Somethings want wront with the accel init stop accel */ 770254885Sdumbbell dev_err(rdev->dev, "Disabling GPU acceleration\n"); 771254885Sdumbbell r100_cp_fini(rdev); 772254885Sdumbbell radeon_wb_fini(rdev); 773254885Sdumbbell radeon_ib_pool_fini(rdev); 774254885Sdumbbell rs400_gart_fini(rdev); 775254885Sdumbbell radeon_irq_kms_fini(rdev); 776254885Sdumbbell rdev->accel_working = false; 777254885Sdumbbell } 778254885Sdumbbell return 0; 779254885Sdumbbell} 780