radeon: first pass at using atombios on r4xx hw
authorAlex Deucher <alexdeucher@gmail.com>
Thu, 25 Sep 2008 22:45:07 +0000 (18:45 -0400)
committerAlex Deucher <alexdeucher@gmail.com>
Thu, 25 Sep 2008 22:45:07 +0000 (18:45 -0400)
linux-core/atombios_crtc.c
linux-core/radeon_display.c
linux-core/radeon_encoders.c
linux-core/radeon_legacy_crtc.c

index 16bcbe8..922cc7e 100644 (file)
@@ -121,6 +121,29 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
        }
 }
 
+static void
+atombios_set_crtc_dtd_timing(struct drm_crtc *crtc, SET_CRTC_USING_DTD_TIMING_PARAMETERS *crtc_param)
+{
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+       SET_CRTC_USING_DTD_TIMING_PARAMETERS conv_param;
+       int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);
+
+       conv_param.usH_Size                     = cpu_to_le16(crtc_param->usH_Size);
+       conv_param.usH_Blanking_Time    = cpu_to_le16(crtc_param->usH_Blanking_Time);
+       conv_param.usV_Size                     = cpu_to_le16(crtc_param->usV_Size);
+       conv_param.usV_Blanking_Time    = cpu_to_le16(crtc_param->usV_Blanking_Time);
+       conv_param.usH_SyncOffset               = cpu_to_le16(crtc_param->usH_SyncOffset);
+       conv_param.usH_SyncWidth                = cpu_to_le16(crtc_param->usH_SyncWidth);
+       conv_param.usV_SyncOffset               = cpu_to_le16(crtc_param->usV_SyncOffset);
+       conv_param.usV_SyncWidth                = cpu_to_le16(crtc_param->usV_SyncWidth);
+       conv_param.susModeMiscInfo.usAccess = cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
+       conv_param.ucCRTC                       = crtc_param->ucCRTC;
+
+       printk("executing set crtc dtd timing\n");
+       atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&conv_param);
+}
 
 void atombios_crtc_set_timing(struct drm_crtc *crtc, SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_param)
 {
@@ -170,7 +193,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
        if (!radeon_is_avivo(dev_priv))
                pll_flags |= RADEON_PLL_LEGACY;
 
-       if (mode->clock > 120000) /* range limits??? */
+       if (mode->clock > 200000) /* range limits??? */
                pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
        else
                pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
@@ -319,8 +342,8 @@ void atombios_crtc_mode_set(struct drm_crtc *crtc,
        struct drm_radeon_private *dev_priv = dev->dev_private;
        struct drm_encoder *encoder;
        SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing;
-       /* TODO color tiling */
 
+       /* TODO color tiling */
        memset(&crtc_timing, 0, sizeof(crtc_timing));
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
@@ -355,14 +378,48 @@ void atombios_crtc_mode_set(struct drm_crtc *crtc,
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
                crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
 
+       atombios_crtc_set_pll(crtc, adjusted_mode);
+       atombios_crtc_set_timing(crtc, &crtc_timing);
+
        if (radeon_is_avivo(dev_priv))
                atombios_crtc_set_base(crtc, x, y);
-       else
+       else {
+               if (radeon_crtc->crtc_id == 0) {
+                       SET_CRTC_USING_DTD_TIMING_PARAMETERS crtc_dtd_timing;
+                       memset(&crtc_dtd_timing, 0, sizeof(crtc_dtd_timing));
+
+                       /* setup FP shadow regs on R4xx */
+                       crtc_dtd_timing.ucCRTC = radeon_crtc->crtc_id;
+                       crtc_dtd_timing.usH_Size = adjusted_mode->crtc_hdisplay;
+                       crtc_dtd_timing.usV_Size = adjusted_mode->crtc_vdisplay;
+                       crtc_dtd_timing.usH_Blanking_Time = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hdisplay;
+                       crtc_dtd_timing.usV_Blanking_Time = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vdisplay;
+                       crtc_dtd_timing.usH_SyncOffset = adjusted_mode->crtc_hsync_start - adjusted_mode->crtc_hdisplay;
+                       crtc_dtd_timing.usV_SyncOffset = adjusted_mode->crtc_vsync_start - adjusted_mode->crtc_vdisplay;
+                       crtc_dtd_timing.usH_SyncWidth = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
+                       crtc_dtd_timing.usV_SyncWidth = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
+                       //crtc_dtd_timing.ucH_Border = adjusted_mode->crtc_hborder;
+                       //crtc_dtd_timing.ucV_Border = adjusted_mode->crtc_vborder;
+
+                       if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+                               crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
+
+                       if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+                               crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
+
+                       if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
+                               crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
+
+                       if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+                               crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
+
+                       if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+                               crtc_dtd_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
+
+                       atombios_set_crtc_dtd_timing(crtc, &crtc_dtd_timing);
+               }
                radeon_crtc_set_base(crtc, x, y);
-
-       atombios_crtc_set_pll(crtc, adjusted_mode);
-
-       atombios_crtc_set_timing(crtc, &crtc_timing);
+       }
 
 }
 
index 257f0ac..5c86f74 100644 (file)
@@ -195,7 +195,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
                radeon_crtc->lut_b[i] = i;
        }
 
-       if (dev_priv->is_atom_bios && radeon_is_avivo(dev_priv))
+       if (dev_priv->is_atom_bios)
                radeon_atombios_init_crtc(dev, radeon_crtc);
        else
                radeon_legacy_init_crtc(dev, radeon_crtc);
@@ -237,10 +237,7 @@ bool radeon_setup_enc_conn(struct drm_device *dev)
                encoder = NULL;
                /* if we find an LVDS connector */
                if (mode_info->bios_connector[i].connector_type == CONNECTOR_LVDS) {
-                       if (radeon_is_avivo(dev_priv))
-                               encoder = radeon_encoder_lvtma_add(dev, i);
-                       else
-                               encoder = radeon_encoder_legacy_lvds_add(dev, i);
+                       encoder = radeon_encoder_lvtma_add(dev, i);
                        if (encoder)
                                drm_mode_connector_attach_encoder(connector, encoder);
                }
@@ -249,14 +246,7 @@ bool radeon_setup_enc_conn(struct drm_device *dev)
                if ((mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_I) ||
                    (mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_A) ||
                    (mode_info->bios_connector[i].connector_type == CONNECTOR_VGA)) {
-                       if (radeon_is_avivo(dev_priv)) {
-                               encoder = radeon_encoder_atom_dac_add(dev, i, mode_info->bios_connector[i].dac_type, 0);
-                       } else {
-                               if (mode_info->bios_connector[i].dac_type == DAC_PRIMARY)
-                                       encoder = radeon_encoder_legacy_primary_dac_add(dev, i, 0);
-                               else if (mode_info->bios_connector[i].dac_type == DAC_TVDAC)
-                                       encoder = radeon_encoder_legacy_tv_dac_add(dev, i, 0);
-                       }
+                       encoder = radeon_encoder_atom_dac_add(dev, i, mode_info->bios_connector[i].dac_type, 0);
                        if (encoder)
                                drm_mode_connector_attach_encoder(connector, encoder);
                }
@@ -264,26 +254,14 @@ bool radeon_setup_enc_conn(struct drm_device *dev)
                /* TMDS on DVI */
                if ((mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_I) ||
                    (mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_D)) {
-                       if (radeon_is_avivo(dev_priv))
-                               encoder = radeon_encoder_atom_tmds_add(dev, i, mode_info->bios_connector[i].tmds_type);
-                       else {
-                               if (mode_info->bios_connector[i].tmds_type == TMDS_INT)
-                                       encoder = radeon_encoder_legacy_tmds_int_add(dev, i);
-                               else if (mode_info->bios_connector[i].tmds_type == TMDS_EXT)
-                                       encoder = radeon_encoder_legacy_tmds_ext_add(dev, i);
-                       }
+                       encoder = radeon_encoder_atom_tmds_add(dev, i, mode_info->bios_connector[i].tmds_type);
                        if (encoder)
                                drm_mode_connector_attach_encoder(connector, encoder);
                }
 
                /* TVDAC on DIN */
                if (mode_info->bios_connector[i].connector_type == CONNECTOR_DIN) {
-                       if (radeon_is_avivo(dev_priv))
-                               encoder = radeon_encoder_atom_dac_add(dev, i, mode_info->bios_connector[i].dac_type, 1);
-                       else {
-                               if (mode_info->bios_connector[i].dac_type == DAC_TVDAC)
-                                       encoder = radeon_encoder_legacy_tv_dac_add(dev, i, 0);
-                       }
+                       encoder = radeon_encoder_atom_dac_add(dev, i, mode_info->bios_connector[i].dac_type, 1);
                        if (encoder)
                                drm_mode_connector_attach_encoder(connector, encoder);
                }
index 0387860..04ab03a 100644 (file)
@@ -146,6 +146,10 @@ static void atombios_scaler_setup(struct drm_encoder *encoder, struct drm_displa
        ENABLE_SCALER_PS_ALLOCATION args;
        int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
 
+       /* pre-avivo chips only have 1 scaler */
+       if (!radeon_is_avivo(dev_priv) && radeon_crtc->crtc_id)
+               return;
+
        memset(&args, 0, sizeof(args));
        args.ucScaler = radeon_crtc->crtc_id;
 
@@ -154,8 +158,12 @@ static void atombios_scaler_setup(struct drm_encoder *encoder, struct drm_displa
                        args.ucEnable = ATOM_SCALER_EXPANSION;
                else if (radeon_encoder->rmx_type == RMX_CENTER)
                        args.ucEnable = ATOM_SCALER_CENTER;
-       } else
-               args.ucEnable = ATOM_SCALER_DISABLE;
+       } else {
+               if (radeon_is_avivo(dev_priv))
+                       args.ucEnable = ATOM_SCALER_DISABLE;
+               else
+                       args.ucEnable = ATOM_SCALER_CENTER;
+       }
 
        atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
 }
