diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2008-08-12 18:13:21 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2008-08-14 09:19:03 +1000 |
commit | f38fff5416bc8e40ce9426f78bfea1bad415faab (patch) | |
tree | 6d540bd97492fc6ff741313a334af12a255e5c48 | |
parent | 9b79d356c171e86e529ad1a4e5e145a36d1af601 (diff) |
Fill in and make use of more com bios tables on legacy chips
-rw-r--r-- | linux-core/radeon_combios.c | 192 | ||||
-rw-r--r-- | linux-core/radeon_legacy_crtc.c | 172 | ||||
-rw-r--r-- | linux-core/radeon_legacy_encoders.c | 33 | ||||
-rw-r--r-- | linux-core/radeon_mode.h | 36 | ||||
-rw-r--r-- | linux-core/radeon_reg.h | 9 |
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) |