drm/radeon/cik: properly set up the clearstate buffer for pg (v2)
authorAlex Deucher <alexander.deucher@amd.com>
Thu, 22 Aug 2013 15:57:46 +0000 (11:57 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 30 Aug 2013 20:30:56 +0000 (16:30 -0400)
The format of the clearstate buffer used for pg (powergating)
changed between NI and SI.  This formats it properly for what
the hardware expects on SI+.

v2: fix addresses

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/evergreen.c

index 1f088800295d4df93db113e234ca593d57d81993..582f8e4f36d4372ef86120f871a4f8014589291c 100644 (file)
@@ -5622,7 +5622,7 @@ static void cik_init_gfx_cgpg(struct radeon_device *rdev)
        if (rdev->rlc.cs_data) {
                WREG32(RLC_GPM_SCRATCH_ADDR, RLC_CLEAR_STATE_DESCRIPTOR_OFFSET);
                WREG32(RLC_GPM_SCRATCH_DATA, upper_32_bits(rdev->rlc.clear_state_gpu_addr));
-               WREG32(RLC_GPM_SCRATCH_DATA, rdev->rlc.clear_state_gpu_addr);
+               WREG32(RLC_GPM_SCRATCH_DATA, lower_32_bits(rdev->rlc.clear_state_gpu_addr));
                WREG32(RLC_GPM_SCRATCH_DATA, rdev->rlc.clear_state_size);
        } else {
                WREG32(RLC_GPM_SCRATCH_ADDR, RLC_CLEAR_STATE_DESCRIPTOR_OFFSET);
@@ -5670,6 +5670,97 @@ static void cik_update_gfx_pg(struct radeon_device *rdev, bool enable)
        cik_enable_gfx_dynamic_mgpg(rdev, enable);
 }
 
+u32 cik_get_csb_size(struct radeon_device *rdev)
+{
+       u32 count = 0;
+       const struct cs_section_def *sect = NULL;
+       const struct cs_extent_def *ext = NULL;
+
+       if (rdev->rlc.cs_data == NULL)
+               return 0;
+
+       /* begin clear state */
+       count += 2;
+       /* context control state */
+       count += 3;
+
+       for (sect = rdev->rlc.cs_data; sect->section != NULL; ++sect) {
+               for (ext = sect->section; ext->extent != NULL; ++ext) {
+                       if (sect->id == SECT_CONTEXT)
+                               count += 2 + ext->reg_count;
+                       else
+                               return 0;
+               }
+       }
+       /* pa_sc_raster_config/pa_sc_raster_config1 */
+       count += 4;
+       /* end clear state */
+       count += 2;
+       /* clear state */
+       count += 2;
+
+       return count;
+}
+
+void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer)
+{
+       u32 count = 0, i;
+       const struct cs_section_def *sect = NULL;
+       const struct cs_extent_def *ext = NULL;
+
+       if (rdev->rlc.cs_data == NULL)
+               return;
+       if (buffer == NULL)
+               return;
+
+       buffer[count++] = PACKET3(PACKET3_PREAMBLE_CNTL, 0);
+       buffer[count++] = PACKET3_PREAMBLE_BEGIN_CLEAR_STATE;
+
+       buffer[count++] = PACKET3(PACKET3_CONTEXT_CONTROL, 1);
+       buffer[count++] = 0x80000000;
+       buffer[count++] = 0x80000000;
+
+       for (sect = rdev->rlc.cs_data; sect->section != NULL; ++sect) {
+               for (ext = sect->section; ext->extent != NULL; ++ext) {
+                       if (sect->id == SECT_CONTEXT) {
+                               buffer[count++] = PACKET3(PACKET3_SET_CONTEXT_REG, ext->reg_count);
+                               buffer[count++] = ext->reg_index - 0xa000;
+                               for (i = 0; i < ext->reg_count; i++)
+                                       buffer[count++] = ext->extent[i];
+                       } else {
+                               return;
+                       }
+               }
+       }
+
+       buffer[count++] = PACKET3(PACKET3_SET_CONTEXT_REG, 2);
+       buffer[count++] = PA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START;
+       switch (rdev->family) {
+       case CHIP_BONAIRE:
+               buffer[count++] = 0x16000012;
+               buffer[count++] = 0x00000000;
+               break;
+       case CHIP_KAVERI:
+               buffer[count++] = 0x00000000; /* XXX */
+               buffer[count++] = 0x00000000;
+               break;
+       case CHIP_KABINI:
+               buffer[count++] = 0x00000000; /* XXX */
+               buffer[count++] = 0x00000000;
+               break;
+       default:
+               buffer[count++] = 0x00000000;
+               buffer[count++] = 0x00000000;
+               break;
+       }
+
+       buffer[count++] = PACKET3(PACKET3_PREAMBLE_CNTL, 0);
+       buffer[count++] = PACKET3_PREAMBLE_END_CLEAR_STATE;
+
+       buffer[count++] = PACKET3(PACKET3_CLEAR_STATE, 0);
+       buffer[count++] = 0;
+}
+
 static void cik_init_pg(struct radeon_device *rdev)
 {
        if (rdev->pg_flags) {
index 536908109001982e02ae1732a2908598f15dca42..2ca9f13f2c79bdc2cda7b99de12d85939fc6d2cb 100644 (file)
@@ -144,6 +144,8 @@ void cik_init_cp_pg_table(struct radeon_device *rdev);
 
 extern u32 si_get_csb_size(struct radeon_device *rdev);
 extern void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
+extern u32 cik_get_csb_size(struct radeon_device *rdev);
+extern void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
 
 static const u32 evergreen_golden_registers[] =
 {
@@ -3903,6 +3905,9 @@ int sumo_rlc_init(struct radeon_device *rdev)
 
        src_ptr = rdev->rlc.reg_list;
        dws = rdev->rlc.reg_list_size;
+       if (rdev->family >= CHIP_BONAIRE) {
+               dws += (5 * 16) + 48 + 48 + 64;
+       }
        cs_data = rdev->rlc.cs_data;
 
        if (src_ptr) {
@@ -3966,7 +3971,9 @@ int sumo_rlc_init(struct radeon_device *rdev)
 
        if (cs_data) {
                /* clear state block */
-               if (rdev->family >= CHIP_TAHITI) {
+               if (rdev->family >= CHIP_BONAIRE) {
+                       rdev->rlc.clear_state_size = dws = cik_get_csb_size(rdev);
+               } else if (rdev->family >= CHIP_TAHITI) {
                        rdev->rlc.clear_state_size = si_get_csb_size(rdev);
                        dws = rdev->rlc.clear_state_size + (256 / 4);
                } else {
@@ -4014,7 +4021,9 @@ int sumo_rlc_init(struct radeon_device *rdev)
                }
                /* set up the cs buffer */
                dst_ptr = rdev->rlc.cs_ptr;
-               if (rdev->family >= CHIP_TAHITI) {
+               if (rdev->family >= CHIP_BONAIRE) {
+                       cik_get_csb_buffer(rdev, dst_ptr);
+               } else if (rdev->family >= CHIP_TAHITI) {
                        reg_list_mc_addr = rdev->rlc.clear_state_gpu_addr + 256;
                        dst_ptr[0] = upper_32_bits(reg_list_mc_addr);
                        dst_ptr[1] = lower_32_bits(reg_list_mc_addr);