Fill in and make use of more com bios tables on legacy chips

main
Alex Deucher 2008-08-12 18:13:21 -04:00 committed by Dave Airlie
parent 9b79d356c1
commit f38fff5416
5 changed files with 352 additions and 98 deletions

View File

@ -428,7 +428,7 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)
struct radeon_mode_info *mode_info = &dev_priv->mode_info; struct radeon_mode_info *mode_info = &dev_priv->mode_info;
uint16_t pll_info; uint16_t pll_info;
struct radeon_pll *pll = &mode_info->pll; struct radeon_pll *pll = &mode_info->pll;
int rev; int8_t rev;
pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE); pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE);
if (pll_info) { if (pll_info) {
@ -450,17 +450,153 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)
pll->xclk = radeon_bios16(dev_priv, pll_info + 0x08); pll->xclk = radeon_bios16(dev_priv, pll_info + 0x08);
// sclk/mclk use fixed point // sclk/mclk use fixed point
//sclk = radeon_bios16(pll_info + 8) / 100.0;
//mclk = radeon_bios16(pll_info + 10) / 100.0;
//if (sclk == 0) sclk = 200;
//if (mclk == 0) mclk = 200;
return true; return true;
} }
return false; return false;
} }
bool radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
uint16_t dac_info;
uint8_t rev, bg, dac;
/* first check TV table */
dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
if (dac_info) {
rev = radeon_bios8(dev_priv, dac_info + 0x3);
if (rev > 4) {
bg = radeon_bios8(dev_priv, dac_info + 0xc) & 0xf;
dac = radeon_bios8(dev_priv, dac_info + 0xd) & 0xf;
encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20);
bg = radeon_bios8(dev_priv, dac_info + 0xe) & 0xf;
dac = radeon_bios8(dev_priv, dac_info + 0xf) & 0xf;
encoder->pal_tvdac_adj = (bg << 16) | (dac << 20);
bg = radeon_bios8(dev_priv, dac_info + 0x10) & 0xf;
dac = radeon_bios8(dev_priv, dac_info + 0x11) & 0xf;
encoder->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
return true;
} else if (rev > 1) {
bg = radeon_bios8(dev_priv, dac_info + 0xc) & 0xf;
dac = (radeon_bios8(dev_priv, dac_info + 0xc) >> 4) & 0xf;
encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20);
bg = radeon_bios8(dev_priv, dac_info + 0xd) & 0xf;
dac = (radeon_bios8(dev_priv, dac_info + 0xd) >> 4) & 0xf;
encoder->pal_tvdac_adj = (bg << 16) | (dac << 20);
bg = radeon_bios8(dev_priv, dac_info + 0xe) & 0xf;
dac = (radeon_bios8(dev_priv, dac_info + 0xe) >> 4) & 0xf;
encoder->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
return true;
}
}
/* then check CRT table */
dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
if (dac_info) {
rev = radeon_bios8(dev_priv, dac_info) & 0x3;
if (rev < 2) {
bg = radeon_bios8(dev_priv, dac_info + 0x3) & 0xf;
dac = (radeon_bios8(dev_priv, dac_info + 0x3) >> 4) & 0xf;
encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20);
encoder->pal_tvdac_adj = encoder->ps2_tvdac_adj;
encoder->ntsc_tvdac_adj = encoder->ps2_tvdac_adj;
return true;
} else {
bg = radeon_bios8(dev_priv, dac_info + 0x4) & 0xf;
dac = radeon_bios8(dev_priv, dac_info + 0x5) & 0xf;
encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20);
encoder->pal_tvdac_adj = encoder->ps2_tvdac_adj;
encoder->ntsc_tvdac_adj = encoder->ps2_tvdac_adj;
return true;
}
}
return false;
}
bool radeon_combios_get_tv_info(struct radeon_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
uint16_t tv_info;
tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
if (tv_info) {
if (radeon_bios8(dev_priv, tv_info + 6) == 'T') {
switch (radeon_bios8(dev_priv, tv_info + 7) & 0xf) {
case 1:
encoder->tv_std = TV_STD_NTSC;
DRM_INFO("Default TV standard: NTSC\n");
break;
case 2:
encoder->tv_std = TV_STD_PAL;
DRM_INFO("Default TV standard: PAL\n");
break;
case 3:
encoder->tv_std = TV_STD_PAL_M;
DRM_INFO("Default TV standard: PAL-M\n");
break;
case 4:
encoder->tv_std = TV_STD_PAL_60;
DRM_INFO("Default TV standard: PAL-60\n");
break;
case 5:
encoder->tv_std = TV_STD_NTSC_J;
DRM_INFO("Default TV standard: NTSC-J\n");
break;
case 6:
encoder->tv_std = TV_STD_SCART_PAL;
DRM_INFO("Default TV standard: SCART-PAL\n");
break;
default:
encoder->tv_std = TV_STD_NTSC;
DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
break;
}
switch ((radeon_bios8(dev_priv, tv_info + 9) >> 2) & 0x3) {
case 0:
DRM_INFO("29.498928713 MHz TV ref clk\n");
break;
case 1:
DRM_INFO("28.636360000 MHz TV ref clk\n");
break;
case 2:
DRM_INFO("14.318180000 MHz TV ref clk\n");
break;
case 3:
DRM_INFO("27.000000000 MHz TV ref clk\n");
break;
default:
break;
}
return true;
}
}
return false;
}
bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder) bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder)
{ {
struct drm_device *dev = encoder->base.dev; struct drm_device *dev = encoder->base.dev;
struct drm_radeon_private *dev_priv = dev->dev_private; struct drm_radeon_private *dev_priv = dev->dev_private;
uint16_t lcd_info; uint16_t lcd_info;
uint32_t panel_setup;
char stmp[30]; char stmp[30];
int tmp, i; int tmp, i;
@ -478,9 +614,57 @@ bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder)
DRM_INFO("Panel Size %dx%d\n", encoder->panel_xres, encoder->panel_yres); DRM_INFO("Panel Size %dx%d\n", encoder->panel_xres, encoder->panel_yres);
encoder->panel_pwr_delay = radeon_bios16(dev_priv, lcd_info + 44); encoder->panel_vcc_delay = radeon_bios16(dev_priv, lcd_info + 44);
if (encoder->panel_pwr_delay > 2000 || encoder->panel_pwr_delay < 0) if (encoder->panel_vcc_delay > 2000 || encoder->panel_vcc_delay < 0)
encoder->panel_pwr_delay = 2000; encoder->panel_vcc_delay = 2000;
encoder->panel_pwr_delay = radeon_bios16(dev_priv, lcd_info + 0x24);
encoder->panel_digon_delay = radeon_bios16(dev_priv, lcd_info + 0x38) & 0xf;
encoder->panel_blon_delay = (radeon_bios16(dev_priv, lcd_info + 0x38) >> 4) & 0xf;
encoder->panel_ref_divider = radeon_bios16(dev_priv, lcd_info + 46);
encoder->panel_post_divider = radeon_bios8(dev_priv, lcd_info + 48);
encoder->panel_fb_divider = radeon_bios16(dev_priv, lcd_info + 49);
if ((encoder->panel_ref_divider != 0) &&
(encoder->panel_fb_divider > 3))
encoder->use_bios_dividers = true;
panel_setup = radeon_bios32(dev_priv, lcd_info + 0x39);
encoder->lvds_gen_cntl = 0;
if (panel_setup & 0x1)
encoder->lvds_gen_cntl |= RADEON_LVDS_PANEL_FORMAT;
if ((panel_setup >> 4) & 0x1)
encoder->lvds_gen_cntl |= RADEON_LVDS_PANEL_TYPE;
switch ((panel_setup >> 8) & 0x8) {
case 0:
encoder->lvds_gen_cntl |= RADEON_LVDS_NO_FM;
break;
case 1:
encoder->lvds_gen_cntl |= RADEON_LVDS_2_GREY;
break;
case 2:
encoder->lvds_gen_cntl |= RADEON_LVDS_4_GREY;
break;
default:
break;
}
if ((panel_setup >> 16) & 0x1)
encoder->lvds_gen_cntl |= RADEON_LVDS_FP_POL_LOW;
if ((panel_setup >> 17) & 0x1)
encoder->lvds_gen_cntl |= RADEON_LVDS_LP_POL_LOW;
if ((panel_setup >> 18) & 0x1)
encoder->lvds_gen_cntl |= RADEON_LVDS_DTM_POL_LOW;
if ((panel_setup >> 23) & 0x1)
encoder->lvds_gen_cntl |= RADEON_LVDS_BL_CLK_SEL;
encoder->lvds_gen_cntl |= (panel_setup & 0xf0000000);
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
tmp = radeon_bios16(dev_priv, lcd_info + 64 + i * 2); tmp = radeon_bios16(dev_priv, lcd_info + 64 + i * 2);

View File

@ -356,13 +356,9 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo
uint32_t tv_dac_cntl = RADEON_READ(RADEON_TV_DAC_CNTL); uint32_t tv_dac_cntl = RADEON_READ(RADEON_TV_DAC_CNTL);
uint32_t dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2); uint32_t dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2);
uint32_t crtc2_gen_cntl = RADEON_READ(RADEON_CRTC2_GEN_CNTL); uint32_t crtc2_gen_cntl = RADEON_READ(RADEON_CRTC2_GEN_CNTL);
// state->dac2_cntl = info->StatedReg->dac2_cntl;
// state->tv_dac_cntl = info->StatedReg->tv_dac_cntl;
// state->crtc2_gen_cntl = info->StatedReg->crtc2_gen_cntl;
// state->disp_hw_debug = info->StatedReg->disp_hw_debug;
// state->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
// state->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
/* For CRT on DAC2, don't turn it on if BIOS didn't /* For CRT on DAC2, don't turn it on if BIOS didn't
enable it, even it's detected. enable it, even it's detected.
@ -395,19 +391,22 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo
return true; return true;
} }
static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode, int flags) static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private; struct drm_radeon_private *dev_priv = dev->dev_private;
struct drm_encoder *encoder;
uint32_t feedback_div = 0; uint32_t feedback_div = 0;
uint32_t reference_div = 0; uint32_t reference_div = 0;
uint32_t post_divider = 0; uint32_t post_divider = 0;
uint32_t freq = 0; uint32_t freq = 0;
uint8_t pll_gain; uint8_t pll_gain;
int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV;
bool use_bios_divs = false;
/* PLL registers */ /* PLL registers */
uint32_t ppll_ref_div; uint32_t ppll_ref_div = 0;
uint32_t ppll_div_3; uint32_t ppll_div_3 = 0;
uint32_t htotal_cntl; uint32_t htotal_cntl = 0;
uint32_t vclk_ecp_cntl; uint32_t vclk_ecp_cntl;
struct radeon_pll *pll = &dev_priv->mode_info.pll; struct radeon_pll *pll = &dev_priv->mode_info.pll;
@ -432,17 +431,29 @@ static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode
{ 0, 0 } { 0, 0 }
}; };
#if 0 // TODO list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { if (encoder->crtc == crtc) {
ppll_ref_div = info->RefDivider; if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
if (radeon_encoder->use_bios_dividers) {
ppll_ref_div = radeon_encoder->panel_ref_divider;
ppll_div_3 = (radeon_encoder->panel_fb_divider |
(radeon_encoder->panel_post_divider << 16));
htotal_cntl = 0; htotal_cntl = 0;
return; use_bios_divs = true;
} else
pll_flags |= RADEON_PLL_USE_REF_DIV;
}
}
} }
#endif
DRM_DEBUG("\n"); DRM_DEBUG("\n");
radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, flags);
if (!use_bios_divs) {
radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, pll_flags);
for (post_div = &post_divs[0]; post_div->divider; ++post_div) { for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
if (post_div->divider == post_divider) if (post_div->divider == post_divider)
@ -460,7 +471,6 @@ static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode
post_divider); post_divider);
ppll_ref_div = reference_div; ppll_ref_div = reference_div;
#if defined(__powerpc__) && (0) /* TODO */ #if defined(__powerpc__) && (0) /* TODO */
/* apparently programming this otherwise causes a hang??? */ /* apparently programming this otherwise causes a hang??? */
if (info->MacModel == RADEON_MAC_IBOOK) if (info->MacModel == RADEON_MAC_IBOOK)
@ -468,9 +478,10 @@ static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode
else else
#endif #endif
ppll_div_3 = (feedback_div | (post_div->bitvalue << 16)); ppll_div_3 = (feedback_div | (post_div->bitvalue << 16));
htotal_cntl = mode->htotal & 0x7; htotal_cntl = mode->htotal & 0x7;
}
vclk_ecp_cntl = (RADEON_READ_PLL(dev_priv, RADEON_VCLK_ECP_CNTL) & vclk_ecp_cntl = (RADEON_READ_PLL(dev_priv, RADEON_VCLK_ECP_CNTL) &
~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK;
@ -783,19 +794,22 @@ static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mo
} }
static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode, int flags) static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private; struct drm_radeon_private *dev_priv = dev->dev_private;
struct drm_encoder *encoder;
uint32_t feedback_div = 0; uint32_t feedback_div = 0;
uint32_t reference_div = 0; uint32_t reference_div = 0;
uint32_t post_divider = 0; uint32_t post_divider = 0;
uint32_t freq = 0; uint32_t freq = 0;
uint8_t pll_gain; uint8_t pll_gain;
int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV;
bool use_bios_divs = false;
/* PLL2 registers */ /* PLL2 registers */
uint32_t p2pll_ref_div; uint32_t p2pll_ref_div = 0;
uint32_t p2pll_div_0; uint32_t p2pll_div_0 = 0;
uint32_t htotal_cntl2; uint32_t htotal_cntl2 = 0;
uint32_t pixclks_cntl; uint32_t pixclks_cntl;
struct radeon_pll *pll = &dev_priv->mode_info.pll; struct radeon_pll *pll = &dev_priv->mode_info.pll;
@ -819,16 +833,29 @@ static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode
{ 0, 0 } { 0, 0 }
}; };
#if 0 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { if (encoder->crtc == crtc) {
p2pll_ref_div = info->RefDivider; if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
p2pll_div_0 = info->FeedbackDivider | (info->PostDivider << 16); pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
htotal_cntl2 = 0; if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
return; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
}
#endif
radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, flags); if (radeon_encoder->use_bios_dividers) {
p2pll_ref_div = radeon_encoder->panel_ref_divider;
p2pll_div_0 = (radeon_encoder->panel_fb_divider |
(radeon_encoder->panel_post_divider << 16));
htotal_cntl2 = 0;
use_bios_divs = true;
} else
pll_flags |= RADEON_PLL_USE_REF_DIV;
}
}
}
DRM_DEBUG("\n");
if (!use_bios_divs) {
radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, pll_flags);
for (post_div = &post_divs[0]; post_div->divider; ++post_div) { for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
if (post_div->divider == post_divider) if (post_div->divider == post_divider)
@ -846,11 +873,11 @@ static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode
post_divider); post_divider);
p2pll_ref_div = reference_div; p2pll_ref_div = reference_div;
p2pll_div_0 = (feedback_div | (post_div->bitvalue << 16)); p2pll_div_0 = (feedback_div | (post_div->bitvalue << 16));
htotal_cntl2 = mode->htotal & 0x7; htotal_cntl2 = mode->htotal & 0x7;
}
pixclks_cntl = ((RADEON_READ_PLL(dev_priv, RADEON_PIXCLKS_CNTL) & pixclks_cntl = ((RADEON_READ_PLL(dev_priv, RADEON_PIXCLKS_CNTL) &
~(RADEON_PIX2CLK_SRC_SEL_MASK)) | ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
@ -946,22 +973,9 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc,
int x, int y) int x, int y)
{ {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_encoder *encoder;
int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV;
DRM_DEBUG("\n"); DRM_DEBUG("\n");
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc == crtc) {
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS)
pll_flags |= RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV;
}
}
/* TODO TV */ /* TODO TV */
radeon_crtc_set_base(crtc, x, y); radeon_crtc_set_base(crtc, x, y);
@ -969,11 +983,11 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc,
switch(radeon_crtc->crtc_id) { switch(radeon_crtc->crtc_id) {
case 0: case 0:
radeon_set_crtc1_timing(crtc, adjusted_mode); radeon_set_crtc1_timing(crtc, adjusted_mode);
radeon_set_pll1(crtc, adjusted_mode, pll_flags); radeon_set_pll1(crtc, adjusted_mode);
break; break;
case 1: case 1:
radeon_set_crtc2_timing(crtc, adjusted_mode); radeon_set_crtc2_timing(crtc, adjusted_mode);
radeon_set_pll2(crtc, adjusted_mode, pll_flags); radeon_set_pll2(crtc, adjusted_mode);
break; break;
} }

