Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 156015
b: refs/heads/master
c: c93bb85
h: refs/heads/master
i:
  156013: e3cbe3f
  156011: 479a083
  156007: 58363ab
  155999: 2da096e
v: v3
  • Loading branch information
Jerome Glisse authored and Dave Airlie committed Jul 29, 2009
1 parent 6aeb29d commit 342782d
Show file tree
Hide file tree
Showing 20 changed files with 2,378 additions and 1,355 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e024e11070a0a0dc7163ce1ec2da354a638bdbed
refs/heads/master: c93bb85b5cba3e3a06f2cad8e9bc5c23d3d10aac
276 changes: 131 additions & 145 deletions trunk/drivers/gpu/drm/radeon/atombios_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,132 @@
#include "atom.h"
#include "atom-bits.h"

static void atombios_overscan_setup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
SET_CRTC_OVERSCAN_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
int a1, a2;

memset(&args, 0, sizeof(args));

args.usOverscanRight = 0;
args.usOverscanLeft = 0;
args.usOverscanBottom = 0;
args.usOverscanTop = 0;
args.ucCRTC = radeon_crtc->crtc_id;

switch (radeon_crtc->rmx_type) {
case RMX_CENTER:
args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
break;
case RMX_ASPECT:
a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;

if (a1 > a2) {
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
} else if (a2 > a1) {
args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
}
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
break;
case RMX_FULL:
default:
args.usOverscanRight = 0;
args.usOverscanLeft = 0;
args.usOverscanBottom = 0;
args.usOverscanTop = 0;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
break;
}
}

static void atombios_scaler_setup(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
ENABLE_SCALER_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
/* fixme - fill in enc_priv for atom dac */
enum radeon_tv_std tv_std = TV_STD_NTSC;

if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
return;

memset(&args, 0, sizeof(args));

args.ucScaler = radeon_crtc->crtc_id;

if (radeon_crtc->devices & (ATOM_DEVICE_TV_SUPPORT)) {
switch (tv_std) {
case TV_STD_NTSC:
default:
args.ucTVStandard = ATOM_TV_NTSC;
break;
case TV_STD_PAL:
args.ucTVStandard = ATOM_TV_PAL;
break;
case TV_STD_PAL_M:
args.ucTVStandard = ATOM_TV_PALM;
break;
case TV_STD_PAL_60:
args.ucTVStandard = ATOM_TV_PAL60;
break;
case TV_STD_NTSC_J:
args.ucTVStandard = ATOM_TV_NTSCJ;
break;
case TV_STD_SCART_PAL:
args.ucTVStandard = ATOM_TV_PAL; /* ??? */
break;
case TV_STD_SECAM:
args.ucTVStandard = ATOM_TV_SECAM;
break;
case TV_STD_PAL_CN:
args.ucTVStandard = ATOM_TV_PALCN;
break;
}
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
} else if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT)) {
args.ucTVStandard = ATOM_TV_CV;
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
} else {
switch (radeon_crtc->rmx_type) {
case RMX_FULL:
args.ucEnable = ATOM_SCALER_EXPANSION;
break;
case RMX_CENTER:
args.ucEnable = ATOM_SCALER_CENTER;
break;
case RMX_ASPECT:
args.ucEnable = ATOM_SCALER_EXPANSION;
break;
default:
if (ASIC_IS_AVIVO(rdev))
args.ucEnable = ATOM_SCALER_DISABLE;
else
args.ucEnable = ATOM_SCALER_CENTER;
break;
}
}
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
&& rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) {
atom_rv515_force_tv_scaler(rdev);
}
}

static void atombios_lock_crtc(struct drm_crtc *crtc, int lock)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
Expand Down Expand Up @@ -522,13 +648,18 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
radeon_crtc_set_base(crtc, x, y, old_fb);
radeon_legacy_atom_set_surface(crtc);
}
atombios_overscan_setup(crtc, mode, adjusted_mode);
atombios_scaler_setup(crtc);
radeon_bandwidth_update(rdev);
return 0;
}

