From 285484e2d55e76031b45926720c10b1aec8b782a Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 16 Dec 2011 17:03:42 -0500 Subject: drm/radeon: add support for evergreen/ni tiling informations v11 evergreen and northern island gpu needs more informations for 2D tiling than previous r6xx/r7xx. Add field to tiling ioctl to allow userspace to provide those. The v8 cs checking change to track color view on r6xx/r7xx doesn't affect old userspace as old userspace always emited 0 for this register. v2 fix r6xx/r7xx 2D tiling computation v3 fix r6xx/r7xx height align for untiled surface & add support for tile split on evergreen and newer v4 improve tiling debugging output v5 fix tile split code for evergreen and newer v6 set proper tile split for crtc register v7 fix tile split limit value v8 add COLOR_VIEW checking to r6xx/r7xx checker, add evergreen cs checking, update safe reg for r600, evergreen and cayman. Evergreen checking need some work around for stencil alignment issues v9 fix tile split value range, fix compressed texture handling and mipmap calculation, allow evergreen check to be silencious in front of current broken userspace (depth/stencil alignment issue) v10 fix eg 3d texture and compressed texture, fix r600 depth array, fix r600 color view computation, add support for evergreen stencil split v11 more verbose debugging in some case Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 742f17f009a9..72672ea3f6d3 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1031,6 +1031,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, struct radeon_bo *rbo; uint64_t fb_location; uint32_t fb_format, fb_pitch_pixels, tiling_flags; + unsigned bankw, bankh, mtaspect, tile_split; u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); u32 tmp, viewport_w, viewport_h; int r; @@ -1121,20 +1122,13 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, break; } - switch ((tmp & 0xf000) >> 12) { - case 0: /* 1KB rows */ - default: - fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB); - break; - case 1: /* 2KB rows */ - fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB); - break; - case 2: /* 4KB rows */ - fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB); - break; - } - fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1); + + evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split); + fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split); + fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw); + fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh); + fb_format |= EVERGREEN_GRPH_MACRO_TILE_ASPECT(mtaspect); } else if (tiling_flags & RADEON_TILING_MICRO) fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1); -- cgit v1.2.3 From 79f17c64b231918c10fdccb55192d1d6e8ab4a2b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 20 Mar 2012 17:18:02 -0400 Subject: drm/radeon/kms/atom: DCE6 no longer has crtcmemreq bits The hw no longer has the bits and the table is removed. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 72672ea3f6d3..841ee3e1a172 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -243,7 +243,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) /* adjust pm to dpms changes BEFORE enabling crtcs */ radeon_pm_compute_clocks(rdev); atombios_enable_crtc(crtc, ATOM_ENABLE); - if (ASIC_IS_DCE3(rdev)) + if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) atombios_enable_crtc_memreq(crtc, ATOM_ENABLE); atombios_blank_crtc(crtc, ATOM_DISABLE); drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); @@ -255,7 +255,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); if (radeon_crtc->enabled) atombios_blank_crtc(crtc, ATOM_ENABLE); - if (ASIC_IS_DCE3(rdev)) + if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_DISABLE); radeon_crtc->enabled = false; -- cgit v1.2.3 From fef9f91fecf3a767d74823347284e1c0e7b4b849 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 20 Mar 2012 17:18:03 -0400 Subject: drm/radeon/kms/atom: add support for crtc power gating Each pair of crtcs (0/1, 2/3, 4/5) can be power gated. Make sure the power is applied when the crtc is in use and only power down the pair when both are off. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 841ee3e1a172..62ddf8dd9e69 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -231,6 +231,22 @@ static void atombios_blank_crtc(struct drm_crtc *crtc, int state) atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } +static void atombios_powergate_crtc(struct drm_crtc *crtc, int state) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating); + ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args; + + memset(&args, 0, sizeof(args)); + + args.ucDispPipeId = radeon_crtc->crtc_id; + args.ucEnable = state; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; @@ -242,6 +258,9 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) radeon_crtc->enabled = true; /* adjust pm to dpms changes BEFORE enabling crtcs */ radeon_pm_compute_clocks(rdev); + /* disable crtc pair power gating before programming */ + if (ASIC_IS_DCE6(rdev)) + atombios_powergate_crtc(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_ENABLE); if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) atombios_enable_crtc_memreq(crtc, ATOM_ENABLE); @@ -259,6 +278,25 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_DISABLE); radeon_crtc->enabled = false; + /* power gating is per-pair */ + if (ASIC_IS_DCE6(rdev)) { + struct drm_crtc *other_crtc; + struct radeon_crtc *other_radeon_crtc; + list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { + other_radeon_crtc = to_radeon_crtc(other_crtc); + if (((radeon_crtc->crtc_id == 0) && (other_radeon_crtc->crtc_id == 1)) || + ((radeon_crtc->crtc_id == 1) && (other_radeon_crtc->crtc_id == 0)) || + ((radeon_crtc->crtc_id == 2) && (other_radeon_crtc->crtc_id == 3)) || + ((radeon_crtc->crtc_id == 3) && (other_radeon_crtc->crtc_id == 2)) || + ((radeon_crtc->crtc_id == 4) && (other_radeon_crtc->crtc_id == 5)) || + ((radeon_crtc->crtc_id == 5) && (other_radeon_crtc->crtc_id == 4))) { + /* if both crtcs in the pair are off, enable power gating */ + if (other_radeon_crtc->enabled == false) + atombios_powergate_crtc(crtc, ATOM_ENABLE); + break; + } + } + } /* adjust pm to dpms changes AFTER disabling crtcs */ radeon_pm_compute_clocks(rdev); break; -- cgit v1.2.3 From f3f1f03ed01c6ee6484a29a14d1e53e49934bdc6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 20 Mar 2012 17:18:04 -0400 Subject: drm/radeon/kms: DCE6 disp eng pll updates Rename the function to better match the functionality. DCPLL became PLL0 on DCE6. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 62ddf8dd9e69..6fe4a6dc4d6e 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -737,7 +737,7 @@ union set_pixel_clock { /* on DCE5, make sure the voltage is high enough to support the * required disp clk. */ -static void atombios_crtc_set_dcpll(struct radeon_device *rdev, +static void atombios_crtc_set_disp_eng_pll(struct radeon_device *rdev, u32 dispclk) { u8 frev, crev; @@ -767,7 +767,10 @@ static void atombios_crtc_set_dcpll(struct radeon_device *rdev, * SetPixelClock provides the dividers */ args.v6.ulDispEngClkFreq = cpu_to_le32(dispclk); - args.v6.ucPpll = ATOM_DCPLL; + if (ASIC_IS_DCE6(rdev)) + args.v6.ucPpll = ATOM_PPLL0; + else + args.v6.ucPpll = ATOM_DCPLL; break; default: DRM_ERROR("Unknown table version %d %d\n", frev, crev); @@ -1521,10 +1524,12 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) } -void radeon_atom_dcpll_init(struct radeon_device *rdev) +void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev) { /* always set DCPLL */ - if (ASIC_IS_DCE4(rdev)) { + if (ASIC_IS_DCE6(rdev)) + atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk); + else if (ASIC_IS_DCE4(rdev)) { struct radeon_atom_ss ss; bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss, ASIC_INTERNAL_SS_ON_DCPLL, @@ -1532,7 +1537,7 @@ void radeon_atom_dcpll_init(struct radeon_device *rdev) if (ss_enabled) atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss); /* XXX: DCE5, make sure voltage, dispclk is high enough */ - atombios_crtc_set_dcpll(rdev, rdev->clock.default_dispclk); + atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk); if (ss_enabled) atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss); } -- cgit v1.2.3 From 729b95ef03fbfc1b0587eedbcfbaf0cb6d27be93 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 20 Mar 2012 17:18:31 -0400 Subject: drm/radeon/kms: DCE6.1 disp eng pll updates DCE6.1 uses EXT_PLL1 for disp eng. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 6fe4a6dc4d6e..224775beb478 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -767,7 +767,9 @@ static void atombios_crtc_set_disp_eng_pll(struct radeon_device *rdev, * SetPixelClock provides the dividers */ args.v6.ulDispEngClkFreq = cpu_to_le32(dispclk); - if (ASIC_IS_DCE6(rdev)) + if (ASIC_IS_DCE61(rdev)) + args.v6.ucPpll = ATOM_EXT_PLL1; + else if (ASIC_IS_DCE6(rdev)) args.v6.ucPpll = ATOM_PPLL0; else args.v6.ucPpll = ATOM_DCPLL; -- cgit v1.2.3 From 24e1f7947b1b93e77a60c8a88cf46ee5ae8f258a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 20 Mar 2012 17:18:32 -0400 Subject: drm/radeon/kms: Adjust pll picker for DCE6.1 On TN, UNIPHYA always uses PPLL2, UNIPHYB/C/D/E/F can use either PPLL1 or PPLL0. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 224775beb478..92263af38f56 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1487,7 +1487,36 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) struct drm_crtc *test_crtc; uint32_t pll_in_use = 0; - if (ASIC_IS_DCE4(rdev)) { + if (ASIC_IS_DCE61(rdev)) { + list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { + if (test_encoder->crtc && (test_encoder->crtc == crtc)) { + struct radeon_encoder *test_radeon_encoder = + to_radeon_encoder(test_encoder); + struct radeon_encoder_atom_dig *dig = + test_radeon_encoder->enc_priv; + + if ((test_radeon_encoder->encoder_id == + ENCODER_OBJECT_ID_INTERNAL_UNIPHY) && + (dig->linkb == false)) /* UNIPHY A uses PPLL2 */ + return ATOM_PPLL2; + } + } + /* UNIPHY B/C/D/E/F */ + list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { + struct radeon_crtc *radeon_test_crtc; + + if (crtc == test_crtc) + continue; + + radeon_test_crtc = to_radeon_crtc(test_crtc); + if ((radeon_test_crtc->pll_id == ATOM_PPLL0) || + (radeon_test_crtc->pll_id == ATOM_PPLL1)) + pll_in_use |= (1 << radeon_test_crtc->pll_id); + } + if (!(pll_in_use & 4)) + return ATOM_PPLL0; + return ATOM_PPLL1; + } else if (ASIC_IS_DCE4(rdev)) { list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { if (test_encoder->crtc && (test_encoder->crtc == crtc)) { /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock, -- cgit v1.2.3 From 641998701b9e4265be5d2cc6cc645ffdf6cd9385 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 20 Mar 2012 17:18:33 -0400 Subject: drm/radeon/kms: disable PPLL0 on DCE6.1 when not in use Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 92263af38f56..a5c4e3fa6bb2 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1646,6 +1646,8 @@ static void atombios_crtc_commit(struct drm_crtc *crtc) static void atombios_crtc_disable(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; struct radeon_atom_ss ss; atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); @@ -1657,6 +1659,12 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss); break; + case ATOM_PPLL0: + /* disable the ppll */ + if (ASIC_IS_DCE61(rdev)) + atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, + 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss); + break; default: break; } -- cgit v1.2.3 From 0671bdd7983c4df674cd0fce263a44cd87bd36d2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 20 Mar 2012 17:18:34 -0400 Subject: drm/radeon/kms/DCE6.1: ss is not supported on the internal pplls It's handled via external clock. It should already be protected by the external ss flag, but add an explicit check just in case. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index a5c4e3fa6bb2..083b3eada001 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -474,7 +474,7 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, return; } args.v3.ucEnable = enable; - if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK)) + if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev)) args.v3.ucEnable = ATOM_DISABLE; } else if (ASIC_IS_DCE4(rdev)) { args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); -- cgit v1.2.3 From 017d213f649c6775e4a4349e50a5631a4e4c7308 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 23 Mar 2012 14:44:47 -0400 Subject: drm/radeon/kms/atom: force bpc to 8 for now Using the bpc (bits per color) specified by the monitor can cause problems in some cases. Until we get a better handle on how to deal with those cases, just use a bpc of 8. Reported-by: Lennert Buytenhek Signed-off-by: Alex Deucher Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 083b3eada001..b5ff1f7b6f7e 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -588,8 +588,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, if (encoder->crtc == crtc) { radeon_encoder = to_radeon_encoder(encoder); connector = radeon_get_connector_for_encoder(encoder); - if (connector && connector->display_info.bpc) - bpc = connector->display_info.bpc; + /* if (connector && connector->display_info.bpc) + bpc = connector->display_info.bpc; */ encoder_mode = atombios_get_encoder_mode(encoder); is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock); if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || @@ -965,7 +965,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; int dp_clock; - bpc = connector->display_info.bpc; + + /* if (connector->display_info.bpc) + bpc = connector->display_info.bpc; */ switch (encoder_mode) { case ATOM_ENCODER_MODE_DP_MST: -- cgit v1.2.3