From 6c0ee5f2fca373ee5ad945064973ded3780db54b Mon Sep 17 00:00:00 2001 From: Mykola Lysenko Date: Thu, 18 Feb 2016 05:43:37 -0500 Subject: [PATCH 0809/1110] drm/amd/dal: fix EXT clock source creation External clock source should only be created based on firmware info provided by bios Fix for dce10 to create pll2 Signed-off-by: Mykola Lysenko Acked-by: Harry Wentland --- .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c | 95 +++++++++++++++------- .../drm/amd/dal/dc/dce110/dce110_clock_source.c | 3 +- .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c | 66 +++++++++------ drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c | 73 +++++++++++------ 4 files changed, 157 insertions(+), 80 deletions(-) diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c index dcf44d4..f241318 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c @@ -61,6 +61,7 @@ enum dce100_clk_src_array_id { DCE100_CLK_SRC_PLL0 = 0, DCE100_CLK_SRC_PLL1, + DCE100_CLK_SRC_PLL2, DCE100_CLK_SRC_EXT, DCE100_CLK_SRC_TOTAL @@ -147,6 +148,10 @@ static const struct dce110_clk_src_reg_offsets dce100_clk_src_reg_offsets[] = { { .pll_cntl = mmBPHYC_PLL1_PLL_CNTL, .pixclk_resync_cntl = mmPIXCLK1_RESYNC_CNTL + }, + { + .pll_cntl = mmBPHYC_PLL2_PLL_CNTL, + .pixclk_resync_cntl = mmPIXCLK2_RESYNC_CNTL } }; @@ -586,13 +591,14 @@ void dce100_destruct_resource_pool(struct resource_pool *pool) static struct clock_source *find_first_free_pll( struct resource_context *res_ctx) { - if (res_ctx->clock_source_ref_count[DCE100_CLK_SRC_PLL0] == 0) - return res_ctx->pool.clock_sources[DCE100_CLK_SRC_PLL0]; + int i; - if (res_ctx->clock_source_ref_count[DCE100_CLK_SRC_PLL1] == 0) - return res_ctx->pool.clock_sources[DCE100_CLK_SRC_PLL1]; + for (i = 0; i < DCE100_CLK_SRC_EXT; ++i) { + if (res_ctx->clock_source_ref_count[i] == 0) + return res_ctx->pool.clock_sources[i]; + } - return 0; + return NULL; } static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) @@ -843,6 +849,7 @@ static enum dc_status map_clock_resources( pipe_ctx->clock_source = find_used_clk_src_for_sharing( &context->res_ctx, pipe_ctx); + if (pipe_ctx->clock_source == NULL) pipe_ctx->clock_source = find_first_free_pll(&context->res_ctx); @@ -926,7 +933,7 @@ static struct resource_funcs dce100_res_pool_funcs = { }; bool dce100_construct_resource_pool( - struct adapter_service *adapter_serv, + struct adapter_service *as, uint8_t num_virtual_links, struct dc *dc, struct resource_pool *pool) @@ -934,8 +941,10 @@ bool dce100_construct_resource_pool( unsigned int i; struct audio_init_data audio_init_data = { 0 }; struct dc_context *ctx = dc->ctx; + struct firmware_info info; + struct dc_bios *bp; - pool->adapter_srv = adapter_serv; + pool->adapter_srv = as; pool->funcs = &dce100_res_pool_funcs; pool->stream_engines.engine.ENGINE_ID_DIGA = 1; @@ -945,16 +954,40 @@ bool dce100_construct_resource_pool( pool->stream_engines.engine.ENGINE_ID_DIGE = 1; pool->stream_engines.engine.ENGINE_ID_DIGF = 1; - pool->clock_sources[DCE100_CLK_SRC_PLL0] = dce100_clock_source_create( - ctx, dal_adapter_service_get_bios_parser(adapter_serv), - CLOCK_SOURCE_ID_PLL0, &dce100_clk_src_reg_offsets[0]); - pool->clock_sources[DCE100_CLK_SRC_PLL1] = dce100_clock_source_create( - ctx, dal_adapter_service_get_bios_parser(adapter_serv), - CLOCK_SOURCE_ID_PLL1, &dce100_clk_src_reg_offsets[1]); - pool->clock_sources[DCE100_CLK_SRC_EXT] = dce100_clock_source_create( - ctx, dal_adapter_service_get_bios_parser(adapter_serv), - CLOCK_SOURCE_ID_EXTERNAL, &dce100_clk_src_reg_offsets[0]); - pool->clk_src_count = DCE100_CLK_SRC_TOTAL; + bp = dal_adapter_service_get_bios_parser(as); + + pool->clock_sources[DCE100_CLK_SRC_PLL0] = + dce100_clock_source_create( + ctx, + bp, + CLOCK_SOURCE_ID_PLL0, + &dce100_clk_src_reg_offsets[0]); + + pool->clock_sources[DCE100_CLK_SRC_PLL1] = + dce100_clock_source_create( + ctx, + bp, + CLOCK_SOURCE_ID_PLL1, + &dce100_clk_src_reg_offsets[1]); + + pool->clock_sources[DCE100_CLK_SRC_PLL2] = + dce100_clock_source_create( + ctx, + bp, + CLOCK_SOURCE_ID_PLL2, + &dce100_clk_src_reg_offsets[2]); + + if (dal_adapter_service_get_firmware_info(as, &info) && + info.external_clock_source_frequency_for_dp != 0) { + pool->clock_sources[DCE100_CLK_SRC_EXT] = + dce100_clock_source_create( + ctx, + bp, + CLOCK_SOURCE_ID_EXTERNAL, + NULL); + pool->clk_src_count = DCE100_CLK_SRC_TOTAL; + } else + pool->clk_src_count = DCE100_CLK_SRC_TOTAL - 1; for (i = 0; i < pool->clk_src_count; i++) { if (pool->clock_sources[i] == NULL) { @@ -964,7 +997,7 @@ bool dce100_construct_resource_pool( } } - pool->display_clock = dal_display_clock_dce110_create(ctx, adapter_serv); + pool->display_clock = dal_display_clock_dce110_create(ctx, as); if (pool->display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); @@ -984,11 +1017,10 @@ bool dce100_construct_resource_pool( } - pool->pipe_count = - dal_adapter_service_get_func_controllers_num(adapter_serv); - pool->stream_enc_count = dal_adapter_service_get_stream_engines_num( - adapter_serv); + pool->pipe_count = dal_adapter_service_get_func_controllers_num(as); + pool->stream_enc_count = dal_adapter_service_get_stream_engines_num(as); pool->scaler_filter = dal_scaler_filter_create(ctx); + if (pool->scaler_filter == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create filter!\n"); @@ -996,8 +1028,12 @@ bool dce100_construct_resource_pool( } for (i = 0; i < pool->pipe_count; i++) { - pool->timing_generators[i] = dce100_timing_generator_create( - adapter_serv, ctx, i, &dce100_tg_offsets[i]); + pool->timing_generators[i] = + dce100_timing_generator_create( + as, + ctx, + i, + &dce100_tg_offsets[i]); if (pool->timing_generators[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create tg!\n"); @@ -1043,13 +1079,13 @@ bool dce100_construct_resource_pool( } } - audio_init_data.as = adapter_serv; + audio_init_data.as = as; audio_init_data.ctx = ctx; pool->audio_count = 0; for (i = 0; i < pool->pipe_count; i++) { struct graphics_object_id obj_id; - obj_id = dal_adapter_service_enum_audio_object(adapter_serv, i); + obj_id = dal_adapter_service_enum_audio_object(as, i); if (false == dal_graphics_object_id_is_valid(obj_id)) { /* no more valid audio objects */ break; @@ -1070,8 +1106,7 @@ bool dce100_construct_resource_pool( if (pool->stream_engines.u_all & 1 << i) { pool->stream_enc[i] = dce100_stream_encoder_create( i, dc->ctx, - dal_adapter_service_get_bios_parser( - adapter_serv), + dal_adapter_service_get_bios_parser(as), &stream_enc_regs[i]); if (pool->stream_enc[i] == NULL) { BREAK_TO_DEBUGGER(); @@ -1084,8 +1119,8 @@ bool dce100_construct_resource_pool( for (i = 0; i < num_virtual_links; i++) { pool->stream_enc[pool->stream_enc_count] = virtual_stream_encoder_create( - dc->ctx, dal_adapter_service_get_bios_parser( - adapter_serv)); + dc->ctx, + dal_adapter_service_get_bios_parser(as)); if (pool->stream_enc[pool->stream_enc_count] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create stream_encoder!\n"); diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c index e1bac1f..ba2929b 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c @@ -1110,7 +1110,6 @@ bool dce110_clk_src_construct( clk_src->bios = bios; clk_src->base.id = id; clk_src->base.funcs = &dce110_clk_src_funcs; - clk_src->offsets = *reg_offsets; if (clk_src->bios->funcs->get_firmware_info( clk_src->bios, &fw_info) != BP_RESULT_OK) { @@ -1125,6 +1124,8 @@ bool dce110_clk_src_construct( if (clk_src->base.id == CLOCK_SOURCE_ID_EXTERNAL) return true; + clk_src->offsets = *reg_offsets; + /* PLL only from here on */ ss_info_from_atombios_create(clk_src); diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c index c65f401..26fc104 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c @@ -1046,7 +1046,7 @@ static struct resource_funcs dce110_res_pool_funcs = { }; bool dce110_construct_resource_pool( - struct adapter_service *adapter_serv, + struct adapter_service *as, uint8_t num_virtual_links, struct dc *dc, struct resource_pool *pool) @@ -1054,7 +1054,10 @@ bool dce110_construct_resource_pool( unsigned int i; struct audio_init_data audio_init_data = { 0 }; struct dc_context *ctx = dc->ctx; - pool->adapter_srv = adapter_serv; + struct firmware_info info; + struct dc_bios *bp; + + pool->adapter_srv = as; pool->funcs = &dce110_res_pool_funcs; pool->stream_engines.engine.ENGINE_ID_DIGA = 1; @@ -1064,16 +1067,33 @@ bool dce110_construct_resource_pool( pool->stream_engines.engine.ENGINE_ID_DIGE = 1; pool->stream_engines.engine.ENGINE_ID_DIGF = 1; - pool->clock_sources[DCE110_CLK_SRC_PLL0] = dce110_clock_source_create( - ctx, dal_adapter_service_get_bios_parser(adapter_serv), - CLOCK_SOURCE_ID_PLL0, &dce110_clk_src_reg_offsets[0]); - pool->clock_sources[DCE110_CLK_SRC_PLL1] = dce110_clock_source_create( - ctx, dal_adapter_service_get_bios_parser(adapter_serv), - CLOCK_SOURCE_ID_PLL1, &dce110_clk_src_reg_offsets[1]); - pool->clock_sources[DCE110_CLK_SRC_EXT] = dce110_clock_source_create( - ctx, dal_adapter_service_get_bios_parser(adapter_serv), - CLOCK_SOURCE_ID_EXTERNAL, &dce110_clk_src_reg_offsets[0]); - pool->clk_src_count = DCE110_CLK_SRC_TOTAL; + bp = dal_adapter_service_get_bios_parser(as); + + pool->clock_sources[DCE110_CLK_SRC_PLL0] = + dce110_clock_source_create( + ctx, + bp, + CLOCK_SOURCE_ID_PLL0, + &dce110_clk_src_reg_offsets[0]); + + pool->clock_sources[DCE110_CLK_SRC_PLL1] = + dce110_clock_source_create( + ctx, + bp, + CLOCK_SOURCE_ID_PLL1, + &dce110_clk_src_reg_offsets[1]); + + if (dal_adapter_service_get_firmware_info(as, &info) && + info.external_clock_source_frequency_for_dp != 0) { + pool->clock_sources[DCE110_CLK_SRC_EXT] = + dce110_clock_source_create( + ctx, + bp, + CLOCK_SOURCE_ID_EXTERNAL, + NULL); + pool->clk_src_count = DCE110_CLK_SRC_TOTAL; + } else + pool->clk_src_count = DCE110_CLK_SRC_TOTAL - 1; for (i = 0; i < pool->clk_src_count; i++) { if (pool->clock_sources[i] == NULL) { @@ -1083,7 +1103,7 @@ bool dce110_construct_resource_pool( } } - pool->display_clock = dal_display_clock_dce110_create(ctx, adapter_serv); + pool->display_clock = dal_display_clock_dce110_create(ctx, as); if (pool->display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); @@ -1102,10 +1122,8 @@ bool dce110_construct_resource_pool( } - pool->pipe_count = - dal_adapter_service_get_func_controllers_num(adapter_serv); - pool->stream_enc_count = dal_adapter_service_get_stream_engines_num( - adapter_serv); + pool->pipe_count = dal_adapter_service_get_func_controllers_num(as); + pool->stream_enc_count = dal_adapter_service_get_stream_engines_num(as); pool->scaler_filter = dal_scaler_filter_create(ctx); if (pool->scaler_filter == NULL) { BREAK_TO_DEBUGGER(); @@ -1115,7 +1133,7 @@ bool dce110_construct_resource_pool( for (i = 0; i < pool->pipe_count; i++) { pool->timing_generators[i] = dce110_timing_generator_create( - adapter_serv, ctx, i, &dce110_tg_offsets[i]); + as, ctx, i, &dce110_tg_offsets[i]); if (pool->timing_generators[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create tg!\n"); @@ -1160,13 +1178,13 @@ bool dce110_construct_resource_pool( } } - audio_init_data.as = adapter_serv; + audio_init_data.as = as; audio_init_data.ctx = ctx; pool->audio_count = 0; for (i = 0; i < pool->pipe_count; i++) { struct graphics_object_id obj_id; - obj_id = dal_adapter_service_enum_audio_object(adapter_serv, i); + obj_id = dal_adapter_service_enum_audio_object(as, i); if (false == dal_graphics_object_id_is_valid(obj_id)) { /* no more valid audio objects */ break; @@ -1187,8 +1205,7 @@ bool dce110_construct_resource_pool( if (pool->stream_engines.u_all & 1 << i) { pool->stream_enc[i] = dce110_stream_encoder_create( i, dc->ctx, - dal_adapter_service_get_bios_parser( - adapter_serv), + dal_adapter_service_get_bios_parser(as), &stream_enc_regs[i]); if (pool->stream_enc[i] == NULL) { BREAK_TO_DEBUGGER(); @@ -1201,8 +1218,9 @@ bool dce110_construct_resource_pool( for (i = 0; i < num_virtual_links; i++) { pool->stream_enc[pool->stream_enc_count] = virtual_stream_encoder_create( - dc->ctx, dal_adapter_service_get_bios_parser( - adapter_serv)); + dc->ctx, + dal_adapter_service_get_bios_parser(as)); + if (pool->stream_enc[pool->stream_enc_count] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create stream_encoder!\n"); diff --git a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c index 1eeb469..c7bfa28 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c @@ -1048,7 +1048,7 @@ static struct resource_funcs dce80_res_pool_funcs = { }; bool dce80_construct_resource_pool( - struct adapter_service *adapter_serv, + struct adapter_service *as, uint8_t num_virtual_links, struct dc *dc, struct resource_pool *pool) @@ -1056,7 +1056,10 @@ bool dce80_construct_resource_pool( unsigned int i; struct audio_init_data audio_init_data = { 0 }; struct dc_context *ctx = dc->ctx; - pool->adapter_srv = adapter_serv; + struct firmware_info info; + struct dc_bios *bp; + + pool->adapter_srv = as; pool->funcs = &dce80_res_pool_funcs; pool->stream_engines.engine.ENGINE_ID_DIGA = 1; @@ -1066,19 +1069,41 @@ bool dce80_construct_resource_pool( pool->stream_engines.engine.ENGINE_ID_DIGE = 1; pool->stream_engines.engine.ENGINE_ID_DIGF = 1; - pool->clock_sources[DCE80_CLK_SRC_PLL0] = dce80_clock_source_create( - ctx, dal_adapter_service_get_bios_parser(adapter_serv), - CLOCK_SOURCE_ID_PLL0, &dce80_clk_src_reg_offsets[0]); - pool->clock_sources[DCE80_CLK_SRC_PLL1] = dce80_clock_source_create( - ctx, dal_adapter_service_get_bios_parser(adapter_serv), - CLOCK_SOURCE_ID_PLL1, &dce80_clk_src_reg_offsets[1]); - pool->clock_sources[DCE80_CLK_SRC_PLL2] = dce80_clock_source_create( - ctx, dal_adapter_service_get_bios_parser(adapter_serv), - CLOCK_SOURCE_ID_PLL2, &dce80_clk_src_reg_offsets[2]); - pool->clock_sources[DCE80_CLK_SRC_EXT] = dce80_clock_source_create( - ctx, dal_adapter_service_get_bios_parser(adapter_serv), - CLOCK_SOURCE_ID_EXTERNAL, &dce80_clk_src_reg_offsets[0]); - pool->clk_src_count = DCE80_CLK_SRC_TOTAL; + bp = dal_adapter_service_get_bios_parser(as); + + pool->clock_sources[DCE80_CLK_SRC_PLL0] = + dce80_clock_source_create( + ctx, + bp, + CLOCK_SOURCE_ID_PLL0, + &dce80_clk_src_reg_offsets[0]); + + pool->clock_sources[DCE80_CLK_SRC_PLL1] = + dce80_clock_source_create( + ctx, + bp, + CLOCK_SOURCE_ID_PLL1, + &dce80_clk_src_reg_offsets[1]); + + pool->clock_sources[DCE80_CLK_SRC_PLL2] = + dce80_clock_source_create( + ctx, + bp, + CLOCK_SOURCE_ID_PLL2, + &dce80_clk_src_reg_offsets[2]); + + if (dal_adapter_service_get_firmware_info(as, &info) && + info.external_clock_source_frequency_for_dp != 0) { + pool->clock_sources[DCE80_CLK_SRC_EXT] = + dce80_clock_source_create( + ctx, + bp, + CLOCK_SOURCE_ID_EXTERNAL, + NULL); + + pool->clk_src_count = DCE80_CLK_SRC_TOTAL; + } else + pool->clk_src_count = DCE80_CLK_SRC_TOTAL - 1; for (i = 0; i < pool->clk_src_count; i++) { if (pool->clock_sources[i] == NULL) { @@ -1088,7 +1113,7 @@ bool dce80_construct_resource_pool( } } - pool->display_clock = dal_display_clock_dce80_create(ctx, adapter_serv); + pool->display_clock = dal_display_clock_dce80_create(ctx, as); if (pool->display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); @@ -1107,10 +1132,8 @@ bool dce80_construct_resource_pool( } - pool->pipe_count = - dal_adapter_service_get_func_controllers_num(adapter_serv); - pool->stream_enc_count = - dal_adapter_service_get_stream_engines_num(adapter_serv); + pool->pipe_count = dal_adapter_service_get_func_controllers_num(as); + pool->stream_enc_count = dal_adapter_service_get_stream_engines_num(as); pool->scaler_filter = dal_scaler_filter_create(ctx); if (pool->scaler_filter == NULL) { BREAK_TO_DEBUGGER(); @@ -1120,7 +1143,7 @@ bool dce80_construct_resource_pool( for (i = 0; i < pool->pipe_count; i++) { pool->timing_generators[i] = dce80_timing_generator_create( - adapter_serv, ctx, i, &dce80_tg_offsets[i]); + as, ctx, i, &dce80_tg_offsets[i]); if (pool->timing_generators[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create tg!\n"); @@ -1161,13 +1184,13 @@ bool dce80_construct_resource_pool( } } - audio_init_data.as = adapter_serv; + audio_init_data.as = as; audio_init_data.ctx = ctx; pool->audio_count = 0; for (i = 0; i < pool->pipe_count; i++) { struct graphics_object_id obj_id; - obj_id = dal_adapter_service_enum_audio_object(adapter_serv, i); + obj_id = dal_adapter_service_enum_audio_object(as, i); if (false == dal_graphics_object_id_is_valid(obj_id)) { /* no more valid audio objects */ break; @@ -1188,7 +1211,7 @@ bool dce80_construct_resource_pool( pool->stream_enc[i] = dce80_stream_encoder_create( i, dc->ctx, dal_adapter_service_get_bios_parser( - adapter_serv), + as), &stream_enc_regs[i]); if (pool->stream_enc[i] == NULL) { @@ -1203,7 +1226,7 @@ bool dce80_construct_resource_pool( pool->stream_enc[pool->stream_enc_count] = virtual_stream_encoder_create( dc->ctx, dal_adapter_service_get_bios_parser( - adapter_serv)); + as)); if (pool->stream_enc[pool->stream_enc_count] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create stream_encoder!\n"); -- 2.7.4