aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2008-08-12 18:13:21 -0400
committerDave Airlie <airlied@redhat.com>2008-08-14 09:19:03 +1000
commitf38fff5416bc8e40ce9426f78bfea1bad415faab (patch)
tree6d540bd97492fc6ff741313a334af12a255e5c48
parent9b79d356c171e86e529ad1a4e5e145a36d1af601 (diff)
Fill in and make use of more com bios tables on legacy chips
-rw-r--r--linux-core/radeon_combios.c192
-rw-r--r--linux-core/radeon_legacy_crtc.c172
-rw-r--r--linux-core/radeon_legacy_encoders.c33
-rw-r--r--linux-core/radeon_mode.h36
-rw-r--r--linux-core/radeon_reg.h9
5 files changed, 348 insertions, 94 deletions
diff --git a/linux-core/radeon_combios.c b/linux-core/radeon_combios.c
index 1080079f..bb8d0b27 100644
--- a/linux-core/radeon_combios.c
+++ b/linux-core/radeon_combios.c
@@ -428,7 +428,7 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
uint16_t pll_info;
struct radeon_pll *pll = &mode_info->pll;
- int rev;
+ int8_t rev;
pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE);
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);
// 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 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)
{
struct drm_device *dev = encoder->base.dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
uint16_t lcd_info;
+ uint32_t panel_setup;
char stmp[30];
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);
- encoder->panel_pwr_delay = radeon_bios16(dev_priv, lcd_info + 44);
- if (encoder->panel_pwr_delay > 2000 || encoder->panel_pwr_delay < 0)
- encoder->panel_pwr_delay = 2000;
+ encoder->panel_vcc_delay = radeon_bios16(dev_priv, lcd_info + 44);
+ if (encoder->panel_vcc_delay > 2000 || encoder->panel_vcc_delay < 0)
+ 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++) {
tmp = radeon_bios16(dev_priv, lcd_info + 64 + i * 2);
diff --git a/linux-core/radeon_legacy_crtc.c b/linux-core/radeon_legacy_crtc.c
index 08d4a477..6775ffc0 100644
--- a/linux-core/radeon_legacy_crtc.c
+++ b/linux-core/radeon_legacy_crtc.c
@@ -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 dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2);
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;
-// state->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
+ dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
+ dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
/* For CRT on DAC2, don't turn it on if BIOS didn't
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;
}
-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_radeon_private *dev_priv = dev->dev_private;
+ struct drm_encoder *encoder;
uint32_t feedback_div = 0;
uint32_t reference_div = 0;
uint32_t post_divider = 0;
uint32_t freq = 0;
uint8_t pll_gain;
+ int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV;
+ bool use_bios_divs = false;
/* PLL registers */
- uint32_t ppll_ref_div;
- uint32_t ppll_div_3;
- uint32_t htotal_cntl;
+ uint32_t ppll_ref_div = 0;
+ uint32_t ppll_div_3 = 0;
+ uint32_t htotal_cntl = 0;
uint32_t vclk_ecp_cntl;
struct radeon_pll *pll = &dev_priv->mode_info.pll;
@@ -432,44 +431,56 @@ static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode
{ 0, 0 }
};
-#if 0 // TODO
- if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) {
- ppll_ref_div = info->RefDivider;
- ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16);
- htotal_cntl = 0;
- return;
+ 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) {
+ 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;
+ use_bios_divs = true;
+ } else
+ pll_flags |= RADEON_PLL_USE_REF_DIV;
+ }
+ }
}
-#endif
DRM_DEBUG("\n");
- radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, flags);
- for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
- if (post_div->divider == post_divider)
- break;
- }
+ if (!use_bios_divs) {
+ radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, pll_flags);
- if (!post_div->divider) {
- post_div = &post_divs[0];
- }
+ for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+ if (post_div->divider == post_divider)
+ break;
+ }
- DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n",
- (unsigned)freq,
- feedback_div,
- reference_div,
- post_divider);
+ if (!post_div->divider) {
+ post_div = &post_divs[0];
+ }
- ppll_ref_div = reference_div;
+ DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n",
+ (unsigned)freq,
+ feedback_div,
+ reference_div,
+ post_divider);
+ ppll_ref_div = reference_div;
#if defined(__powerpc__) && (0) /* TODO */
- /* apparently programming this otherwise causes a hang??? */
- if (info->MacModel == RADEON_MAC_IBOOK)
- state->ppll_div_3 = 0x000600ad;
- else
+ /* apparently programming this otherwise causes a hang??? */
+ if (info->MacModel == RADEON_MAC_IBOOK)
+ state->ppll_div_3 = 0x000600ad;
+ else
#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) &
~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_radeon_private *dev_priv = dev->dev_private;
+ struct drm_encoder *encoder;
uint32_t feedback_div = 0;
uint32_t reference_div = 0;
uint32_t post_divider = 0;
uint32_t freq = 0;
uint8_t pll_gain;
+ int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV;
+ bool use_bios_divs = false;
/* PLL2 registers */
- uint32_t p2pll_ref_div;
- uint32_t p2pll_div_0;
- uint32_t htotal_cntl2;
+ uint32_t p2pll_ref_div = 0;
+ uint32_t p2pll_div_0 = 0;
+ uint32_t htotal_cntl2 = 0;
uint32_t pixclks_cntl;
struct radeon_pll *pll = &dev_priv->mode_info.pll;
@@ -819,37 +833,50 @@ static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode
{ 0, 0 }
};
-#if 0
- if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) {
- p2pll_ref_div = info->RefDivider;
- p2pll_div_0 = info->FeedbackDivider | (info->PostDivider << 16);
- htotal_cntl2 = 0;
- return;
+ 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) {
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+ 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;
+ }
+ }
}
-#endif
- radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, flags);
+ DRM_DEBUG("\n");
- for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
- if (post_div->divider == post_divider)
- break;
- }
+ if (!use_bios_divs) {
+ radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, pll_flags);
- if (!post_div->divider) {
- post_div = &post_divs[0];
- }
+ for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+ if (post_div->divider == post_divider)
+ break;
+ }
- DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n",
- (unsigned)freq,
- feedback_div,
- reference_div,
- post_divider);
+ if (!post_div->divider) {
+ post_div = &post_divs[0];
+ }
- p2pll_ref_div = reference_div;
+ DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n",
+ (unsigned)freq,
+ feedback_div,
+ reference_div,
+ post_divider);
- p2pll_div_0 = (feedback_div | (post_div->bitvalue << 16));
+ p2pll_ref_div = reference_div;
+ 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) &
~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
@@ -946,22 +973,9 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc,
int x, int y)
{
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");
- 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 */
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) {
case 0:
radeon_set_crtc1_timing(crtc, adjusted_mode);
- radeon_set_pll1(crtc, adjusted_mode, pll_flags);
+ radeon_set_pll1(crtc, adjusted_mode);
break;
case 1:
radeon_set_crtc2_timing(crtc, adjusted_mode);
- radeon_set_pll2(crtc, adjusted_mode, pll_flags);
+ radeon_set_pll2(crtc, adjusted_mode);
break;
}
diff --git a/linux-core/radeon_legacy_encoders.c b/linux-core/radeon_legacy_encoders.c
index de9e8ac6..172f93de 100644
--- a/linux-core/radeon_legacy_encoders.c
+++ b/linux-core/radeon_legacy_encoders.c
@@ -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_LVDS_PLL_RESET;
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_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);
- 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);
break;
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);
lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL);
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_PLL(dev_priv, RADEON_PIXCLKS_CNTL, pixclks_cntl);
break;
@@ -260,7 +270,10 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL);
lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
- lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL);
+ 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_LVDS_DISPLAY_DIS;
lvds_gen_cntl &= ~(RADEON_LVDS_ON |
RADEON_LVDS_BLON |
@@ -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);
- /* TODO get the LVDS info from the BIOS for panel size etc. */
/* get the lvds info from the bios */
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);
radeon_combios_get_tmds_info(radeon_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_radeon_private *dev_priv = dev->dev_private;
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 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
tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
RADEON_TV_DAC_NHOLD |
- RADEON_TV_DAC_STD_PS2 /*|
- radeon_encoder->ps2_tvdac_adj*/); // fixme, get from bios
+ RADEON_TV_DAC_STD_PS2 |
+ radeon_encoder->ps2_tvdac_adj);
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);
- /* TODO get the tv dac vals from bios tables */
- //radeon_combios_get_lvds_info(radeon_encoder);
+ /* get the tv dac vals from bios tables */
+ radeon_combios_get_tv_info(radeon_encoder);
+ radeon_combios_get_tv_dac_info(radeon_encoder);
return encoder;
}
diff --git a/linux-core/radeon_mode.h b/linux-core/radeon_mode.h
index 6a2e275c..3271375d 100644
--- a/linux-core/radeon_mode.h
+++ b/linux-core/radeon_mode.h
@@ -87,6 +87,17 @@ enum radeon_rmx_type {
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 {
bool valid;
uint32_t mask_clk_reg;
@@ -337,13 +348,33 @@ struct radeon_encoder {
enum radeon_tmds_type tmds;
} type;
int atom_device; /* atom devices */
+
+ /* preferred mode */
uint32_t panel_xres, panel_yres;
uint32_t hoverplus, hsync_width;
uint32_t hblank;
uint32_t voverplus, vsync_width;
uint32_t vblank;
- uint32_t panel_pwr_delay;
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];
};
@@ -351,7 +382,6 @@ struct radeon_connector {
struct drm_connector base;
struct radeon_i2c_chan *ddc_bus;
int use_digital;
-
};
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 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_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,
u16 blue, int regno);
struct drm_framebuffer *radeon_user_framebuffer_create(struct drm_device *dev,
diff --git a/linux-core/radeon_reg.h b/linux-core/radeon_reg.h
index ad91e04c..59108979 100644
--- a/linux-core/radeon_reg.h
+++ b/linux-core/radeon_reg.h
@@ -1027,14 +1027,23 @@
# define RADEON_LVDS_DISPLAY_DIS (1 << 1)
# define RADEON_LVDS_PANEL_TYPE (1 << 2)
# 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_EN (1 << 7)
# define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8
# define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8)
# 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_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_FPDI_EN (1 << 27)
+# define RADEON_LVDS_HSYNC_DELAY_SHIFT 28
#define RADEON_LVDS_PLL_CNTL 0x02d4
# define RADEON_HSYNC_DELAY_SHIFT 28
# define RADEON_HSYNC_DELAY_MASK (0xf << 28)