static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
return false;
return true;
}

Expand Down Expand Up @@ -561,148 +692,3 @@ void radeon_atombios_init_crtc(struct drm_device *dev,
AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
}

void radeon_init_disp_bw_avivo(struct drm_device *dev,
struct drm_display_mode *mode1,
uint32_t pixel_bytes1,
struct drm_display_mode *mode2,
uint32_t pixel_bytes2)
{
struct radeon_device *rdev = dev->dev_private;
fixed20_12 min_mem_eff;
fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff;
fixed20_12 sclk_ff, mclk_ff;
uint32_t dc_lb_memory_split, temp;

min_mem_eff.full = rfixed_const_8(0);
if (rdev->disp_priority == 2) {
uint32_t mc_init_misc_lat_timer = 0;
if (rdev->family == CHIP_RV515)
mc_init_misc_lat_timer =
RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER);
else if (rdev->family == CHIP_RS690)
mc_init_misc_lat_timer =
RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER);

mc_init_misc_lat_timer &=
~(R300_MC_DISP1R_INIT_LAT_MASK <<
R300_MC_DISP1R_INIT_LAT_SHIFT);
mc_init_misc_lat_timer &=
~(R300_MC_DISP0R_INIT_LAT_MASK <<
R300_MC_DISP0R_INIT_LAT_SHIFT);

if (mode2)
mc_init_misc_lat_timer |=
(1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
if (mode1)
mc_init_misc_lat_timer |=
(1 << R300_MC_DISP0R_INIT_LAT_SHIFT);

if (rdev->family == CHIP_RV515)
WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER,
mc_init_misc_lat_timer);
else if (rdev->family == CHIP_RS690)
WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER,
mc_init_misc_lat_timer);
}

/*
* determine is there is enough bw for current mode
*/
temp_ff.full = rfixed_const(100);
mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
sclk_ff.full = rfixed_div(sclk_ff, temp_ff);

temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
temp_ff.full = rfixed_const(temp);
mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);

pix_clk.full = 0;
pix_clk2.full = 0;
peak_disp_bw.full = 0;
if (mode1) {
temp_ff.full = rfixed_const(1000);
pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */
pix_clk.full = rfixed_div(pix_clk, temp_ff);
temp_ff.full = rfixed_const(pixel_bytes1);
peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
}
if (mode2) {
temp_ff.full = rfixed_const(1000);
pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */
pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
temp_ff.full = rfixed_const(pixel_bytes2);
peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
}

if (peak_disp_bw.full >= mem_bw.full) {
DRM_ERROR
("You may not have enough display bandwidth for current mode\n"
"If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
printk("peak disp bw %d, mem_bw %d\n",
rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw));
}

/*
* Line Buffer Setup
* There is a single line buffer shared by both display controllers.
* DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display
* controllers. The paritioning can either be done manually or via one of four
* preset allocations specified in bits 1:0:
* 0 - line buffer is divided in half and shared between each display controller
* 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
* 2 - D1 gets the whole buffer
* 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
* Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode.
* In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits
* 14:4; D2 allocation follows D1.
*/

/* is auto or manual better ? */
dc_lb_memory_split =
RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK;
dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
#if 1
/* auto */
if (mode1 && mode2) {
if (mode1->hdisplay > mode2->hdisplay) {
if (mode1->hdisplay > 2560)
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
else
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else if (mode2->hdisplay > mode1->hdisplay) {
if (mode2->hdisplay > 2560)
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
else
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else if (mode1) {
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY;
} else if (mode2) {
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
}
#else
/* manual */
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
dc_lb_memory_split &=
~(AVIVO_DC_LB_DISP1_END_ADR_MASK <<
AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
if (mode1) {
dc_lb_memory_split |=
((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK)
<< AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
} else if (mode2) {
dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
}
#endif
WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
}
Loading

0 comments on commit 342782d

Please sign in to comment.