View File

@ -213,10 +213,20 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL); lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL);
lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
RADEON_WRITE(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); RADEON_WRITE(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
/* enable lvds, turn on voltage */
lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL);
lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
udelay(radeon_encoder->panel_digon_delay * 1000);
/* enable data */
lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
udelay(radeon_encoder->panel_pwr_delay * 1000); RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
udelay(radeon_encoder->panel_blon_delay * 1000);
/* enable backlight */
lvds_gen_cntl |= RADEON_LVDS_BLON;
RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
break; break;
case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_STANDBY:
@ -226,7 +236,7 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
RADEON_WRITE_PLL_P(dev_priv, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); RADEON_WRITE_PLL_P(dev_priv, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL);
lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, pixclks_cntl); RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, pixclks_cntl);
break; break;
@ -260,6 +270,9 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL); lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL);
lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
if (radeon_encoder->lvds_gen_cntl)
lvds_gen_cntl = radeon_encoder->lvds_gen_cntl;
else
lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL);
lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
lvds_gen_cntl &= ~(RADEON_LVDS_ON | lvds_gen_cntl &= ~(RADEON_LVDS_ON |
@ -339,7 +352,6 @@ struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int b
drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs); drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs);
/* TODO get the LVDS info from the BIOS for panel size etc. */
/* get the lvds info from the bios */ /* get the lvds info from the bios */
radeon_combios_get_lvds_info(radeon_encoder); radeon_combios_get_lvds_info(radeon_encoder);
@ -659,6 +671,7 @@ struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, i
drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs); drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs);
radeon_combios_get_tmds_info(radeon_encoder); radeon_combios_get_tmds_info(radeon_encoder);
return encoder; return encoder;
} }
@ -893,6 +906,7 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private; struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0; uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0;
uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0; uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0;
@ -924,8 +938,8 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
// FIXME TV // FIXME TV
tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
RADEON_TV_DAC_NHOLD | RADEON_TV_DAC_NHOLD |
RADEON_TV_DAC_STD_PS2 /*| RADEON_TV_DAC_STD_PS2 |
radeon_encoder->ps2_tvdac_adj*/); // fixme, get from bios radeon_encoder->ps2_tvdac_adj);
RADEON_WRITE(RADEON_TV_DAC_CNTL, tv_dac_cntl); RADEON_WRITE(RADEON_TV_DAC_CNTL, tv_dac_cntl);
} }
@ -1015,8 +1029,9 @@ struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int
drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs); drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs);
/* TODO get the tv dac vals from bios tables */ /* get the tv dac vals from bios tables */
//radeon_combios_get_lvds_info(radeon_encoder); radeon_combios_get_tv_info(radeon_encoder);
radeon_combios_get_tv_dac_info(radeon_encoder);
return encoder; return encoder;
} }

