diff options
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.patch | 4120 |
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, ¶ms); ++ pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, ¶ms); + } + + 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 + |