OSDN Git Service

Fill in and make use of more com bios tables on legacy chips
authorAlex Deucher <alexdeucher@gmail.com>
Tue, 12 Aug 2008 22:13:21 +0000 (18:13 -0400)
committerDave Airlie <airlied@redhat.com>
Wed, 13 Aug 2008 23:19:03 +0000 (09:19 +1000)
linux-core/radeon_combios.c
linux-core/radeon_legacy_crtc.c
linux-core/radeon_legacy_encoders.c
linux-core/radeon_mode.h
linux-core/radeon_reg.h

index 1080079..bb8d0b2 100644 (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;
        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);
index 08d4a47..6775ffc 100644 (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 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;
 
        }
index de9e8ac..172f93d 100644 (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_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;
 }
index 6a2e275..3271375 100644 (file)
@@ -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,
index ad91e04..5910897 100644 (file)
 #       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)