View File

@ -87,6 +87,17 @@ enum radeon_rmx_type {
RMX_CENTER, RMX_CENTER,
}; };
enum radeon_tv_std {
TV_STD_NTSC,
TV_STD_PAL,
TV_STD_PAL_M,
TV_STD_PAL_60,
TV_STD_NTSC_J,
TV_STD_SCART_PAL,
TV_STD_SECAM,
TV_STD_PAL_CN,
};
struct radeon_i2c_bus_rec { struct radeon_i2c_bus_rec {
bool valid; bool valid;
uint32_t mask_clk_reg; uint32_t mask_clk_reg;
@ -337,13 +348,33 @@ struct radeon_encoder {
enum radeon_tmds_type tmds; enum radeon_tmds_type tmds;
} type; } type;
int atom_device; /* atom devices */ int atom_device; /* atom devices */
/* preferred mode */
uint32_t panel_xres, panel_yres; uint32_t panel_xres, panel_yres;
uint32_t hoverplus, hsync_width; uint32_t hoverplus, hsync_width;
uint32_t hblank; uint32_t hblank;
uint32_t voverplus, vsync_width; uint32_t voverplus, vsync_width;
uint32_t vblank; uint32_t vblank;
uint32_t panel_pwr_delay;
uint32_t dotclock; uint32_t dotclock;
/* legacy lvds */
uint16_t panel_vcc_delay;
uint16_t panel_pwr_delay;
uint16_t panel_digon_delay;
uint16_t panel_blon_delay;
uint32_t panel_ref_divider;
uint32_t panel_post_divider;
uint32_t panel_fb_divider;
bool use_bios_dividers;
uint32_t lvds_gen_cntl;
/* legacy tv dac */
uint32_t ps2_tvdac_adj;
uint32_t ntsc_tvdac_adj;
uint32_t pal_tvdac_adj;
enum radeon_tv_std tv_std;
/* legacy int tmds */
struct radeon_tmds_pll tmds_pll[4]; struct radeon_tmds_pll tmds_pll[4];
}; };
@ -351,7 +382,6 @@ struct radeon_connector {
struct drm_connector base; struct drm_connector base;
struct radeon_i2c_chan *ddc_bus; struct radeon_i2c_chan *ddc_bus;
int use_digital; int use_digital;
}; };
struct radeon_framebuffer { struct radeon_framebuffer {
@ -407,6 +437,8 @@ extern bool radeon_combios_get_clock_info(struct drm_device *dev);
extern void radeon_get_lvds_info(struct radeon_encoder *encoder); extern void radeon_get_lvds_info(struct radeon_encoder *encoder);
extern bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder); extern bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder);
extern bool radeon_combios_get_tmds_info(struct radeon_encoder *encoder); extern bool radeon_combios_get_tmds_info(struct radeon_encoder *encoder);
extern bool radeon_combios_get_tv_info(struct radeon_encoder *encoder);
extern bool radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder);
extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno); u16 blue, int regno);
struct drm_framebuffer *radeon_user_framebuffer_create(struct drm_device *dev, struct drm_framebuffer *radeon_user_framebuffer_create(struct drm_device *dev,

View File

@ -1027,14 +1027,23 @@
# define RADEON_LVDS_DISPLAY_DIS (1 << 1) # define RADEON_LVDS_DISPLAY_DIS (1 << 1)
# define RADEON_LVDS_PANEL_TYPE (1 << 2) # define RADEON_LVDS_PANEL_TYPE (1 << 2)
# define RADEON_LVDS_PANEL_FORMAT (1 << 3) # define RADEON_LVDS_PANEL_FORMAT (1 << 3)
# define RADEON_LVDS_NO_FM (0 << 4)
# define RADEON_LVDS_2_GREY (1 << 4)
# define RADEON_LVDS_4_GREY (2 << 4)
# define RADEON_LVDS_RST_FM (1 << 6) # define RADEON_LVDS_RST_FM (1 << 6)
# define RADEON_LVDS_EN (1 << 7) # define RADEON_LVDS_EN (1 << 7)
# define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8 # define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8
# define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8) # define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8)
# define RADEON_LVDS_BL_MOD_EN (1 << 16) # define RADEON_LVDS_BL_MOD_EN (1 << 16)
# define RADEON_LVDS_BL_CLK_SEL (1 << 17)
# define RADEON_LVDS_DIGON (1 << 18) # define RADEON_LVDS_DIGON (1 << 18)
# define RADEON_LVDS_BLON (1 << 19) # define RADEON_LVDS_BLON (1 << 19)
# define RADEON_LVDS_FP_POL_LOW (1 << 20)
# define RADEON_LVDS_LP_POL_LOW (1 << 21)
# define RADEON_LVDS_DTM_POL_LOW (1 << 22)
# define RADEON_LVDS_SEL_CRTC2 (1 << 23) # define RADEON_LVDS_SEL_CRTC2 (1 << 23)
# define RADEON_LVDS_FPDI_EN (1 << 27)
# define RADEON_LVDS_HSYNC_DELAY_SHIFT 28
#define RADEON_LVDS_PLL_CNTL 0x02d4 #define RADEON_LVDS_PLL_CNTL 0x02d4
# define RADEON_HSYNC_DELAY_SHIFT 28 # define RADEON_HSYNC_DELAY_SHIFT 28
# define RADEON_HSYNC_DELAY_MASK (0xf << 28) # define RADEON_HSYNC_DELAY_MASK (0xf << 28)