diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0759-drm-amd-disply-dc-add-resource-support-for-DCE8-APUs.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0759-drm-amd-disply-dc-add-resource-support-for-DCE8-APUs.patch | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0759-drm-amd-disply-dc-add-resource-support-for-DCE8-APUs.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0759-drm-amd-disply-dc-add-resource-support-for-DCE8-APUs.patch new file mode 100644 index 00000000..f87d75ee --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0759-drm-amd-disply-dc-add-resource-support-for-DCE8-APUs.patch @@ -0,0 +1,434 @@ +From 9a0578275e9610338c200947c5fb02ffcb6b2f32 Mon Sep 17 00:00:00 2001 +From: Alex Deucher <alexdeucher@gmail.com> +Date: Thu, 10 Aug 2017 14:39:51 -0400 +Subject: [PATCH 0759/4131] drm/amd/disply/dc: add resource support for DCE8 + APUs (v2) + +Add the appropriate resources for APUs: +KV: 4 pipes, 7 dig, 3 PPLLs +KB/ML: 2 pipes, 6 dig, 2 PPLLs + +v2: rebase changes + +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Reviewed-by: Harry Wentland <harry.wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 +- + .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 343 ++++++++++++++++++++- + .../gpu/drm/amd/display/dc/dce80/dce80_resource.h | 8 + + 3 files changed, 356 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index e7d9045..f010039 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -101,9 +101,15 @@ struct resource_pool *dc_create_resource_pool( + + switch (dc_version) { + case DCE_VERSION_8_0: ++ res_pool = dce80_create_resource_pool( ++ num_virtual_links, dc); ++ break; + case DCE_VERSION_8_1: ++ res_pool = dce81_create_resource_pool( ++ num_virtual_links, dc); ++ break; + case DCE_VERSION_8_3: +- res_pool = dce80_create_resource_pool( ++ res_pool = dce83_create_resource_pool( + num_virtual_links, dc); + break; + case DCE_VERSION_10_0: +diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +index 40a9591..132117e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +@@ -350,6 +350,20 @@ static const struct resource_caps res_cap = { + .num_pll = 3, + }; + ++static const struct resource_caps res_cap_81 = { ++ .num_timing_generator = 4, ++ .num_audio = 7, ++ .num_stream_encoder = 7, ++ .num_pll = 3, ++}; ++ ++static const struct resource_caps res_cap_83 = { ++ .num_timing_generator = 2, ++ .num_audio = 6, ++ .num_stream_encoder = 6, ++ .num_pll = 2, ++}; ++ + #define CTX ctx + #define REG(reg) mm ## reg + +@@ -829,7 +843,7 @@ static const struct resource_funcs dce80_res_pool_funcs = { + .validate_plane = dce100_validate_plane + }; + +-static bool construct( ++static bool dce80_construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +@@ -987,10 +1001,335 @@ struct resource_pool *dce80_create_resource_pool( + if (!pool) + return NULL; + +- if (construct(num_virtual_links, dc, pool)) ++ if (dce80_construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; + } + ++static bool dce81_construct( ++ uint8_t num_virtual_links, ++ struct core_dc *dc, ++ struct dce110_resource_pool *pool) ++{ ++ unsigned int i; ++ struct dc_context *ctx = dc->ctx; ++ struct dc_firmware_info info; ++ struct dc_bios *bp; ++ struct dm_pp_static_clock_info static_clk_info = {0}; ++ ++ ctx->dc_bios->regs = &bios_regs; ++ ++ pool->base.res_cap = &res_cap_81; ++ pool->base.funcs = &dce80_res_pool_funcs; ++ ++ ++ /************************************************* ++ * Resource + asic cap harcoding * ++ *************************************************/ ++ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; ++ pool->base.pipe_count = res_cap_81.num_timing_generator; ++ dc->public.caps.max_downscale_ratio = 200; ++ dc->public.caps.i2c_speed_in_khz = 40; ++ dc->public.caps.max_cursor_size = 128; ++ ++ /************************************************* ++ * Create resources * ++ *************************************************/ ++ ++ bp = ctx->dc_bios; ++ ++ if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && ++ info.external_clock_source_frequency_for_dp != 0) { ++ pool->base.dp_clock_source = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); ++ ++ pool->base.clock_sources[0] = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); ++ pool->base.clock_sources[1] = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); ++ pool->base.clock_sources[2] = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); ++ pool->base.clk_src_count = 3; ++ ++ } else { ++ pool->base.dp_clock_source = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); ++ ++ pool->base.clock_sources[0] = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); ++ pool->base.clock_sources[1] = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); ++ pool->base.clk_src_count = 2; ++ } ++ ++ if (pool->base.dp_clock_source == NULL) { ++ dm_error("DC: failed to create dp clock source!\n"); ++ BREAK_TO_DEBUGGER(); ++ goto res_create_fail; ++ } ++ ++ for (i = 0; i < pool->base.clk_src_count; i++) { ++ if (pool->base.clock_sources[i] == NULL) { ++ dm_error("DC: failed to create clock sources!\n"); ++ BREAK_TO_DEBUGGER(); ++ goto res_create_fail; ++ } ++ } ++ ++ pool->base.display_clock = dce_disp_clk_create(ctx, ++ &disp_clk_regs, ++ &disp_clk_shift, ++ &disp_clk_mask); ++ if (pool->base.display_clock == NULL) { ++ dm_error("DC: failed to create display clock!\n"); ++ BREAK_TO_DEBUGGER(); ++ goto res_create_fail; ++ } ++ ++ ++ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) ++ pool->base.display_clock->max_clks_state = ++ static_clk_info.max_clocks_state; ++ ++ { ++ struct irq_service_init_data init_data; ++ init_data.ctx = dc->ctx; ++ pool->base.irqs = dal_irq_service_dce80_create(&init_data); ++ if (!pool->base.irqs) ++ goto res_create_fail; ++ } ++ ++ for (i = 0; i < pool->base.pipe_count; i++) { ++ pool->base.timing_generators[i] = dce80_timing_generator_create( ++ ctx, i, &dce80_tg_offsets[i]); ++ if (pool->base.timing_generators[i] == NULL) { ++ BREAK_TO_DEBUGGER(); ++ dm_error("DC: failed to create tg!\n"); ++ goto res_create_fail; ++ } ++ ++ pool->base.mis[i] = dce80_mem_input_create(ctx, i); ++ if (pool->base.mis[i] == NULL) { ++ BREAK_TO_DEBUGGER(); ++ dm_error("DC: failed to create memory input!\n"); ++ goto res_create_fail; ++ } ++ ++ pool->base.ipps[i] = dce80_ipp_create(ctx, i); ++ if (pool->base.ipps[i] == NULL) { ++ BREAK_TO_DEBUGGER(); ++ dm_error("DC: failed to create input pixel processor!\n"); ++ goto res_create_fail; ++ } ++ ++ pool->base.transforms[i] = dce80_transform_create(ctx, i); ++ if (pool->base.transforms[i] == NULL) { ++ BREAK_TO_DEBUGGER(); ++ dm_error("DC: failed to create transform!\n"); ++ goto res_create_fail; ++ } ++ ++ pool->base.opps[i] = dce80_opp_create(ctx, i); ++ if (pool->base.opps[i] == NULL) { ++ BREAK_TO_DEBUGGER(); ++ dm_error("DC: failed to create output pixel processor!\n"); ++ goto res_create_fail; ++ } ++ } ++ ++ dc->public.caps.max_planes = pool->base.pipe_count; ++ ++ if (!resource_construct(num_virtual_links, dc, &pool->base, ++ &res_create_funcs)) ++ goto res_create_fail; ++ ++ /* Create hardware sequencer */ ++ if (!dce80_hw_sequencer_construct(dc)) ++ goto res_create_fail; ++ ++ return true; ++ ++res_create_fail: ++ destruct(pool); ++ return false; ++} ++ ++struct resource_pool *dce81_create_resource_pool( ++ uint8_t num_virtual_links, ++ struct core_dc *dc) ++{ ++ struct dce110_resource_pool *pool = ++ dm_alloc(sizeof(struct dce110_resource_pool)); ++ ++ if (!pool) ++ return NULL; ++ ++ if (dce81_construct(num_virtual_links, dc, pool)) ++ return &pool->base; ++ ++ BREAK_TO_DEBUGGER(); ++ return NULL; ++} ++ ++static bool dce83_construct( ++ uint8_t num_virtual_links, ++ struct core_dc *dc, ++ struct dce110_resource_pool *pool) ++{ ++ unsigned int i; ++ struct dc_context *ctx = dc->ctx; ++ struct dc_firmware_info info; ++ struct dc_bios *bp; ++ struct dm_pp_static_clock_info static_clk_info = {0}; ++ ++ ctx->dc_bios->regs = &bios_regs; ++ ++ pool->base.res_cap = &res_cap_83; ++ pool->base.funcs = &dce80_res_pool_funcs; ++ ++ ++ /************************************************* ++ * Resource + asic cap harcoding * ++ *************************************************/ ++ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; ++ pool->base.pipe_count = res_cap_83.num_timing_generator; ++ dc->public.caps.max_downscale_ratio = 200; ++ dc->public.caps.i2c_speed_in_khz = 40; ++ dc->public.caps.max_cursor_size = 128; ++ ++ /************************************************* ++ * Create resources * ++ *************************************************/ ++ ++ bp = ctx->dc_bios; ++ ++ if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && ++ info.external_clock_source_frequency_for_dp != 0) { ++ pool->base.dp_clock_source = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); ++ ++ pool->base.clock_sources[0] = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false); ++ pool->base.clock_sources[1] = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); ++ pool->base.clk_src_count = 2; ++ ++ } else { ++ pool->base.dp_clock_source = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true); ++ ++ pool->base.clock_sources[0] = ++ dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); ++ pool->base.clk_src_count = 1; ++ } ++ ++ if (pool->base.dp_clock_source == NULL) { ++ dm_error("DC: failed to create dp clock source!\n"); ++ BREAK_TO_DEBUGGER(); ++ goto res_create_fail; ++ } ++ ++ for (i = 0; i < pool->base.clk_src_count; i++) { ++ if (pool->base.clock_sources[i] == NULL) { ++ dm_error("DC: failed to create clock sources!\n"); ++ BREAK_TO_DEBUGGER(); ++ goto res_create_fail; ++ } ++ } ++ ++ pool->base.display_clock = dce_disp_clk_create(ctx, ++ &disp_clk_regs, ++ &disp_clk_shift, ++ &disp_clk_mask); ++ if (pool->base.display_clock == NULL) { ++ dm_error("DC: failed to create display clock!\n"); ++ BREAK_TO_DEBUGGER(); ++ goto res_create_fail; ++ } ++ ++ ++ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) ++ pool->base.display_clock->max_clks_state = ++ static_clk_info.max_clocks_state; ++ ++ { ++ struct irq_service_init_data init_data; ++ init_data.ctx = dc->ctx; ++ pool->base.irqs = dal_irq_service_dce80_create(&init_data); ++ if (!pool->base.irqs) ++ goto res_create_fail; ++ } ++ ++ for (i = 0; i < pool->base.pipe_count; i++) { ++ pool->base.timing_generators[i] = dce80_timing_generator_create( ++ ctx, i, &dce80_tg_offsets[i]); ++ if (pool->base.timing_generators[i] == NULL) { ++ BREAK_TO_DEBUGGER(); ++ dm_error("DC: failed to create tg!\n"); ++ goto res_create_fail; ++ } ++ ++ pool->base.mis[i] = dce80_mem_input_create(ctx, i); ++ if (pool->base.mis[i] == NULL) { ++ BREAK_TO_DEBUGGER(); ++ dm_error("DC: failed to create memory input!\n"); ++ goto res_create_fail; ++ } ++ ++ pool->base.ipps[i] = dce80_ipp_create(ctx, i); ++ if (pool->base.ipps[i] == NULL) { ++ BREAK_TO_DEBUGGER(); ++ dm_error("DC: failed to create input pixel processor!\n"); ++ goto res_create_fail; ++ } ++ ++ pool->base.transforms[i] = dce80_transform_create(ctx, i); ++ if (pool->base.transforms[i] == NULL) { ++ BREAK_TO_DEBUGGER(); ++ dm_error("DC: failed to create transform!\n"); ++ goto res_create_fail; ++ } ++ ++ pool->base.opps[i] = dce80_opp_create(ctx, i); ++ if (pool->base.opps[i] == NULL) { ++ BREAK_TO_DEBUGGER(); ++ dm_error("DC: failed to create output pixel processor!\n"); ++ goto res_create_fail; ++ } ++ } ++ ++ dc->public.caps.max_planes = pool->base.pipe_count; ++ ++ if (!resource_construct(num_virtual_links, dc, &pool->base, ++ &res_create_funcs)) ++ goto res_create_fail; ++ ++ /* Create hardware sequencer */ ++ if (!dce80_hw_sequencer_construct(dc)) ++ goto res_create_fail; ++ ++ return true; ++ ++res_create_fail: ++ destruct(pool); ++ return false; ++} ++ ++struct resource_pool *dce83_create_resource_pool( ++ uint8_t num_virtual_links, ++ struct core_dc *dc) ++{ ++ struct dce110_resource_pool *pool = ++ dm_alloc(sizeof(struct dce110_resource_pool)); ++ ++ if (!pool) ++ return NULL; ++ ++ if (dce83_construct(num_virtual_links, dc, pool)) ++ return &pool->base; ++ ++ BREAK_TO_DEBUGGER(); ++ return NULL; ++} +diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h +index 2a0cdcc..04f0cfe 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h ++++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h +@@ -35,5 +35,13 @@ struct resource_pool *dce80_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + ++struct resource_pool *dce81_create_resource_pool( ++ uint8_t num_virtual_links, ++ struct core_dc *dc); ++ ++struct resource_pool *dce83_create_resource_pool( ++ uint8_t num_virtual_links, ++ struct core_dc *dc); ++ + #endif /* __DC_RESOURCE_DCE80_H__ */ + +-- +2.7.4 + |