From d883347f087eb1ce410392a379dfa6a44b2d14d1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 25 Sep 2008 18:45:07 -0400 Subject: [PATCH] radeon: first pass at using atombios on r4xx hw --- linux-core/atombios_crtc.c | 71 +++++++++++++++++++++++++++++++---- linux-core/radeon_display.c | 32 +++------------- linux-core/radeon_encoders.c | 15 +++++++- linux-core/radeon_legacy_crtc.c | 82 +++++++++++++++++++++++++++++++++-------- 4 files changed, 149 insertions(+), 51 deletions(-) diff --git a/linux-core/atombios_crtc.c b/linux-core/atombios_crtc.c index 16bcbe8..922cc7e 100644 --- a/linux-core/atombios_crtc.c +++ b/linux-core/atombios_crtc.c @@ -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); + } } diff --git a/linux-core/radeon_display.c b/linux-core/radeon_display.c index 257f0ac..5c86f74 100644 --- a/linux-core/radeon_display.c +++ b/linux-core/radeon_display.c @@ -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); } diff --git a/linux-core/radeon_encoders.c b/linux-core/radeon_encoders.c index 0387860..04ab03a 100644 --- a/linux-core/radeon_encoders.c +++ b/linux-core/radeon_encoders.c @@ -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 */ diff --git a/linux-core/radeon_legacy_crtc.c b/linux-core/radeon_legacy_crtc.c index bc28c43..f99cbda 100644 --- a/linux-core/radeon_legacy_crtc.c +++ b/linux-core/radeon_legacy_crtc.c @@ -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) -- 2.7.4