diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-08-11 08:19:09 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-08-11 08:19:09 -0400 |
| commit | 89034bc2c7b839702c00a704e79d112737f98be0 (patch) | |
| tree | e65b1f3d4c751baa840efc81bc4734f089379eb3 /drivers/gpu/drm/radeon/rs690.c | |
| parent | fb82ad719831db58e9baa4c67015aae3fe27e7e3 (diff) | |
| parent | 85dfd81dc57e8183a277ddd7a56aa65c96f3f487 (diff) | |
Merge branch 'linus' into tracing/core
Conflicts:
kernel/trace/trace_events_filter.c
We use the tracing/core version.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/gpu/drm/radeon/rs690.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/rs690.c | 479 |
1 files changed, 476 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 79ba85042b5f..839595b00728 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c | |||
| @@ -28,6 +28,9 @@ | |||
| 28 | #include "drmP.h" | 28 | #include "drmP.h" |
| 29 | #include "radeon_reg.h" | 29 | #include "radeon_reg.h" |
| 30 | #include "radeon.h" | 30 | #include "radeon.h" |
| 31 | #include "rs690r.h" | ||
| 32 | #include "atom.h" | ||
| 33 | #include "atom-bits.h" | ||
| 31 | 34 | ||
| 32 | /* rs690,rs740 depends on : */ | 35 | /* rs690,rs740 depends on : */ |
| 33 | void r100_hdp_reset(struct radeon_device *rdev); | 36 | void r100_hdp_reset(struct radeon_device *rdev); |
| @@ -64,7 +67,7 @@ int rs690_mc_init(struct radeon_device *rdev) | |||
| 64 | rs400_gart_disable(rdev); | 67 | rs400_gart_disable(rdev); |
| 65 | 68 | ||
| 66 | /* Setup GPU memory space */ | 69 | /* Setup GPU memory space */ |
| 67 | rdev->mc.gtt_location = rdev->mc.vram_size; | 70 | rdev->mc.gtt_location = rdev->mc.mc_vram_size; |
| 68 | rdev->mc.gtt_location += (rdev->mc.gtt_size - 1); | 71 | rdev->mc.gtt_location += (rdev->mc.gtt_size - 1); |
| 69 | rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1); | 72 | rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1); |
| 70 | rdev->mc.vram_location = 0xFFFFFFFFUL; | 73 | rdev->mc.vram_location = 0xFFFFFFFFUL; |
| @@ -79,7 +82,7 @@ int rs690_mc_init(struct radeon_device *rdev) | |||
| 79 | printk(KERN_WARNING "Failed to wait MC idle while " | 82 | printk(KERN_WARNING "Failed to wait MC idle while " |
| 80 | "programming pipes. Bad things might happen.\n"); | 83 | "programming pipes. Bad things might happen.\n"); |
| 81 | } | 84 | } |
| 82 | tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; | 85 | tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; |
| 83 | tmp = REG_SET(RS690_MC_FB_TOP, tmp >> 16); | 86 | tmp = REG_SET(RS690_MC_FB_TOP, tmp >> 16); |
| 84 | tmp |= REG_SET(RS690_MC_FB_START, rdev->mc.vram_location >> 16); | 87 | tmp |= REG_SET(RS690_MC_FB_START, rdev->mc.vram_location >> 16); |
| 85 | WREG32_MC(RS690_MCCFG_FB_LOCATION, tmp); | 88 | WREG32_MC(RS690_MCCFG_FB_LOCATION, tmp); |
| @@ -138,9 +141,82 @@ void rs690_gpu_init(struct radeon_device *rdev) | |||
| 138 | /* | 141 | /* |
| 139 | * VRAM info. | 142 | * VRAM info. |
| 140 | */ | 143 | */ |
| 144 | void rs690_pm_info(struct radeon_device *rdev) | ||
| 145 | { | ||
| 146 | int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); | ||
| 147 | struct _ATOM_INTEGRATED_SYSTEM_INFO *info; | ||
| 148 | struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2; | ||
| 149 | void *ptr; | ||
| 150 | uint16_t data_offset; | ||
| 151 | uint8_t frev, crev; | ||
| 152 | fixed20_12 tmp; | ||
| 153 | |||
| 154 | atom_parse_data_header(rdev->mode_info.atom_context, index, NULL, | ||
| 155 | &frev, &crev, &data_offset); | ||
| 156 | ptr = rdev->mode_info.atom_context->bios + data_offset; | ||
| 157 | info = (struct _ATOM_INTEGRATED_SYSTEM_INFO *)ptr; | ||
| 158 | info_v2 = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *)ptr; | ||
| 159 | /* Get various system informations from bios */ | ||
| 160 | switch (crev) { | ||
| 161 | case 1: | ||
| 162 | tmp.full = rfixed_const(100); | ||
| 163 | rdev->pm.igp_sideport_mclk.full = rfixed_const(info->ulBootUpMemoryClock); | ||
| 164 | rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp); | ||
| 165 | rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->usK8MemoryClock)); | ||
| 166 | rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock)); | ||
| 167 | rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth); | ||
| 168 | break; | ||
| 169 | case 2: | ||
| 170 | tmp.full = rfixed_const(100); | ||
| 171 | rdev->pm.igp_sideport_mclk.full = rfixed_const(info_v2->ulBootUpSidePortClock); | ||
| 172 | rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp); | ||
| 173 | rdev->pm.igp_system_mclk.full = rfixed_const(info_v2->ulBootUpUMAClock); | ||
| 174 | rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp); | ||
| 175 | rdev->pm.igp_ht_link_clk.full = rfixed_const(info_v2->ulHTLinkFreq); | ||
| 176 | rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp); | ||
| 177 | rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth)); | ||
| 178 | break; | ||
| 179 | default: | ||
| 180 | tmp.full = rfixed_const(100); | ||
| 181 | /* We assume the slower possible clock ie worst case */ | ||
| 182 | /* DDR 333Mhz */ | ||
| 183 | rdev->pm.igp_sideport_mclk.full = rfixed_const(333); | ||
| 184 | /* FIXME: system clock ? */ | ||
| 185 | rdev->pm.igp_system_mclk.full = rfixed_const(100); | ||
| 186 | rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp); | ||
| 187 | rdev->pm.igp_ht_link_clk.full = rfixed_const(200); | ||
| 188 | rdev->pm.igp_ht_link_width.full = rfixed_const(8); | ||
| 189 | DRM_ERROR("No integrated system info for your GPU, using safe default\n"); | ||
| 190 | break; | ||
| 191 | } | ||
| 192 | /* Compute various bandwidth */ | ||
| 193 | /* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4 */ | ||
| 194 | tmp.full = rfixed_const(4); | ||
| 195 | rdev->pm.k8_bandwidth.full = rfixed_mul(rdev->pm.igp_system_mclk, tmp); | ||
| 196 | /* ht_bandwidth = ht_clk * 2 * ht_width / 8 * 0.8 | ||
| 197 | * = ht_clk * ht_width / 5 | ||
| 198 | */ | ||
| 199 | tmp.full = rfixed_const(5); | ||
| 200 | rdev->pm.ht_bandwidth.full = rfixed_mul(rdev->pm.igp_ht_link_clk, | ||
| 201 | rdev->pm.igp_ht_link_width); | ||
| 202 | rdev->pm.ht_bandwidth.full = rfixed_div(rdev->pm.ht_bandwidth, tmp); | ||
| 203 | if (tmp.full < rdev->pm.max_bandwidth.full) { | ||
| 204 | /* HT link is a limiting factor */ | ||
| 205 | rdev->pm.max_bandwidth.full = tmp.full; | ||
| 206 | } | ||
| 207 | /* sideport_bandwidth = (sideport_clk / 2) * 2 * 2 * 0.7 | ||
| 208 | * = (sideport_clk * 14) / 10 | ||
| 209 | */ | ||
| 210 | tmp.full = rfixed_const(14); | ||
| 211 | rdev->pm.sideport_bandwidth.full = rfixed_mul(rdev->pm.igp_sideport_mclk, tmp); | ||
| 212 | tmp.full = rfixed_const(10); | ||
| 213 | rdev->pm.sideport_bandwidth.full = rfixed_div(rdev->pm.sideport_bandwidth, tmp); | ||
| 214 | } | ||
| 215 | |||
| 141 | void rs690_vram_info(struct radeon_device *rdev) | 216 | void rs690_vram_info(struct radeon_device *rdev) |
| 142 | { | 217 | { |
| 143 | uint32_t tmp; | 218 | uint32_t tmp; |
| 219 | fixed20_12 a; | ||
| 144 | 220 | ||
| 145 | rs400_gart_adjust_size(rdev); | 221 | rs400_gart_adjust_size(rdev); |
| 146 | /* DDR for all card after R300 & IGP */ | 222 | /* DDR for all card after R300 & IGP */ |
| @@ -152,12 +228,409 @@ void rs690_vram_info(struct radeon_device *rdev) | |||
| 152 | } else { | 228 | } else { |
| 153 | rdev->mc.vram_width = 64; | 229 | rdev->mc.vram_width = 64; |
| 154 | } | 230 | } |
| 155 | rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); | 231 | rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
| 232 | rdev->mc.mc_vram_size = rdev->mc.real_vram_size; | ||
| 156 | 233 | ||
| 157 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | 234 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); |
| 158 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | 235 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); |
| 236 | rs690_pm_info(rdev); | ||
| 237 | /* FIXME: we should enforce default clock in case GPU is not in | ||
| 238 | * default setup | ||
| 239 | */ | ||
| 240 | a.full = rfixed_const(100); | ||
| 241 | rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk); | ||
| 242 | rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); | ||
| 243 | a.full = rfixed_const(16); | ||
| 244 | /* core_bandwidth = sclk(Mhz) * 16 */ | ||
| 245 | rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a); | ||
| 246 | } | ||
| 247 | |||
| 248 | void rs690_line_buffer_adjust(struct radeon_device *rdev, | ||
| 249 | struct drm_display_mode *mode1, | ||
| 250 | struct drm_display_mode *mode2) | ||
| 251 | { | ||
| 252 | u32 tmp; | ||
| 253 | |||
| 254 | /* | ||
| 255 | * Line Buffer Setup | ||
| 256 | * There is a single line buffer shared by both display controllers. | ||
| 257 | * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between | ||
| 258 | * the display controllers. The paritioning can either be done | ||
| 259 | * manually or via one of four preset allocations specified in bits 1:0: | ||
| 260 | * 0 - line buffer is divided in half and shared between crtc | ||
| 261 | * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4 | ||
| 262 | * 2 - D1 gets the whole buffer | ||
| 263 | * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4 | ||
| 264 | * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual | ||
| 265 | * allocation mode. In manual allocation mode, D1 always starts at 0, | ||
| 266 | * D1 end/2 is specified in bits 14:4; D2 allocation follows D1. | ||
| 267 | */ | ||
| 268 | tmp = RREG32(DC_LB_MEMORY_SPLIT) & ~DC_LB_MEMORY_SPLIT_MASK; | ||
| 269 | tmp &= ~DC_LB_MEMORY_SPLIT_SHIFT_MODE; | ||
| 270 | /* auto */ | ||
| 271 | if (mode1 && mode2) { | ||
| 272 | if (mode1->hdisplay > mode2->hdisplay) { | ||
| 273 | if (mode1->hdisplay > 2560) | ||
| 274 | tmp |= DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q; | ||
| 275 | else | ||
| 276 | tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; | ||
| 277 | } else if (mode2->hdisplay > mode1->hdisplay) { | ||
| 278 | if (mode2->hdisplay > 2560) | ||
| 279 | tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; | ||
| 280 | else | ||
| 281 | tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; | ||
| 282 | } else | ||
| 283 | tmp |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; | ||
| 284 | } else if (mode1) { | ||
| 285 | tmp |= DC_LB_MEMORY_SPLIT_D1_ONLY; | ||
| 286 | } else if (mode2) { | ||
| 287 | tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; | ||
| 288 | } | ||
| 289 | WREG32(DC_LB_MEMORY_SPLIT, tmp); | ||
| 159 | } | 290 | } |
| 160 | 291 | ||
| 292 | struct rs690_watermark { | ||
| 293 | u32 lb_request_fifo_depth; | ||
| 294 | fixed20_12 num_line_pair; | ||
| 295 | fixed20_12 estimated_width; | ||
| 296 | fixed20_12 worst_case_latency; | ||
| 297 | fixed20_12 consumption_rate; | ||
| 298 | fixed20_12 active_time; | ||
| 299 | fixed20_12 dbpp; | ||
| 300 | fixed20_12 priority_mark_max; | ||
| 301 | fixed20_12 priority_mark; | ||
| 302 | fixed20_12 sclk; | ||
| 303 | }; | ||
| 304 | |||
| 305 | void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, | ||
| 306 | struct radeon_crtc *crtc, | ||
| 307 | struct rs690_watermark *wm) | ||
| 308 | { | ||
| 309 | struct drm_display_mode *mode = &crtc->base.mode; | ||
| 310 | fixed20_12 a, b, c; | ||
| 311 | fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; | ||
| 312 | fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; | ||
| 313 | /* FIXME: detect IGP with sideport memory, i don't think there is any | ||
| 314 | * such product available | ||
| 315 | */ | ||
| 316 | bool sideport = false; | ||
| 317 | |||
| 318 | if (!crtc->base.enabled) { | ||
| 319 | /* FIXME: wouldn't it better to set priority mark to maximum */ | ||
| 320 | wm->lb_request_fifo_depth = 4; | ||
| 321 | return; | ||
| 322 | } | ||
| 323 | |||
| 324 | if (crtc->vsc.full > rfixed_const(2)) | ||
| 325 | wm->num_line_pair.full = rfixed_const(2); | ||
| 326 | else | ||
| 327 | wm->num_line_pair.full = rfixed_const(1); | ||
| 328 | |||
| 329 | b.full = rfixed_const(mode->crtc_hdisplay); | ||
| 330 | c.full = rfixed_const(256); | ||
| 331 | a.full = rfixed_mul(wm->num_line_pair, b); | ||
| 332 | request_fifo_depth.full = rfixed_div(a, c); | ||
| 333 | if (a.full < rfixed_const(4)) { | ||
| 334 | wm->lb_request_fifo_depth = 4; | ||
| 335 | } else { | ||
| 336 | wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth); | ||
| 337 | } | ||
| 338 | |||
| 339 | /* Determine consumption rate | ||
| 340 | * pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000) | ||
| 341 | * vtaps = number of vertical taps, | ||
| 342 | * vsc = vertical scaling ratio, defined as source/destination | ||
| 343 | * hsc = horizontal scaling ration, defined as source/destination | ||
| 344 | */ | ||
| 345 | a.full = rfixed_const(mode->clock); | ||
| 346 | b.full = rfixed_const(1000); | ||
| 347 | a.full = rfixed_div(a, b); | ||
| 348 | pclk.full = rfixed_div(b, a); | ||
| 349 | if (crtc->rmx_type != RMX_OFF) { | ||
| 350 | b.full = rfixed_const(2); | ||
| 351 | if (crtc->vsc.full > b.full) | ||
| 352 | b.full = crtc->vsc.full; | ||
| 353 | b.full = rfixed_mul(b, crtc->hsc); | ||
| 354 | c.full = rfixed_const(2); | ||
| 355 | b.full = rfixed_div(b, c); | ||
| 356 | consumption_time.full = rfixed_div(pclk, b); | ||
| 357 | } else { | ||
| 358 | consumption_time.full = pclk.full; | ||
| 359 | } | ||
| 360 | a.full = rfixed_const(1); | ||
| 361 | wm->consumption_rate.full = rfixed_div(a, consumption_time); | ||
| 362 | |||
| 363 | |||
| 364 | /* Determine line time | ||
| 365 | * LineTime = total time for one line of displayhtotal | ||
| 366 | * LineTime = total number of horizontal pixels | ||
| 367 | * pclk = pixel clock period(ns) | ||
| 368 | */ | ||
| 369 | a.full = rfixed_const(crtc->base.mode.crtc_htotal); | ||
| 370 | line_time.full = rfixed_mul(a, pclk); | ||
| 371 | |||
| 372 | /* Determine active time | ||
| 373 | * ActiveTime = time of active region of display within one line, | ||
| 374 | * hactive = total number of horizontal active pixels | ||
| 375 | * htotal = total number of horizontal pixels | ||
| 376 | */ | ||
| 377 | a.full = rfixed_const(crtc->base.mode.crtc_htotal); | ||
| 378 | b.full = rfixed_const(crtc->base.mode.crtc_hdisplay); | ||
| 379 | wm->active_time.full = rfixed_mul(line_time, b); | ||
| 380 | wm->active_time.full = rfixed_div(wm->active_time, a); | ||
| 381 | |||
| 382 | /* Maximun bandwidth is the minimun bandwidth of all component */ | ||
| 383 | rdev->pm.max_bandwidth = rdev->pm.core_bandwidth; | ||
| 384 | if (sideport) { | ||
| 385 | if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full && | ||
| 386 | rdev->pm.sideport_bandwidth.full) | ||
| 387 | rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth; | ||
| 388 | read_delay_latency.full = rfixed_const(370 * 800 * 1000); | ||
| 389 | read_delay_latency.full = rfixed_div(read_delay_latency, | ||
| 390 | rdev->pm.igp_sideport_mclk); | ||
| 391 | } else { | ||
| 392 | if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full && | ||
| 393 | rdev->pm.k8_bandwidth.full) | ||
| 394 | rdev->pm.max_bandwidth = rdev->pm.k8_bandwidth; | ||
| 395 | if (rdev->pm.max_bandwidth.full > rdev->pm.ht_bandwidth.full && | ||
| 396 | rdev->pm.ht_bandwidth.full) | ||
| 397 | rdev->pm.max_bandwidth = rdev->pm.ht_bandwidth; | ||
| 398 | read_delay_latency.full = rfixed_const(5000); | ||
| 399 | } | ||
| 400 | |||
| 401 | /* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */ | ||
| 402 | a.full = rfixed_const(16); | ||
| 403 | rdev->pm.sclk.full = rfixed_mul(rdev->pm.max_bandwidth, a); | ||
| 404 | a.full = rfixed_const(1000); | ||
| 405 | rdev->pm.sclk.full = rfixed_div(a, rdev->pm.sclk); | ||
| 406 | /* Determine chunk time | ||
| 407 | * ChunkTime = the time it takes the DCP to send one chunk of data | ||
| 408 | * to the LB which consists of pipeline delay and inter chunk gap | ||
| 409 | * sclk = system clock(ns) | ||
| 410 | */ | ||
| 411 | a.full = rfixed_const(256 * 13); | ||
| 412 | chunk_time.full = rfixed_mul(rdev->pm.sclk, a); | ||
| 413 | a.full = rfixed_const(10); | ||
| 414 | chunk_time.full = rfixed_div(chunk_time, a); | ||
| 415 | |||
| 416 | /* Determine the worst case latency | ||
| 417 | * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines) | ||
| 418 | * WorstCaseLatency = worst case time from urgent to when the MC starts | ||
| 419 | * to return data | ||
| 420 | * READ_DELAY_IDLE_MAX = constant of 1us | ||
| 421 | * ChunkTime = time it takes the DCP to send one chunk of data to the LB | ||
| 422 | * which consists of pipeline delay and inter chunk gap | ||
| 423 | */ | ||
| 424 | if (rfixed_trunc(wm->num_line_pair) > 1) { | ||
| 425 | a.full = rfixed_const(3); | ||
| 426 | wm->worst_case_latency.full = rfixed_mul(a, chunk_time); | ||
| 427 | wm->worst_case_latency.full += read_delay_latency.full; | ||
| 428 | } else { | ||
| 429 | a.full = rfixed_const(2); | ||
| 430 | wm->worst_case_latency.full = rfixed_mul(a, chunk_time); | ||
| 431 | wm->worst_case_latency.full += read_delay_latency.full; | ||
| 432 | } | ||
| 433 | |||
| 434 | /* Determine the tolerable latency | ||
| 435 | * TolerableLatency = Any given request has only 1 line time | ||
| 436 | * for the data to be returned | ||
| 437 | * LBRequestFifoDepth = Number of chunk requests the LB can | ||
| 438 | * put into the request FIFO for a display | ||
| 439 | * LineTime = total time for one line of display | ||
| 440 | * ChunkTime = the time it takes the DCP to send one chunk | ||
| 441 | * of data to the LB which consists of | ||
| 442 | * pipeline delay and inter chunk gap | ||
| 443 | */ | ||
| 444 | if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) { | ||
| 445 | tolerable_latency.full = line_time.full; | ||
| 446 | } else { | ||
| 447 | tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2); | ||
| 448 | tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full; | ||
| 449 | tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time); | ||
| 450 | tolerable_latency.full = line_time.full - tolerable_latency.full; | ||
| 451 | } | ||
| 452 | /* We assume worst case 32bits (4 bytes) */ | ||
| 453 | wm->dbpp.full = rfixed_const(4 * 8); | ||
| 454 | |||
| 455 | /* Determine the maximum priority mark | ||
| 456 | * width = viewport width in pixels | ||
| 457 | */ | ||
| 458 | a.full = rfixed_const(16); | ||
| 459 | wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay); | ||
| 460 | wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a); | ||
| 461 | |||
| 462 | /* Determine estimated width */ | ||
| 463 | estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; | ||
| 464 | estimated_width.full = rfixed_div(estimated_width, consumption_time); | ||
| 465 | if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { | ||
| 466 | wm->priority_mark.full = rfixed_const(10); | ||
| 467 | } else { | ||
| 468 | a.full = rfixed_const(16); | ||
| 469 | wm->priority_mark.full = rfixed_div(estimated_width, a); | ||
| 470 | wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; | ||
| 471 | } | ||
| 472 | } | ||
| 473 | |||
| 474 | void rs690_bandwidth_update(struct radeon_device *rdev) | ||
| 475 | { | ||
| 476 | struct drm_display_mode *mode0 = NULL; | ||
| 477 | struct drm_display_mode *mode1 = NULL; | ||
| 478 | struct rs690_watermark wm0; | ||
| 479 | struct rs690_watermark wm1; | ||
| 480 | u32 tmp; | ||
| 481 | fixed20_12 priority_mark02, priority_mark12, fill_rate; | ||
| 482 | fixed20_12 a, b; | ||
| 483 | |||
| 484 | if (rdev->mode_info.crtcs[0]->base.enabled) | ||
| 485 | mode0 = &rdev->mode_info.crtcs[0]->base.mode; | ||
| 486 | if (rdev->mode_info.crtcs[1]->base.enabled) | ||
| 487 | mode1 = &rdev->mode_info.crtcs[1]->base.mode; | ||
| 488 | /* | ||
| 489 | * Set display0/1 priority up in the memory controller for | ||
| 490 | * modes if the user specifies HIGH for displaypriority | ||
| 491 | * option. | ||
| 492 | */ | ||
| 493 | if (rdev->disp_priority == 2) { | ||
| 494 | tmp = RREG32_MC(MC_INIT_MISC_LAT_TIMER); | ||
| 495 | tmp &= ~MC_DISP1R_INIT_LAT_MASK; | ||
| 496 | tmp &= ~MC_DISP0R_INIT_LAT_MASK; | ||
| 497 | if (mode1) | ||
| 498 | tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT); | ||
| 499 | if (mode0) | ||
| 500 | tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT); | ||
| 501 | WREG32_MC(MC_INIT_MISC_LAT_TIMER, tmp); | ||
| 502 | } | ||
| 503 | rs690_line_buffer_adjust(rdev, mode0, mode1); | ||
| 504 | |||
| 505 | if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) | ||
| 506 | WREG32(DCP_CONTROL, 0); | ||
| 507 | if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880)) | ||
| 508 | WREG32(DCP_CONTROL, 2); | ||
| 509 | |||
| 510 | rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0); | ||
| 511 | rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1); | ||
| 512 | |||
| 513 | tmp = (wm0.lb_request_fifo_depth - 1); | ||
| 514 | tmp |= (wm1.lb_request_fifo_depth - 1) << 16; | ||
| 515 | WREG32(LB_MAX_REQ_OUTSTANDING, tmp); | ||
| 516 | |||
| 517 | if (mode0 && mode1) { | ||
| 518 | if (rfixed_trunc(wm0.dbpp) > 64) | ||
| 519 | a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair); | ||
| 520 | else | ||
| 521 | a.full = wm0.num_line_pair.full; | ||
| 522 | if (rfixed_trunc(wm1.dbpp) > 64) | ||
| 523 | b.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair); | ||
| 524 | else | ||
| 525 | b.full = wm1.num_line_pair.full; | ||
| 526 | a.full += b.full; | ||
| 527 | fill_rate.full = rfixed_div(wm0.sclk, a); | ||
| 528 | if (wm0.consumption_rate.full > fill_rate.full) { | ||
| 529 | b.full = wm0.consumption_rate.full - fill_rate.full; | ||
| 530 | b.full = rfixed_mul(b, wm0.active_time); | ||
| 531 | a.full = rfixed_mul(wm0.worst_case_latency, | ||
| 532 | wm0.consumption_rate); | ||
| 533 | a.full = a.full + b.full; | ||
| 534 | b.full = rfixed_const(16 * 1000); | ||
| 535 | priority_mark02.full = rfixed_div(a, b); | ||
| 536 | } else { | ||
| 537 | a.full = rfixed_mul(wm0.worst_case_latency, | ||
| 538 | wm0.consumption_rate); | ||
| 539 | b.full = rfixed_const(16 * 1000); | ||
| 540 | priority_mark02.full = rfixed_div(a, b); | ||
| 541 | } | ||
| 542 | if (wm1.consumption_rate.full > fill_rate.full) { | ||
| 543 | b.full = wm1.consumption_rate.full - fill_rate.full; | ||
| 544 | b.full = rfixed_mul(b, wm1.active_time); | ||
| 545 | a.full = rfixed_mul(wm1.worst_case_latency, | ||
| 546 | wm1.consumption_rate); | ||
| 547 | a.full = a.full + b.full; | ||
| 548 | b.full = rfixed_const(16 * 1000); | ||
| 549 | priority_mark12.full = rfixed_div(a, b); | ||
| 550 | } else { | ||
| 551 | a.full = rfixed_mul(wm1.worst_case_latency, | ||
| 552 | wm1.consumption_rate); | ||
| 553 | b.full = rfixed_const(16 * 1000); | ||
| 554 | priority_mark12.full = rfixed_div(a, b); | ||
| 555 | } | ||
| 556 | if (wm0.priority_mark.full > priority_mark02.full) | ||
| 557 | priority_mark02.full = wm0.priority_mark.full; | ||
| 558 | if (rfixed_trunc(priority_mark02) < 0) | ||
| 559 | priority_mark02.full = 0; | ||
| 560 | if (wm0.priority_mark_max.full > priority_mark02.full) | ||
| 561 | priority_mark02.full = wm0.priority_mark_max.full; | ||
| 562 | if (wm1.priority_mark.full > priority_mark12.full) | ||
| 563 | priority_mark12.full = wm1.priority_mark.full; | ||
| 564 | if (rfixed_trunc(priority_mark12) < 0) | ||
| 565 | priority_mark12.full = 0; | ||
| 566 | if (wm1.priority_mark_max.full > priority_mark12.full) | ||
| 567 | priority_mark12.full = wm1.priority_mark_max.full; | ||
| 568 | WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02)); | ||
| 569 | WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02)); | ||
| 570 | WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12)); | ||
| 571 | WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12)); | ||
| 572 | } else if (mode0) { | ||
| 573 | if (rfixed_trunc(wm0.dbpp) > 64) | ||
| 574 | a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair); | ||
| 575 | else | ||
| 576 | a.full = wm0.num_line_pair.full; | ||
| 577 | fill_rate.full = rfixed_div(wm0.sclk, a); | ||
| 578 | if (wm0.consumption_rate.full > fill_rate.full) { | ||
| 579 | b.full = wm0.consumption_rate.full - fill_rate.full; | ||
| 580 | b.full = rfixed_mul(b, wm0.active_time); | ||
| 581 | a.full = rfixed_mul(wm0.worst_case_latency, | ||
| 582 | wm0.consumption_rate); | ||
| 583 | a.full = a.full + b.full; | ||
| 584 | b.full = rfixed_const(16 * 1000); | ||
| 585 | priority_mark02.full = rfixed_div(a, b); | ||
| 586 | } else { | ||
| 587 | a.full = rfixed_mul(wm0.worst_case_latency, | ||
| 588 | wm0.consumption_rate); | ||
| 589 | b.full = rfixed_const(16 * 1000); | ||
| 590 | priority_mark02.full = rfixed_div(a, b); | ||
| 591 | } | ||
| 592 | if (wm0.priority_mark.full > priority_mark02.full) | ||
| 593 | priority_mark02.full = wm0.priority_mark.full; | ||
| 594 | if (rfixed_trunc(priority_mark02) < 0) | ||
| 595 | priority_mark02.full = 0; | ||
| 596 | if (wm0.priority_mark_max.full > priority_mark02.full) | ||
| 597 | priority_mark02.full = wm0.priority_mark_max.full; | ||
| 598 | WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02)); | ||
| 599 | WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02)); | ||
| 600 | WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); | ||
| 601 | WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); | ||
| 602 | } else { | ||
| 603 | if (rfixed_trunc(wm1.dbpp) > 64) | ||
| 604 | a.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair); | ||
| 605 | else | ||
| 606 | a.full = wm1.num_line_pair.full; | ||
| 607 | fill_rate.full = rfixed_div(wm1.sclk, a); | ||
| 608 | if (wm1.consumption_rate.full > fill_rate.full) { | ||
| 609 | b.full = wm1.consumption_rate.full - fill_rate.full; | ||
| 610 | b.full = rfixed_mul(b, wm1.active_time); | ||
| 611 | a.full = rfixed_mul(wm1.worst_case_latency, | ||
| 612 | wm1.consumption_rate); | ||
| 613 | a.full = a.full + b.full; | ||
| 614 | b.full = rfixed_const(16 * 1000); | ||
| 615 | priority_mark12.full = rfixed_div(a, b); | ||
| 616 | } else { | ||
| 617 | a.full = rfixed_mul(wm1.worst_case_latency, | ||
| 618 | wm1.consumption_rate); | ||
| 619 | b.full = rfixed_const(16 * 1000); | ||
| 620 | priority_mark12.full = rfixed_div(a, b); | ||
| 621 | } | ||
| 622 | if (wm1.priority_mark.full > priority_mark12.full) | ||
| 623 | priority_mark12.full = wm1.priority_mark.full; | ||
| 624 | if (rfixed_trunc(priority_mark12) < 0) | ||
| 625 | priority_mark12.full = 0; | ||
| 626 | if (wm1.priority_mark_max.full > priority_mark12.full) | ||
| 627 | priority_mark12.full = wm1.priority_mark_max.full; | ||
| 628 | WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); | ||
| 629 | WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); | ||
| 630 | WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12)); | ||
| 631 | WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12)); | ||
| 632 | } | ||
| 633 | } | ||
| 161 | 634 | ||
| 162 | /* | 635 | /* |
| 163 | * Indirect registers accessor | 636 | * Indirect registers accessor |
