Rev 1129 | Rev 1182 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1129 | Rev 1179 | ||
---|---|---|---|
Line 21... | Line 21... | ||
21 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | * OTHER DEALINGS IN THE SOFTWARE. |
22 | * |
22 | * |
23 | * Authors: Dave Airlie |
23 | * Authors: Dave Airlie |
24 | * Alex Deucher |
24 | * Alex Deucher |
25 | */ |
25 | */ |
26 | #include |
26 | #include |
27 | #include |
27 | #include |
28 | #include "radeon_drm.h" |
28 | #include |
29 | #include "radeon_fixed.h" |
29 | #include "radeon_fixed.h" |
30 | #include "radeon.h" |
30 | #include "radeon.h" |
31 | #include "atom.h" |
31 | #include "atom.h" |
32 | #include "atom-bits.h" |
32 | #include "atom-bits.h" |
Line -... | Line 33... | ||
- | 33 | ||
- | 34 | /* evil but including atombios.h is much worse */ |
|
- | 35 | bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, |
|
- | 36 | SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing, |
|
- | 37 | int32_t *pixel_clock); |
|
- | 38 | static void atombios_overscan_setup(struct drm_crtc *crtc, |
|
- | 39 | struct drm_display_mode *mode, |
|
- | 40 | struct drm_display_mode *adjusted_mode) |
|
- | 41 | { |
|
- | 42 | struct drm_device *dev = crtc->dev; |
|
- | 43 | struct radeon_device *rdev = dev->dev_private; |
|
- | 44 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
|
- | 45 | SET_CRTC_OVERSCAN_PS_ALLOCATION args; |
|
- | 46 | int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); |
|
- | 47 | int a1, a2; |
|
- | 48 | ||
- | 49 | memset(&args, 0, sizeof(args)); |
|
- | 50 | ||
- | 51 | args.usOverscanRight = 0; |
|
- | 52 | args.usOverscanLeft = 0; |
|
- | 53 | args.usOverscanBottom = 0; |
|
- | 54 | args.usOverscanTop = 0; |
|
- | 55 | args.ucCRTC = radeon_crtc->crtc_id; |
|
- | 56 | ||
- | 57 | switch (radeon_crtc->rmx_type) { |
|
- | 58 | case RMX_CENTER: |
|
- | 59 | args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; |
|
- | 60 | args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; |
|
- | 61 | args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; |
|
- | 62 | args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; |
|
- | 63 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
|
- | 64 | break; |
|
- | 65 | case RMX_ASPECT: |
|
- | 66 | a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay; |
|
- | 67 | a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay; |
|
- | 68 | ||
- | 69 | if (a1 > a2) { |
|
- | 70 | args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; |
|
- | 71 | args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; |
|
- | 72 | } else if (a2 > a1) { |
|
- | 73 | args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; |
|
- | 74 | args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; |
|
- | 75 | } |
|
- | 76 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
|
- | 77 | break; |
|
- | 78 | case RMX_FULL: |
|
- | 79 | default: |
|
- | 80 | args.usOverscanRight = 0; |
|
- | 81 | args.usOverscanLeft = 0; |
|
- | 82 | args.usOverscanBottom = 0; |
|
- | 83 | args.usOverscanTop = 0; |
|
- | 84 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
|
- | 85 | break; |
|
- | 86 | } |
|
- | 87 | } |
|
- | 88 | ||
- | 89 | static void atombios_scaler_setup(struct drm_crtc *crtc) |
|
- | 90 | { |
|
- | 91 | struct drm_device *dev = crtc->dev; |
|
- | 92 | struct radeon_device *rdev = dev->dev_private; |
|
- | 93 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
|
- | 94 | ENABLE_SCALER_PS_ALLOCATION args; |
|
- | 95 | int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); |
|
- | 96 | ||
- | 97 | /* fixme - fill in enc_priv for atom dac */ |
|
- | 98 | enum radeon_tv_std tv_std = TV_STD_NTSC; |
|
- | 99 | bool is_tv = false, is_cv = false; |
|
- | 100 | struct drm_encoder *encoder; |
|
- | 101 | ||
- | 102 | if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id) |
|
- | 103 | return; |
|
- | 104 | ||
- | 105 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
|
- | 106 | /* find tv std */ |
|
- | 107 | if (encoder->crtc == crtc) { |
|
- | 108 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
|
- | 109 | if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { |
|
- | 110 | struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; |
|
- | 111 | tv_std = tv_dac->tv_std; |
|
- | 112 | is_tv = true; |
|
- | 113 | } |
|
- | 114 | } |
|
- | 115 | } |
|
- | 116 | ||
- | 117 | memset(&args, 0, sizeof(args)); |
|
- | 118 | ||
- | 119 | args.ucScaler = radeon_crtc->crtc_id; |
|
- | 120 | ||
- | 121 | if (is_tv) { |
|
- | 122 | switch (tv_std) { |
|
- | 123 | case TV_STD_NTSC: |
|
- | 124 | default: |
|
- | 125 | args.ucTVStandard = ATOM_TV_NTSC; |
|
- | 126 | break; |
|
- | 127 | case TV_STD_PAL: |
|
- | 128 | args.ucTVStandard = ATOM_TV_PAL; |
|
- | 129 | break; |
|
- | 130 | case TV_STD_PAL_M: |
|
- | 131 | args.ucTVStandard = ATOM_TV_PALM; |
|
- | 132 | break; |
|
- | 133 | case TV_STD_PAL_60: |
|
- | 134 | args.ucTVStandard = ATOM_TV_PAL60; |
|
- | 135 | break; |
|
- | 136 | case TV_STD_NTSC_J: |
|
- | 137 | args.ucTVStandard = ATOM_TV_NTSCJ; |
|
- | 138 | break; |
|
- | 139 | case TV_STD_SCART_PAL: |
|
- | 140 | args.ucTVStandard = ATOM_TV_PAL; /* ??? */ |
|
- | 141 | break; |
|
- | 142 | case TV_STD_SECAM: |
|
- | 143 | args.ucTVStandard = ATOM_TV_SECAM; |
|
- | 144 | break; |
|
- | 145 | case TV_STD_PAL_CN: |
|
- | 146 | args.ucTVStandard = ATOM_TV_PALCN; |
|
- | 147 | break; |
|
- | 148 | } |
|
- | 149 | args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; |
|
- | 150 | } else if (is_cv) { |
|
- | 151 | args.ucTVStandard = ATOM_TV_CV; |
|
- | 152 | args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; |
|
- | 153 | } else { |
|
- | 154 | switch (radeon_crtc->rmx_type) { |
|
- | 155 | case RMX_FULL: |
|
- | 156 | args.ucEnable = ATOM_SCALER_EXPANSION; |
|
- | 157 | break; |
|
- | 158 | case RMX_CENTER: |
|
- | 159 | args.ucEnable = ATOM_SCALER_CENTER; |
|
- | 160 | break; |
|
- | 161 | case RMX_ASPECT: |
|
- | 162 | args.ucEnable = ATOM_SCALER_EXPANSION; |
|
- | 163 | break; |
|
- | 164 | default: |
|
- | 165 | if (ASIC_IS_AVIVO(rdev)) |
|
- | 166 | args.ucEnable = ATOM_SCALER_DISABLE; |
|
- | 167 | else |
|
- | 168 | args.ucEnable = ATOM_SCALER_CENTER; |
|
- | 169 | break; |
|
- | 170 | } |
|
- | 171 | } |
|
- | 172 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
|
- | 173 | if ((is_tv || is_cv) |
|
- | 174 | && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_R580) { |
|
- | 175 | atom_rv515_force_tv_scaler(rdev, radeon_crtc); |
|
- | 176 | } |
|
- | 177 | } |
|
33 | 178 | ||
34 | static void atombios_lock_crtc(struct drm_crtc *crtc, int lock) |
179 | static void atombios_lock_crtc(struct drm_crtc *crtc, int lock) |
35 | { |
180 | { |
36 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
181 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
37 | struct drm_device *dev = crtc->dev; |
182 | struct drm_device *dev = crtc->dev; |
Line 201... | Line 346... | ||
201 | memset(&args, 0, sizeof(args)); |
346 | memset(&args, 0, sizeof(args)); |
Line 202... | Line 347... | ||
202 | 347 | ||
203 | if (ASIC_IS_AVIVO(rdev)) { |
348 | if (ASIC_IS_AVIVO(rdev)) { |
Line -... | Line 349... | ||
- | 349 | uint32_t ss_cntl; |
|
- | 350 | ||
- | 351 | if ((rdev->family == CHIP_RS600) || |
|
- | 352 | (rdev->family == CHIP_RS690) || |
|
- | 353 | (rdev->family == CHIP_RS740)) |
|
- | 354 | pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV | |
|
204 | uint32_t ss_cntl; |
355 | RADEON_PLL_PREFER_CLOSEST_LOWER); |
205 | 356 | ||
206 | if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ |
357 | if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ |
207 | pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
358 | pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
Line 236... | Line 387... | ||
236 | && (encoder->encoder_type == |
387 | && (encoder->encoder_type == |
237 | DRM_MODE_ENCODER_LVDS)) |
388 | DRM_MODE_ENCODER_LVDS)) |
238 | pll_flags |= RADEON_PLL_USE_REF_DIV; |
389 | pll_flags |= RADEON_PLL_USE_REF_DIV; |
239 | } |
390 | } |
240 | radeon_encoder = to_radeon_encoder(encoder); |
391 | radeon_encoder = to_radeon_encoder(encoder); |
- | 392 | break; |
|
241 | } |
393 | } |
242 | } |
394 | } |
Line 243... | Line 395... | ||
243 | 395 | ||
244 | if (radeon_crtc->crtc_id == 0) |
396 | if (radeon_crtc->crtc_id == 0) |
Line 319... | Line 471... | ||
319 | struct radeon_device *rdev = dev->dev_private; |
471 | struct radeon_device *rdev = dev->dev_private; |
320 | struct radeon_framebuffer *radeon_fb; |
472 | struct radeon_framebuffer *radeon_fb; |
321 | struct drm_gem_object *obj; |
473 | struct drm_gem_object *obj; |
322 | struct drm_radeon_gem_object *obj_priv; |
474 | struct drm_radeon_gem_object *obj_priv; |
323 | uint64_t fb_location; |
475 | uint64_t fb_location; |
324 | uint32_t fb_format, fb_pitch_pixels; |
476 | uint32_t fb_format, fb_pitch_pixels, tiling_flags; |
325 | - | ||
326 | ENTRY(); |
- | |
Line 327... | Line 477... | ||
327 | 477 | ||
328 | if (!crtc->fb) |
478 | if (!crtc->fb) |
Line -... | Line 479... | ||
- | 479 | return -EINVAL; |
|
- | 480 | ||
- | 481 | dbgprintf("x = %d y = %d width = %d height = %d\n", |
|
- | 482 | x, y, crtc->fb->width, crtc->fb->height); |
|
329 | return -EINVAL; |
483 | dbgprintf("hdisplay = %d\n", crtc->mode.hdisplay); |
Line 330... | Line 484... | ||
330 | 484 | ||
331 | radeon_fb = to_radeon_framebuffer(crtc->fb); |
485 | radeon_fb = to_radeon_framebuffer(crtc->fb); |
Line 338... | Line 492... | ||
338 | //} |
492 | // } |
Line 339... | Line 493... | ||
339 | 493 | ||
Line 340... | Line 494... | ||
340 | fb_location = 0; //rdev->mc.vram_location; |
494 | fb_location = 0; //rdev->mc.vram_location; |
341 | 495 | ||
Line 342... | Line 496... | ||
342 | dbgprintf("fb_location %x\n", fb_location); |
496 | dbgprintf("fb_location %x\n", fb_location); |
- | 497 | dbgprintf("bpp %d\n", crtc->fb->bits_per_pixel); |
|
- | 498 | ||
- | 499 | switch (crtc->fb->bits_per_pixel) { |
|
- | 500 | case 8: |
|
- | 501 | fb_format = |
|
343 | dbgprintf("bpp %x\n", crtc->fb->bits_per_pixel); |
502 | AVIVO_D1GRPH_CONTROL_DEPTH_8BPP | |
344 | 503 | AVIVO_D1GRPH_CONTROL_8BPP_INDEXED; |
|
345 | switch (crtc->fb->bits_per_pixel) { |
504 | break; |
346 | case 15: |
505 | case 15: |
347 | fb_format = |
506 | fb_format = |
Line 363... | Line 522... | ||
363 | DRM_ERROR("Unsupported screen depth %d\n", |
522 | DRM_ERROR("Unsupported screen depth %d\n", |
364 | crtc->fb->bits_per_pixel); |
523 | crtc->fb->bits_per_pixel); |
365 | return -EINVAL; |
524 | return -EINVAL; |
366 | } |
525 | } |
Line -... | Line 526... | ||
- | 526 | ||
367 | 527 | // radeon_object_get_tiling_flags(obj->driver_private, |
|
- | 528 | // &tiling_flags, NULL); |
|
- | 529 | // if (tiling_flags & RADEON_TILING_MACRO) |
|
- | 530 | // fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE; |
|
- | 531 | ||
- | 532 | // if (tiling_flags & RADEON_TILING_MICRO) |
|
- | 533 | // fb_format |= AVIVO_D1GRPH_TILED; |
|
368 | /* TODO tiling */ |
534 | |
369 | if (radeon_crtc->crtc_id == 0) |
535 | if (radeon_crtc->crtc_id == 0) |
370 | WREG32(AVIVO_D1VGA_CONTROL, 0); |
536 | WREG32(AVIVO_D1VGA_CONTROL, 0); |
371 | else |
537 | else |
372 | WREG32(AVIVO_D2VGA_CONTROL, 0); |
538 | WREG32(AVIVO_D2VGA_CONTROL, 0); |
Line 401... | Line 567... | ||
401 | AVIVO_D1MODE_INTERLEAVE_EN); |
567 | AVIVO_D1MODE_INTERLEAVE_EN); |
402 | else |
568 | else |
403 | WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); |
569 | WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); |
Line 404... | Line 570... | ||
404 | 570 | ||
405 | if (old_fb && old_fb != crtc->fb) { |
571 | if (old_fb && old_fb != crtc->fb) { |
406 | radeon_fb = to_radeon_framebuffer(old_fb); |
572 | // radeon_fb = to_radeon_framebuffer(old_fb); |
407 | // radeon_gem_object_unpin(radeon_fb->obj); |
573 | // radeon_gem_object_unpin(radeon_fb->obj); |
408 | } |
- | |
409 | LEAVE(); |
574 | } |
410 | return 0; |
575 | return 0; |
Line 411... | Line 576... | ||
411 | } |
576 | } |
412 | 577 | ||
Line 418... | Line 583... | ||
418 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
583 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
419 | struct drm_device *dev = crtc->dev; |
584 | struct drm_device *dev = crtc->dev; |
420 | struct radeon_device *rdev = dev->dev_private; |
585 | struct radeon_device *rdev = dev->dev_private; |
421 | struct drm_encoder *encoder; |
586 | struct drm_encoder *encoder; |
422 | SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing; |
587 | SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing; |
423 | - | ||
- | 588 | int need_tv_timings = 0; |
|
424 | ENTRY(); |
589 | bool ret; |
Line 425... | Line 590... | ||
425 | 590 | ||
426 | /* TODO color tiling */ |
591 | /* TODO color tiling */ |
Line 427... | Line -... | ||
427 | memset(&crtc_timing, 0, sizeof(crtc_timing)); |
- | |
428 | 592 | memset(&crtc_timing, 0, sizeof(crtc_timing)); |
|
- | 593 | ||
- | 594 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
|
- | 595 | /* find tv std */ |
|
Line -... | Line 596... | ||
- | 596 | if (encoder->crtc == crtc) { |
|
- | 597 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
|
- | 598 | ||
- | 599 | if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { |
|
- | 600 | struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; |
|
- | 601 | if (tv_dac) { |
|
- | 602 | if (tv_dac->tv_std == TV_STD_NTSC || |
|
- | 603 | tv_dac->tv_std == TV_STD_NTSC_J || |
|
- | 604 | tv_dac->tv_std == TV_STD_PAL_M) |
|
- | 605 | need_tv_timings = 1; |
|
- | 606 | else |
|
- | 607 | need_tv_timings = 2; |
|
- | 608 | break; |
|
429 | /* TODO tv */ |
609 | } |
Line 430... | Line 610... | ||
430 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
610 | } |
- | 611 | } |
|
- | 612 | } |
|
- | 613 | ||
- | 614 | crtc_timing.ucCRTC = radeon_crtc->crtc_id; |
|
- | 615 | if (need_tv_timings) { |
|
- | 616 | ret = radeon_atom_get_tv_timings(rdev, need_tv_timings - 1, |
|
- | 617 | &crtc_timing, &adjusted_mode->clock); |
|
- | 618 | if (ret == false) |
|
431 | 619 | need_tv_timings = 0; |
|
432 | } |
620 | } |
433 | 621 | ||
434 | crtc_timing.ucCRTC = radeon_crtc->crtc_id; |
622 | if (!need_tv_timings) { |
435 | crtc_timing.usH_Total = adjusted_mode->crtc_htotal; |
623 | crtc_timing.usH_Total = adjusted_mode->crtc_htotal; |
Line 456... | Line 644... | ||
456 | if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) |
644 | if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) |
457 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE; |
645 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE; |
Line 458... | Line 646... | ||
458 | 646 | ||
459 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) |
647 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) |
- | 648 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE; |
|
Line 460... | Line 649... | ||
460 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE; |
649 | } |
461 | 650 | ||
Line 462... | Line 651... | ||
462 | atombios_crtc_set_pll(crtc, adjusted_mode); |
651 | atombios_crtc_set_pll(crtc, adjusted_mode); |
Line 517... | Line 706... | ||
517 | atombios_set_crtc_dtd_timing(crtc, &crtc_dtd_timing); |
706 | atombios_set_crtc_dtd_timing(crtc, &crtc_dtd_timing); |
518 | } |
707 | } |
519 | radeon_crtc_set_base(crtc, x, y, old_fb); |
708 | radeon_crtc_set_base(crtc, x, y, old_fb); |
520 | radeon_legacy_atom_set_surface(crtc); |
709 | radeon_legacy_atom_set_surface(crtc); |
521 | } |
710 | } |
- | 711 | atombios_overscan_setup(crtc, mode, adjusted_mode); |
|
522 | LEAVE(); |
712 | atombios_scaler_setup(crtc); |
523 | - | ||
- | 713 | radeon_bandwidth_update(rdev); |
|
524 | return 0; |
714 | return 0; |
525 | } |
715 | } |
Line 526... | Line 716... | ||
526 | 716 | ||
527 | static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, |
717 | static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, |
528 | struct drm_display_mode *mode, |
718 | struct drm_display_mode *mode, |
529 | struct drm_display_mode *adjusted_mode) |
719 | struct drm_display_mode *adjusted_mode) |
- | 720 | { |
|
- | 721 | if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) |
|
530 | { |
722 | return false; |
531 | return true; |
723 | return true; |
Line 532... | Line 724... | ||
532 | } |
724 | } |
533 | 725 | ||
Line 558... | Line 750... | ||
558 | if (radeon_crtc->crtc_id == 1) |
750 | if (radeon_crtc->crtc_id == 1) |
559 | radeon_crtc->crtc_offset = |
751 | radeon_crtc->crtc_offset = |
560 | AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; |
752 | AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; |
561 | drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); |
753 | drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); |
562 | } |
754 | }><>><>><>=> |
563 | - | ||
564 | void radeon_init_disp_bw_avivo(struct drm_device *dev, |
- | |
565 | struct drm_display_mode *mode1, |
- | |
566 | uint32_t pixel_bytes1, |
- | |
567 | struct drm_display_mode *mode2, |
- | |
568 | uint32_t pixel_bytes2) |
- | |
569 | { |
- | |
570 | struct radeon_device *rdev = dev->dev_private; |
- | |
571 | fixed20_12 min_mem_eff; |
- | |
572 | fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff; |
- | |
573 | fixed20_12 sclk_ff, mclk_ff; |
- | |
574 | uint32_t dc_lb_memory_split, temp; |
- | |
575 | - | ||
576 | min_mem_eff.full = rfixed_const_8(0); |
- | |
577 | if (rdev->disp_priority == 2) { |
- | |
578 | uint32_t mc_init_misc_lat_timer = 0; |
- | |
579 | if (rdev->family == CHIP_RV515) |
- | |
580 | mc_init_misc_lat_timer = |
- | |
581 | RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER); |
- | |
582 | else if (rdev->family == CHIP_RS690) |
- | |
583 | mc_init_misc_lat_timer = |
- | |
584 | RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER); |
- | |
585 | - | ||
586 | mc_init_misc_lat_timer &= |
- | |
587 | ~(R300_MC_DISP1R_INIT_LAT_MASK << |
- | |
588 | R300_MC_DISP1R_INIT_LAT_SHIFT); |
- | |
589 | mc_init_misc_lat_timer &= |
- | |
590 | ~(R300_MC_DISP0R_INIT_LAT_MASK << |
- | |
591 | R300_MC_DISP0R_INIT_LAT_SHIFT); |
- | |
592 | - | ||
593 | if (mode2) |
- | |
594 | mc_init_misc_lat_timer |= |
- | |
595 | (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); |
- | |
596 | if (mode1) |
- | |
597 | mc_init_misc_lat_timer |= |
- | |
598 | (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); |
- | |
599 | - | ||
600 | if (rdev->family == CHIP_RV515) |
- | |
601 | WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER, |
- | |
602 | mc_init_misc_lat_timer); |
- | |
603 | else if (rdev->family == CHIP_RS690) |
- | |
604 | WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER, |
- | |
605 | mc_init_misc_lat_timer); |
- | |
606 | } |
- | |
607 | - | ||
608 | /* |
- | |
609 | * determine is there is enough bw for current mode |
- | |
610 | */ |
- | |
611 | temp_ff.full = rfixed_const(100); |
- | |
612 | mclk_ff.full = rfixed_const(rdev->clock.default_mclk); |
- | |
613 | mclk_ff.full = rfixed_div(mclk_ff, temp_ff); |
- | |
614 | sclk_ff.full = rfixed_const(rdev->clock.default_sclk); |
- | |
615 | sclk_ff.full = rfixed_div(sclk_ff, temp_ff); |
- | |
616 | - | ||
617 | temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); |
- | |
618 | temp_ff.full = rfixed_const(temp); |
- | |
619 | mem_bw.full = rfixed_mul(mclk_ff, temp_ff); |
- | |
620 | mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); |
- | |
621 | - | ||
622 | pix_clk.full = 0; |
- | |
623 | pix_clk2.full = 0; |
- | |
624 | peak_disp_bw.full = 0; |
- | |
625 | if (mode1) { |
- | |
626 | temp_ff.full = rfixed_const(1000); |
- | |
627 | pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ |
- | |
628 | pix_clk.full = rfixed_div(pix_clk, temp_ff); |
- | |
629 | temp_ff.full = rfixed_const(pixel_bytes1); |
- | |
630 | peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); |
- | |
631 | } |
- | |
632 | if (mode2) { |
- | |
633 | temp_ff.full = rfixed_const(1000); |
- | |
634 | pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ |
- | |
635 | pix_clk2.full = rfixed_div(pix_clk2, temp_ff); |
- | |
636 | temp_ff.full = rfixed_const(pixel_bytes2); |
- | |
637 | peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); |
- | |
638 | } |
- | |
639 | - | ||
640 | if (peak_disp_bw.full >= mem_bw.full) { |
- | |
641 | DRM_ERROR |
- | |
642 | ("You may not have enough display bandwidth for current mode\n" |
- | |
643 | "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); |
- | |
644 | printk("peak disp bw %d, mem_bw %d\n", |
- | |
645 | rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw)); |
- | |
646 | } |
- | |
647 | - | ||
648 | /* |
- | |
649 | * Line Buffer Setup |
- | |
650 | * There is a single line buffer shared by both display controllers. |
- | |
651 | * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display |
- | |
652 | * controllers. The paritioning can either be done manually or via one of four |
- | |
653 | * preset allocations specified in bits 1:0: |
- | |
654 | * 0 - line buffer is divided in half and shared between each display controller |
- | |
655 | * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4 |
- | |
656 | * 2 - D1 gets the whole buffer |
- | |
657 | * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4 |
- | |
658 | * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode. |
- | |
659 | * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits |
- | |
660 | * 14:4; D2 allocation follows D1. |
- | |
661 | */ |
- | |
662 | - | ||
663 | /* is auto or manual better ? */ |
- | |
664 | dc_lb_memory_split = |
- | |
665 | RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK; |
- | |
666 | dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; |
- | |
667 | #if 1 |
- | |
668 | /* auto */ |
- | |
669 | if (mode1 && mode2) { |
- | |
670 | if (mode1->hdisplay > mode2->hdisplay) { |
- | |
671 | if (mode1->hdisplay > 2560) |
- | |
672 | dc_lb_memory_split |= |
- | |
673 | AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q; |
- | |
674 | else |
- | |
675 | dc_lb_memory_split |= |
- | |
676 | AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; |
- | |
677 | } else if (mode2->hdisplay > mode1->hdisplay) { |
- | |
678 | if (mode2->hdisplay > 2560) |
- | |
679 | dc_lb_memory_split |= |
- | |
680 | AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; |
- | |
681 | else |
- | |
682 | dc_lb_memory_split |= |
- | |
683 | AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; |
- | |
684 | } else |
- | |
685 | dc_lb_memory_split |= |
- | |
686 | AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; |
- | |
687 | } else if (mode1) { |
- | |
688 | dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY; |
- | |
689 | } else if (mode2) { |
- | |
690 | dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; |
- | |
691 | } |
- | |
692 | #else |
- | |
693 | /* manual */ |
- | |
694 | dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; |
- | |
695 | dc_lb_memory_split &= |
- | |
696 | ~(AVIVO_DC_LB_DISP1_END_ADR_MASK << |
- | |
697 | AVIVO_DC_LB_DISP1_END_ADR_SHIFT); |
- | |
698 | if (mode1) { |
- | |
699 | dc_lb_memory_split |= |
- | |
700 | ((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK) |
- | |
701 | << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); |
- | |
702 | } else if (mode2) { |
- | |
703 | dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); |
- | |
704 | } |
- | |
705 | #endif |
- | |
706 | WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split); |
- | |
707 | }><>><> |
- | |
708 | >< |
- | |
709 | >><>><> |
- |