drm/amd/display: Add missing VM conversion from hw values
authorJun Lei <Jun.Lei@amd.com>
Mon, 13 May 2019 19:09:13 +0000 (15:09 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Sat, 22 Jun 2019 14:34:13 +0000 (09:34 -0500)
[why]
VM implemenation is missing conversion from HW values in hubbub
DM not passing actual PTB during flip

[how]
add proper HW conversion from logical values
fix cases where we programmed VA even though we are in PA
plumb in PTB from DM

Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c

index a851574f118ab59cdaf8b36a6cca3ac1698f0241..724f1c5ef61406bddb8f311979c9becb9ddba1af 100644 (file)
@@ -303,6 +303,49 @@ void hubbub2_setup_vmid_ptb(struct hubbub *hubbub,
        dcn20_vmid_set_ptb(&hubbub1->vmid[vmid], ptb);
 }
 
+static enum dcn_hubbub_page_table_depth page_table_depth_to_hw(unsigned int page_table_depth)
+{
+       enum dcn_hubbub_page_table_depth depth = 0;
+
+       switch (page_table_depth) {
+       case 1:
+               depth = DCN_PAGE_TABLE_DEPTH_1_LEVEL;
+               break;
+       case 2:
+               depth = DCN_PAGE_TABLE_DEPTH_2_LEVEL;
+               break;
+       case 3:
+               depth = DCN_PAGE_TABLE_DEPTH_3_LEVEL;
+               break;
+       case 4:
+               depth = DCN_PAGE_TABLE_DEPTH_4_LEVEL;
+               break;
+       default:
+               ASSERT(false);
+               break;
+       }
+
+       return depth;
+}
+
+static enum dcn_hubbub_page_table_block_size page_table_block_size_to_hw(unsigned int page_table_block_size)
+{
+       enum dcn_hubbub_page_table_block_size block_size = 0;
+
+       switch (page_table_block_size) {
+       case 4096:
+               block_size = DCN_PAGE_TABLE_BLOCK_SIZE_4KB;
+               break;
+       case 65536:
+               block_size = DCN_PAGE_TABLE_BLOCK_SIZE_64KB;
+               break;
+       default:
+               ASSERT(false);
+               break;
+       }
+
+       return block_size;
+}
 
 void hubbub2_init_dchub(struct hubbub *hubbub,
                struct hubbub_addr_config *config)
@@ -312,11 +355,6 @@ void hubbub2_init_dchub(struct hubbub *hubbub,
        struct dcn_vmid_page_table_config phys_config;
        struct dcn_vmid_page_table_config virt_config;
 
-       phys_config.depth = 0; // Depth 1
-       phys_config.block_size = 0; // Block size 4KB
-       phys_config.page_table_start_addr = config->pa_config.gart_config.page_table_start_addr;
-       phys_config.page_table_end_addr = config->pa_config.gart_config.page_table_end_addr;
-
        REG_SET(DCN_VM_FB_LOCATION_BASE, 0,
                        FB_BASE, config->pa_config.system_aperture.fb_base);
        REG_SET(DCN_VM_FB_LOCATION_TOP, 0,
@@ -330,18 +368,27 @@ void hubbub2_init_dchub(struct hubbub *hubbub,
        REG_SET(DCN_VM_AGP_BASE, 0,
                        AGP_BASE, config->pa_config.system_aperture.agp_base);
 
-       // Init VMID 0 based on PA config
-       dcn20_vmid_setup(&hubbub1->vmid[0], &phys_config);
-       dcn20_vmid_set_ptb(&hubbub1->vmid[0], config->pa_config.gart_config.page_table_base_addr);
+       if (config->pa_config.gart_config.page_table_start_addr != config->pa_config.gart_config.page_table_end_addr) {
+               phys_config.depth = 1;
+               phys_config.block_size = 4096;
+               phys_config.page_table_start_addr = config->pa_config.gart_config.page_table_start_addr >> 12;
+               phys_config.page_table_end_addr = config->pa_config.gart_config.page_table_end_addr >> 12;
 
-       // Init VMID 1-15 based on VA config
-       for (i = 1; i < 16; i++) {
-               virt_config.page_table_start_addr = config->va_config.page_table_start_addr;
-               virt_config.page_table_end_addr = config->va_config.page_table_end_addr;
-               virt_config.depth = config->va_config.page_table_depth;
-               virt_config.block_size = config->va_config.page_table_block_size;
+               // Init VMID 0 based on PA config
+               dcn20_vmid_setup(&hubbub1->vmid[0], &phys_config);
+               dcn20_vmid_set_ptb(&hubbub1->vmid[0], config->pa_config.gart_config.page_table_base_addr);
+       }
+
+       if (config->va_config.page_table_start_addr != config->va_config.page_table_end_addr) {
+               // Init VMID 1-15 based on VA config
+               for (i = 1; i < 16; i++) {
+                       virt_config.page_table_start_addr = config->va_config.page_table_start_addr >> 12;
+                       virt_config.page_table_end_addr = config->va_config.page_table_end_addr >> 12;
+                       virt_config.depth = page_table_depth_to_hw(config->va_config.page_table_depth);
+                       virt_config.block_size = page_table_block_size_to_hw(config->va_config.page_table_block_size);
 
-               dcn20_vmid_setup(&hubbub1->vmid[i], &virt_config);
+                       dcn20_vmid_setup(&hubbub1->vmid[i], &virt_config);
+               }
        }
 }
 
index 914071393d1c1aaadf2e123db9e26a3f23cca8c9..2cbffe2809b63d9dd07830e442abf254d40e5230 100644 (file)
@@ -1631,8 +1631,9 @@ static void dcn20_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c
                        plane_state->address.page_table_base.quad_part,
                        pipe_ctx->pipe_idx);
 
-       // Call hubbub to program PTB of VMID
-       if (dc->res_pool->hubbub->funcs->setup_vmid_ptb)
+       // Call hubbub to program PTB of VMID only if its VA
+       // PA PTB is a one-time setup at init
+       if (vmid > 0 && dc->res_pool->hubbub->funcs->setup_vmid_ptb)
                dc->res_pool->hubbub->funcs->setup_vmid_ptb(dc->res_pool->hubbub,
                                plane_state->address.page_table_base.quad_part,
                                vmid);