@@ -225,6 +233,9 @@ static void radeon_dfp_disable_dither(struct drm_encoder *encoder, int device)
        struct drm_device *dev = encoder->dev;
        struct drm_radeon_private *dev_priv = dev->dev_private;
 
+       if (!radeon_is_avivo(dev_priv))
+               return;
+
        switch (device) {
        case ATOM_DEVICE_DFP1_INDEX:
                RADEON_WRITE(AVIVO_TMDSA_BIT_DEPTH_CONTROL, 0); /* TMDSA */
index bc28c43..f99cbda 100644 (file)
@@ -171,6 +171,50 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
        }
 }
 
+/* properly set crtc bpp when using atombios */
+static void radeon_legacy_atom_set_surface(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       int format;
+       uint32_t crtc_gen_cntl, crtc2_gen_cntl;
+
+       switch (crtc->fb->bits_per_pixel) {
+       case 15:      /*  555 */
+               format = 3;
+               break;
+       case 16:      /*  565 */
+               format = 4;
+               break;
+       case 24:      /*  RGB */
+               format = 5;
+               break;
+       case 32:      /* xRGB */
+               format = 6;
+               break;
+       default:
+               return;
+       }
+
+       switch (radeon_crtc->crtc_id) {
+       case 0:
+               crtc_gen_cntl = RADEON_READ(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff;
+               crtc_gen_cntl |= (format << 8);
+               crtc_gen_cntl |= RADEON_CRTC_EXT_DISP_EN;
+               RADEON_WRITE(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
+               break;
+       case 1:
+               crtc2_gen_cntl = RADEON_READ(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff;
+               crtc2_gen_cntl |= (format << 8);
+               RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+               // not sure we need these...
+               RADEON_WRITE(RADEON_FP_H2_SYNC_STRT_WID,   RADEON_READ(RADEON_CRTC2_H_SYNC_STRT_WID));
+               RADEON_WRITE(RADEON_FP_V2_SYNC_STRT_WID,   RADEON_READ(RADEON_CRTC2_V_SYNC_STRT_WID));
+               break;
+       }
+}
+
 static bool radeon_set_crtc1_base(struct drm_crtc *crtc, int x, int y)
 {
        struct drm_device *dev = crtc->dev;
@@ -181,6 +225,7 @@ static bool radeon_set_crtc1_base(struct drm_crtc *crtc, int x, int y)
        uint32_t base;
        uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0;
        uint32_t crtc_pitch;
+       uint32_t disp_merge_cntl;
 
        DRM_DEBUG("\n");
 
@@ -263,6 +308,13 @@ static bool radeon_set_crtc1_base(struct drm_crtc *crtc, int x, int y)
        RADEON_WRITE(RADEON_CRTC_OFFSET, crtc_offset);
        RADEON_WRITE(RADEON_CRTC_PITCH, crtc_pitch);
 
+       disp_merge_cntl = RADEON_READ(RADEON_DISP_MERGE_CNTL);
+       disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
+       RADEON_WRITE(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
+
+       if (dev_priv->is_atom_bios)
+               radeon_legacy_atom_set_surface(crtc);
+
        return true;
 }
 
@@ -280,12 +332,10 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo
        uint32_t crtc_h_sync_strt_wid;
        uint32_t crtc_v_total_disp;
        uint32_t crtc_v_sync_strt_wid;
-       uint32_t disp_merge_cntl;
 
        DRM_DEBUG("\n");
 
        switch (crtc->fb->bits_per_pixel) {
-               
        case 15:      /*  555 */
                format = 3;
                break;
@@ -321,9 +371,6 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo
                          RADEON_CRTC_HSYNC_DIS |
                          RADEON_CRTC_DISPLAY_DIS);
 
-       disp_merge_cntl = RADEON_READ(RADEON_DISP_MERGE_CNTL);
-       disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
-
        crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
                             | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
 
@@ -386,8 +433,6 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo
        RADEON_WRITE(RADEON_CRTC_V_TOTAL_DISP, crtc_v_total_disp);
        RADEON_WRITE(RADEON_CRTC_V_SYNC_STRT_WID, crtc_v_sync_strt_wid);
 
-       RADEON_WRITE(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
-
        RADEON_WRITE(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
 
        return true;
@@ -433,7 +478,7 @@ static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode
                {  0, 0 }
        };
 
-       if (mode->clock > 120000) /* range limits??? */
+       if (mode->clock > 200000) /* range limits??? */
                pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
        else
                pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
@@ -606,6 +651,7 @@ static bool radeon_set_crtc2_base(struct drm_crtc *crtc, int x, int y)
        uint32_t base;
        uint32_t crtc2_offset, crtc2_offset_cntl, crtc2_tile_x0_y0 = 0;
         uint32_t crtc2_pitch;
+       uint32_t disp2_merge_cntl;
 
        DRM_DEBUG("\n");
 
@@ -686,6 +732,13 @@ static bool radeon_set_crtc2_base(struct drm_crtc *crtc, int x, int y)
        RADEON_WRITE(RADEON_CRTC2_OFFSET, crtc2_offset);
        RADEON_WRITE(RADEON_CRTC2_PITCH, crtc2_pitch);
 
+       disp2_merge_cntl = RADEON_READ(RADEON_DISP2_MERGE_CNTL);
+       disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
+       RADEON_WRITE(RADEON_DISP2_MERGE_CNTL,      disp2_merge_cntl);
+
+       if (dev_priv->is_atom_bios)
+               radeon_legacy_atom_set_surface(crtc);
+
        return true;
 }
 
@@ -702,7 +755,6 @@ static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mo
         uint32_t crtc2_h_sync_strt_wid;
         uint32_t crtc2_v_total_disp;
         uint32_t crtc2_v_sync_strt_wid;
-       uint32_t disp2_merge_cntl;
        uint32_t fp_h2_sync_strt_wid;
        uint32_t fp_v2_sync_strt_wid;
 
@@ -776,9 +828,6 @@ static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mo
                              ? RADEON_CRTC2_INTERLACE_EN
                              : 0));
 
-       disp2_merge_cntl = RADEON_READ(RADEON_DISP2_MERGE_CNTL);
-       disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
-
        fp_h2_sync_strt_wid = crtc2_h_sync_strt_wid;
        fp_v2_sync_strt_wid = crtc2_v_sync_strt_wid;
 
@@ -795,8 +844,6 @@ static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mo
        RADEON_WRITE(RADEON_FP_H2_SYNC_STRT_WID,   fp_h2_sync_strt_wid);
        RADEON_WRITE(RADEON_FP_V2_SYNC_STRT_WID,   fp_v2_sync_strt_wid);
 
-       RADEON_WRITE(RADEON_DISP2_MERGE_CNTL,      disp2_merge_cntl);
-
        RADEON_WRITE(RADEON_CRTC2_GEN_CNTL,        crtc2_gen_cntl);
 
        return true;
@@ -813,7 +860,7 @@ static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode
        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;
+       int pll_flags = RADEON_PLL_LEGACY;
        bool use_bios_divs = false;
        /* PLL2 registers */
        uint32_t p2pll_ref_div = 0;
@@ -842,6 +889,11 @@ static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode
                {  0, 0 }
        };
 
+       if (mode->clock > 200000) /* range limits??? */
+               pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+       else
+               pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                if (encoder->crtc == crtc) {
                        if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)