summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-09-28 11:27:05 +1000
committerDave Airlie <airlied@redhat.com>2016-09-28 11:27:05 +1000
commit9f4ef05bcdcfdf911b056b471dd3c6a4f331b644 (patch)
treeba8dfba87b4fe5295598f5438881822b6d3395f0 /drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
parent81c5d6aa3983662b6b48b504fe3a0a4c640f6a84 (diff)
parentbeb86f29c9c7f2d04f9a42c4c61cc469c3689779 (diff)
Merge branch 'drm-next-4.9' of git://people.freedesktop.org/~agd5f/linux into drm-next
Last set of radeon and amdgpu changes for 4.9. This is mostly just the powerplay cleanup for dGPUs. Beyond that, just misc code cleanups and bug fixes. * 'drm-next-4.9' of git://people.freedesktop.org/~agd5f/linux: (49 commits) drm/amd/amdgpu: Clean up afmt allocation in DCEv6. (v2) drm/amd/amdgpu: Remove division from vblank_wait drm/radeon/atif: Send a hotplug event when we get dgpu display request drm/radeon/atpx: check for ATIF dGPU wake for display events support drm/amdgpu/atif: Send a hotplug event when we get dgpu display request drm/amdgpu/atpx: check for ATIF dGPU wake for display events support drm/amdgpu: bump version for new vce packet support drm/amdgpu/vce: allow the clock table packet drm/amdgpu:cleanup virt related define drm/amdgpu: use powerplay module for dgpu in Vi. drm/amdgpu: set gfx clock gating for tonga/polaris. drm/amdgpu: set system clock gating for tonga/polaris. drm/amd/powerplay: export function to help to set cg by smu. drm/amdgpu: avoid out of bounds access on array interrupt_status_offsets drm/amdgpu: mark symbols static where possible drm/amdgpu: remove unused functions drm/amd/powerplay: Replace per-asic print_performance with generic drm/radeon: narrow asic_init for virtualization drm/amdgpu:add fw version entry to info drm/amdgpu:determine if vPost is needed indeed ...
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c131
1 files changed, 130 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index 410b29c05671..40abb6b81c09 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -931,6 +931,123 @@ static u32 gfx_v6_0_get_rb_disabled(struct amdgpu_device *adev,
return data & mask;
}
+static void gfx_v6_0_raster_config(struct amdgpu_device *adev, u32 *rconf)
+{
+ switch (adev->asic_type) {
+ case CHIP_TAHITI:
+ case CHIP_PITCAIRN:
+ *rconf |= RB_XSEL2(2) | RB_XSEL | PKR_MAP(2) | PKR_YSEL(1) |
+ SE_MAP(2) | SE_XSEL(2) | SE_YSEL(2);
+ break;
+ case CHIP_VERDE:
+ *rconf |= RB_XSEL | PKR_MAP(2) | PKR_YSEL(1);
+ break;
+ case CHIP_OLAND:
+ *rconf |= RB_YSEL;
+ break;
+ case CHIP_HAINAN:
+ *rconf |= 0x0;
+ break;
+ default:
+ DRM_ERROR("unknown asic: 0x%x\n", adev->asic_type);
+ break;
+ }
+}
+
+static void gfx_v6_0_write_harvested_raster_configs(struct amdgpu_device *adev,
+ u32 raster_config, unsigned rb_mask,
+ unsigned num_rb)
+{
+ unsigned sh_per_se = max_t(unsigned, adev->gfx.config.max_sh_per_se, 1);
+ unsigned num_se = max_t(unsigned, adev->gfx.config.max_shader_engines, 1);
+ unsigned rb_per_pkr = min_t(unsigned, num_rb / num_se / sh_per_se, 2);
+ unsigned rb_per_se = num_rb / num_se;
+ unsigned se_mask[4];
+ unsigned se;
+
+ se_mask[0] = ((1 << rb_per_se) - 1) & rb_mask;
+ se_mask[1] = (se_mask[0] << rb_per_se) & rb_mask;
+ se_mask[2] = (se_mask[1] << rb_per_se) & rb_mask;
+ se_mask[3] = (se_mask[2] << rb_per_se) & rb_mask;
+
+ WARN_ON(!(num_se == 1 || num_se == 2 || num_se == 4));
+ WARN_ON(!(sh_per_se == 1 || sh_per_se == 2));
+ WARN_ON(!(rb_per_pkr == 1 || rb_per_pkr == 2));
+
+ for (se = 0; se < num_se; se++) {
+ unsigned raster_config_se = raster_config;
+ unsigned pkr0_mask = ((1 << rb_per_pkr) - 1) << (se * rb_per_se);
+ unsigned pkr1_mask = pkr0_mask << rb_per_pkr;
+ int idx = (se / 2) * 2;
+
+ if ((num_se > 1) && (!se_mask[idx] || !se_mask[idx + 1])) {
+ raster_config_se &= ~SE_MAP_MASK;
+
+ if (!se_mask[idx]) {
+ raster_config_se |= SE_MAP(RASTER_CONFIG_SE_MAP_3);
+ } else {
+ raster_config_se |= SE_MAP(RASTER_CONFIG_SE_MAP_0);
+ }
+ }
+
+ pkr0_mask &= rb_mask;
+ pkr1_mask &= rb_mask;
+ if (rb_per_se > 2 && (!pkr0_mask || !pkr1_mask)) {
+ raster_config_se &= ~PKR_MAP_MASK;
+
+ if (!pkr0_mask) {
+ raster_config_se |= PKR_MAP(RASTER_CONFIG_PKR_MAP_3);
+ } else {
+ raster_config_se |= PKR_MAP(RASTER_CONFIG_PKR_MAP_0);
+ }
+ }
+
+ if (rb_per_se >= 2) {
+ unsigned rb0_mask = 1 << (se * rb_per_se);
+ unsigned rb1_mask = rb0_mask << 1;
+
+ rb0_mask &= rb_mask;
+ rb1_mask &= rb_mask;
+ if (!rb0_mask || !rb1_mask) {
+ raster_config_se &= ~RB_MAP_PKR0_MASK;
+
+ if (!rb0_mask) {
+ raster_config_se |=
+ RB_MAP_PKR0(RASTER_CONFIG_RB_MAP_3);
+ } else {
+ raster_config_se |=
+ RB_MAP_PKR0(RASTER_CONFIG_RB_MAP_0);
+ }
+ }
+
+ if (rb_per_se > 2) {
+ rb0_mask = 1 << (se * rb_per_se + rb_per_pkr);
+ rb1_mask = rb0_mask << 1;
+ rb0_mask &= rb_mask;
+ rb1_mask &= rb_mask;
+ if (!rb0_mask || !rb1_mask) {
+ raster_config_se &= ~RB_MAP_PKR1_MASK;
+
+ if (!rb0_mask) {
+ raster_config_se |=
+ RB_MAP_PKR1(RASTER_CONFIG_RB_MAP_3);
+ } else {
+ raster_config_se |=
+ RB_MAP_PKR1(RASTER_CONFIG_RB_MAP_0);
+ }
+ }
+ }
+ }
+
+ /* GRBM_GFX_INDEX has a different offset on SI */
+ gfx_v6_0_select_se_sh(adev, se, 0xffffffff, 0xffffffff);
+ WREG32(PA_SC_RASTER_CONFIG, raster_config_se);
+ }
+
+ /* GRBM_GFX_INDEX has a different offset on SI */
+ gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+}
+
static void gfx_v6_0_setup_rb(struct amdgpu_device *adev,
u32 se_num, u32 sh_per_se,
u32 max_rb_num_per_se)
@@ -939,6 +1056,7 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev,
u32 data, mask;
u32 disabled_rbs = 0;
u32 enabled_rbs = 0;
+ unsigned num_rb_pipes;
mutex_lock(&adev->grbm_idx_mutex);
for (i = 0; i < se_num; i++) {
@@ -961,6 +1079,9 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev,
adev->gfx.config.backend_enable_mask = enabled_rbs;
adev->gfx.config.num_rbs = hweight32(enabled_rbs);
+ num_rb_pipes = min_t(unsigned, adev->gfx.config.max_backends_per_se *
+ adev->gfx.config.max_shader_engines, 16);
+
mutex_lock(&adev->grbm_idx_mutex);
for (i = 0; i < se_num; i++) {
gfx_v6_0_select_se_sh(adev, i, 0xffffffff, 0xffffffff);
@@ -980,7 +1101,15 @@ static void gfx_v6_0_setup_rb(struct amdgpu_device *adev,
}
enabled_rbs >>= 2;
}
- WREG32(PA_SC_RASTER_CONFIG, data);
+ gfx_v6_0_raster_config(adev, &data);
+
+ if (!adev->gfx.config.backend_enable_mask ||
+ adev->gfx.config.num_rbs >= num_rb_pipes)
+ WREG32(PA_SC_RASTER_CONFIG, data);
+ else
+ gfx_v6_0_write_harvested_raster_configs(adev, data,
+ adev->gfx.config.backend_enable_mask,
+ num_rb_pipes);
}
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);