aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amdfalconx86/recipes-kernel/linux/files/0789-drm-amd-dal-non-destructive-validate.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amdfalconx86/recipes-kernel/linux/files/0789-drm-amd-dal-non-destructive-validate.patch')
-rw-r--r--meta-amdfalconx86/recipes-kernel/linux/files/0789-drm-amd-dal-non-destructive-validate.patch4120
1 files changed, 4120 insertions, 0 deletions
diff --git a/meta-amdfalconx86/recipes-kernel/linux/files/0789-drm-amd-dal-non-destructive-validate.patch b/meta-amdfalconx86/recipes-kernel/linux/files/0789-drm-amd-dal-non-destructive-validate.patch
new file mode 100644
index 00000000..5d834481
--- /dev/null
+++ b/meta-amdfalconx86/recipes-kernel/linux/files/0789-drm-amd-dal-non-destructive-validate.patch
@@ -0,0 +1,4120 @@
+From c49d3cd9af2452b28e673fa354f057989062011e Mon Sep 17 00:00:00 2001
+From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Date: Fri, 5 Feb 2016 11:41:55 -0500
+Subject: [PATCH 0789/1110] drm/amd/dal: non destructive validate
+
+This changes the way resources are handled to make validate non
+destructive to current state and allow allocating mpo resources
+if needed.
+
+Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c | 2 +-
+ .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c | 3 +-
+ drivers/gpu/drm/amd/dal/dc/core/dc.c | 46 +-
+ drivers/gpu/drm/amd/dal/dc/core/dc_link.c | 133 +++--
+ drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c | 4 +-
+ drivers/gpu/drm/amd/dal/dc/core/dc_resource.c | 398 +++++++-------
+ drivers/gpu/drm/amd/dal/dc/core/dc_target.c | 350 +++++++-----
+ drivers/gpu/drm/amd/dal/dc/dc.h | 8 +-
+ drivers/gpu/drm/amd/dal/dc/dc_types.h | 23 +-
+ .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c | 210 ++++----
+ .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c | 586 +++++++++------------
+ .../drm/amd/dal/dc/dce110/dce110_link_encoder.c | 13 +-
+ .../drm/amd/dal/dc/dce110/dce110_link_encoder.h | 2 +-
+ .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c | 345 ++++++------
+ drivers/gpu/drm/amd/dal/dc/inc/core_types.h | 107 ++--
+ drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h | 23 +-
+ drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h | 5 +-
+ drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h | 2 +-
+ drivers/gpu/drm/amd/dal/dc/inc/resource.h | 13 +-
+ .../drm/amd/dal/dc/virtual/virtual_link_encoder.c | 2 +-
+ drivers/gpu/drm/amd/dal/include/grph_csc_types.h | 13 -
+ 21 files changed, 1145 insertions(+), 1143 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
+index 9b5fd70..2ba79ab 100644
+--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
++++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
+@@ -688,7 +688,7 @@ static inline int dm_irq_state(
+ return 0;
+ }
+
+- irq_source = dc_target_get_irq_src(acrtc->target, dal_irq_type);
++ irq_source = dc_target_get_irq_src(adev->dm.dc, acrtc->target, dal_irq_type);
+
+ st = (state == AMDGPU_IRQ_STATE_ENABLE);
+
+diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
+index 2cb445d..39490bf 100644
+--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
++++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
+@@ -484,8 +484,7 @@ static void fill_plane_attributes_from_fb(
+ surface->scaling_quality.v_taps_c = 2;
+
+ /* TODO: unhardcode */
+- surface->colorimetry.limited_range = false;
+- surface->colorimetry.color_space = SURFACE_COLOR_SPACE_SRGB;
++ surface->color_space = COLOR_SPACE_SRGB_FULL_RANGE;
+ surface->scaling_quality.h_taps = 2;
+ surface->scaling_quality.v_taps = 2;
+ surface->stereo_format = PLANE_STEREO_FORMAT_NONE;
+diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c
+index d788917..bcc6f68 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c
+@@ -172,7 +172,7 @@ static void init_hw(struct dc *dc)
+ struct transform *xfm;
+
+ bp = dal_adapter_service_get_bios_parser(dc->res_pool.adapter_srv);
+- for(i = 0; i < dc->res_pool.controller_count; i++) {
++ for (i = 0; i < dc->res_pool.pipe_count; i++) {
+ xfm = dc->res_pool.transforms[i];
+
+ dc->hwss.enable_display_power_gating(
+@@ -201,7 +201,7 @@ static void init_hw(struct dc *dc)
+ link->link_enc->funcs->hw_init(link->link_enc);
+ }
+
+- for(i = 0; i < dc->res_pool.controller_count; i++) {
++ for (i = 0; i < dc->res_pool.pipe_count; i++) {
+ struct timing_generator *tg = dc->res_pool.timing_generators[i];
+
+ tg->funcs->disable_vga(tg);
+@@ -466,11 +466,11 @@ static void program_timing_sync(
+ uint8_t i;
+ uint8_t j;
+ uint8_t group_size = 0;
+- uint8_t tg_count = ctx->res_ctx.pool.controller_count;
++ uint8_t tg_count = ctx->res_ctx.pool.pipe_count;
+ struct timing_generator *tg_set[3];
+
+ for (i = 0; i < tg_count; i++) {
+- if (!ctx->res_ctx.controller_ctx[i].stream)
++ if (!ctx->res_ctx.pipe_ctx[i].stream)
+ continue;
+
+ tg_set[0] = ctx->res_ctx.pool.timing_generators[i];
+@@ -480,13 +480,13 @@ static void program_timing_sync(
+ * same timing, add all tgs with same timing to the group
+ */
+ for (j = i + 1; j < tg_count; j++) {
+- if (!ctx->res_ctx.controller_ctx[j].stream)
++ if (!ctx->res_ctx.pipe_ctx[j].stream)
+ continue;
+
+ if (is_same_timing(
+- &ctx->res_ctx.controller_ctx[j].stream->public
++ &ctx->res_ctx.pipe_ctx[j].stream->public
+ .timing,
+- &ctx->res_ctx.controller_ctx[i].stream->public
++ &ctx->res_ctx.pipe_ctx[i].stream->public
+ .timing)) {
+ tg_set[group_size] =
+ ctx->res_ctx.pool.timing_generators[j];
+@@ -580,7 +580,7 @@ bool dc_commit_targets(
+ }
+
+ if (result == DC_OK) {
+- dc->hwss.reset_hw_ctx(dc, context, target_count);
++ dc->hwss.reset_hw_ctx(dc, context);
+
+ if (context->target_count > 0)
+ result = dc->hwss.apply_ctx_to_hw(dc, context);
+@@ -588,7 +588,7 @@ bool dc_commit_targets(
+
+ for (i = 0; i < context->target_count; i++) {
+ struct dc_target *dc_target = &context->targets[i]->public;
+- if (context->targets[i]->status.surface_count > 0)
++ if (context->target_status[i].surface_count > 0)
+ dc_target_enable_memory_requests(dc_target);
+ }
+
+@@ -609,7 +609,6 @@ bool dc_commit_targets(
+
+ pplib_apply_display_requirements(dc, context, &context->pp_display_cfg);
+
+- /* TODO: disable unused plls*/
+ fail:
+ dm_free(dc->ctx, context);
+
+@@ -659,12 +658,13 @@ const struct audio **dc_get_audios(struct dc *dc)
+
+ void dc_get_caps(const struct dc *dc, struct dc_caps *caps)
+ {
+- caps->max_targets = dc->res_pool.controller_count;
++ caps->max_targets = dc->res_pool.pipe_count;
+ caps->max_links = dc->link_count;
+ caps->max_audios = dc->res_pool.audio_count;
+ }
+
+-void dc_flip_surface_addrs(struct dc* dc,
++void dc_flip_surface_addrs(
++ struct dc *dc,
+ const struct dc_surface *const surfaces[],
+ struct dc_flip_addrs flip_addrs[],
+ uint32_t count)
+@@ -679,10 +679,8 @@ void dc_flip_surface_addrs(struct dc* dc,
+ surface->public.address = flip_addrs[i].address;
+ surface->public.flip_immediate = flip_addrs[i].flip_immediate;
+
+- dc->hwss.update_plane_address(
+- dc,
+- surface,
+- DC_TARGET_TO_CORE(surface->status.dc_target));
++ dc->hwss.update_plane_addrs(
++ dc, &dc->current_context.res_ctx, surface);
+ }
+ }
+
+@@ -737,27 +735,19 @@ const struct dc_target *dc_get_target_on_irq_source(
+
+ for (i = 0; i < dc->current_context.target_count; i++) {
+ struct core_target *target = dc->current_context.targets[i];
+-
+- struct dc_target *dc_target;
+-
+- if (NULL == target) {
+- dm_error("%s: 'dc_target' is NULL for irq source: %d\n!",
+- __func__, src);
+- continue;
+- }
+-
+- dc_target = &target->public;
++ struct dc_target *dc_target = &target->public;
+
+ for (j = 0; j < target->public.stream_count; j++) {
+ const struct core_stream *stream =
+ DC_STREAM_TO_CORE(dc_target->streams[j]);
+- const uint8_t controller_idx = stream->controller_idx;
+
+- if (controller_idx == crtc_idx)
++ if (dc->current_context.res_ctx.
++ pipe_ctx[crtc_idx].stream == stream)
+ return dc_target;
+ }
+ }
+
++ dm_error("%s: 'dc_target' is NULL for irq source: %d\n!", __func__, src);
+ return NULL;
+ }
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
+index 9a5eadf..5fd5800 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
+@@ -1142,8 +1142,9 @@ static void dpcd_configure_panel_mode(
+ panel_mode_edp);
+ }
+
+-static enum dc_status enable_link_dp(struct core_stream *stream)
++static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx)
+ {
++ struct core_stream *stream = pipe_ctx->stream;
+ enum dc_status status;
+ bool skip_video_pattern;
+ struct core_link *link = stream->sink->link;
+@@ -1154,7 +1155,7 @@ static enum dc_status enable_link_dp(struct core_stream *stream)
+ decide_link_settings(stream, &link_settings);
+ dp_enable_link_phy(
+ stream->sink->link,
+- stream->signal,
++ pipe_ctx->signal,
+ &link_settings);
+
+ panel_mode = dp_get_panel_mode(link);
+@@ -1175,9 +1176,9 @@ static enum dc_status enable_link_dp(struct core_stream *stream)
+ return status;
+ }
+
+-static enum dc_status enable_link_dp_mst(struct core_stream *stream)
++static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx)
+ {
+- struct core_link *link = stream->sink->link;
++ struct core_link *link = pipe_ctx->stream->sink->link;
+
+ /* sink signal type after MST branch is MST. Multiple MST sinks
+ * share one link. Link DP PHY is enable or training only once.
+@@ -1185,11 +1186,12 @@ static enum dc_status enable_link_dp_mst(struct core_stream *stream)
+ if (link->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN)
+ return DC_OK;
+
+- return enable_link_dp(stream);
++ return enable_link_dp(pipe_ctx);
+ }
+
+-static void enable_link_hdmi(struct core_stream *stream)
++static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
+ {
++ struct core_stream *stream = pipe_ctx->stream;
+ struct core_link *link = stream->sink->link;
+
+ /* enable video output */
+@@ -1214,7 +1216,7 @@ static void enable_link_hdmi(struct core_stream *stream)
+ break;
+ }
+
+- if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
++ if (pipe_ctx->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+ dal_ddc_service_write_scdc_data(
+ stream->sink->link->ddc,
+ normalized_pix_clk,
+@@ -1225,33 +1227,33 @@ static void enable_link_hdmi(struct core_stream *stream)
+
+ link->link_enc->funcs->enable_tmds_output(
+ link->link_enc,
+- stream->clock_source->id,
++ pipe_ctx->clock_source->id,
+ stream->public.timing.display_color_depth,
+- stream->signal == SIGNAL_TYPE_HDMI_TYPE_A,
+- stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK,
++ pipe_ctx->signal == SIGNAL_TYPE_HDMI_TYPE_A,
++ pipe_ctx->signal == SIGNAL_TYPE_DVI_DUAL_LINK,
+ stream->public.timing.pix_clk_khz);
+
+- if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
++ if (pipe_ctx->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+ dal_ddc_service_read_scdc_data(link->ddc);
+ }
+
+ /****************************enable_link***********************************/
+-static enum dc_status enable_link(struct core_stream *stream)
++static enum dc_status enable_link(struct pipe_ctx *pipe_ctx)
+ {
+ enum dc_status status = DC_ERROR_UNEXPECTED;
+- switch (stream->signal) {
++ switch (pipe_ctx->signal) {
+ case SIGNAL_TYPE_DISPLAY_PORT:
+ case SIGNAL_TYPE_EDP:
+- status = enable_link_dp(stream);
++ status = enable_link_dp(pipe_ctx);
+ break;
+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
+- status = enable_link_dp_mst(stream);
+- dm_sleep_in_milliseconds(stream->ctx, 200);
++ status = enable_link_dp_mst(pipe_ctx);
++ dm_sleep_in_milliseconds(pipe_ctx->stream->ctx, 200);
+ break;
+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
+ case SIGNAL_TYPE_DVI_DUAL_LINK:
+ case SIGNAL_TYPE_HDMI_TYPE_A:
+- enable_link_hdmi(stream);
++ enable_link_hdmi(pipe_ctx);
+ status = DC_OK;
+ break;
+ case SIGNAL_TYPE_VIRTUAL:
+@@ -1261,20 +1263,20 @@ static enum dc_status enable_link(struct core_stream *stream)
+ break;
+ }
+
+- if (stream->audio && status == DC_OK) {
++ if (pipe_ctx->audio && status == DC_OK) {
+ /* notify audio driver for audio modes of monitor */
+- dal_audio_enable_azalia_audio_jack_presence(stream->audio,
+- stream->stream_enc->id);
++ dal_audio_enable_azalia_audio_jack_presence(pipe_ctx->audio,
++ pipe_ctx->stream_enc->id);
+
+ /* un-mute audio */
+- dal_audio_unmute(stream->audio, stream->stream_enc->id,
+- stream->signal);
++ dal_audio_unmute(pipe_ctx->audio, pipe_ctx->stream_enc->id,
++ pipe_ctx->signal);
+ }
+
+ return status;
+ }
+
+-static void disable_link(struct core_stream *stream)
++static void disable_link(struct core_link *link, enum signal_type signal)
+ {
+ /*
+ * TODO: implement call for dp_set_hw_test_pattern
+@@ -1286,21 +1288,14 @@ static void disable_link(struct core_stream *stream)
+ * it will lead to querying dynamic link capabilities
+ * which should be done before enable output */
+
+- if (dc_is_dp_signal(stream->signal)) {
++ if (dc_is_dp_signal(signal)) {
+ /* SST DP, eDP */
+- if (dc_is_dp_sst_signal(stream->signal))
+- dp_disable_link_phy(
+- stream->sink->link, stream->signal);
+- else {
+- dp_disable_link_phy_mst(
+- stream->sink->link, stream);
+- }
+- } else {
+- struct link_encoder *encoder =
+- stream->sink->link->link_enc;
+-
+- encoder->funcs->disable_output(encoder, stream->signal);
+- }
++ if (dc_is_dp_sst_signal(signal))
++ dp_disable_link_phy(link, signal);
++ else
++ dp_disable_link_phy_mst(link, signal);
++ } else
++ link->link_enc->funcs->disable_output(link->link_enc, signal);
+ }
+
+ enum dc_status dc_link_validate_mode_timing(
+@@ -1360,9 +1355,9 @@ static struct fixed31_32 get_pbn_per_slot(struct core_stream *stream)
+ return dal_fixed31_32_div_int(mbps, 54);
+ }
+
+-static int get_color_depth(struct core_stream *stream)
++static int get_color_depth(enum dc_color_depth color_depth)
+ {
+- switch (stream->pix_clk_params.color_depth) {
++ switch (color_depth) {
+ case COLOR_DEPTH_666: return 6;
+ case COLOR_DEPTH_888: return 8;
+ case COLOR_DEPTH_101010: return 10;
+@@ -1373,7 +1368,7 @@ static int get_color_depth(struct core_stream *stream)
+ }
+ }
+
+-static struct fixed31_32 get_pbn_from_timing(struct core_stream *stream)
++static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)
+ {
+ uint32_t bpc;
+ uint64_t kbps;
+@@ -1381,8 +1376,8 @@ static struct fixed31_32 get_pbn_from_timing(struct core_stream *stream)
+ uint32_t numerator;
+ uint32_t denominator;
+
+- bpc = get_color_depth(stream);
+- kbps = stream->pix_clk_params.requested_pix_clk * bpc * 3;
++ bpc = get_color_depth(pipe_ctx->pix_clk_params.color_depth);
++ kbps = pipe_ctx->pix_clk_params.requested_pix_clk * bpc * 3;
+
+ /*
+ * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
+@@ -1405,7 +1400,7 @@ static struct fixed31_32 get_pbn_from_timing(struct core_stream *stream)
+
+ static void update_mst_stream_alloc_table(
+ struct core_link *link,
+- struct core_stream *stream,
++ struct stream_encoder *stream_enc,
+ const struct dp_mst_stream_allocation_table *proposed_table)
+ {
+ struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = {
+@@ -1440,7 +1435,7 @@ static void update_mst_stream_alloc_table(
+ proposed_table->stream_allocations[i].vcp_id;
+ work_table[i].slot_count =
+ proposed_table->stream_allocations[i].slot_count;
+- work_table[i].stream_enc = stream->stream_enc;
++ work_table[i].stream_enc = stream_enc;
+ }
+ }
+
+@@ -1455,11 +1450,12 @@ static void update_mst_stream_alloc_table(
+ /* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table
+ * because stream_encoder is not exposed to dm
+ */
+-static enum dc_status allocate_mst_payload(struct core_stream *stream)
++static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
+ {
++ struct core_stream *stream = pipe_ctx->stream;
+ struct core_link *link = stream->sink->link;
+ struct link_encoder *link_encoder = link->link_enc;
+- struct stream_encoder *stream_encoder = stream->stream_enc;
++ struct stream_encoder *stream_encoder = pipe_ctx->stream_enc;
+ struct dp_mst_stream_allocation_table proposed_table = {0};
+ struct fixed31_32 avg_time_slots_per_mtp;
+ struct fixed31_32 pbn;
+@@ -1478,7 +1474,8 @@ static enum dc_status allocate_mst_payload(struct core_stream *stream)
+ &proposed_table,
+ true);
+
+- update_mst_stream_alloc_table(link, stream, &proposed_table);
++ update_mst_stream_alloc_table(
++ link, pipe_ctx->stream_enc, &proposed_table);
+
+ dal_logger_write(link->ctx->logger,
+ LOG_MAJOR_MST,
+@@ -1532,7 +1529,7 @@ static enum dc_status allocate_mst_payload(struct core_stream *stream)
+
+ /* slot X.Y for only current stream */
+ pbn_per_slot = get_pbn_per_slot(stream);
+- pbn = get_pbn_from_timing(stream);
++ pbn = get_pbn_from_timing(pipe_ctx);
+ avg_time_slots_per_mtp = dal_fixed31_32_div(pbn, pbn_per_slot);
+
+
+@@ -1545,11 +1542,12 @@ static enum dc_status allocate_mst_payload(struct core_stream *stream)
+
+ }
+
+-static enum dc_status deallocate_mst_payload(struct core_stream *stream)
++static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
+ {
++ struct core_stream *stream = pipe_ctx->stream;
+ struct core_link *link = stream->sink->link;
+ struct link_encoder *link_encoder = link->link_enc;
+- struct stream_encoder *stream_encoder = stream->stream_enc;
++ struct stream_encoder *stream_encoder = pipe_ctx->stream_enc;
+ struct dp_mst_stream_allocation_table proposed_table = {0};
+ struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0);
+ uint8_t i;
+@@ -1575,7 +1573,8 @@ static enum dc_status deallocate_mst_payload(struct core_stream *stream)
+ &proposed_table,
+ false);
+
+- update_mst_stream_alloc_table(link, stream, &proposed_table);
++ update_mst_stream_alloc_table(
++ link, pipe_ctx->stream_enc, &proposed_table);
+
+ dal_logger_write(link->ctx->logger,
+ LOG_MAJOR_MST,
+@@ -1618,38 +1617,32 @@ static enum dc_status deallocate_mst_payload(struct core_stream *stream)
+ return DC_OK;
+ }
+
+-void core_link_enable_stream(
+- struct core_link *link,
+- struct core_stream *stream)
++void core_link_enable_stream(struct pipe_ctx *pipe_ctx)
+ {
+- struct dc *dc = stream->ctx->dc;
++ struct dc *dc = pipe_ctx->stream->ctx->dc;
+
+- if (DC_OK != enable_link(stream)) {
++ if (DC_OK != enable_link(pipe_ctx)) {
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+
+- dc->hwss.enable_stream(stream);
+- stream->status.link = &link->public;
++ dc->hwss.enable_stream(pipe_ctx);
+
+- if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+- allocate_mst_payload(stream);
++ if (pipe_ctx->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
++ allocate_mst_payload(pipe_ctx);
+ }
+
+-void core_link_disable_stream(
+- struct core_link *link,
+- struct core_stream *stream)
++void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
+ {
+- struct dc *dc = stream->ctx->dc;
+-
+- if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+- deallocate_mst_payload(stream);
++ struct dc *dc = pipe_ctx->stream->ctx->dc;
+
+- stream->status.link = NULL;
+- dc->hwss.disable_stream(stream);
++ pipe_ctx->stream->status.link = NULL;
++ if (pipe_ctx->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
++ deallocate_mst_payload(pipe_ctx);
+
+- disable_link(stream);
++ dc->hwss.disable_stream(pipe_ctx);
+
++ disable_link(pipe_ctx->stream->sink->link, pipe_ctx->signal);
+ }
+
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
+index 92d70ed..04a0c17 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
+@@ -93,13 +93,13 @@ void dp_disable_link_phy(struct core_link *link, enum signal_type signal)
+ sizeof(link->public.cur_link_settings));
+ }
+
+-void dp_disable_link_phy_mst(struct core_link *link, struct core_stream *stream)
++void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal)
+ {
+ /* MST disable link only when no stream use the link */
+ if (link->mst_stream_alloc_table.stream_count > 0)
+ return;
+
+- dp_disable_link_phy(link, stream->signal);
++ dp_disable_link_phy(link, signal);
+ }
+
+ bool dp_set_hw_training_pattern(
+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 ec6db8d..70bf935 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
+@@ -99,13 +99,13 @@ bool is_same_timing(
+ }
+
+ static bool is_sharable_clk_src(
+- const struct core_stream *stream_with_clk_src,
+- const struct core_stream *stream)
++ const struct pipe_ctx *pipe_with_clk_src,
++ const struct pipe_ctx *pipe)
+ {
+- enum clock_source_id id = stream_with_clk_src->clock_source->id;
++ enum clock_source_id id = pipe_with_clk_src->clock_source->id;
+ #if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+ enum dce_version dce_ver = dal_adapter_service_get_dce_version(
+- stream->sink->link->adapter_srv);
++ pipe->stream->sink->link->adapter_srv);
+
+ /* Currently no clocks are shared for DCE 10 until VBIOS behaviour
+ * is verified for this use case
+@@ -114,37 +114,32 @@ static bool is_sharable_clk_src(
+ return false;
+ #endif
+
+- if (stream_with_clk_src->clock_source == NULL)
++ if (pipe_with_clk_src->clock_source == NULL)
+ return false;
+
+ if (id == CLOCK_SOURCE_ID_EXTERNAL)
+ return false;
+
+-
+ if(!is_same_timing(
+- &stream_with_clk_src->public.timing, &stream->public.timing))
++ &pipe_with_clk_src->stream->public.timing,
++ &pipe->stream->public.timing))
+ return false;
+
+ return true;
+ }
+
+ struct clock_source *find_used_clk_src_for_sharing(
+- struct validate_context *context,
+- struct core_stream *stream)
++ struct resource_context *res_ctx,
++ struct pipe_ctx *pipe_ctx)
+ {
+- uint8_t i, j;
+- for (i = 0; i < context->target_count; i++) {
+- struct core_target *target = context->targets[i];
+- for (j = 0; j < target->public.stream_count; j++) {
+- struct core_stream *clock_source_stream =
+- DC_STREAM_TO_CORE(target->public.streams[j]);
++ uint8_t i;
+
+- if (clock_source_stream->clock_source == NULL)
+- continue;
++ for (i = 0; i < MAX_PIPES; i++) {
++ if (res_ctx->pipe_ctx[i].clock_source == NULL)
++ continue;
+
+- if (is_sharable_clk_src(clock_source_stream, stream))
+- return clock_source_stream->clock_source;
+- }
++ if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
++ return res_ctx->pipe_ctx[i].clock_source;
+ }
+
+ return NULL;
+@@ -236,7 +231,7 @@ static enum pixel_format convert_pixel_format_to_dalsurface(
+
+ static void calculate_viewport(
+ const struct dc_surface *surface,
+- struct core_stream *stream)
++ struct pipe_ctx *pipe_ctx)
+ {
+ const struct rect src = surface->src_rect;
+ const struct rect clip = surface->clip_rect;
+@@ -245,61 +240,59 @@ static void calculate_viewport(
+ /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio
+ * num_pixels = clip.num_pix * scl_ratio
+ */
+- stream->viewport.x = src.x + (clip.x - dst.x) * src.width / dst.width;
+- stream->viewport.width = clip.width * src.width / dst.width;
++ pipe_ctx->viewport.x = src.x + (clip.x - dst.x) * src.width / dst.width;
++ pipe_ctx->viewport.width = clip.width * src.width / dst.width;
+
+- stream->viewport.y = src.y + (clip.y - dst.y) * src.height / dst.height;
+- stream->viewport.height = clip.height * src.height / dst.height;
++ pipe_ctx->viewport.y = src.y + (clip.y - dst.y) * src.height / dst.height;
++ pipe_ctx->viewport.height = clip.height * src.height / dst.height;
+
+ /* Minimum viewport such that 420/422 chroma vp is non 0 */
+- if (stream->viewport.width < 2)
+- {
+- stream->viewport.width = 2;
+- }
+- if (stream->viewport.height < 2)
+- {
+- stream->viewport.height = 2;
+- }
++ if (pipe_ctx->viewport.width < 2)
++ pipe_ctx->viewport.width = 2;
++ if (pipe_ctx->viewport.height < 2)
++ pipe_ctx->viewport.height = 2;
+ }
+
+ static void calculate_overscan(
+ const struct dc_surface *surface,
+- struct core_stream *stream)
++ struct pipe_ctx *pipe_ctx)
+ {
+- stream->overscan.left = stream->public.dst.x;
++ struct core_stream *stream = pipe_ctx->stream;
++
++ pipe_ctx->overscan.left = stream->public.dst.x;
+ if (stream->public.src.x < surface->clip_rect.x)
+- stream->overscan.left += (surface->clip_rect.x
++ pipe_ctx->overscan.left += (surface->clip_rect.x
+ - stream->public.src.x) * stream->public.dst.width
+ / stream->public.src.width;
+
+- stream->overscan.right = stream->public.timing.h_addressable
++ pipe_ctx->overscan.right = stream->public.timing.h_addressable
+ - stream->public.dst.x - stream->public.dst.width;
+ if (stream->public.src.x + stream->public.src.width
+ > surface->clip_rect.x + surface->clip_rect.width)
+- stream->overscan.right = stream->public.timing.h_addressable -
++ pipe_ctx->overscan.right = stream->public.timing.h_addressable -
+ dal_fixed31_32_floor(dal_fixed31_32_div(
+ dal_fixed31_32_from_int(
+- stream->viewport.width),
+- stream->ratios.horz)) -
+- stream->overscan.left;
++ pipe_ctx->viewport.width),
++ pipe_ctx->ratios.horz)) -
++ pipe_ctx->overscan.left;
+
+
+- stream->overscan.top = stream->public.dst.y;
++ pipe_ctx->overscan.top = stream->public.dst.y;
+ if (stream->public.src.y < surface->clip_rect.y)
+- stream->overscan.top += (surface->clip_rect.y
++ pipe_ctx->overscan.top += (surface->clip_rect.y
+ - stream->public.src.y) * stream->public.dst.height
+ / stream->public.src.height;
+
+- stream->overscan.bottom = stream->public.timing.v_addressable
++ pipe_ctx->overscan.bottom = stream->public.timing.v_addressable
+ - stream->public.dst.y - stream->public.dst.height;
+ if (stream->public.src.y + stream->public.src.height
+ > surface->clip_rect.y + surface->clip_rect.height)
+- stream->overscan.bottom = stream->public.timing.v_addressable -
++ pipe_ctx->overscan.bottom = stream->public.timing.v_addressable -
+ dal_fixed31_32_floor(dal_fixed31_32_div(
+ dal_fixed31_32_from_int(
+- stream->viewport.height),
+- stream->ratios.vert)) -
+- stream->overscan.top;
++ pipe_ctx->viewport.height),
++ pipe_ctx->ratios.vert)) -
++ pipe_ctx->overscan.top;
+
+
+ /* TODO: Add timing overscan to finalize overscan calculation*/
+@@ -307,81 +300,81 @@ static void calculate_overscan(
+
+ static void calculate_scaling_ratios(
+ const struct dc_surface *surface,
+- struct core_stream *stream)
++ struct pipe_ctx *pipe_ctx)
+ {
++ struct core_stream *stream = pipe_ctx->stream;
+ const uint32_t in_w = stream->public.src.width;
+ const uint32_t in_h = stream->public.src.height;
+ const uint32_t out_w = stream->public.dst.width;
+ const uint32_t out_h = stream->public.dst.height;
+
+- stream->ratios.horz = dal_fixed31_32_from_fraction(
++ pipe_ctx->ratios.horz = dal_fixed31_32_from_fraction(
+ surface->src_rect.width,
+ surface->dst_rect.width);
+- stream->ratios.vert = dal_fixed31_32_from_fraction(
++ pipe_ctx->ratios.vert = dal_fixed31_32_from_fraction(
+ surface->src_rect.height,
+ surface->dst_rect.height);
+
+ if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE)
+- stream->ratios.horz.value *= 2;
++ pipe_ctx->ratios.horz.value *= 2;
+ else if (surface->stereo_format
+ == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM)
+- stream->ratios.vert.value *= 2;
++ pipe_ctx->ratios.vert.value *= 2;
+
+- stream->ratios.vert.value = div64_s64(stream->ratios.vert.value * in_h,
++ pipe_ctx->ratios.vert.value = div64_s64(pipe_ctx->ratios.vert.value * in_h,
+ out_h);
+- stream->ratios.horz.value = div64_s64(stream->ratios.horz.value * in_w ,
++ pipe_ctx->ratios.horz.value = div64_s64(pipe_ctx->ratios.horz.value * in_w,
+ out_w);
+
+- stream->ratios.horz_c = stream->ratios.horz;
+- stream->ratios.vert_c = stream->ratios.vert;
++ pipe_ctx->ratios.horz_c = pipe_ctx->ratios.horz;
++ pipe_ctx->ratios.vert_c = pipe_ctx->ratios.vert;
+
+- if (stream->format == PIXEL_FORMAT_420BPP12) {
+- stream->ratios.horz_c.value /= 2;
+- stream->ratios.vert_c.value /= 2;
+- } else if (stream->format == PIXEL_FORMAT_422BPP16) {
+- stream->ratios.horz_c.value /= 2;
++ if (pipe_ctx->format == PIXEL_FORMAT_420BPP12) {
++ pipe_ctx->ratios.horz_c.value /= 2;
++ pipe_ctx->ratios.vert_c.value /= 2;
++ } else if (pipe_ctx->format == PIXEL_FORMAT_422BPP16) {
++ pipe_ctx->ratios.horz_c.value /= 2;
+ }
+ }
+
+-/*TODO: per pipe not per stream*/
+ void build_scaling_params(
+ const struct dc_surface *surface,
+- struct core_stream *stream)
++ struct pipe_ctx *pipe_ctx)
+ {
+ /* Important: scaling ratio calculation requires pixel format,
+ * overscan calculation requires scaling ratios and viewport
+ * and lb depth/taps calculation requires overscan. Call sequence
+ * is therefore important */
+- stream->format = convert_pixel_format_to_dalsurface(surface->format);
++ pipe_ctx->format = convert_pixel_format_to_dalsurface(surface->format);
+
+- calculate_viewport(surface, stream);
++ calculate_viewport(surface, pipe_ctx);
+
+- calculate_scaling_ratios(surface, stream);
++ calculate_scaling_ratios(surface, pipe_ctx);
+
+- calculate_overscan(surface, stream);
++ calculate_overscan(surface, pipe_ctx);
+
+ /* Check if scaling is required update taps if not */
+- if (dal_fixed31_32_u2d19(stream->ratios.horz) == 1 << 19)
+- stream->taps.h_taps = 1;
++ if (dal_fixed31_32_u2d19(pipe_ctx->ratios.horz) == 1 << 19)
++ pipe_ctx->taps.h_taps = 1;
+ else
+- stream->taps.h_taps = surface->scaling_quality.h_taps;
++ pipe_ctx->taps.h_taps = surface->scaling_quality.h_taps;
+
+- if (dal_fixed31_32_u2d19(stream->ratios.horz_c) == 1 << 19)
+- stream->taps.h_taps_c = 1;
++ if (dal_fixed31_32_u2d19(pipe_ctx->ratios.horz_c) == 1 << 19)
++ pipe_ctx->taps.h_taps_c = 1;
+ else
+- stream->taps.h_taps_c = surface->scaling_quality.h_taps_c;
++ pipe_ctx->taps.h_taps_c = surface->scaling_quality.h_taps_c;
+
+- if (dal_fixed31_32_u2d19(stream->ratios.vert) == 1 << 19)
+- stream->taps.v_taps = 1;
++ if (dal_fixed31_32_u2d19(pipe_ctx->ratios.vert) == 1 << 19)
++ pipe_ctx->taps.v_taps = 1;
+ else
+- stream->taps.v_taps = surface->scaling_quality.v_taps;
++ pipe_ctx->taps.v_taps = surface->scaling_quality.v_taps;
+
+- if (dal_fixed31_32_u2d19(stream->ratios.vert_c) == 1 << 19)
+- stream->taps.v_taps_c = 1;
++ if (dal_fixed31_32_u2d19(pipe_ctx->ratios.vert_c) == 1 << 19)
++ pipe_ctx->taps.v_taps_c = 1;
+ else
+- stream->taps.v_taps_c = surface->scaling_quality.v_taps_c;
++ pipe_ctx->taps.v_taps_c = surface->scaling_quality.v_taps_c;
+
+- dal_logger_write(stream->ctx->logger,
++ dal_logger_write(pipe_ctx->stream->ctx->logger,
+ LOG_MAJOR_DCP,
+ LOG_MINOR_DCP_SCALER,
+ "%s: Overscan:\n bot:%d left:%d right:%d "
+@@ -389,14 +382,14 @@ void build_scaling_params(
+ "y:%d\n dst_rect:\nheight:%d width:%d x:%d "
+ "y:%d\n",
+ __func__,
+- stream->overscan.bottom,
+- stream->overscan.left,
+- stream->overscan.right,
+- stream->overscan.top,
+- stream->viewport.height,
+- stream->viewport.width,
+- stream->viewport.x,
+- stream->viewport.y,
++ pipe_ctx->overscan.bottom,
++ pipe_ctx->overscan.left,
++ pipe_ctx->overscan.right,
++ pipe_ctx->overscan.top,
++ pipe_ctx->viewport.height,
++ pipe_ctx->viewport.width,
++ pipe_ctx->viewport.x,
++ pipe_ctx->viewport.y,
+ surface->dst_rect.height,
+ surface->dst_rect.width,
+ surface->dst_rect.x,
+@@ -407,32 +400,25 @@ void build_scaling_params_for_context(
+ const struct dc *dc,
+ struct validate_context *context)
+ {
+- uint8_t i, j, k;
+- for (i = 0; i < context->target_count; i++) {
+- struct core_target *target = context->targets[i];
+- if (context->target_flags[i].unchanged)
+- continue;
+- for (j = 0; j < target->status.surface_count; j++) {
+- const struct dc_surface *surface =
+- target->status.surfaces[j];
+- for (k = 0; k < target->public.stream_count; k++) {
+- struct core_stream *stream =
+- DC_STREAM_TO_CORE(
+- target->public.streams[k]);
+-
+- build_scaling_params(surface, stream);
+- }
+- }
++ uint8_t i;
++
++ for (i = 0; i < MAX_PIPES; i++) {
++ if (context->res_ctx.pipe_ctx[i].surface != NULL &&
++ context->res_ctx.pipe_ctx[i].stream != NULL)
++ build_scaling_params(
++ &context->res_ctx.pipe_ctx[i].surface->public,
++ &context->res_ctx.pipe_ctx[i]);
+ }
+ }
+
+-bool logical_attach_surfaces_to_target(
++bool attach_surfaces_to_context(
+ struct dc_surface *surfaces[],
+ uint8_t surface_count,
+- struct dc_target *dc_target)
++ struct dc_target *dc_target,
++ struct validate_context *context)
+ {
+- uint8_t i;
+- struct core_target *target = DC_TARGET_TO_CORE(dc_target);
++ uint8_t i, j, k;
++ struct dc_target_status *target_status = NULL;
+
+ if (surface_count > MAX_SURFACE_NUM) {
+ dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
+@@ -440,16 +426,46 @@ bool logical_attach_surfaces_to_target(
+ return false;
+ }
+
+- for (i = 0; i < target->status.surface_count; i++)
+- dc_surface_release(target->status.surfaces[i]);
++ for (i = 0; i < context->target_count; i++)
++ if (&context->targets[i]->public == dc_target) {
++ target_status = &context->target_status[i];
++ break;
++ }
++ if (target_status == NULL) {
++ dm_error("Existing target not found; failed to attach surfaces\n");
++ return false;
++ }
++
++ for (i = 0; i < target_status->surface_count; i++)
++ dc_surface_release(target_status->surfaces[i]);
+
+ for (i = 0; i < surface_count; i++) {
+- struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
+- surface->status.dc_target = &target->public;
+- target->status.surfaces[i] = surfaces[i];
+- dc_surface_retain(target->status.surfaces[i]);
++ target_status->surfaces[i] = surfaces[i];
++ dc_surface_retain(target_status->surfaces[i]);
++ }
++ target_status->surface_count = surface_count;
++
++ for (i = 0; i < dc_target->stream_count; i++) {
++ k = 0;
++ for (j = 0; j < MAX_PIPES; j++) {
++ struct core_surface *surface =
++ DC_SURFACE_TO_CORE(surfaces[k]);
++
++ if (context->res_ctx.pipe_ctx[j].stream !=
++ DC_STREAM_TO_CORE(dc_target->streams[i]))
++ continue;
++ if (k == surface_count) {
++ /* this means there are more pipes per stream
++ * than there are planes and makes no sense
++ */
++ BREAK_TO_DEBUGGER();
++ continue;
++ }
++
++ context->res_ctx.pipe_ctx[j].surface = surface;
++ k++;
++ }
+ }
+- target->status.surface_count = surface_count;
+
+ return true;
+ }
+@@ -492,13 +508,21 @@ static void fill_display_configs(
+
+ for (j = 0; j < target->public.stream_count; j++) {
+ const struct core_stream *stream =
+- DC_STREAM_TO_CORE(target->public.streams[j]);
++ DC_STREAM_TO_CORE(target->public.streams[j]);
+ struct dc_pp_single_disp_config *cfg =
+ &pp_display_cfg->disp_configs[num_cfgs];
++ const struct pipe_ctx *pipe_ctx = NULL;
++
++ for (j = 0; j < MAX_PIPES; j++)
++ if (stream ==
++ context->res_ctx.pipe_ctx[j].stream) {
++ pipe_ctx = &context->res_ctx.pipe_ctx[j];
++ break;
++ }
+
+ num_cfgs++;
+- cfg->signal = stream->signal;
+- cfg->pipe_idx = stream->opp->inst;
++ cfg->signal = pipe_ctx->signal;
++ cfg->pipe_idx = pipe_ctx->pipe_idx;
+ cfg->src_height = stream->public.src.height;
+ cfg->src_width = stream->public.src.width;
+ cfg->ddi_channel_mapping =
+@@ -582,13 +606,6 @@ void pplib_apply_display_requirements(
+ /* Maximum TMDS single link pixel clock 165MHz */
+ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
+
+-static void attach_stream_to_controller(
+- struct resource_context *res_ctx,
+- struct core_stream *stream)
+-{
+- res_ctx->controller_ctx[stream->controller_idx].stream = stream;
+-}
+-
+ static void set_stream_engine_in_use(
+ struct resource_context *res_ctx,
+ struct stream_encoder *stream_enc)
+@@ -614,24 +631,28 @@ static void set_audio_in_use(
+ }
+ }
+
+-static bool assign_first_free_controller(
++static int8_t acquire_first_free_pipe(
+ struct resource_context *res_ctx,
+ struct core_stream *stream)
+ {
+ uint8_t i;
+- for (i = 0; i < res_ctx->pool.controller_count; i++) {
+- if (!res_ctx->controller_ctx[i].stream) {
+- stream->tg = res_ctx->pool.timing_generators[i];
+- stream->mi = res_ctx->pool.mis[i];
+- stream->ipp = res_ctx->pool.ipps[i];
+- stream->xfm = res_ctx->pool.transforms[i];
+- stream->opp = res_ctx->pool.opps[i];
+- stream->controller_idx = i;
+- stream->dis_clk = res_ctx->pool.display_clock;
+- return true;
++ for (i = 0; i < res_ctx->pool.pipe_count; i++) {
++ if (!res_ctx->pipe_ctx[i].stream) {
++ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
++
++ pipe_ctx->tg = res_ctx->pool.timing_generators[i];
++ pipe_ctx->mi = res_ctx->pool.mis[i];
++ pipe_ctx->ipp = res_ctx->pool.ipps[i];
++ pipe_ctx->xfm = res_ctx->pool.transforms[i];
++ pipe_ctx->opp = res_ctx->pool.opps[i];
++ pipe_ctx->dis_clk = res_ctx->pool.display_clock;
++ pipe_ctx->pipe_idx = i;
++
++ pipe_ctx->stream = stream;
++ return i;
+ }
+ }
+- return false;
++ return -1;
+ }
+
+ static struct stream_encoder *find_first_free_match_stream_enc_for_link(
+@@ -704,9 +725,10 @@ static bool check_timing_change(struct core_stream *cur_stream,
+ &new_stream->public.timing);
+ }
+
+-static void set_stream_signal(struct core_stream *stream)
++static void set_stream_signal(struct pipe_ctx *pipe_ctx)
+ {
+- struct dc_sink *dc_sink = (struct dc_sink *)stream->public.sink;
++ struct dc_sink *dc_sink =
++ (struct dc_sink *) pipe_ctx->stream->public.sink;
+
+ /* For asic supports dual link DVI, we should adjust signal type
+ * based on timing pixel clock. If pixel clock more than 165Mhz,
+@@ -714,21 +736,21 @@ static void set_stream_signal(struct core_stream *stream)
+ */
+ if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
+ dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) {
+- if (stream->public.timing.pix_clk_khz >
+- TMDS_MAX_PIXEL_CLOCK_IN_KHZ)
++ if (pipe_ctx->stream->public.timing.pix_clk_khz >
++ TMDS_MAX_PIXEL_CLOCK_IN_KHZ)
+ dc_sink->sink_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+ else
+ dc_sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+ }
+
+- stream->signal = dc_sink->sink_signal;
++ pipe_ctx->signal = dc_sink->sink_signal;
+ }
+
+ enum dc_status map_resources(
+ const struct dc *dc,
+ struct validate_context *context)
+ {
+- uint8_t i, j;
++ uint8_t i, j, k;
+
+ /* mark resources used for targets that are already active */
+ for (i = 0; i < context->target_count; i++) {
+@@ -741,21 +763,29 @@ enum dc_status map_resources(
+ struct core_stream *stream =
+ DC_STREAM_TO_CORE(target->public.streams[j]);
+
+- attach_stream_to_controller(
+- &context->res_ctx,
+- stream);
++ for (k = 0; k < MAX_PIPES; k++) {
++ struct pipe_ctx *pipe_ctx =
++ &context->res_ctx.pipe_ctx[k];
+
+- set_stream_engine_in_use(
+- &context->res_ctx,
+- stream->stream_enc);
++ if (dc->current_context.res_ctx.pipe_ctx[k].stream
++ != stream)
++ continue;
+
+- reference_clock_source(
+- &context->res_ctx,
+- stream->clock_source);
++ *pipe_ctx =
++ dc->current_context.res_ctx.pipe_ctx[k];
++ pipe_ctx->flags.timing_changed = false;
++ pipe_ctx->flags.unchanged = true;
++
++ set_stream_engine_in_use(
++ &context->res_ctx,
++ pipe_ctx->stream_enc);
++
++ reference_clock_source(
++ &context->res_ctx,
++ pipe_ctx->clock_source);
+
+- if (stream->audio) {
+ set_audio_in_use(&context->res_ctx,
+- stream->audio);
++ pipe_ctx->audio);
+ }
+ }
+ }
+@@ -768,49 +798,48 @@ enum dc_status map_resources(
+ continue;
+
+ for (j = 0; j < target->public.stream_count; j++) {
++ struct pipe_ctx *pipe_ctx = NULL;
+ struct core_stream *stream =
+ DC_STREAM_TO_CORE(target->public.streams[j]);
+ struct core_stream *curr_stream;
+
+- if (!assign_first_free_controller(
+- &context->res_ctx, stream))
++ int8_t pipe_idx = acquire_first_free_pipe(
++ &context->res_ctx, stream);
++ if (pipe_idx < 0)
+ return DC_NO_CONTROLLER_RESOURCE;
+
+- attach_stream_to_controller(&context->res_ctx, stream);
+-
+- set_stream_signal(stream);
++ pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
++ set_stream_signal(pipe_ctx);
+
+ curr_stream =
+- dc->current_context.res_ctx.controller_ctx
+- [stream->controller_idx].stream;
+- context->res_ctx.controller_ctx[stream->controller_idx]
+- .flags.timing_changed =
++ dc->current_context.res_ctx.pipe_ctx[pipe_idx].stream;
++ context->res_ctx.pipe_ctx[pipe_idx].flags.timing_changed =
+ check_timing_change(curr_stream, stream);
+
+- stream->stream_enc =
++ pipe_ctx->stream_enc =
+ find_first_free_match_stream_enc_for_link(
+ &context->res_ctx,
+ stream->sink->link);
+
+- if (!stream->stream_enc)
++ if (!pipe_ctx->stream_enc)
+ return DC_NO_STREAM_ENG_RESOURCE;
+
+ set_stream_engine_in_use(
+ &context->res_ctx,
+- stream->stream_enc);
++ pipe_ctx->stream_enc);
+
+ /* TODO: Add check if ASIC support and EDID audio */
+ if (!stream->sink->converter_disable_audio &&
+ dc_is_audio_capable_signal(
+- stream->signal)) {
+- stream->audio = find_first_free_audio(
++ pipe_ctx->signal)) {
++ pipe_ctx->audio = find_first_free_audio(
+ &context->res_ctx);
+
+- if (!stream->audio)
++ if (!pipe_ctx->audio)
+ return DC_NO_STREAM_AUDIO_RESOURCE;
+
+ set_audio_in_use(&context->res_ctx,
+- stream->audio);
++ pipe_ctx->audio);
+ }
+ }
+ }
+@@ -819,13 +848,13 @@ enum dc_status map_resources(
+ }
+
+ static enum ds_color_space build_default_color_space(
+- struct core_stream *stream)
++ struct pipe_ctx *pipe_ctx)
+ {
+ enum ds_color_space color_space =
+ DS_COLOR_SPACE_SRGB_FULLRANGE;
+- struct dc_crtc_timing *timing = &stream->public.timing;
++ struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
+
+- switch (stream->signal) {
++ switch (pipe_ctx->signal) {
+ /* TODO: implement other signal color space setting */
+ case SIGNAL_TYPE_DISPLAY_PORT:
+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
+@@ -934,9 +963,11 @@ static void translate_info_frame(const struct hw_info_frame *hw_info_frame,
+ }
+ }
+
+-static void set_avi_info_frame(struct hw_info_packet *info_packet,
+- struct core_stream *stream)
++static void set_avi_info_frame(
++ struct hw_info_packet *info_packet,
++ struct pipe_ctx *pipe_ctx)
+ {
++ struct core_stream *stream = pipe_ctx->stream;
+ enum ds_color_space color_space = DS_COLOR_SPACE_UNKNOWN;
+ struct info_frame info_frame = { {0} };
+ uint32_t pixel_encoding = 0;
+@@ -950,7 +981,7 @@ static void set_avi_info_frame(struct hw_info_packet *info_packet,
+ if (info_packet == NULL)
+ return;
+
+- color_space = build_default_color_space(stream);
++ color_space = build_default_color_space(pipe_ctx);
+
+ /* Initialize header */
+ info_frame.avi_info_packet.info_packet_hdmi.bits.header.
+@@ -1223,7 +1254,7 @@ static void set_vendor_info_packet(struct core_stream *stream,
+ info_packet->valid = true;
+ }
+
+-void build_info_frame(struct core_stream *stream)
++void build_info_frame(struct pipe_ctx *pipe_ctx)
+ {
+ enum signal_type signal = SIGNAL_TYPE_NONE;
+ struct hw_info_frame info_frame = { { 0 } };
+@@ -1235,15 +1266,16 @@ void build_info_frame(struct core_stream *stream)
+ info_frame.spd_packet.valid = false;
+ info_frame.vsc_packet.valid = false;
+
+- signal = stream->sink->public.sink_signal;
++ signal = pipe_ctx->stream->sink->public.sink_signal;
+
+ /* HDMi and DP have different info packets*/
+ if (signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+- set_avi_info_frame(&info_frame.avi_info_packet,
+- stream);
+- set_vendor_info_packet(stream, &info_frame.vendor_info_packet);
++ set_avi_info_frame(
++ &info_frame.avi_info_packet, pipe_ctx);
++ set_vendor_info_packet(
++ pipe_ctx->stream, &info_frame.vendor_info_packet);
+ }
+
+ translate_info_frame(&info_frame,
+- &stream->encoder_info_frame);
++ &pipe_ctx->encoder_info_frame);
+ }
+diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
+index e8579bc..f00b5af 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
+@@ -65,12 +65,20 @@ static void construct(
+
+ static void destruct(struct core_target *core_target)
+ {
+- int i;
++ int i, j;
++ struct validate_context *context =
++ &core_target->ctx->dc->current_context;
+
+- for (i = 0; i < core_target->status.surface_count; i++) {
+- dc_surface_release(core_target->status.surfaces[i]);
+- core_target->status.surfaces[i] = NULL;
++ for (i = 0; i < context->target_count; i++) {
++ if (context->targets[i] != core_target)
++ continue;
++ for (j = 0; j < context->target_status[i].surface_count; j++)
++ dc_surface_release(
++ context->target_status[i].surfaces[j]);
++ context->target_status[i].surface_count = 0;
++ break;
+ }
++
+ for (i = 0; i < core_target->public.stream_count; i++) {
+ dc_stream_release(
+ (struct dc_stream *)core_target->public.streams[i]);
+@@ -101,8 +109,15 @@ void dc_target_release(struct dc_target *dc_target)
+ const struct dc_target_status *dc_target_get_status(
+ const struct dc_target* dc_target)
+ {
++ uint8_t i;
+ struct core_target* target = DC_TARGET_TO_CORE(dc_target);
+- return &target->status;
++ struct dc *dc = target->ctx->dc;
++
++ for (i = 0; i < dc->current_context.target_count; i++)
++ if (target == dc->current_context.targets[i])
++ return &dc->current_context.target_status[i];
++
++ return NULL;
+ }
+
+ struct dc_target *dc_create_target_for_streams(
+@@ -169,26 +184,28 @@ bool dc_commit_surfaces_to_target(
+ int i, j;
+ uint32_t prev_disp_clk = dc->current_context.bw_results.dispclk_khz;
+ struct core_target *target = DC_TARGET_TO_CORE(dc_target);
+-
++ struct dc_target_status *status = NULL;
++ struct validate_context *context;
+ int current_enabled_surface_count = 0;
+ int new_enabled_surface_count = 0;
+
+- if (!dal_adapter_service_is_in_accelerated_mode(
+- dc->res_pool.adapter_srv) ||
+- dc->current_context.target_count == 0) {
+- return false;
+- }
+-
+- for (i = 0; i < dc->current_context.target_count; i++)
+- if (target == dc->current_context.targets[i])
+- break;
++ context = dm_alloc(dc->ctx, sizeof(struct validate_context));
++ *context = dc->current_context;
+
+ /* Cannot commit surface to a target that is not commited */
+- if (i == dc->current_context.target_count)
+- return false;
++ for (i = 0; i < context->target_count; i++)
++ if (target == context->targets[i])
++ break;
++ status = &context->target_status[i];
++ if (!dal_adapter_service_is_in_accelerated_mode(
++ dc->res_pool.adapter_srv)
++ || i == context->target_count) {
++ BREAK_TO_DEBUGGER();
++ goto unexpected_fail;
++ }
+
+- for (i = 0; i < target->status.surface_count; i++)
+- if (target->status.surfaces[i]->visible)
++ for (i = 0; i < status->surface_count; i++)
++ if (status->surfaces[i]->visible)
+ current_enabled_surface_count++;
+
+ for (i = 0; i < new_surface_count; i++)
+@@ -204,83 +221,100 @@ bool dc_commit_surfaces_to_target(
+ dc_target);
+
+
+- if (!logical_attach_surfaces_to_target(
+- new_surfaces,
+- new_surface_count,
+- dc_target)) {
++ if (!attach_surfaces_to_context(
++ new_surfaces, new_surface_count, dc_target, context)) {
+ BREAK_TO_DEBUGGER();
+ goto unexpected_fail;
+ }
+
+ for (i = 0; i < new_surface_count; i++)
+- for (j = 0; j < target->public.stream_count; j++)
++ for (j = 0; j < MAX_PIPES; j++) {
++ if (context->res_ctx.pipe_ctx[j].surface !=
++ DC_SURFACE_TO_CORE(new_surfaces[i]))
++ continue;
++
+ build_scaling_params(
+- new_surfaces[i],
+- DC_STREAM_TO_CORE(target->public.streams[j]));
++ new_surfaces[i], &context->res_ctx.pipe_ctx[j]);
++ }
+
+- if (dc->res_pool.funcs->validate_bandwidth(dc, &dc->current_context)
+- != DC_OK) {
++ if (dc->res_pool.funcs->validate_bandwidth(dc, context) != DC_OK) {
+ BREAK_TO_DEBUGGER();
+ goto unexpected_fail;
+ }
+
+- if (prev_disp_clk < dc->current_context.bw_results.dispclk_khz) {
+- dc->hwss.program_bw(dc, &dc->current_context);
+- pplib_apply_display_requirements(dc, &dc->current_context,
+- &dc->current_context.pp_display_cfg);
++ if (prev_disp_clk < context->bw_results.dispclk_khz) {
++ dc->hwss.program_bw(dc, context);
++ pplib_apply_display_requirements(dc, context,
++ &context->pp_display_cfg);
+ }
+
+ if (current_enabled_surface_count > 0 && new_enabled_surface_count == 0)
+ dc_target_disable_memory_requests(dc_target);
+
+- for (i = 0; i < new_surface_count; i++) {
+- struct dc_surface *surface = new_surfaces[i];
+- struct core_surface *core_surface = DC_SURFACE_TO_CORE(surface);
+- struct core_stream *stream =
+- DC_STREAM_TO_CORE(target->public.streams[0]);
+- bool is_valid_address =
+- validate_surface_address(surface->address);
+-
+-
+- dal_logger_write(dc->ctx->logger,
+- LOG_MAJOR_INTERFACE_TRACE,
+- LOG_MINOR_COMPONENT_DC,
+- "0x%x:",
+- surface);
+-
+- if (surface->gamma_correction) {
+- struct core_gamma *gamma = DC_GAMMA_TO_CORE(
+- surface->gamma_correction);
+-
+- dc->hwss.set_gamma_correction(
+- stream->ipp,
+- stream->opp,
+- gamma, core_surface);
++ for (i = 0; i < new_surface_count; i++)
++ for (j = 0; j < MAX_PIPES; j++) {
++ struct dc_surface *dc_surface = new_surfaces[i];
++ struct core_surface *surface =
++ DC_SURFACE_TO_CORE(dc_surface);
++ struct pipe_ctx *pipe_ctx =
++ &context->res_ctx.pipe_ctx[j];
++
++ if (pipe_ctx->surface !=
++ DC_SURFACE_TO_CORE(new_surfaces[i]))
++ continue;
++
++ dal_logger_write(dc->ctx->logger,
++ LOG_MAJOR_INTERFACE_TRACE,
++ LOG_MINOR_COMPONENT_DC,
++ "Pipe:%d 0x%x: src: %d, %d, %d,"
++ " %d; dst: %d, %d, %d, %d;\n",
++ pipe_ctx->pipe_idx,
++ dc_surface,
++ dc_surface->src_rect.x,
++ dc_surface->src_rect.y,
++ dc_surface->src_rect.width,
++ dc_surface->src_rect.height,
++ dc_surface->dst_rect.x,
++ dc_surface->dst_rect.y,
++ dc_surface->dst_rect.width,
++ dc_surface->dst_rect.height);
++
++ if (dc_surface->gamma_correction) {
++ struct core_gamma *gamma = DC_GAMMA_TO_CORE(
++ dc_surface->gamma_correction);
++
++ dc->hwss.set_gamma_correction(
++ pipe_ctx->ipp,
++ pipe_ctx->opp,
++ gamma, surface);
++ }
++
++ dc->hwss.set_plane_config(dc, surface, pipe_ctx);
++
++ if (validate_surface_address(dc_surface->address))
++ dc->hwss.update_plane_addrs(
++ dc, &context->res_ctx, surface);
+ }
+
+- dc->hwss.set_plane_config(dc, core_surface, target);
+-
+- if (is_valid_address)
+- dc->hwss.update_plane_address(dc, core_surface, target);
+- }
+-
+ if (current_enabled_surface_count == 0 && new_enabled_surface_count > 0)
+ dc_target_enable_memory_requests(dc_target);
+
+ /* Lower display clock if necessary */
+- if (prev_disp_clk > dc->current_context.bw_results.dispclk_khz) {
+- dc->hwss.program_bw(dc, &dc->current_context);
+- pplib_apply_display_requirements(dc, &dc->current_context,
+- &dc->current_context.pp_display_cfg);
++ if (prev_disp_clk > context->bw_results.dispclk_khz) {
++ dc->hwss.program_bw(dc, context);
++ pplib_apply_display_requirements(dc, context,
++ &context->pp_display_cfg);
+ }
+
++ dc->current_context = *context;
++ dm_free(dc->ctx, context);
+ return true;
+
+ unexpected_fail:
+ for (i = 0; i < new_surface_count; i++) {
+- target->status.surfaces[i] = NULL;
++ status->surfaces[i] = NULL;
+ }
+- target->status.surface_count = 0;
++ status->surface_count = 0;
+
+ return false;
+ }
+@@ -298,38 +332,48 @@ bool dc_target_is_connected_to_sink(
+ return false;
+ }
+
+-void dc_target_enable_memory_requests(struct dc_target *target)
++void dc_target_enable_memory_requests(struct dc_target *dc_target)
+ {
+- uint8_t i;
+- struct core_target *core_target = DC_TARGET_TO_CORE(target);
+- for (i = 0; i < core_target->public.stream_count; i++) {
+- struct timing_generator *tg =
+- DC_STREAM_TO_CORE(core_target->public.streams[i])->tg;
++ uint8_t i, j;
++ struct core_target *target = DC_TARGET_TO_CORE(dc_target);
++ struct resource_context *res_ctx =
++ &target->ctx->dc->current_context.res_ctx;
++
++ for (i = 0; i < target->public.stream_count; i++) {
++ for (j = 0; j < MAX_PIPES; j++) {
++ struct timing_generator *tg = res_ctx->pipe_ctx[j].tg;
++
++ if (res_ctx->pipe_ctx[j].stream !=
++ DC_STREAM_TO_CORE(target->public.streams[i]))
++ continue;
+
+- if (!tg->funcs->set_blank(tg, false)) {
+- dm_error("DC: failed to unblank crtc!\n");
+- BREAK_TO_DEBUGGER();
++ if (!tg->funcs->set_blank(tg, false)) {
++ dm_error("DC: failed to unblank crtc!\n");
++ BREAK_TO_DEBUGGER();
++ }
+ }
+ }
+ }
+
+-void dc_target_disable_memory_requests(struct dc_target *target)
++void dc_target_disable_memory_requests(struct dc_target *dc_target)
+ {
+- uint8_t i;
+- struct core_target *core_target = DC_TARGET_TO_CORE(target);
+- for (i = 0; i < core_target->public.stream_count; i++) {
+- struct timing_generator *tg =
+- DC_STREAM_TO_CORE(core_target->public.streams[i])->tg;
++ uint8_t i, j;
++ struct core_target *target = DC_TARGET_TO_CORE(dc_target);
++ struct resource_context *res_ctx =
++ &target->ctx->dc->current_context.res_ctx;
+
+- if (NULL == tg) {
+- dm_error("DC: timing generator is NULL!\n");
+- BREAK_TO_DEBUGGER();
+- continue;
+- }
++ for (i = 0; i < target->public.stream_count; i++) {
++ for (j = 0; j < MAX_PIPES; j++) {
++ struct timing_generator *tg = res_ctx->pipe_ctx[j].tg;
++
++ if (res_ctx->pipe_ctx[j].stream !=
++ DC_STREAM_TO_CORE(target->public.streams[i]))
++ continue;
+
+- if (false == tg->funcs->set_blank(tg, true)) {
+- dm_error("DC: failed to blank crtc!\n");
+- BREAK_TO_DEBUGGER();
++ if (!tg->funcs->set_blank(tg, true)) {
++ dm_error("DC: failed to blank crtc!\n");
++ BREAK_TO_DEBUGGER();
++ }
+ }
+ }
+ }
+@@ -341,25 +385,42 @@ bool dc_target_set_cursor_attributes(
+ struct dc_target *dc_target,
+ const struct dc_cursor_attributes *attributes)
+ {
+- struct core_target *core_target;
+- struct input_pixel_processor *ipp;
++ uint8_t i, j;
++ struct core_target *target;
++ struct resource_context *res_ctx;
+
+ if (NULL == dc_target) {
+ dm_error("DC: dc_target is NULL!\n");
+ return false;
+
+ }
++ if (NULL == attributes) {
++ dm_error("DC: attributes is NULL!\n");
++ return false;
+
+- core_target = DC_TARGET_TO_CORE(dc_target);
+- ipp = DC_STREAM_TO_CORE(core_target->public.streams[0])->ipp;
+-
+- if (NULL == ipp) {
+- dm_error("DC: input pixel processor is NULL!\n");
+- return false;
+ }
+
+- if (true == ipp->funcs->ipp_cursor_set_attributes(ipp, attributes))
+- return true;
++ target = DC_TARGET_TO_CORE(dc_target);
++ res_ctx = &target->ctx->dc->current_context.res_ctx;
++
++ for (i = 0; i < target->public.stream_count; i++) {
++ for (j = 0; j < MAX_PIPES; j++) {
++ struct input_pixel_processor *ipp =
++ res_ctx->pipe_ctx[j].ipp;
++
++ if (res_ctx->pipe_ctx[j].stream !=
++ DC_STREAM_TO_CORE(target->public.streams[i]))
++ continue;
++
++ /* As of writing of this code cursor is on the top
++ * plane so we only need to set it on first pipe we
++ * find. May need to make this code dce specific later.
++ */
++ if (ipp->funcs->ipp_cursor_set_attributes(
++ ipp, attributes))
++ return true;
++ }
++ }
+
+ return false;
+ }
+@@ -368,8 +429,9 @@ bool dc_target_set_cursor_position(
+ struct dc_target *dc_target,
+ const struct dc_cursor_position *position)
+ {
+- struct core_target *core_target;
+- struct input_pixel_processor *ipp;
++ uint8_t i, j;
++ struct core_target *target;
++ struct resource_context *res_ctx;
+
+ if (NULL == dc_target) {
+ dm_error("DC: dc_target is NULL!\n");
+@@ -381,62 +443,67 @@ bool dc_target_set_cursor_position(
+ return false;
+ }
+
+- core_target = DC_TARGET_TO_CORE(dc_target);
+- ipp = DC_STREAM_TO_CORE(core_target->public.streams[0])->ipp;
++ target = DC_TARGET_TO_CORE(dc_target);
++ res_ctx = &target->ctx->dc->current_context.res_ctx;
+
+- if (NULL == ipp) {
+- dm_error("DC: input pixel processor is NULL!\n");
+- return false;
++ for (i = 0; i < target->public.stream_count; i++) {
++ for (j = 0; j < MAX_PIPES; j++) {
++ struct input_pixel_processor *ipp =
++ res_ctx->pipe_ctx[j].ipp;
++
++ if (res_ctx->pipe_ctx[j].stream !=
++ DC_STREAM_TO_CORE(target->public.streams[i]))
++ continue;
++
++ /* As of writing of this code cursor is on the top
++ * plane so we only need to set it on first pipe we
++ * find. May need to make this code dce specific later.
++ */
++ if (ipp->funcs->ipp_cursor_set_position(ipp, position))
++ return true;
++ }
+ }
+
+-
+- if (true == ipp->funcs->ipp_cursor_set_position(ipp, position))
+- return true;
+-
+ return false;
+ }
+
+-/* TODO: #flip temporary to make flip work */
+-uint8_t dc_target_get_link_index(const struct dc_target *dc_target)
++uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target)
+ {
+- const struct core_target *target = CONST_DC_TARGET_TO_CORE(dc_target);
+- const struct core_sink *sink =
+- DC_SINK_TO_CORE(target->public.streams[0]->sink);
++ uint8_t i, j;
++ struct core_target *target = DC_TARGET_TO_CORE(dc_target);
++ struct resource_context *res_ctx =
++ &target->ctx->dc->current_context.res_ctx;
+
+- return sink->link->public.link_index;
+-}
++ for (i = 0; i < target->public.stream_count; i++) {
++ for (j = 0; j < MAX_PIPES; j++) {
++ struct timing_generator *tg = res_ctx->pipe_ctx[j].tg;
+
+-uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target)
+-{
+- struct core_target *core_target = DC_TARGET_TO_CORE(dc_target);
+- struct timing_generator *tg =
+- DC_STREAM_TO_CORE(core_target->public.streams[0])->tg;
++ if (res_ctx->pipe_ctx[j].stream !=
++ DC_STREAM_TO_CORE(target->public.streams[i]))
++ continue;
+
+- return tg->funcs->get_frame_count(tg);
++ return tg->funcs->get_frame_count(tg);
++ }
++ }
++
++ return 0;
+ }
+
+ enum dc_irq_source dc_target_get_irq_src(
+- const struct dc_target *dc_target, const enum irq_type irq_type)
++ const struct dc *dc,
++ const struct dc_target *dc_target,
++ const enum irq_type irq_type)
+ {
++ uint8_t i;
+ struct core_target *core_target = DC_TARGET_TO_CORE(dc_target);
+-
+- /* #TODO - Remove the assumption that the controller is always in the
+- * first stream of a core target */
+ struct core_stream *stream =
+- DC_STREAM_TO_CORE(core_target->public.streams[0]);
+- uint8_t controller_idx = stream->controller_idx;
+-
+- /* Get controller id */
+- enum controller_id crtc_id = controller_idx + 1;
+-
+- /* Calculate controller offset */
+- unsigned int offset = crtc_id - CONTROLLER_ID_D0;
+- unsigned int base = irq_type;
++ DC_STREAM_TO_CORE(core_target->public.streams[0]);
+
+- /* Calculate irq source */
+- enum dc_irq_source src = base + offset;
++ for (i = 0; i < MAX_PIPES; i++)
++ if (dc->current_context.res_ctx.pipe_ctx[i].stream == stream)
++ return irq_type + i;
+
+- return src;
++ return irq_type;
+ }
+
+ void dc_target_log(
+@@ -453,9 +520,8 @@ void dc_target_log(
+ dal_logger_write(dal_logger,
+ log_major,
+ log_minor,
+- "core_target 0x%x: surface_count=%d, stream_count=%d\n",
++ "core_target 0x%x: stream_count=%d\n",
+ core_target,
+- core_target->status.surface_count,
+ core_target->public.stream_count);
+
+ for (i = 0; i < core_target->public.stream_count; i++) {
+diff --git a/drivers/gpu/drm/amd/dal/dc/dc.h b/drivers/gpu/drm/amd/dal/dc/dc.h
+index 901c8c4..9cd239c 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dc.h
++++ b/drivers/gpu/drm/amd/dal/dc/dc.h
+@@ -108,7 +108,7 @@ struct dc_surface {
+
+ union plane_size plane_size;
+ struct dc_tiling_info tiling_info;
+- struct plane_colorimetry colorimetry;
++ enum color_space color_space;
+
+ enum surface_pixel_format format;
+ enum dc_rotation_angle rotation;
+@@ -125,7 +125,6 @@ struct dc_surface {
+ struct dc_surface_status {
+ struct dc_plane_address requested_address;
+ struct dc_plane_address current_address;
+- const struct dc_target *dc_target;
+ };
+
+ /*
+@@ -228,12 +227,13 @@ bool dc_target_is_connected_to_sink(
+ const struct dc_target *dc_target,
+ const struct dc_sink *dc_sink);
+
+-uint8_t dc_target_get_link_index(const struct dc_target *dc_target);
+ uint8_t dc_target_get_controller_id(const struct dc_target *dc_target);
+
+ uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target);
+ enum dc_irq_source dc_target_get_irq_src(
+- const struct dc_target *dc_target, const enum irq_type irq_type);
++ const struct dc *dc,
++ const struct dc_target *dc_target,
++ const enum irq_type irq_type);
+
+ void dc_target_enable_memory_requests(struct dc_target *target);
+ void dc_target_disable_memory_requests(struct dc_target *target);
+diff --git a/drivers/gpu/drm/amd/dal/dc/dc_types.h b/drivers/gpu/drm/amd/dal/dc/dc_types.h
+index 5593c17..863443b 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dc_types.h
++++ b/drivers/gpu/drm/amd/dal/dc/dc_types.h
+@@ -67,13 +67,17 @@ enum dce_environment {
+ #define MAX_SURFACE_NUM 2
+ #define NUM_PIXEL_FORMATS 10
+
+-enum surface_color_space {
+- SURFACE_COLOR_SPACE_SRGB = 0x0000,
+- SURFACE_COLOR_SPACE_BT601 = 0x0001,
+- SURFACE_COLOR_SPACE_BT709 = 0x0002,
+- SURFACE_COLOR_SPACE_XVYCC_BT601 = 0x0004,
+- SURFACE_COLOR_SPACE_XVYCC_BT709 = 0x0008,
+- SURFACE_COLOR_SPACE_XRRGB = 0x0010
++enum color_space {
++ COLOR_SPACE_UNKNOWN,
++ COLOR_SPACE_SRGB_FULL_RANGE,
++ COLOR_SPACE_SRGB_LIMITED_RANGE,
++ COLOR_SPACE_YPBPR601,
++ COLOR_SPACE_YPBPR709,
++ COLOR_SPACE_YCBCR601,
++ COLOR_SPACE_YCBCR709,
++ COLOR_SPACE_YCBCR601_YONLY,
++ COLOR_SPACE_YCBCR709_YONLY,
++ COLOR_SPACE_N_MVPU_SUPER_AA,
+ };
+
+
+@@ -170,11 +174,6 @@ enum dc_edid_status {
+ EDID_BAD_CHECKSUM,
+ };
+
+-struct plane_colorimetry {
+- enum surface_color_space color_space;
+- bool limited_range;
+-};
+-
+ /* audio capability from EDID*/
+ struct dc_cea_audio_mode {
+ uint8_t format_code; /* ucData[0] [6:3]*/
+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 783d47e..efa592f 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
+@@ -530,7 +530,7 @@ void dce100_destruct_resource_pool(struct resource_pool *pool)
+ {
+ unsigned int i;
+
+- for (i = 0; i < pool->controller_count; i++) {
++ for (i = 0; i < pool->pipe_count; i++) {
+ if (pool->opps[i] != NULL)
+ dce100_opp_destroy(&pool->opps[i]);
+
+@@ -615,12 +615,13 @@ static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
+ }
+
+ static void build_audio_output(
+- const struct core_stream *stream,
++ const struct pipe_ctx *pipe_ctx,
+ struct audio_output *audio_output)
+ {
+- audio_output->engine_id = stream->stream_enc->id;
++ const struct core_stream *stream = pipe_ctx->stream;
++ audio_output->engine_id = pipe_ctx->stream_enc->id;
+
+- audio_output->signal = stream->signal;
++ audio_output->signal = pipe_ctx->signal;
+
+ /* audio_crtc_info */
+
+@@ -654,44 +655,45 @@ static void build_audio_output(
+ stream->public.timing.display_color_depth;
+
+ audio_output->crtc_info.requested_pixel_clock =
+- stream->pix_clk_params.requested_pix_clk;
++ pipe_ctx->pix_clk_params.requested_pix_clk;
+
+ /*
+ * TODO - Investigate why calculated pixel clk has to be
+ * requested pixel clk
+ */
+ audio_output->crtc_info.calculated_pixel_clock =
+- stream->pix_clk_params.requested_pix_clk;
++ pipe_ctx->pix_clk_params.requested_pix_clk;
+
+- if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
+- stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
++ if (pipe_ctx->signal == SIGNAL_TYPE_DISPLAY_PORT ||
++ pipe_ctx->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+ audio_output->pll_info.dp_dto_source_clock_in_khz =
+ dal_display_clock_get_dp_ref_clk_frequency(
+- stream->dis_clk);
++ pipe_ctx->dis_clk);
+ }
+
+ audio_output->pll_info.feed_back_divider =
+- stream->pll_settings.feedback_divider;
++ pipe_ctx->pll_settings.feedback_divider;
+
+ audio_output->pll_info.dto_source =
+ translate_to_dto_source(
+- stream->controller_idx + 1);
++ pipe_ctx->pipe_idx + 1);
+
+ /* TODO hard code to enable for now. Need get from stream */
+ audio_output->pll_info.ss_enabled = true;
+
+ audio_output->pll_info.ss_percentage =
+- stream->pll_settings.ss_percentage;
++ pipe_ctx->pll_settings.ss_percentage;
+ }
+
+ static void get_pixel_clock_parameters(
+- const struct core_stream *stream,
++ const struct pipe_ctx *pipe_ctx,
+ struct pixel_clk_params *pixel_clk_params)
+ {
++ const struct core_stream *stream = pipe_ctx->stream;
+ pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz;
+ pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id;
+ pixel_clk_params->signal_type = stream->sink->public.sink_signal;
+- pixel_clk_params->controller_id = stream->controller_idx + 1;
++ pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1;
+ /* TODO: un-hardcode*/
+ pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
+ LINK_RATE_REF_FREQ_IN_KHZ;
+@@ -701,20 +703,20 @@ static void get_pixel_clock_parameters(
+ pixel_clk_params->flags.DISPLAY_BLANKED = 1;
+ }
+
+-static enum dc_status build_stream_hw_param(struct core_stream *stream)
++static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx)
+ {
+ /*TODO: unhardcode*/
+- stream->max_tmds_clk_from_edid_in_mhz = 0;
+- stream->max_hdmi_deep_color = COLOR_DEPTH_121212;
+- stream->max_hdmi_pixel_clock = 600000;
++ pipe_ctx->max_tmds_clk_from_edid_in_mhz = 0;
++ pipe_ctx->max_hdmi_deep_color = COLOR_DEPTH_121212;
++ pipe_ctx->max_hdmi_pixel_clock = 600000;
+
+- get_pixel_clock_parameters(stream, &stream->pix_clk_params);
+- stream->clock_source->funcs->get_pix_clk_dividers(
+- stream->clock_source,
+- &stream->pix_clk_params,
+- &stream->pll_settings);
++ get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params);
++ pipe_ctx->clock_source->funcs->get_pix_clk_dividers(
++ pipe_ctx->clock_source,
++ &pipe_ctx->pix_clk_params,
++ &pipe_ctx->pll_settings);
+
+- build_audio_output(stream, &stream->audio_output);
++ build_audio_output(pipe_ctx, &pipe_ctx->audio_output);
+
+ return DC_OK;
+ }
+@@ -724,7 +726,7 @@ static enum dc_status validate_mapped_resource(
+ struct validate_context *context)
+ {
+ enum dc_status status = DC_OK;
+- uint8_t i, j;
++ uint8_t i, j, k;
+
+ for (i = 0; i < context->target_count; i++) {
+ struct core_target *target = context->targets[i];
+@@ -736,33 +738,44 @@ static enum dc_status validate_mapped_resource(
+ DC_STREAM_TO_CORE(target->public.streams[j]);
+ struct core_link *link = stream->sink->link;
+
+- if (!stream->tg->funcs->validate_timing(
+- stream->tg, &stream->public.timing))
+- return DC_FAIL_CONTROLLER_VALIDATE;
++ for (k = 0; k < MAX_PIPES; k++) {
++ struct pipe_ctx *pipe_ctx =
++ &context->res_ctx.pipe_ctx[k];
++
++ if (context->res_ctx.pipe_ctx[k].stream != stream)
++ continue;
++
++ if (!pipe_ctx->tg->funcs->validate_timing(
++ pipe_ctx->tg, &stream->public.timing))
++ return DC_FAIL_CONTROLLER_VALIDATE;
++
++ if (pipe_ctx->signal == SIGNAL_TYPE_VIRTUAL)
++ return status;
+
+- if (stream->signal == SIGNAL_TYPE_VIRTUAL)
+- return status;
++ status = build_pipe_hw_param(pipe_ctx);
+
+- status = build_stream_hw_param(stream);
++ if (status != DC_OK)
++ return status;
+
+- if (status != DC_OK)
+- return status;
++ if (!link->link_enc->funcs->validate_output_with_stream(
++ link->link_enc,
++ pipe_ctx))
++ return DC_FAIL_ENC_VALIDATE;
+
+- if (!link->link_enc->funcs->validate_output_with_stream(
+- link->link_enc,
+- stream))
+- return DC_FAIL_ENC_VALIDATE;
++ /* TODO: validate audio ASIC caps, encoder */
+
+- /* TODO: validate audio ASIC caps, encoder */
++ status = dc_link_validate_mode_timing(stream->sink,
++ link,
++ &stream->public.timing);
+
+- status = dc_link_validate_mode_timing(stream->sink,
+- link,
+- &stream->public.timing);
++ if (status != DC_OK)
++ return status;
+
+- if (status != DC_OK)
+- return status;
++ build_info_frame(pipe_ctx);
+
+- build_info_frame(stream);
++ /* do not need to validate non root pipes */
++ break;
++ }
+ }
+ }
+
+@@ -783,16 +796,17 @@ static void set_target_unchanged(
+ struct validate_context *context,
+ uint8_t target_idx)
+ {
+- uint8_t i;
++ uint8_t i, j;
+ struct core_target *target = context->targets[target_idx];
+-
+ context->target_flags[target_idx].unchanged = true;
+ for (i = 0; i < target->public.stream_count; i++) {
+- struct core_stream *core_stream =
++ struct core_stream *stream =
+ DC_STREAM_TO_CORE(target->public.streams[i]);
+- uint8_t index = core_stream->controller_idx;
+-
+- context->res_ctx.controller_ctx[index].flags.unchanged = true;
++ for (j = 0; j < MAX_PIPES; j++) {
++ if (context->res_ctx.pipe_ctx[j].stream == stream)
++ context->res_ctx.pipe_ctx[j].flags.unchanged =
++ true;
++ }
+ }
+ }
+
+@@ -800,24 +814,7 @@ static enum dc_status map_clock_resources(
+ const struct dc *dc,
+ struct validate_context *context)
+ {
+- uint8_t i, j;
+-
+- /* mark resources used for targets that are already active */
+- for (i = 0; i < context->target_count; i++) {
+- struct core_target *target = context->targets[i];
+-
+- if (!context->target_flags[i].unchanged)
+- continue;
+-
+- for (j = 0; j < target->public.stream_count; j++) {
+- struct core_stream *stream =
+- DC_STREAM_TO_CORE(target->public.streams[j]);
+-
+- reference_clock_source(
+- &context->res_ctx,
+- stream->clock_source);
+- }
+- }
++ uint8_t i, j, k;
+
+ /* acquire new resources */
+ for (i = 0; i < context->target_count; i++) {
+@@ -830,24 +827,35 @@ static enum dc_status map_clock_resources(
+ struct core_stream *stream =
+ DC_STREAM_TO_CORE(target->public.streams[j]);
+
+- if (dc_is_dp_signal(stream->signal)
+- || stream->signal == SIGNAL_TYPE_VIRTUAL)
+- stream->clock_source = context->res_ctx.
+- pool.clock_sources[DCE100_CLK_SRC_EXT];
+- else
+- stream->clock_source =
+- find_used_clk_src_for_sharing(
+- context, stream);
+- if (stream->clock_source == NULL)
+- stream->clock_source =
+- find_first_free_pll(&context->res_ctx);
+-
+- if (stream->clock_source == NULL)
+- return DC_NO_CLOCK_SOURCE_RESOURCE;
+-
+- reference_clock_source(
+- &context->res_ctx,
+- stream->clock_source);
++ for (k = 0; k < MAX_PIPES; k++) {
++ struct pipe_ctx *pipe_ctx =
++ &context->res_ctx.pipe_ctx[k];
++
++ if (context->res_ctx.pipe_ctx[k].stream != stream)
++ continue;
++
++ 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];
++ 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)
++ return DC_NO_CLOCK_SOURCE_RESOURCE;
++
++ reference_clock_source(
++ &context->res_ctx,
++ pipe_ctx->clock_source);
++
++ /* only one cs per stream regardless of mpo */
++ break;
++ }
+ }
+ }
+
+@@ -865,24 +873,30 @@ enum dc_status dce100_validate_with_context(
+ struct dc_context *dc_ctx = dc->ctx;
+
+ for (i = 0; i < set_count; i++) {
++ bool unchanged = false;
++
+ context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
++ context->target_count++;
+
+ for (j = 0; j < dc->current_context.target_count; j++)
+- if (dc->current_context.targets[j] == context->targets[i])
++ if (dc->current_context.targets[j]
++ == context->targets[i]) {
++ unchanged = true;
+ set_target_unchanged(context, i);
+-
+- if (!context->target_flags[i].unchanged)
+- if (!logical_attach_surfaces_to_target(
++ context->target_status[i] =
++ dc->current_context.target_status[j];
++ }
++ if (!unchanged)
++ if (!attach_surfaces_to_context(
+ (struct dc_surface **)set[i].surfaces,
+ set[i].surface_count,
+- &context->targets[i]->public)) {
++ &context->targets[i]->public,
++ context)) {
+ DC_ERROR("Failed to attach surface to target!\n");
+ return DC_FAIL_ATTACH_SURFACES;
+ }
+ }
+
+- context->target_count = set_count;
+-
+ context->res_ctx.pool = dc->res_pool;
+
+ result = map_resources(dc, context);
+@@ -969,7 +983,7 @@ bool dce100_construct_resource_pool(
+
+ }
+
+- pool->controller_count =
++ 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);
+@@ -980,7 +994,7 @@ bool dce100_construct_resource_pool(
+ goto filter_create_fail;
+ }
+
+- for (i = 0; i < pool->controller_count; i++) {
++ for (i = 0; i < pool->pipe_count; i++) {
+ pool->timing_generators[i] = dce100_timing_generator_create(
+ adapter_serv, ctx, i, &dce100_tg_offsets[i]);
+ if (pool->timing_generators[i] == NULL) {
+@@ -1031,7 +1045,7 @@ bool dce100_construct_resource_pool(
+ audio_init_data.as = adapter_serv;
+ audio_init_data.ctx = ctx;
+ pool->audio_count = 0;
+- for (i = 0; i < pool->controller_count; i++) {
++ 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);
+@@ -1089,13 +1103,13 @@ stream_enc_create_fail:
+ }
+
+ audio_create_fail:
+- for (i = 0; i < pool->controller_count; i++) {
++ for (i = 0; i < pool->pipe_count; i++) {
+ if (pool->audios[i] != NULL)
+ dal_audio_destroy(&pool->audios[i]);
+ }
+
+ controller_create_fail:
+- for (i = 0; i < pool->controller_count; i++) {
++ for (i = 0; i < pool->pipe_count; i++) {
+ if (pool->opps[i] != NULL)
+ dce100_opp_destroy(&pool->opps[i]);
+
+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 a815a6d..70349a0 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
+@@ -546,17 +546,17 @@ prescale_alloc_fail:
+ }
+
+ static enum dc_status bios_parser_crtc_source_select(
+- struct core_stream *stream)
++ struct pipe_ctx *pipe_ctx)
+ {
+ struct dc_bios *dcb;
+ /* call VBIOS table to set CRTC source for the HW
+ * encoder block
+ * note: video bios clears all FMT setting here. */
+ struct bp_crtc_source_select crtc_source_select = {0};
+- const struct core_sink *sink = stream->sink;
++ const struct core_sink *sink = pipe_ctx->stream->sink;
+
+- crtc_source_select.engine_id = stream->stream_enc->id;
+- crtc_source_select.controller_id = stream->controller_idx + 1;
++ crtc_source_select.engine_id = pipe_ctx->stream_enc->id;
++ crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1;
+ /*TODO: Need to un-hardcode color depth, dp_audio and account for
+ * the case where signal and sink signal is different (translator
+ * encoder)*/
+@@ -576,32 +576,6 @@ static enum dc_status bios_parser_crtc_source_select(
+ return DC_OK;
+ }
+
+-static enum color_space surface_color_to_color_space(
+- struct plane_colorimetry *colorimetry)
+-{
+- enum color_space color_space = COLOR_SPACE_UNKNOWN;
+-
+- switch (colorimetry->color_space) {
+- case SURFACE_COLOR_SPACE_SRGB:
+- case SURFACE_COLOR_SPACE_XRRGB:
+- if (colorimetry->limited_range)
+- color_space = COLOR_SPACE_SRGB_LIMITED_RANGE;
+- else
+- color_space = COLOR_SPACE_SRGB_FULL_RANGE;
+- break;
+- case SURFACE_COLOR_SPACE_BT601:
+- case SURFACE_COLOR_SPACE_XVYCC_BT601:
+- color_space = COLOR_SPACE_YCBCR601;
+- break;
+- case SURFACE_COLOR_SPACE_BT709:
+- case SURFACE_COLOR_SPACE_XVYCC_BT709:
+- color_space = COLOR_SPACE_YCBCR709;
+- break;
+- }
+-
+- return color_space;
+-}
+-
+ /*******************************FMT**************************************/
+ static void program_fmt(
+ struct output_pixel_processor *opp,
+@@ -630,35 +604,35 @@ static void update_bios_scratch_critical_state(struct adapter_service *as,
+ dcb->funcs->set_scratch_critical_state(dcb, state);
+ }
+
+-static void update_info_frame(struct core_stream *stream)
++static void update_info_frame(struct pipe_ctx *pipe_ctx)
+ {
+- if (dc_is_hdmi_signal(stream->signal))
+- stream->stream_enc->funcs->update_hdmi_info_packets(
+- stream->stream_enc,
+- &stream->encoder_info_frame);
+- else if (dc_is_dp_signal(stream->signal))
+- stream->stream_enc->funcs->update_dp_info_packets(
+- stream->stream_enc,
+- &stream->encoder_info_frame);
++ if (dc_is_hdmi_signal(pipe_ctx->signal))
++ pipe_ctx->stream_enc->funcs->update_hdmi_info_packets(
++ pipe_ctx->stream_enc,
++ &pipe_ctx->encoder_info_frame);
++ else if (dc_is_dp_signal(pipe_ctx->signal))
++ pipe_ctx->stream_enc->funcs->update_dp_info_packets(
++ pipe_ctx->stream_enc,
++ &pipe_ctx->encoder_info_frame);
+ }
+
+
+-static void enable_stream(struct core_stream *stream)
++static void enable_stream(struct pipe_ctx *pipe_ctx)
+ {
+ enum dc_lane_count lane_count =
+- stream->sink->link->public.cur_link_settings.lane_count;
++ pipe_ctx->stream->sink->link->public.cur_link_settings.lane_count;
+
+- struct dc_crtc_timing *timing = &stream->public.timing;
+- struct core_link *link = stream->sink->link;
++ struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
++ struct core_link *link = pipe_ctx->stream->sink->link;
+
+ /* 1. update AVI info frame (HDMI, DP)
+ * we always need to update info frame
+ */
+ uint32_t active_total_with_borders;
+ uint32_t early_control = 0;
+- struct timing_generator *tg = stream->tg;
++ struct timing_generator *tg = pipe_ctx->tg;
+
+- update_info_frame(stream);
++ update_info_frame(pipe_ctx);
+ /* enable early control to avoid corruption on DP monitor*/
+ active_total_with_borders =
+ timing->h_addressable
+@@ -674,11 +648,11 @@ static void enable_stream(struct core_stream *stream)
+ tg->funcs->set_early_control(tg, early_control);
+
+ /* enable audio only within mode set */
+- if (stream->audio != NULL) {
++ if (pipe_ctx->audio != NULL) {
+ dal_audio_enable_output(
+- stream->audio,
+- stream->stream_enc->id,
+- stream->signal);
++ pipe_ctx->audio,
++ pipe_ctx->stream_enc->id,
++ pipe_ctx->signal);
+ }
+
+ /* For MST, there are multiply stream go to only one link.
+@@ -686,26 +660,27 @@ static void enable_stream(struct core_stream *stream)
+ * disconnect them during disable_stream
+ * BY this, it is logic clean to separate stream and link */
+ link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
+- stream->stream_enc->id, true);
++ pipe_ctx->stream_enc->id, true);
+
+ }
+
+-static void disable_stream(struct core_stream *stream)
++static void disable_stream(struct pipe_ctx *pipe_ctx)
+ {
++ struct core_stream *stream = pipe_ctx->stream;
+ struct core_link *link = stream->sink->link;
+
+- if (dc_is_hdmi_signal(stream->signal))
+- stream->stream_enc->funcs->stop_hdmi_info_packets(
+- stream->stream_enc);
++ if (dc_is_hdmi_signal(pipe_ctx->signal))
++ pipe_ctx->stream_enc->funcs->stop_hdmi_info_packets(
++ pipe_ctx->stream_enc);
+
+- if (dc_is_dp_signal(stream->signal))
+- stream->stream_enc->funcs->stop_dp_info_packets(
+- stream->stream_enc);
++ if (dc_is_dp_signal(pipe_ctx->signal))
++ pipe_ctx->stream_enc->funcs->stop_dp_info_packets(
++ pipe_ctx->stream_enc);
+
+- if (stream->audio) {
++ if (pipe_ctx->audio) {
+ /* mute audio */
+- dal_audio_mute(stream->audio, stream->stream_enc->id,
+- stream->signal);
++ dal_audio_mute(pipe_ctx->audio, pipe_ctx->stream_enc->id,
++ pipe_ctx->signal);
+
+ /* TODO: notify audio driver for if audio modes list changed
+ * add audio mode list change flag */
+@@ -715,27 +690,26 @@ static void disable_stream(struct core_stream *stream)
+ }
+
+ /* blank at encoder level */
+- if (dc_is_dp_signal(stream->signal))
+- stream->stream_enc->funcs->dp_blank(stream->stream_enc);
++ if (dc_is_dp_signal(pipe_ctx->signal))
++ pipe_ctx->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc);
+
+ link->link_enc->funcs->connect_dig_be_to_fe(
+ link->link_enc,
+- stream->stream_enc->id,
++ pipe_ctx->stream_enc->id,
+ false);
+
+ }
+
+-static void unblank_stream(struct core_stream *stream,
++static void unblank_stream(struct pipe_ctx *pipe_ctx,
+ struct dc_link_settings *link_settings)
+ {
+ struct encoder_unblank_param params = { { 0 } };
+
+ /* only 3 items below are used by unblank */
+ params.crtc_timing.pixel_clock =
+- stream->public.timing.pix_clk_khz;
++ pipe_ctx->stream->public.timing.pix_clk_khz;
+ params.link_settings.link_rate = link_settings->link_rate;
+- stream->stream_enc->funcs->dp_unblank(
+- stream->stream_enc, &params);
++ pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, &params);
+ }
+
+ static enum color_space get_output_color_space(
+@@ -776,106 +750,102 @@ static enum color_space get_output_color_space(
+ return color_space;
+ }
+
+-static enum dc_status apply_single_controller_ctx_to_hw(uint8_t controller_idx,
++static enum dc_status apply_single_controller_ctx_to_hw(
++ struct pipe_ctx *pipe_ctx,
+ struct validate_context *context,
+- const struct dc *dc)
++ struct dc *dc)
+ {
+- struct core_stream *stream =
+- context->res_ctx.controller_ctx[controller_idx].stream;
+- struct core_stream *old_stream =
+- dc->current_context.res_ctx.controller_ctx[controller_idx].stream;
+- struct output_pixel_processor *opp =
+- context->res_ctx.pool.opps[controller_idx];
+- bool timing_changed = context->res_ctx.controller_ctx[controller_idx]
+- .flags.timing_changed;
++ struct core_stream *stream = pipe_ctx->stream;
++ struct pipe_ctx *old_pipe_ctx =
++ &dc->current_context.res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
++ bool timing_changed = context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]
++ .flags.timing_changed;
+ enum color_space color_space;
+
+ if (timing_changed) {
+ /* Must blank CRTC after disabling power gating and before any
+ * programming, otherwise CRTC will be hung in bad state
+ */
+- stream->tg->funcs->set_blank(stream->tg, true);
++ pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
+
+ /*
+ * only disable stream in case it was ever enabled
+ */
+- if (old_stream)
+- core_link_disable_stream(
+- old_stream->sink->link,
+- old_stream);
++ if (old_pipe_ctx->stream)
++ core_link_disable_stream(old_pipe_ctx);
+
+ /*TODO: AUTO check if timing changed*/
+- if (false == stream->clock_source->funcs->program_pix_clk(
+- stream->clock_source,
+- &stream->pix_clk_params,
+- &stream->pll_settings)) {
++ if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
++ pipe_ctx->clock_source,
++ &pipe_ctx->pix_clk_params,
++ &pipe_ctx->pll_settings)) {
+ BREAK_TO_DEBUGGER();
+ return DC_ERROR_UNEXPECTED;
+ }
+
+- stream->tg->funcs->program_timing(
+- stream->tg,
++ pipe_ctx->tg->funcs->program_timing(
++ pipe_ctx->tg,
+ &stream->public.timing,
+ true);
+ }
+
+ /*TODO: mst support - use total stream count*/
+- stream->mi->funcs->allocate_mem_input(
+- stream->mi,
++ pipe_ctx->mi->funcs->allocate_mem_input(
++ pipe_ctx->mi,
+ stream->public.timing.h_total,
+ stream->public.timing.v_total,
+ stream->public.timing.pix_clk_khz,
+ context->target_count);
+
+ if (timing_changed) {
+- if (false == stream->tg->funcs->enable_crtc(
+- stream->tg)) {
++ if (false == pipe_ctx->tg->funcs->enable_crtc(
++ pipe_ctx->tg)) {
+ BREAK_TO_DEBUGGER();
+ return DC_ERROR_UNEXPECTED;
+ }
+ }
+
+ /* TODO: move to stream encoder */
+- if (stream->signal != SIGNAL_TYPE_VIRTUAL)
+- if (DC_OK != bios_parser_crtc_source_select(stream)) {
++ if (pipe_ctx->signal != SIGNAL_TYPE_VIRTUAL)
++ if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) {
+ BREAK_TO_DEBUGGER();
+ return DC_ERROR_UNEXPECTED;
+ }
+
+- opp->funcs->opp_set_dyn_expansion(
+- opp,
++ pipe_ctx->opp->funcs->opp_set_dyn_expansion(
++ pipe_ctx->opp,
+ COLOR_SPACE_YCBCR601,
+ stream->public.timing.display_color_depth,
+ stream->sink->public.sink_signal);
+
+- program_fmt(opp, &stream->bit_depth_params, &stream->clamping);
++ program_fmt(pipe_ctx->opp, &stream->bit_depth_params, &stream->clamping);
+
+ stream->sink->link->link_enc->funcs->setup(
+ stream->sink->link->link_enc,
+- stream->signal);
++ pipe_ctx->signal);
+
+- if (dc_is_dp_signal(stream->signal))
+- stream->stream_enc->funcs->dp_set_stream_attribute(
+- stream->stream_enc,
++ if (dc_is_dp_signal(pipe_ctx->signal))
++ pipe_ctx->stream_enc->funcs->dp_set_stream_attribute(
++ pipe_ctx->stream_enc,
+ &stream->public.timing);
+
+- if (dc_is_hdmi_signal(stream->signal))
+- stream->stream_enc->funcs->hdmi_set_stream_attribute(
+- stream->stream_enc,
++ if (dc_is_hdmi_signal(pipe_ctx->signal))
++ pipe_ctx->stream_enc->funcs->hdmi_set_stream_attribute(
++ pipe_ctx->stream_enc,
+ &stream->public.timing,
+- stream->audio != NULL);
++ pipe_ctx->audio != NULL);
+
+- if (dc_is_dvi_signal(stream->signal))
+- stream->stream_enc->funcs->dvi_set_stream_attribute(
+- stream->stream_enc,
++ if (dc_is_dvi_signal(pipe_ctx->signal))
++ pipe_ctx->stream_enc->funcs->dvi_set_stream_attribute(
++ pipe_ctx->stream_enc,
+ &stream->public.timing,
+- (stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
++ (pipe_ctx->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
+ true : false);
+
+- if (stream->audio != NULL) {
++ if (pipe_ctx->audio != NULL) {
+ if (AUDIO_RESULT_OK != dal_audio_setup(
+- stream->audio,
+- &stream->audio_output,
++ pipe_ctx->audio,
++ &pipe_ctx->audio_output,
+ &stream->public.audio_info)) {
+ BREAK_TO_DEBUGGER();
+ return DC_ERROR_UNEXPECTED;
+@@ -883,24 +853,24 @@ static enum dc_status apply_single_controller_ctx_to_hw(uint8_t controller_idx,
+ }
+
+ /* Setup audio rate clock source */
+- if (stream->audio != NULL)
++ if (pipe_ctx->audio != NULL)
+ dal_audio_setup_audio_wall_dto(
+- stream->audio,
+- stream->signal,
+- &stream->audio_output.crtc_info,
+- &stream->audio_output.pll_info);
++ pipe_ctx->audio,
++ pipe_ctx->signal,
++ &pipe_ctx->audio_output.crtc_info,
++ &pipe_ctx->audio_output.pll_info);
+
+ /* program blank color */
+ color_space = get_output_color_space(&stream->public.timing);
+- stream->tg->funcs->set_blank_color(
+- context->res_ctx.pool.timing_generators[controller_idx],
++ pipe_ctx->tg->funcs->set_blank_color(
++ pipe_ctx->tg,
+ color_space);
+
+ if (timing_changed)
+- core_link_enable_stream(stream->sink->link, stream);
++ core_link_enable_stream(pipe_ctx);
+
+- if (dc_is_dp_signal(stream->signal))
+- unblank_stream(stream,
++ if (dc_is_dp_signal(pipe_ctx->signal))
++ unblank_stream(pipe_ctx,
+ &stream->sink->link->public.cur_link_settings);
+
+ return DC_OK;
+@@ -923,7 +893,7 @@ static void power_down_controllers(struct dc *dc)
+ {
+ int i;
+
+- for (i = 0; i < dc->res_pool.controller_count; i++) {
++ for (i = 0; i < dc->res_pool.pipe_count; i++) {
+ dc->res_pool.timing_generators[i]->funcs->disable_crtc(
+ dc->res_pool.timing_generators[i]);
+ }
+@@ -960,7 +930,7 @@ static void disable_vga_and_power_gate_all_controllers(
+ dcb = dal_adapter_service_get_bios_parser(
+ dc->res_pool.adapter_srv);
+
+- for (i = 0; i < dc->res_pool.controller_count; i++) {
++ for (i = 0; i < dc->res_pool.pipe_count; i++) {
+ tg = dc->res_pool.timing_generators[i];
+ ctx = dc->ctx;
+
+@@ -1133,14 +1103,13 @@ static void set_display_clock(struct validate_context *context)
+ }
+
+ static uint32_t compute_pstate_blackout_duration(
+- const struct dc *dc,
++ struct bw_fixed blackout_duration,
+ const struct core_stream *stream)
+ {
+ uint32_t total_dest_line_time_ns;
+ uint32_t pstate_blackout_duration_ns;
+
+- pstate_blackout_duration_ns = 1000 *
+- dc->bw_vbios.blackout_duration.value >> 24;
++ pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
+
+ total_dest_line_time_ns = 1000000UL *
+ stream->public.timing.h_total /
+@@ -1154,63 +1123,50 @@ static void set_displaymarks(
+ const struct dc *dc,
+ struct validate_context *context)
+ {
+- uint8_t i, j;
+- uint8_t total_streams = 0;
+- uint8_t target_count = context->target_count;
+- uint32_t pstate_blackout_duration_ns;
++ uint8_t i, num_pipes;
++
++ for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) {
++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
++ uint32_t total_dest_line_time_ns;
++
++ if (pipe_ctx->stream == NULL)
++ continue;
+
+- for (i = 0; i < target_count; i++) {
+- const struct core_target *target = context->targets[i];
+-
+- for (j = 0; j < target->public.stream_count; j++) {
+- const struct core_stream *stream =
+- DC_STREAM_TO_CORE(target->public.streams[j]);
+-
+- pstate_blackout_duration_ns =
+- compute_pstate_blackout_duration(dc, stream);
+-
+- stream->mi->funcs->mem_input_program_display_marks(
+- stream->mi,
+- context->bw_results
+- .nbp_state_change_wm_ns[total_streams],
+- context->bw_results
+- .stutter_exit_wm_ns[total_streams],
+- context->bw_results.
+- urgent_wm_ns[total_streams],
+- pstate_blackout_duration_ns);
+-
+- total_streams++;
+- } /* for ()*/
+- } /* for() */
++ total_dest_line_time_ns = compute_pstate_blackout_duration(
++ dc->bw_vbios.blackout_duration, pipe_ctx->stream);
++ pipe_ctx->mi->funcs->mem_input_program_display_marks(
++ pipe_ctx->mi,
++ context->bw_results.nbp_state_change_wm_ns[num_pipes],
++ context->bw_results.stutter_exit_wm_ns[num_pipes],
++ context->bw_results.urgent_wm_ns[num_pipes],
++ total_dest_line_time_ns);
++ num_pipes++;
++ }
+ }
+
+-static void set_safe_displaymarks(const struct dc *dc, struct validate_context *context)
++
++static void set_safe_displaymarks(struct resource_context *res_ctx)
+ {
+- uint8_t i, j;
+- uint8_t target_count = context->target_count;
++ uint8_t i;
+ struct bw_watermarks max_marks = { MAX_WATERMARK, MAX_WATERMARK };
+ struct bw_watermarks nbp_marks = { SAFE_NBP_MARK, SAFE_NBP_MARK };
+
+- for (i = 0; i < target_count; i++) {
+- struct core_target *target = context->targets[i];
+-
+- for (j = 0; j < target->public.stream_count; j++) {
+- struct core_stream *stream =
+- DC_STREAM_TO_CORE(target->public.streams[j]);
++ for (i = 0; i < MAX_PIPES; i++) {
++ if (res_ctx->pipe_ctx[i].stream == NULL)
++ continue;
+
+- stream->mi->funcs->mem_input_program_display_marks(
+- stream->mi,
++ res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_display_marks(
++ res_ctx->pipe_ctx[i].mi,
+ nbp_marks,
+ max_marks,
+ max_marks,
+ MAX_WATERMARK);
+- }
+ }
+ }
+
+ static void program_bw(struct dc *dc, struct validate_context *context)
+ {
+- set_safe_displaymarks(dc, context);
++ set_safe_displaymarks(&context->res_ctx);
+ /*TODO: when pplib works*/
+ /*dc_set_clocks_and_clock_state(context);*/
+
+@@ -1220,31 +1176,27 @@ static void program_bw(struct dc *dc, struct validate_context *context)
+
+ static void switch_dp_clock_sources(
+ const struct dc *dc,
+- struct validate_context *val_context)
++ struct resource_context *res_ctx)
+ {
+- uint8_t i, j;
+- for (i = 0; i < val_context->target_count; i++) {
+- struct core_target *target = val_context->targets[i];
+- for (j = 0; j < target->public.stream_count; j++) {
+- struct core_stream *stream =
+- DC_STREAM_TO_CORE(target->public.streams[j]);
+-
+- if (dc_is_dp_signal(stream->signal)) {
+- struct clock_source *clk_src =
+- find_used_clk_src_for_sharing(
+- val_context, stream);
+-
+- if (clk_src &&
+- clk_src != stream->clock_source) {
+- unreference_clock_source(
+- &val_context->res_ctx,
+- stream->clock_source);
+- stream->clock_source = clk_src;
+- reference_clock_source(
+- &val_context->res_ctx, clk_src);
+- dc->hwss.crtc_switch_to_clk_src(
+- clk_src, stream->opp->inst);
+- }
++ uint8_t i;
++ for (i = 0; i < MAX_PIPES; i++) {
++ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
++
++ if (pipe_ctx->stream == NULL)
++ continue;
++
++ if (dc_is_dp_signal(pipe_ctx->signal)) {
++ struct clock_source *clk_src =
++ find_used_clk_src_for_sharing(
++ res_ctx, pipe_ctx);
++
++ if (clk_src &&
++ clk_src != pipe_ctx->clock_source) {
++ unreference_clock_source(
++ res_ctx, pipe_ctx->clock_source);
++ pipe_ctx->clock_source = clk_src;
++ reference_clock_source(res_ctx, clk_src);
++ dc->hwss.crtc_switch_to_clk_src(clk_src, i);
+ }
+ }
+ }
+@@ -1256,22 +1208,20 @@ static void switch_dp_clock_sources(
+
+ /*TODO: const validate_context*/
+ static enum dc_status apply_ctx_to_hw(
+- const struct dc *dc,
++ struct dc *dc,
+ struct validate_context *context)
+ {
+ enum dc_status status;
+ uint8_t i;
+- struct resource_pool *pool = &context->res_ctx.pool;
+
+ update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv,
+ true);
+
+- for (i = 0; i < pool->controller_count; i++) {
+- struct controller_ctx *ctlr_ctx
+- = &context->res_ctx.controller_ctx[i];
++ for (i = 0; i < MAX_PIPES; i++) {
++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+ struct dc_bios *dcb;
+
+- if (ctlr_ctx->flags.unchanged || !ctlr_ctx->stream)
++ if (pipe_ctx->stream == NULL || pipe_ctx->flags.unchanged)
+ continue;
+
+ dcb = dal_adapter_service_get_bios_parser(
+@@ -1282,7 +1232,7 @@ static enum dc_status apply_ctx_to_hw(
+ PIPE_GATING_CONTROL_DISABLE);
+ }
+
+- set_safe_displaymarks(dc, context);
++ set_safe_displaymarks(&context->res_ctx);
+ /*TODO: when pplib works*/
+ /*dc_set_clocks_and_clock_state(context);*/
+
+@@ -1290,14 +1240,14 @@ static enum dc_status apply_ctx_to_hw(
+ > dc->current_context.bw_results.dispclk_khz)
+ set_display_clock(context);
+
+- for (i = 0; i < pool->controller_count; i++) {
+- struct controller_ctx *ctlr_ctx
+- = &context->res_ctx.controller_ctx[i];
+- if (ctlr_ctx->flags.unchanged || !ctlr_ctx->stream)
++ for (i = 0; i < MAX_PIPES; i++) {
++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
++
++ if (pipe_ctx->stream == NULL || pipe_ctx->flags.unchanged)
+ continue;
+
+ status = apply_single_controller_ctx_to_hw(
+- i,
++ pipe_ctx,
+ context,
+ dc);
+
+@@ -1309,7 +1259,7 @@ static enum dc_status apply_ctx_to_hw(
+ update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv,
+ false);
+
+- switch_dp_clock_sources(dc, context);
++ switch_dp_clock_sources(dc, &context->res_ctx);
+
+ return DC_OK;
+ }
+@@ -1320,14 +1270,14 @@ static enum dc_status apply_ctx_to_hw(
+ ******************************************************************************/
+
+ static bool setup_line_buffer_pixel_depth(
+- const struct core_stream *stream,
++ const struct pipe_ctx *pipe_ctx,
+ enum lb_pixel_depth depth,
+ bool blank)
+ {
+ enum lb_pixel_depth current_depth;
+
+- struct timing_generator *tg = stream->tg;
+- struct transform *xfm = stream->xfm;
++ struct timing_generator *tg = pipe_ctx->tg;
++ struct transform *xfm = pipe_ctx->xfm;
+
+ if (!xfm->funcs->transform_get_current_pixel_storage_depth(
+ xfm,
+@@ -1339,14 +1289,14 @@ static bool setup_line_buffer_pixel_depth(
+ tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
+
+ return xfm->funcs->transform_set_pixel_storage_depth(xfm, depth,
+- &stream->bit_depth_params);
++ &pipe_ctx->stream->bit_depth_params);
+ }
+
+ return false;
+ }
+
+ static void hw_sequencer_build_scaler_parameter_plane(
+- const struct core_stream *stream,
++ const struct pipe_ctx *pipe_ctx,
+ struct scaler_data *scaler_data)
+ {
+ /*TODO: per pipe not per stream*/
+@@ -1361,15 +1311,15 @@ static void hw_sequencer_build_scaler_parameter_plane(
+
+ scaler_data->flags.bits.INTERLACED = 0;
+
+- scaler_data->dal_pixel_format = stream->format;
++ scaler_data->dal_pixel_format = pipe_ctx->format;
+
+- scaler_data->taps = stream->taps;
++ scaler_data->taps = pipe_ctx->taps;
+
+- scaler_data->viewport = stream->viewport;
++ scaler_data->viewport = pipe_ctx->viewport;
+
+- scaler_data->overscan = stream->overscan;
++ scaler_data->overscan = pipe_ctx->overscan;
+
+- scaler_data->ratios = &stream->ratios;
++ scaler_data->ratios = &pipe_ctx->ratios;
+
+ /*TODO rotation and adjustment */
+ scaler_data->h_sharpness = 0;
+@@ -1377,23 +1327,19 @@ static void hw_sequencer_build_scaler_parameter_plane(
+
+ }
+
+-static void set_default_colors(
+- struct input_pixel_processor *ipp,
+- struct output_pixel_processor *opp,
+- enum pixel_format format,
+- enum color_space input_color_space,
+- enum color_space output_color_space,
+- enum dc_color_depth color_depth)
++static void set_default_colors(struct pipe_ctx *pipe_ctx)
+ {
+ struct default_adjustment default_adjust = { 0 };
+
+ default_adjust.force_hw_default = false;
+- default_adjust.color_space = output_color_space;
++ default_adjust.color_space = get_output_color_space(
++ &pipe_ctx->stream->public.timing);
+ default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
+- default_adjust.surface_pixel_format = format;
++ default_adjust.surface_pixel_format = pipe_ctx->format;
+
+ /* display color depth */
+- default_adjust.color_depth = color_depth;
++ default_adjust.color_depth =
++ pipe_ctx->stream->public.timing.display_color_depth;
+
+ /* Lb color depth */
+ default_adjust.lb_color_depth = LB_PIXEL_DEPTH_24BPP;
+@@ -1401,99 +1347,74 @@ static void set_default_colors(
+ build_params->
+ line_buffer_params[path_id][plane_id].depth);*/
+
+- opp->funcs->opp_set_csc_default(opp, &default_adjust);
++ pipe_ctx->opp->funcs->opp_set_csc_default(
++ pipe_ctx->opp, &default_adjust);
+ }
+
+ static void program_scaler(
+- uint8_t controller_idx,
+- struct timing_generator *tg,
+- struct transform *xfm,
+ const struct core_surface *surface,
+- const struct core_stream *stream)
++ const struct pipe_ctx *pipe_ctx)
+ {
+ struct scaler_data scaler_data = { { 0 } };
+
+ hw_sequencer_build_scaler_parameter_plane(
+- stream,
++ pipe_ctx,
+ &scaler_data);
+
+ setup_line_buffer_pixel_depth(
+- stream,
++ pipe_ctx,
+ LB_PIXEL_DEPTH_24BPP,
+ false);
+
+- tg->funcs->set_overscan_blank_color(tg, surface->public.colorimetry.color_space);
++ pipe_ctx->tg->funcs->set_overscan_blank_color(
++ pipe_ctx->tg, surface->public.color_space);
+
+- xfm->funcs->transform_set_scaler(xfm, &scaler_data);
++ pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm, &scaler_data);
+
+- xfm->funcs->transform_update_viewport(
+- xfm,
+- &scaler_data.viewport,
+- false);
++ pipe_ctx->xfm->funcs->transform_update_viewport(
++ pipe_ctx->xfm, &scaler_data.viewport, false);
+ }
+
+ /**
+ * Program the Front End of the Pipe.
+ * The Back End was already programmed by Set Mode.
+ */
+-static bool set_plane_config(
++static void set_plane_config(
+ const struct dc *dc,
+ struct core_surface *surface,
+- struct core_target *target)
++ struct pipe_ctx *pipe_ctx)
+ {
+- const struct core_stream *core_stream =
+- DC_STREAM_TO_CORE(target->public.streams[0]);
+- const struct dc_crtc_timing *dc_crtc_timing =
+- &target->public.streams[0]->timing;
+- struct mem_input *mi = core_stream->mi;
+- struct input_pixel_processor *ipp = core_stream->ipp;
+- struct timing_generator *tg = core_stream->tg;
+- struct transform *xfm = core_stream->xfm;
+- struct output_pixel_processor *opp = core_stream->opp;
+- struct dc_context *ctx = core_stream->ctx;
+- uint8_t controller_idx = core_stream->controller_idx;
+-
+- /* TODO: Clean up change, possibly change to use same type */
+- enum color_space input_color_space =
+- surface_color_to_color_space(&(surface->public.colorimetry));
++ const struct dc_crtc_timing *crtc_timing =
++ &pipe_ctx->stream->public.timing;
++ struct mem_input *mi = pipe_ctx->mi;
++ struct timing_generator *tg = pipe_ctx->tg;
++ struct dc_context *ctx = pipe_ctx->stream->ctx;
+
+ dc->hwss.pipe_control_lock(
+- ctx,
+- controller_idx,
+- PIPE_LOCK_CONTROL_MODE,
+- false);
++ ctx, pipe_ctx->pipe_idx, PIPE_LOCK_CONTROL_MODE, false);
+
+ /* While a non-root controller is programmed we
+ * have to lock the root controller. */
+ dc->hwss.pipe_control_lock(
+ ctx,
+- controller_idx,
++ pipe_ctx->pipe_idx,
+ PIPE_LOCK_CONTROL_GRAPHICS |
+ PIPE_LOCK_CONTROL_SCL |
+ PIPE_LOCK_CONTROL_BLENDER |
+ PIPE_LOCK_CONTROL_SURFACE,
+ true);
+
+- tg->funcs->program_timing(tg, dc_crtc_timing, false);
++ tg->funcs->program_timing(tg, crtc_timing, false);
+
+- dc->hwss.enable_fe_clock(ctx, controller_idx, true);
++ dc->hwss.enable_fe_clock(ctx, pipe_ctx->pipe_idx, true);
+
+- set_default_colors(
+- ipp,
+- opp,
+- core_stream->format,
+- input_color_space,
+- get_output_color_space(dc_crtc_timing),
+- dc_crtc_timing->display_color_depth);
++ set_default_colors(pipe_ctx);
+
+ /* program Scaler */
+- program_scaler(
+- controller_idx, tg, xfm, surface, core_stream);
++ program_scaler(surface, pipe_ctx);
+
+ dc->hwss.set_blender_mode(
+- ctx,
+- controller_idx,
+- BLENDER_MODE_CURRENT_PIPE);
++ ctx, pipe_ctx->pipe_idx, BLENDER_MODE_CURRENT_PIPE);
+
+ mi->funcs->mem_input_program_surface_config(
+ mi,
+@@ -1504,96 +1425,92 @@ static bool set_plane_config(
+
+ dc->hwss.pipe_control_lock(
+ ctx,
+- controller_idx,
++ pipe_ctx->pipe_idx,
+ PIPE_LOCK_CONTROL_GRAPHICS |
+ PIPE_LOCK_CONTROL_SCL |
+ PIPE_LOCK_CONTROL_BLENDER |
+ PIPE_LOCK_CONTROL_SURFACE,
+ false);
+-
+- return true;
+ }
+
+-static bool update_plane_address(
+- const struct dc *dc,
+- const struct core_surface *surface,
+- struct core_target *target)
++static void update_plane_addrs(
++ struct dc *dc,
++ struct resource_context *res_ctx,
++ const struct core_surface *surface)
+ {
+- const struct core_stream *core_stream =
+- DC_STREAM_TO_CORE(target->public.streams[0]);
+- struct dc_context *ctx = core_stream->ctx;
+- struct mem_input *mi = core_stream->mi;
+- uint8_t controller_id = core_stream->controller_idx;
++ uint8_t j;
+
+- /* TODO: crtc should be per surface, NOT per-target */
+- dc->hwss.pipe_control_lock(
+- ctx,
+- controller_id,
+- PIPE_LOCK_CONTROL_SURFACE,
+- true);
+-
+- if (false ==
+- core_stream->mi->funcs->mem_input_program_surface_flip_and_addr(
+- mi, &surface->public.address, surface->public.flip_immediate))
+- return false;
++ for (j = 0; j < MAX_PIPES; j++) {
++ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[j];
+
+- dc->hwss.pipe_control_lock(
+- ctx,
+- controller_id,
+- PIPE_LOCK_CONTROL_SURFACE,
+- false);
++ if (pipe_ctx->surface != surface)
++ continue;
+
+- return true;
++ dc->hwss.pipe_control_lock(
++ dc->ctx,
++ j,
++ PIPE_LOCK_CONTROL_SURFACE,
++ true);
++
++ pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr(
++ pipe_ctx->mi,
++ &surface->public.address,
++ surface->public.flip_immediate);
++
++ dc->hwss.pipe_control_lock(
++ dc->ctx,
++ j,
++ PIPE_LOCK_CONTROL_SURFACE,
++ false);
++
++ break;
++ }
+ }
+
+-static void reset_single_stream_hw_ctx(
++static void reset_single_pipe_hw_ctx(
+ const struct dc *dc,
+- struct core_stream *stream,
++ struct pipe_ctx *pipe_ctx,
+ struct validate_context *context)
+ {
+ struct dc_bios *dcb;
+
+ dcb = dal_adapter_service_get_bios_parser(
+ context->res_ctx.pool.adapter_srv);
+- if (stream->audio) {
+- dal_audio_disable_output(stream->audio,
+- stream->stream_enc->id,
+- stream->signal);
+- stream->audio = NULL;
++ if (pipe_ctx->audio) {
++ dal_audio_disable_output(pipe_ctx->audio,
++ pipe_ctx->stream_enc->id,
++ pipe_ctx->signal);
++ pipe_ctx->audio = NULL;
+ }
+
+- core_link_disable_stream(stream->sink->link, stream);
++ core_link_disable_stream(pipe_ctx);
+
+- stream->tg->funcs->set_blank(stream->tg, true);
+- stream->tg->funcs->disable_crtc(stream->tg);
+- stream->mi->funcs->free_mem_input(
+- stream->mi, context->target_count);
+- stream->xfm->funcs->transform_set_scaler_bypass(stream->xfm);
+- unreference_clock_source(&context->res_ctx, stream->clock_source);
++ pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
++ pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg);
++ pipe_ctx->mi->funcs->free_mem_input(
++ pipe_ctx->mi, context->target_count);
++ pipe_ctx->xfm->funcs->transform_set_scaler_bypass(pipe_ctx->xfm);
++ unreference_clock_source(&context->res_ctx, pipe_ctx->clock_source);
+ dc->hwss.enable_display_power_gating(
+- stream->ctx, stream->controller_idx, dcb,
++ pipe_ctx->stream->ctx, pipe_ctx->pipe_idx, dcb,
+ PIPE_GATING_CONTROL_ENABLE);
+ }
+
+-static void reset_hw_ctx(struct dc *dc,
+- struct validate_context *context,
+- uint8_t target_count)
++static void reset_hw_ctx(
++ struct dc *dc,
++ struct validate_context *new_context)
+ {
+ uint8_t i;
+- /* look up the targets that have been removed since last commit */
+- for (i = 0; i < dc->current_context.target_count; i++) {
+- const struct core_target *core_target =
+- dc->current_context.targets[i];
+- struct core_stream *core_stream =
+- DC_STREAM_TO_CORE(core_target->public.streams[0]);
+- uint8_t controller_idx = core_stream->controller_idx;
+-
+- if (context->res_ctx.controller_ctx[controller_idx].stream &&
+- !context->res_ctx.controller_ctx[controller_idx]
+- .flags.timing_changed)
+- continue;
+
+- reset_single_stream_hw_ctx(dc, core_stream, &dc->current_context);
++ /* look up the targets that have been removed since last commit */
++ for (i = 0; i < MAX_PIPES; i++) {
++ struct pipe_ctx *pipe_ctx_old =
++ &dc->current_context.res_ctx.pipe_ctx[i];
++ struct pipe_ctx *pipe_ctx = &new_context->res_ctx.pipe_ctx[i];
++
++ if (pipe_ctx_old->stream && !pipe_ctx->stream)
++ reset_single_pipe_hw_ctx(
++ dc, pipe_ctx_old, &dc->current_context);
+ }
+ }
+
+@@ -1601,7 +1518,6 @@ static void power_down(struct dc *dc)
+ {
+ power_down_all_hw_blocks(dc);
+ disable_vga_and_power_gate_all_controllers(dc);
+-
+ }
+
+ static bool wait_for_reset_trigger_to_occur(
+@@ -1697,7 +1613,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {
+ .apply_ctx_to_hw = apply_ctx_to_hw,
+ .reset_hw_ctx = reset_hw_ctx,
+ .set_plane_config = set_plane_config,
+- .update_plane_address = update_plane_address,
++ .update_plane_addrs = update_plane_addrs,
+ .set_gamma_correction = set_gamma_ramp,
+ .power_down = power_down,
+ .enable_accelerated_mode = enable_accelerated_mode,
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
+index 3c78431..9efed4f 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
+@@ -1168,27 +1168,28 @@ bool dce110_link_encoder_construct(
+
+ bool dce110_link_encoder_validate_output_with_stream(
+ struct link_encoder *enc,
+- struct core_stream *stream)
++ struct pipe_ctx *pipe_ctx)
+ {
++ struct core_stream *stream = pipe_ctx->stream;
+ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+ bool is_valid;
+
+- switch (stream->signal) {
++ switch (pipe_ctx->signal) {
+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
+ case SIGNAL_TYPE_DVI_DUAL_LINK:
+ is_valid = validate_dvi_output(
+ enc110,
+ stream->sink->link->public.connector_signal,
+- stream->signal,
++ pipe_ctx->signal,
+ &stream->public.timing);
+ break;
+ case SIGNAL_TYPE_HDMI_TYPE_A:
+ is_valid = validate_hdmi_output(
+ enc110,
+ &stream->public.timing,
+- stream->max_tmds_clk_from_edid_in_mhz,
+- stream->max_hdmi_deep_color,
+- stream->max_hdmi_pixel_clock);
++ pipe_ctx->max_tmds_clk_from_edid_in_mhz,
++ pipe_ctx->max_hdmi_deep_color,
++ pipe_ctx->max_hdmi_pixel_clock);
+ break;
+ case SIGNAL_TYPE_RGB:
+ is_valid = validate_rgb_output(
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
+index 64a81f2..bbddd0b 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
+@@ -81,7 +81,7 @@ bool dce110_link_encoder_construct(
+
+ bool dce110_link_encoder_validate_output_with_stream(
+ struct link_encoder *enc,
+- struct core_stream *stream);
++ struct pipe_ctx *pipe_ctx);
+
+ /****************** HW programming ************************/
+
+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 9e2b5d9..4fdf1f0 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
+@@ -477,7 +477,7 @@ void dce110_destruct_resource_pool(struct resource_pool *pool)
+ {
+ unsigned int i;
+
+- for (i = 0; i < pool->controller_count; i++) {
++ for (i = 0; i < pool->pipe_count; i++) {
+ if (pool->opps[i] != NULL)
+ dce110_opp_destroy(&pool->opps[i]);
+
+@@ -567,12 +567,13 @@ static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
+ }
+
+ static void build_audio_output(
+- const struct core_stream *stream,
++ const struct pipe_ctx *pipe_ctx,
+ struct audio_output *audio_output)
+ {
+- audio_output->engine_id = stream->stream_enc->id;
++ const struct core_stream *stream = pipe_ctx->stream;
++ audio_output->engine_id = pipe_ctx->stream_enc->id;
+
+- audio_output->signal = stream->signal;
++ audio_output->signal = pipe_ctx->signal;
+
+ /* audio_crtc_info */
+
+@@ -604,42 +605,43 @@ static void build_audio_output(
+ stream->public.timing.display_color_depth;
+
+ audio_output->crtc_info.requested_pixel_clock =
+- stream->pix_clk_params.requested_pix_clk;
++ pipe_ctx->pix_clk_params.requested_pix_clk;
+
+ /* TODO - Investigate why calculated pixel clk has to be
+ * requested pixel clk */
+ audio_output->crtc_info.calculated_pixel_clock =
+- stream->pix_clk_params.requested_pix_clk;
++ pipe_ctx->pix_clk_params.requested_pix_clk;
+
+- if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
+- stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
++ if (pipe_ctx->signal == SIGNAL_TYPE_DISPLAY_PORT ||
++ pipe_ctx->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+ audio_output->pll_info.dp_dto_source_clock_in_khz =
+ dal_display_clock_get_dp_ref_clk_frequency(
+- stream->dis_clk);
++ pipe_ctx->dis_clk);
+ }
+
+ audio_output->pll_info.feed_back_divider =
+- stream->pll_settings.feedback_divider;
++ pipe_ctx->pll_settings.feedback_divider;
+
+ audio_output->pll_info.dto_source =
+ translate_to_dto_source(
+- stream->controller_idx + 1);
++ pipe_ctx->pipe_idx + 1);
+
+ /* TODO hard code to enable for now. Need get from stream */
+ audio_output->pll_info.ss_enabled = true;
+
+ audio_output->pll_info.ss_percentage =
+- stream->pll_settings.ss_percentage;
++ pipe_ctx->pll_settings.ss_percentage;
+ }
+
+ static void get_pixel_clock_parameters(
+- const struct core_stream *stream,
++ const struct pipe_ctx *pipe_ctx,
+ struct pixel_clk_params *pixel_clk_params)
+ {
++ const struct core_stream *stream = pipe_ctx->stream;
+ pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz;
+ pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id;
+ pixel_clk_params->signal_type = stream->sink->public.sink_signal;
+- pixel_clk_params->controller_id = stream->controller_idx + 1;
++ pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1;
+ /* TODO: un-hardcode*/
+ pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
+ LINK_RATE_REF_FREQ_IN_KHZ;
+@@ -649,20 +651,20 @@ static void get_pixel_clock_parameters(
+ pixel_clk_params->flags.DISPLAY_BLANKED = 1;
+ }
+
+-static enum dc_status build_stream_hw_param(struct core_stream *stream)
++static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx)
+ {
+ /*TODO: unhardcode*/
+- stream->max_tmds_clk_from_edid_in_mhz = 0;
+- stream->max_hdmi_deep_color = COLOR_DEPTH_121212;
+- stream->max_hdmi_pixel_clock = 600000;
++ pipe_ctx->max_tmds_clk_from_edid_in_mhz = 0;
++ pipe_ctx->max_hdmi_deep_color = COLOR_DEPTH_121212;
++ pipe_ctx->max_hdmi_pixel_clock = 600000;
+
+- get_pixel_clock_parameters(stream, &stream->pix_clk_params);
+- stream->clock_source->funcs->get_pix_clk_dividers(
+- stream->clock_source,
+- &stream->pix_clk_params,
+- &stream->pll_settings);
++ get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params);
++ pipe_ctx->clock_source->funcs->get_pix_clk_dividers(
++ pipe_ctx->clock_source,
++ &pipe_ctx->pix_clk_params,
++ &pipe_ctx->pll_settings);
+
+- build_audio_output(stream, &stream->audio_output);
++ build_audio_output(pipe_ctx, &pipe_ctx->audio_output);
+
+ return DC_OK;
+ }
+@@ -672,7 +674,7 @@ static enum dc_status validate_mapped_resource(
+ struct validate_context *context)
+ {
+ enum dc_status status = DC_OK;
+- uint8_t i, j;
++ uint8_t i, j, k;
+
+ for (i = 0; i < context->target_count; i++) {
+ struct core_target *target = context->targets[i];
+@@ -683,30 +685,41 @@ static enum dc_status validate_mapped_resource(
+ DC_STREAM_TO_CORE(target->public.streams[j]);
+ struct core_link *link = stream->sink->link;
+
+- if (!stream->tg->funcs->validate_timing(
+- stream->tg, &stream->public.timing))
+- return DC_FAIL_CONTROLLER_VALIDATE;
++ for (k = 0; k < MAX_PIPES; k++) {
++ struct pipe_ctx *pipe_ctx =
++ &context->res_ctx.pipe_ctx[k];
++
++ if (context->res_ctx.pipe_ctx[k].stream != stream)
++ continue;
++
++ if (!pipe_ctx->tg->funcs->validate_timing(
++ pipe_ctx->tg, &stream->public.timing))
++ return DC_FAIL_CONTROLLER_VALIDATE;
+
+- status = build_stream_hw_param(stream);
++ status = build_pipe_hw_param(pipe_ctx);
+
+- if (status != DC_OK)
+- return status;
++ if (status != DC_OK)
++ return status;
+
+- if (!link->link_enc->funcs->validate_output_with_stream(
+- link->link_enc,
+- stream))
+- return DC_FAIL_ENC_VALIDATE;
++ if (!link->link_enc->funcs->validate_output_with_stream(
++ link->link_enc,
++ pipe_ctx))
++ return DC_FAIL_ENC_VALIDATE;
+
+- /* TODO: validate audio ASIC caps, encoder */
++ /* TODO: validate audio ASIC caps, encoder */
+
+- status = dc_link_validate_mode_timing(stream->sink,
+- link,
+- &stream->public.timing);
++ status = dc_link_validate_mode_timing(stream->sink,
++ link,
++ &stream->public.timing);
+
+- if (status != DC_OK)
+- return status;
++ if (status != DC_OK)
++ return status;
+
+- build_info_frame(stream);
++ build_info_frame(pipe_ctx);
++
++ /* do not need to validate non root pipes */
++ break;
++ }
+ }
+ }
+
+@@ -717,7 +730,7 @@ enum dc_status dce110_validate_bandwidth(
+ const struct dc *dc,
+ struct validate_context *context)
+ {
+- uint8_t i, j;
++ uint8_t i;
+ enum dc_status result = DC_ERROR_UNEXPECTED;
+ uint8_t number_of_displays = 0;
+ uint8_t max_htaps = 1;
+@@ -727,76 +740,75 @@ enum dc_status dce110_validate_bandwidth(
+
+ memset(&context->bw_mode_data, 0, sizeof(context->bw_mode_data));
+
+- for (i = 0; i < context->target_count; i++) {
+- struct core_target *target = context->targets[i];
+- for (j = 0; j < target->public.stream_count; j++) {
+- struct core_stream *stream =
+- DC_STREAM_TO_CORE(target->public.streams[j]);
+- struct bw_calcs_input_single_display *disp = &context->
+- bw_mode_data.displays_data[number_of_displays];
+-
+- if (target->status.surface_count == 0) {
+- disp->graphics_scale_ratio = bw_int_to_fixed(1);
+- disp->graphics_h_taps = 2;
+- disp->graphics_v_taps = 2;
+-
+- /* TODO: remove when bw formula accepts taps per
+- * display
+- */
+- if (max_vtaps < 2)
+- max_vtaps = 2;
+- if (max_htaps < 2)
+- max_htaps = 2;
+-
+- } else {
+- disp->graphics_scale_ratio =
+- fixed31_32_to_bw_fixed(
+- stream->ratios.vert.value);
+- disp->graphics_h_taps = stream->taps.h_taps;
+- disp->graphics_v_taps = stream->taps.v_taps;
+-
+- /* TODO: remove when bw formula accepts taps per
+- * display
+- */
+- if (max_vtaps < stream->taps.v_taps)
+- max_vtaps = stream->taps.v_taps;
+- if (max_htaps < stream->taps.h_taps)
+- max_htaps = stream->taps.h_taps;
+- }
++ for (i = 0; i < MAX_PIPES; i++) {
++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
++ struct bw_calcs_input_single_display *disp = &context->
++ bw_mode_data.displays_data[number_of_displays];
++
++ if (pipe_ctx->stream == NULL)
++ continue;
+
+- disp->graphics_src_width =
+- stream->public.timing.h_addressable;
+- disp->graphics_src_height =
+- stream->public.timing.v_addressable;
+- disp->h_total = stream->public.timing.h_total;
+- disp->pixel_rate = bw_frc_to_fixed(
+- stream->public.timing.pix_clk_khz, 1000);
+-
+- /*TODO: get from surface*/
+- disp->graphics_bytes_per_pixel = 4;
+- disp->graphics_tiling_mode = bw_def_tiled;
+-
+- /* DCE11 defaults*/
+- disp->graphics_lb_bpc = 10;
+- disp->graphics_interlace_mode = false;
+- disp->fbc_enable = false;
+- disp->lpt_enable = false;
+- disp->graphics_stereo_mode = bw_def_mono;
+- disp->underlay_mode = bw_def_none;
+-
+- /*All displays will be synchronized if timings are all
+- * the same
++ if (pipe_ctx->ratios.vert.value == 0) {
++ disp->graphics_scale_ratio = bw_int_to_fixed(1);
++ disp->graphics_h_taps = 2;
++ disp->graphics_v_taps = 2;
++
++ /* TODO: remove when bw formula accepts taps per
++ * display
++ */
++ if (max_vtaps < 2)
++ max_vtaps = 2;
++ if (max_htaps < 2)
++ max_htaps = 2;
++
++ } else {
++ disp->graphics_scale_ratio =
++ fixed31_32_to_bw_fixed(
++ pipe_ctx->ratios.vert.value);
++ disp->graphics_h_taps = pipe_ctx->taps.h_taps;
++ disp->graphics_v_taps = pipe_ctx->taps.v_taps;
++
++ /* TODO: remove when bw formula accepts taps per
++ * display
+ */
+- if (number_of_displays != 0 && all_displays_in_sync)
+- if (dm_memcmp(&prev_timing,
+- &stream->public.timing,
+- sizeof(struct dc_crtc_timing))!= 0)
+- all_displays_in_sync = false;
+- if (number_of_displays == 0)
+- prev_timing = stream->public.timing;
+-
+- number_of_displays++;
++ if (max_vtaps < pipe_ctx->taps.v_taps)
++ max_vtaps = pipe_ctx->taps.v_taps;
++ if (max_htaps < pipe_ctx->taps.h_taps)
++ max_htaps = pipe_ctx->taps.h_taps;
+ }
++
++ disp->graphics_src_width =
++ pipe_ctx->stream->public.timing.h_addressable;
++ disp->graphics_src_height =
++ pipe_ctx->stream->public.timing.v_addressable;
++ disp->h_total = pipe_ctx->stream->public.timing.h_total;
++ disp->pixel_rate = bw_frc_to_fixed(
++ pipe_ctx->stream->public.timing.pix_clk_khz, 1000);
++
++ /*TODO: get from surface*/
++ disp->graphics_bytes_per_pixel = 4;
++ disp->graphics_tiling_mode = bw_def_tiled;
++
++ /* DCE11 defaults*/
++ disp->graphics_lb_bpc = 10;
++ disp->graphics_interlace_mode = false;
++ disp->fbc_enable = false;
++ disp->lpt_enable = false;
++ disp->graphics_stereo_mode = bw_def_mono;
++ disp->underlay_mode = bw_def_none;
++
++ /*All displays will be synchronized if timings are all
++ * the same
++ */
++ if (number_of_displays != 0 && all_displays_in_sync)
++ if (dm_memcmp(&prev_timing,
++ &pipe_ctx->stream->public.timing,
++ sizeof(struct dc_crtc_timing)) != 0)
++ all_displays_in_sync = false;
++ if (number_of_displays == 0)
++ prev_timing = pipe_ctx->stream->public.timing;
++
++ number_of_displays++;
+ }
+
+ /* TODO: remove when bw formula accepts taps per
+@@ -813,7 +825,7 @@ enum dc_status dce110_validate_bandwidth(
+ dc->ctx->logger,
+ LOG_MAJOR_BWM,
+ LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS,
+- "%s: start\n",
++ "%s: start",
+ __func__);
+
+ if (!bw_calcs(
+@@ -891,14 +903,17 @@ static void set_target_unchanged(
+ struct validate_context *context,
+ uint8_t target_idx)
+ {
+- uint8_t i;
++ uint8_t i, j;
+ struct core_target *target = context->targets[target_idx];
+ context->target_flags[target_idx].unchanged = true;
+ for (i = 0; i < target->public.stream_count; i++) {
+- struct core_stream *core_stream =
++ struct core_stream *stream =
+ DC_STREAM_TO_CORE(target->public.streams[i]);
+- uint8_t index = core_stream->controller_idx;
+- context->res_ctx.controller_ctx[index].flags.unchanged = true;
++ for (j = 0; j < MAX_PIPES; j++) {
++ if (context->res_ctx.pipe_ctx[j].stream == stream)
++ context->res_ctx.pipe_ctx[j].flags.unchanged =
++ true;
++ }
+ }
+ }
+
+@@ -906,24 +921,7 @@ static enum dc_status map_clock_resources(
+ const struct dc *dc,
+ struct validate_context *context)
+ {
+- uint8_t i, j;
+-
+- /* mark resources used for targets that are already active */
+- for (i = 0; i < context->target_count; i++) {
+- struct core_target *target = context->targets[i];
+-
+- if (!context->target_flags[i].unchanged)
+- continue;
+-
+- for (j = 0; j < target->public.stream_count; j++) {
+- struct core_stream *stream =
+- DC_STREAM_TO_CORE(target->public.streams[j]);
+-
+- reference_clock_source(
+- &context->res_ctx,
+- stream->clock_source);
+- }
+- }
++ uint8_t i, j, k;
+
+ /* acquire new resources */
+ for (i = 0; i < context->target_count; i++) {
+@@ -936,24 +934,35 @@ static enum dc_status map_clock_resources(
+ struct core_stream *stream =
+ DC_STREAM_TO_CORE(target->public.streams[j]);
+
+- if (dc_is_dp_signal(stream->signal)
+- || stream->signal == SIGNAL_TYPE_VIRTUAL)
+- stream->clock_source = context->res_ctx.
+- pool.clock_sources[DCE110_CLK_SRC_EXT];
+- else
+- stream->clock_source =
+- find_used_clk_src_for_sharing(
+- context, stream);
+- if (stream->clock_source == NULL)
+- stream->clock_source =
+- find_first_free_pll(&context->res_ctx);
+-
+- if (stream->clock_source == NULL)
+- return DC_NO_CLOCK_SOURCE_RESOURCE;
+-
+- reference_clock_source(
+- &context->res_ctx,
+- stream->clock_source);
++ for (k = 0; k < MAX_PIPES; k++) {
++ struct pipe_ctx *pipe_ctx =
++ &context->res_ctx.pipe_ctx[k];
++
++ if (context->res_ctx.pipe_ctx[k].stream != stream)
++ continue;
++
++ 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 =
++ 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)
++ return DC_NO_CLOCK_SOURCE_RESOURCE;
++
++ reference_clock_source(
++ &context->res_ctx,
++ pipe_ctx->clock_source);
++
++ /* only one cs per stream regardless of mpo */
++ break;
++ }
+ }
+ }
+
+@@ -971,24 +980,30 @@ enum dc_status dce110_validate_with_context(
+ struct dc_context *dc_ctx = dc->ctx;
+
+ for (i = 0; i < set_count; i++) {
++ bool unchanged = false;
++
+ context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
++ context->target_count++;
+
+ for (j = 0; j < dc->current_context.target_count; j++)
+- if (dc->current_context.targets[j] == context->targets[i])
++ if (dc->current_context.targets[j]
++ == context->targets[i]) {
++ unchanged = true;
+ set_target_unchanged(context, i);
+-
+- if (!context->target_flags[i].unchanged)
+- if (!logical_attach_surfaces_to_target(
+- (struct dc_surface **)set[i].surfaces,
+- set[i].surface_count,
+- &context->targets[i]->public)) {
++ context->target_status[i] =
++ dc->current_context.target_status[j];
++ }
++ if (!unchanged)
++ if (!attach_surfaces_to_context(
++ (struct dc_surface **)set[i].surfaces,
++ set[i].surface_count,
++ &context->targets[i]->public,
++ context)) {
+ DC_ERROR("Failed to attach surface to target!\n");
+ return DC_FAIL_ATTACH_SURFACES;
+ }
+ }
+
+- context->target_count = set_count;
+-
+ context->res_ctx.pool = dc->res_pool;
+
+ result = map_resources(dc, context);
+@@ -1073,7 +1088,7 @@ bool dce110_construct_resource_pool(
+
+ }
+
+- pool->controller_count =
++ 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);
+@@ -1084,7 +1099,7 @@ bool dce110_construct_resource_pool(
+ goto filter_create_fail;
+ }
+
+- for (i = 0; i < pool->controller_count; i++) {
++ for (i = 0; i < pool->pipe_count; i++) {
+ pool->timing_generators[i] = dce110_timing_generator_create(
+ adapter_serv, ctx, i, &dce110_tg_offsets[i]);
+ if (pool->timing_generators[i] == NULL) {
+@@ -1134,7 +1149,7 @@ bool dce110_construct_resource_pool(
+ audio_init_data.as = adapter_serv;
+ audio_init_data.ctx = ctx;
+ pool->audio_count = 0;
+- for (i = 0; i < pool->controller_count; i++) {
++ 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);
+@@ -1192,13 +1207,13 @@ stream_enc_create_fail:
+ }
+
+ audio_create_fail:
+- for (i = 0; i < pool->controller_count; i++) {
++ for (i = 0; i < pool->pipe_count; i++) {
+ if (pool->audios[i] != NULL)
+ dal_audio_destroy(&pool->audios[i]);
+ }
+
+ controller_create_fail:
+- for (i = 0; i < pool->controller_count; i++) {
++ for (i = 0; i < pool->pipe_count; i++) {
+ if (pool->opps[i] != NULL)
+ dce110_opp_destroy(&pool->opps[i]);
+
+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 e3dbaeb..18bd2da 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
+@@ -39,12 +39,10 @@ struct core_stream;
+ container_of(dc_target, struct core_target, public)
+
+ #define MAX_PIPES 6
+-#define MAX_STREAMS 6
+ #define MAX_CLOCK_SOURCES 7
+
+ struct core_target {
+ struct dc_target public;
+- struct dc_target_status status;
+
+ struct dc_context *ctx;
+ };
+@@ -90,53 +88,12 @@ struct core_stream {
+ struct dc_stream public;
+
+ /* field internal to DC */
++ struct dc_context *ctx;
+ const struct core_sink *sink;
+
+- struct clock_source *clock_source;
+-
+- struct mem_input *mi;
+- struct input_pixel_processor *ipp;
+- struct transform *xfm;
+- struct output_pixel_processor *opp;
+- struct timing_generator *tg;
+- struct stream_encoder *stream_enc;
+- struct display_clock *dis_clk;
+-
+- struct overscan_info overscan;
+- struct scaling_ratios ratios;
+- struct rect viewport;
+- struct scaling_taps taps;
+- enum pixel_format format;
+-
+- uint8_t controller_idx;
+-
+- struct audio *audio;
+-
+- enum signal_type signal;
+-
+- /* TODO: move these members into appropriate places (work in progress)*/
+- /* timing validation (HDMI only) */
+- uint32_t max_tmds_clk_from_edid_in_mhz;
+- /* maximum supported deep color depth for HDMI */
+- enum dc_color_depth max_hdmi_deep_color;
+- /* maximum supported pixel clock for HDMI */
+- uint32_t max_hdmi_pixel_clock;
+- /* end of TODO */
+-
+- /*TODO: AUTO merge if possible*/
+- struct pixel_clk_params pix_clk_params;
+- struct pll_settings pll_settings;
+-
+- /*fmt*/
+- /*TODO: AUTO new codepath in apply_context to hw to
+- * generate these bw unrelated/no fail params*/
+- struct bit_depth_reduction_params bit_depth_params;/* used by DCP and FMT */
++ /* used by DCP and FMT */
++ struct bit_depth_reduction_params bit_depth_params;
+ struct clamping_and_pixel_encoding_params clamping;
+- struct hw_info_frame info_frame;
+- struct encoder_info_frame encoder_info_frame;
+-
+- struct audio_output audio_output;
+- struct dc_context *ctx;
+
+ struct dc_stream_status status;
+ };
+@@ -267,13 +224,9 @@ enum dc_status dc_link_validate_mode_timing(
+
+ void core_link_resume(struct core_link *link);
+
+-void core_link_enable_stream(
+- struct core_link *link,
+- struct core_stream *stream);
++void core_link_enable_stream(struct pipe_ctx *pipe_ctx);
+
+-void core_link_disable_stream(
+- struct core_link *link,
+- struct core_stream *stream);
++void core_link_disable_stream(struct pipe_ctx *pipe_ctx);
+
+ /********** DAL Core*********************/
+ #include "display_clock_interface.h"
+@@ -304,10 +257,10 @@ struct resource_pool {
+ struct input_pixel_processor *ipps[MAX_PIPES];
+ struct transform *transforms[MAX_PIPES];
+ struct output_pixel_processor *opps[MAX_PIPES];
+- struct timing_generator *timing_generators[MAX_STREAMS];
++ struct timing_generator *timing_generators[MAX_PIPES];
+ struct stream_encoder *stream_enc[MAX_PIPES * 2];
+
+- uint8_t controller_count;
++ uint8_t pipe_count;
+ uint8_t stream_enc_count;
+
+ union supported_stream_engines stream_engines;
+@@ -315,7 +268,7 @@ struct resource_pool {
+ struct clock_source *clock_sources[MAX_CLOCK_SOURCES];
+ uint8_t clk_src_count;
+
+- struct audio *audios[MAX_STREAMS];
++ struct audio *audios[MAX_PIPES];
+ uint8_t audio_count;
+
+ struct display_clock *display_clock;
+@@ -325,9 +278,46 @@ struct resource_pool {
+ struct resource_funcs *funcs;
+ };
+
+-struct controller_ctx {
++struct pipe_ctx {
+ struct core_surface *surface;
+ struct core_stream *stream;
++
++ struct mem_input *mi;
++ struct input_pixel_processor *ipp;
++ struct transform *xfm;
++ struct output_pixel_processor *opp;
++ struct timing_generator *tg;
++
++ struct overscan_info overscan;
++ struct scaling_ratios ratios;
++ struct rect viewport;
++ struct scaling_taps taps;
++ enum pixel_format format;
++
++ struct stream_encoder *stream_enc;
++ struct display_clock *dis_clk;
++ struct clock_source *clock_source;
++
++ struct audio *audio;
++ struct audio_output audio_output;
++
++ enum signal_type signal;
++
++ /* timing validation (HDMI only) */
++ uint32_t max_tmds_clk_from_edid_in_mhz;
++ /* maximum supported deep color depth for HDMI */
++ enum dc_color_depth max_hdmi_deep_color;
++ /* maximum supported pixel clock for HDMI */
++ uint32_t max_hdmi_pixel_clock;
++
++ struct pixel_clk_params pix_clk_params;
++ struct pll_settings pll_settings;
++
++ /*fmt*/
++ struct encoder_info_frame encoder_info_frame;
++
++ uint8_t pipe_idx;
++
+ struct flags {
+ bool unchanged;
+ bool timing_changed;
+@@ -336,10 +326,10 @@ struct controller_ctx {
+
+ struct resource_context {
+ struct resource_pool pool;
+- struct controller_ctx controller_ctx[MAX_PIPES];
++ struct pipe_ctx pipe_ctx[MAX_PIPES];
+ union supported_stream_engines used_stream_engines;
+ bool is_stream_enc_acquired[MAX_PIPES * 2];
+- bool is_audio_acquired[MAX_STREAMS];
++ bool is_audio_acquired[MAX_PIPES];
+ uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES];
+ };
+
+@@ -348,6 +338,7 @@ struct target_flags {
+ };
+ struct validate_context {
+ struct core_target *targets[MAX_PIPES];
++ struct dc_target_status target_status[MAX_PIPES];
+ struct target_flags target_flags[MAX_PIPES];
+ uint8_t target_count;
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
+index 5dd16dc..8b0afe1 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
+@@ -39,22 +39,19 @@ enum pipe_gating_control {
+ struct hw_sequencer_funcs {
+
+ enum dc_status (*apply_ctx_to_hw)(
+- const struct dc *dc, struct validate_context *context);
++ struct dc *dc, struct validate_context *context);
+
+- void (*reset_hw_ctx)(
+- struct dc *dc,
+- struct validate_context *context,
+- uint8_t target_count);
++ void (*reset_hw_ctx)(struct dc *dc, struct validate_context *context);
+
+- bool (*set_plane_config)(
++ void (*set_plane_config)(
+ const struct dc *dc,
+ struct core_surface *surface,
+- struct core_target *target);
++ struct pipe_ctx *pipe_ctx);
+
+- bool (*update_plane_address)(
+- const struct dc *dc,
+- const struct core_surface *surface,
+- struct core_target *target);
++ void (*update_plane_addrs)(
++ struct dc *dc,
++ struct resource_context *res_ctx,
++ const struct core_surface *surface);
+
+ bool (*set_gamma_correction)(
+ struct input_pixel_processor *ipp,
+@@ -93,9 +90,9 @@ struct hw_sequencer_funcs {
+
+ void (*program_bw)(struct dc *dc, struct validate_context *context);
+
+- void (*enable_stream)(struct core_stream *stream);
++ void (*enable_stream)(struct pipe_ctx *pipe_ctx);
+
+- void (*disable_stream)(struct core_stream *stream);
++ void (*disable_stream)(struct pipe_ctx *pipe_ctx);
+
+ void (*enable_fe_clock)(
+ struct dc_context *ctx, uint8_t controller_id, bool enable);
+diff --git a/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h b/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
+index 54e75dc..d11ef05 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
+@@ -19,6 +19,7 @@ struct link_mst_stream_allocation_table;
+ struct dc_link_settings;
+ struct link_training_settings;
+ struct core_stream;
++struct pipe_ctx;
+
+ struct encoder_init_data {
+ struct adapter_service *adapter_service;
+@@ -82,8 +83,8 @@ struct link_encoder {
+ };
+
+ struct link_encoder_funcs {
+- bool (*validate_output_with_stream)(struct link_encoder *enc,
+- struct core_stream *stream);
++ bool (*validate_output_with_stream)(
++ struct link_encoder *enc, struct pipe_ctx *pipe_ctx);
+ void (*hw_init)(struct link_encoder *enc);
+ void (*setup)(struct link_encoder *enc,
+ enum signal_type signal);
+diff --git a/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
+index 551caa3..d56b5d1 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
+@@ -49,7 +49,7 @@ void dp_receiver_power_ctrl(struct core_link *link, bool on);
+
+ void dp_disable_link_phy(struct core_link *link, enum signal_type signal);
+
+-void dp_disable_link_phy_mst(struct core_link *link, struct core_stream *stream);
++void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal);
+
+ bool dp_set_hw_training_pattern(
+ struct core_link *link,
+diff --git a/drivers/gpu/drm/amd/dal/dc/inc/resource.h b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
+index b4936b4..a7b0032 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/resource.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
+@@ -38,7 +38,7 @@ bool dc_construct_resource_pool(struct adapter_service *adapter_serv,
+
+ void build_scaling_params(
+ const struct dc_surface *surface,
+- struct core_stream *stream);
++ struct pipe_ctx *pipe_ctx);
+
+ void build_scaling_params_for_context(
+ const struct dc *dc,
+@@ -57,13 +57,14 @@ bool is_same_timing(
+ const struct dc_crtc_timing *timing2);
+
+ struct clock_source *find_used_clk_src_for_sharing(
+- struct validate_context *context,
+- struct core_stream *stream);
++ struct resource_context *res_ctx,
++ struct pipe_ctx *pipe_ctx);
+
+-bool logical_attach_surfaces_to_target(
++bool attach_surfaces_to_context(
+ struct dc_surface *surfaces[],
+ uint8_t surface_count,
+- struct dc_target *dc_target);
++ struct dc_target *dc_target,
++ struct validate_context *context);
+
+ void pplib_apply_safe_state(const struct dc *dc);
+
+@@ -72,7 +73,7 @@ void pplib_apply_display_requirements(
+ const struct validate_context *context,
+ struct dc_pp_display_configuration *pp_display_cfg);
+
+-void build_info_frame(struct core_stream *stream);
++void build_info_frame(struct pipe_ctx *pipe_ctx);
+
+ enum dc_status map_resources(
+ const struct dc *dc,
+diff --git a/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
+index 36886a4..0b3b1b8 100644
+--- a/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
++++ b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
+@@ -31,7 +31,7 @@
+
+ static bool virtual_link_encoder_validate_output_with_stream(
+ struct link_encoder *enc,
+- struct core_stream *stream) { return true; }
++ struct pipe_ctx *pipe_ctx) { return true; }
+
+ static void virtual_link_encoder_hw_init(struct link_encoder *enc) {}
+
+diff --git a/drivers/gpu/drm/amd/dal/include/grph_csc_types.h b/drivers/gpu/drm/amd/dal/include/grph_csc_types.h
+index 711b458..5927dd0 100644
+--- a/drivers/gpu/drm/amd/dal/include/grph_csc_types.h
++++ b/drivers/gpu/drm/amd/dal/include/grph_csc_types.h
+@@ -28,19 +28,6 @@
+
+ #include "set_mode_types.h"
+
+-enum color_space {
+- COLOR_SPACE_UNKNOWN,
+- COLOR_SPACE_SRGB_FULL_RANGE,
+- COLOR_SPACE_SRGB_LIMITED_RANGE,
+- COLOR_SPACE_YPBPR601,
+- COLOR_SPACE_YPBPR709,
+- COLOR_SPACE_YCBCR601,
+- COLOR_SPACE_YCBCR709,
+- COLOR_SPACE_YCBCR601_YONLY,
+- COLOR_SPACE_YCBCR709_YONLY,
+- COLOR_SPACE_N_MVPU_SUPER_AA,
+-};
+-
+ enum grph_color_adjust_option {
+ GRPH_COLOR_MATRIX_HW_DEFAULT = 1,
+ GRPH_COLOR_MATRIX_SW
+--
+2.7.4
+