aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0861-drm-amd-dal-simplify-clock-sources-allocation.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0861-drm-amd-dal-simplify-clock-sources-allocation.patch')
-rw-r--r--common/recipes-kernel/linux/files/0861-drm-amd-dal-simplify-clock-sources-allocation.patch704
1 files changed, 704 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0861-drm-amd-dal-simplify-clock-sources-allocation.patch b/common/recipes-kernel/linux/files/0861-drm-amd-dal-simplify-clock-sources-allocation.patch
new file mode 100644
index 00000000..009490b3
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0861-drm-amd-dal-simplify-clock-sources-allocation.patch
@@ -0,0 +1,704 @@
+From 115c06efef095c72ba9fa30ebde9ab9418b59b8a Mon Sep 17 00:00:00 2001
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Date: Thu, 25 Feb 2016 06:25:10 -0500
+Subject: [PATCH 0861/1110] drm/amd/dal: simplify clock sources allocation
+
+Separate DP clock source from regular clock sources
+and so simplify DP clock source access
+
+Signed-off-by: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c | 74 ++++--------------
+ drivers/gpu/drm/amd/dal/dc/core/dc_resource.c | 49 ++++++++----
+ .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c | 82 ++++++++------------
+ .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c | 5 ++
+ .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c | 68 ++++++++--------
+ drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c | 90 +++++++++++-----------
+ drivers/gpu/drm/amd/dal/dc/inc/core_types.h | 6 ++
+ drivers/gpu/drm/amd/dal/dc/inc/resource.h | 3 +
+ 8 files changed, 174 insertions(+), 203 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
+index e4ea886..619e910 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
+@@ -1085,63 +1085,6 @@ static enum dc_link_rate get_max_link_rate(struct core_link *link)
+ return max_link_rate;
+ }
+
+-static enum clock_source_id get_clock_source_id_for_link_training(
+- struct core_link *link)
+-{
+- bool result;
+- struct dc_sink_init_data init_params = {0};
+- struct dc_sink *sink;
+- struct dc_stream *stream;
+- struct dc_target *target;
+- struct validate_context *context;
+- struct dc_validation_set set;
+- enum clock_source_id id = CLOCK_SOURCE_ID_UNDEFINED;
+-
+- init_params.link = &link->public;
+- init_params.sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
+- sink = dc_sink_create(&init_params);
+-
+- if (!sink)
+- goto fail_sink;
+-
+- stream = dc_create_stream_for_sink(sink);
+-
+- if (!stream)
+- goto fail_stream;
+-
+- target = dc_create_target_for_streams(&stream, 1);
+-
+- if (!target)
+- goto fail_target;
+-
+- set.surface_count = 0;
+- set.target = target;
+-
+- context = dm_alloc(sizeof(struct validate_context));
+-
+- if (!context)
+- goto fail_context;
+-
+- result = link->dc->res_pool.funcs->validate_with_context(
+- link->dc,
+- &set,
+- 1,
+- context);
+-
+- if (result)
+- id = context->res_ctx.pipe_ctx[0].clock_source->id;
+-
+- dm_free(context);
+-fail_context:
+- dc_target_release(target);
+-fail_target:
+- dc_stream_release(stream);
+-fail_stream:
+- dc_sink_release(sink);
+-fail_sink:
+- return id;
+-}
+-
+ bool dp_hbr_verify_link_cap(
+ struct core_link *link,
+ struct dc_link_settings *known_limit_link_setting)
+@@ -1152,11 +1095,12 @@ bool dp_hbr_verify_link_cap(
+ const struct dc_link_settings *cur;
+ bool skip_video_pattern;
+ uint32_t i;
++ struct clock_source *dp_cs;
++ enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
+
+ success = false;
+ skip_link_training = false;
+
+- /* TODO confirm this is correct for cz */
+ max_link_cap.lane_count = LANE_COUNT_FOUR;
+ max_link_cap.link_rate = get_max_link_rate(link);
+ max_link_cap.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
+@@ -1169,6 +1113,18 @@ bool dp_hbr_verify_link_cap(
+ /* disable PHY done possible by BIOS, will be done by driver itself */
+ dp_disable_link_phy(link, link->public.connector_signal);
+
++ dp_cs = link->dc->res_pool.dp_clock_source;
++
++ if (dp_cs)
++ dp_cs_id = dp_cs->id;
++ else {
++ /*
++ * dp clock source is not initialized for some reason.
++ * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used
++ */
++ ASSERT(dp_cs);
++ }
++
+ for (i = 0; i < get_link_training_fallback_table_len(link) &&
+ !success; i++) {
+ cur = get_link_training_fallback_table(link, i);
+@@ -1188,7 +1144,7 @@ bool dp_hbr_verify_link_cap(
+ dp_enable_link_phy(
+ link,
+ link->public.connector_signal,
+- get_clock_source_id_for_link_training(link),
++ dp_cs_id,
+ cur);
+
+ if (skip_link_training)
+diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
+index fcb9a0f..f5bfaf3 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
+@@ -72,14 +72,23 @@ void unreference_clock_source(
+ {
+ int i;
+ for (i = 0; i < res_ctx->pool.clk_src_count; i++) {
+- if (res_ctx->pool.clock_sources[i] == clock_source) {
+- res_ctx->clock_source_ref_count[i]--;
++ if (res_ctx->pool.clock_sources[i] != clock_source)
++ continue;
++
++ res_ctx->clock_source_ref_count[i]--;
+
+ if (res_ctx->clock_source_ref_count[i] == 0)
+ clock_source->funcs->cs_power_down(clock_source);
+- }
++
++ break;
+ }
+
++ if (res_ctx->pool.dp_clock_source == clock_source) {
++ res_ctx->dp_clock_source_ref_count--;
++
++ if (res_ctx->dp_clock_source_ref_count == 0)
++ clock_source->funcs->cs_power_down(clock_source);
++ }
+ }
+
+ void reference_clock_source(
+@@ -88,10 +97,15 @@ void reference_clock_source(
+ {
+ int i;
+ for (i = 0; i < res_ctx->pool.clk_src_count; i++) {
+- if (res_ctx->pool.clock_sources[i] == clock_source) {
+- res_ctx->clock_source_ref_count[i]++;
+- }
++ if (res_ctx->pool.clock_sources[i] != clock_source)
++ continue;
++
++ res_ctx->clock_source_ref_count[i]++;
++ break;
+ }
++
++ if (res_ctx->pool.dp_clock_source == clock_source)
++ res_ctx->dp_clock_source_ref_count++;
+ }
+
+ bool is_same_timing(
+@@ -109,21 +123,17 @@ static bool is_sharable_clk_src(
+ enum dce_version dce_ver = dal_adapter_service_get_dce_version(
+ pipe->stream->sink->link->adapter_srv);
+
+- /* Currently no clocks are shared for DCE 10 until VBIOS behaviour
++ /* Currently no clocks are shared for DCE 10 until VBIOS behavior
+ * is verified for this use case
+ */
+- if (dce_ver == DCE_VERSION_10_0 && !dc_is_dp_signal(pipe->signal))
++ if (dce_ver == DCE_VERSION_10_0)
+ return false;
+ #endif
+
+ if (pipe_with_clk_src->clock_source == NULL)
+ return false;
+
+- if (dc_is_dp_signal(pipe->signal) &&
+- dc_is_dp_signal(pipe_with_clk_src->signal))
+- return true;
+-
+- if (pipe->signal != pipe_with_clk_src->signal)
++ if (dc_is_dp_signal(pipe_with_clk_src->signal))
+ return false;
+
+ if(!is_same_timing(
+@@ -1275,6 +1285,19 @@ void val_ctx_copy_construct(
+ }
+ }
+
++struct clock_source *dc_resource_find_first_free_pll(
++ struct resource_context *res_ctx)
++{
++ int i;
++
++ for (i = 0; i < res_ctx->pool.clk_src_count; ++i) {
++ if (res_ctx->clock_source_ref_count[i] == 0)
++ return res_ctx->pool.clock_sources[i];
++ }
++
++ return NULL;
++}
++
+ void build_info_frame(struct pipe_ctx *pipe_ctx)
+ {
+ enum signal_type signal = SIGNAL_TYPE_NONE;
+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 6260751..642c82a 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
+@@ -59,10 +59,9 @@
+ #endif
+
+ 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_SRC0 = 0,
++ DCE100_CLK_SRC1,
++ DCE100_CLK_SRC2,
+
+ DCE100_CLK_SRC_TOTAL
+ };
+@@ -560,6 +559,9 @@ void dce100_destruct_resource_pool(struct resource_pool *pool)
+ dce100_clock_source_destroy(&pool->clock_sources[i]);
+ }
+
++ if (pool->dp_clock_source != NULL)
++ dce100_clock_source_destroy(&pool->dp_clock_source);
++
+ for (i = 0; i < pool->audio_count; i++) {
+ if (pool->audios[i] != NULL)
+ dal_audio_destroy(&pool->audios[i]);
+@@ -578,19 +580,6 @@ void dce100_destruct_resource_pool(struct resource_pool *pool)
+ dal_adapter_service_destroy(&pool->adapter_srv);
+ }
+
+-static struct clock_source *find_first_free_pll(
+- struct resource_context *res_ctx)
+-{
+- int i;
+-
+- 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 NULL;
+-}
+-
+ static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
+ {
+ switch (crtc_id) {
+@@ -838,17 +827,18 @@ static enum dc_status map_clock_resources(
+ */
+ if (dc_is_dp_signal(pipe_ctx->signal)
+ || pipe_ctx->signal == SIGNAL_TYPE_VIRTUAL)
+- pipe_ctx->clock_source = context->res_ctx.pool.clock_sources[DCE100_CLK_SRC_EXT];
+-
+- if (pipe_ctx->clock_source == NULL)
++ pipe_ctx->clock_source =
++ context->res_ctx.pool.dp_clock_source;
++ else {
+ 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);
++ if (pipe_ctx->clock_source == NULL)
++ pipe_ctx->clock_source =
++ dc_resource_find_first_free_pll(&context->res_ctx);
++ }
+
+ if (pipe_ctx->clock_source == NULL)
+ return DC_NO_CLOCK_SOURCE_RESOURCE;
+@@ -946,6 +936,7 @@ bool dce100_construct_resource_pool(
+ struct dc_context *ctx = dc->ctx;
+ struct firmware_info info;
+ struct dc_bios *bp;
++ int regular_pll_offset = 0;
+
+ pool->adapter_srv = as;
+ pool->funcs = &dce100_res_pool_funcs;
+@@ -959,38 +950,33 @@ bool dce100_construct_resource_pool(
+
+ 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] =
++ pool->dp_clock_source =
+ 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;
++ } else {
++ pool->dp_clock_source =
++ dce100_clock_source_create(
++ ctx,
++ bp,
++ CLOCK_SOURCE_ID_PLL0,
++ &dce100_clk_src_reg_offsets[0]);
++ regular_pll_offset = 1;
++ }
++
++ pool->clk_src_count = DCE100_CLK_SRC_TOTAL - regular_pll_offset;
++
++ for (i = 0; i < pool->clk_src_count; ++i, ++regular_pll_offset)
++ pool->clock_sources[i] =
++ dce100_clock_source_create(
++ ctx,
++ bp,
++ CLOCK_SOURCE_ID_PLL0 + regular_pll_offset,
++ &dce100_clk_src_reg_offsets[regular_pll_offset]);
+
+ for (i = 0; i < pool->clk_src_count; i++) {
+ if (pool->clock_sources[i] == NULL) {
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
+index de727fb..4e4ada8 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
+@@ -925,6 +925,10 @@ static void power_down_clock_sources(struct core_dc *dc)
+ {
+ int i;
+
++ if (dc->res_pool.dp_clock_source->funcs->cs_power_down(
++ dc->res_pool.dp_clock_source) == false)
++ dm_error("Failed to power down pll! (dp clk src)\n");
++
+ for (i = 0; i < dc->res_pool.clk_src_count; i++) {
+ if (dc->res_pool.clock_sources[i]->funcs->cs_power_down(
+ dc->res_pool.clock_sources[i]) == false)
+@@ -1429,6 +1433,7 @@ static void update_plane_addrs(struct core_dc *dc, struct resource_context *res_
+ PIPE_LOCK_CONTROL_SURFACE,
+ false);
+
++
+ if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, false)) {
+ dm_error("DC: failed to unblank crtc!\n");
+ BREAK_TO_DEBUGGER();
+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 2ebd398..1a315c0 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
+@@ -60,9 +60,8 @@
+ #endif
+
+ enum dce110_clk_src_array_id {
+- DCE110_CLK_SRC_PLL0 = 0,
+- DCE110_CLK_SRC_PLL1,
+- DCE110_CLK_SRC_EXT,
++ DCE110_CLK_SRC0 = 0,
++ DCE110_CLK_SRC1,
+
+ DCE110_CLK_SRC_TOTAL
+ };
+@@ -508,6 +507,9 @@ void dce110_destruct_resource_pool(struct resource_pool *pool)
+ }
+ }
+
++ if (pool->dp_clock_source != NULL)
++ dce110_clock_source_destroy(&pool->dp_clock_source);
++
+ for (i = 0; i < pool->audio_count; i++) {
+ if (pool->audios[i] != NULL) {
+ dal_audio_destroy(&pool->audios[i]);
+@@ -530,19 +532,6 @@ void dce110_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[DCE110_CLK_SRC_PLL0] == 0) {
+- return res_ctx->pool.clock_sources[DCE110_CLK_SRC_PLL0];
+- }
+- if (res_ctx->clock_source_ref_count[DCE110_CLK_SRC_PLL1] == 0) {
+- return res_ctx->pool.clock_sources[DCE110_CLK_SRC_PLL1];
+- }
+-
+- return 0;
+-}
+-
+ static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
+ {
+ switch (crtc_id) {
+@@ -955,15 +944,17 @@ static enum dc_status map_clock_resources(
+
+ if (dc_is_dp_signal(pipe_ctx->signal)
+ || pipe_ctx->signal == SIGNAL_TYPE_VIRTUAL)
+- pipe_ctx->clock_source = context->res_ctx.
+- pool.clock_sources[DCE110_CLK_SRC_EXT];
+- else
++ pipe_ctx->clock_source =
++ context->res_ctx.pool.dp_clock_source;
++ else {
+ 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);
++
++ if (pipe_ctx->clock_source == NULL)
++ pipe_ctx->clock_source =
++ dc_resource_find_first_free_pll(&context->res_ctx);
++ }
+
+ if (pipe_ctx->clock_source == NULL)
+ return DC_NO_CLOCK_SOURCE_RESOURCE;
+@@ -1097,32 +1088,37 @@ bool dce110_construct_resource_pool(
+
+ bp = dal_adapter_service_get_bios_parser(as);
+
+- pool->clock_sources[DCE110_CLK_SRC_PLL0] =
++ if (dal_adapter_service_get_firmware_info(as, &info) &&
++ info.external_clock_source_frequency_for_dp != 0) {
++ pool->dp_clock_source =
++ dce110_clock_source_create(
++ ctx,
++ bp,
++ CLOCK_SOURCE_ID_EXTERNAL,
++ NULL);
++ } else {
++ pool->dp_clock_source =
++ dce110_clock_source_create(
++ ctx,
++ bp,
++ CLOCK_SOURCE_ID_PLL0,
++ &dce110_clk_src_reg_offsets[0]);
++ }
++
++ pool->clock_sources[DCE110_CLK_SRC0] =
+ dce110_clock_source_create(
+ ctx,
+ bp,
+ CLOCK_SOURCE_ID_PLL0,
+ &dce110_clk_src_reg_offsets[0]);
+
+- pool->clock_sources[DCE110_CLK_SRC_PLL1] =
++ pool->clock_sources[DCE110_CLK_SRC1] =
+ 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) {
+ dm_error("DC: failed to create clock sources!\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 04f235a..e4f2bef 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c
+@@ -62,10 +62,9 @@
+ #endif
+
+ enum dce80_clk_src_array_id {
+- DCE80_CLK_SRC_PLL0 = 0,
+- DCE80_CLK_SRC_PLL1,
+- DCE80_CLK_SRC_PLL2,
+- DCE80_CLK_SRC_EXT,
++ DCE80_CLK_SRC0 = 0,
++ DCE80_CLK_SRC1,
++ DCE80_CLK_SRC2,
+
+ DCE80_CLK_SRC_TOTAL
+ };
+@@ -518,6 +517,9 @@ void dce80_destruct_resource_pool(struct resource_pool *pool)
+ }
+ }
+
++ if (pool->dp_clock_source != NULL)
++ dce80_clock_source_destroy(&pool->dp_clock_source);
++
+ for (i = 0; i < pool->audio_count; i++) {
+ if (pool->audios[i] != NULL) {
+ dal_audio_destroy(&pool->audios[i]);
+@@ -540,22 +542,6 @@ void dce80_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[DCE80_CLK_SRC_PLL0] == 0) {
+- return res_ctx->pool.clock_sources[DCE80_CLK_SRC_PLL0];
+- }
+- if (res_ctx->clock_source_ref_count[DCE80_CLK_SRC_PLL1] == 0) {
+- return res_ctx->pool.clock_sources[DCE80_CLK_SRC_PLL1];
+- }
+- if (res_ctx->clock_source_ref_count[DCE80_CLK_SRC_PLL2] == 0) {
+- return res_ctx->pool.clock_sources[DCE80_CLK_SRC_PLL2];
+- }
+-
+- return 0;
+-}
+-
+ static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
+ {
+ switch (crtc_id) {
+@@ -953,15 +939,16 @@ static enum dc_status map_clock_resources(
+
+ if (dc_is_dp_signal(pipe_ctx->signal)
+ || pipe_ctx->signal == SIGNAL_TYPE_VIRTUAL)
+- pipe_ctx->clock_source = context->res_ctx.
+- pool.clock_sources[DCE80_CLK_SRC_EXT];
+- else
++ pipe_ctx->clock_source = context->res_ctx.pool.dp_clock_source;
++ else {
+ 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);
++
++ if (pipe_ctx->clock_source == NULL)
++ pipe_ctx->clock_source =
++ dc_resource_find_first_free_pll(&context->res_ctx);
++ }
+
+ if (pipe_ctx->clock_source == NULL)
+ return DC_NO_CLOCK_SOURCE_RESOURCE;
+@@ -1059,6 +1046,7 @@ bool dce80_construct_resource_pool(
+ struct dc_context *ctx = dc->ctx;
+ struct firmware_info info;
+ struct dc_bios *bp;
++ int regular_pll_offset = 0;
+
+ pool->adapter_srv = as;
+ pool->funcs = &dce80_res_pool_funcs;
+@@ -1072,40 +1060,48 @@ bool dce80_construct_resource_pool(
+
+ 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]);
++ if (dal_adapter_service_get_firmware_info(as, &info) &&
++ info.external_clock_source_frequency_for_dp != 0) {
++ pool->dp_clock_source =
++ dce80_clock_source_create(
++ ctx,
++ bp,
++ CLOCK_SOURCE_ID_EXTERNAL,
++ NULL);
++ } else {
++ pool->dp_clock_source =
++ dce80_clock_source_create(
++ ctx,
++ bp,
++ CLOCK_SOURCE_ID_PLL0,
++ &dce80_clk_src_reg_offsets[0]);
++ regular_pll_offset = 1;
++ }
++
++ pool->clk_src_count = DCE80_CLK_SRC_TOTAL - regular_pll_offset;
++
++ for (i = 0; i < DCE80_CLK_SRC_TOTAL; ++i, ++regular_pll_offset)
++ pool->clock_sources[DCE80_CLK_SRC0 + i] =
++ dce80_clock_source_create(
++ ctx,
++ bp,
++ CLOCK_SOURCE_ID_PLL0 + regular_pll_offset,
++ &dce80_clk_src_reg_offsets[regular_pll_offset]);
+
+- pool->clock_sources[DCE80_CLK_SRC_PLL1] =
++ pool->clock_sources[DCE80_CLK_SRC1] =
+ dce80_clock_source_create(
+ ctx,
+ bp,
+ CLOCK_SOURCE_ID_PLL1,
+ &dce80_clk_src_reg_offsets[1]);
+
+- pool->clock_sources[DCE80_CLK_SRC_PLL2] =
++ pool->clock_sources[DCE80_CLK_SRC2] =
+ 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) {
+ dm_error("DC: failed to create clock sources!\n");
+diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
+index be3a693..02dddc4 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
+@@ -265,6 +265,11 @@ struct resource_pool {
+
+ union supported_stream_engines stream_engines;
+
++ /*
++ * reserved clock source for DP
++ */
++ struct clock_source *dp_clock_source;
++
+ struct clock_source *clock_sources[MAX_CLOCK_SOURCES];
+ uint8_t clk_src_count;
+
+@@ -327,6 +332,7 @@ struct resource_context {
+ bool is_stream_enc_acquired[MAX_PIPES * 2];
+ bool is_audio_acquired[MAX_PIPES];
+ uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES];
++ uint8_t dp_clock_source_ref_count;
+ };
+
+ struct target_flags {
+diff --git a/drivers/gpu/drm/amd/dal/dc/inc/resource.h b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
+index e6a386c..6991c3e 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/resource.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
+@@ -61,6 +61,9 @@ struct clock_source *find_used_clk_src_for_sharing(
+ struct resource_context *res_ctx,
+ struct pipe_ctx *pipe_ctx);
+
++struct clock_source *dc_resource_find_first_free_pll(
++ struct resource_context *res_ctx);
++
+ bool attach_surfaces_to_context(
+ struct dc_surface *surfaces[],
+ uint8_t surface_count,
+--
+2.7.4
+