aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0814-drm-amd-dal-hack-in-CZ-mpo-start-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0814-drm-amd-dal-hack-in-CZ-mpo-start-support.patch')
-rw-r--r--common/recipes-kernel/linux/files/0814-drm-amd-dal-hack-in-CZ-mpo-start-support.patch2506
1 files changed, 2506 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0814-drm-amd-dal-hack-in-CZ-mpo-start-support.patch b/common/recipes-kernel/linux/files/0814-drm-amd-dal-hack-in-CZ-mpo-start-support.patch
new file mode 100644
index 00000000..2ef5df83
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0814-drm-amd-dal-hack-in-CZ-mpo-start-support.patch
@@ -0,0 +1,2506 @@
+From 0c751063ee32626b7bc5f3b7ab45914cb046dacc Mon Sep 17 00:00:00 2001
+From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Date: Wed, 10 Feb 2016 17:03:10 -0500
+Subject: [PATCH 0814/1110] drm/amd/dal: hack in CZ mpo start support
+
+Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ drivers/gpu/drm/amd/dal/dc/core/dc.c | 21 +-
+ drivers/gpu/drm/amd/dal/dc/core/dc_resource.c | 142 ++++-----
+ drivers/gpu/drm/amd/dal/dc/core/dc_target.c | 128 +++++----
+ .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c | 156 +++++-----
+ drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.c | 10 +-
+ drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.h | 4 +-
+ .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c | 88 ++++--
+ .../gpu/drm/amd/dal/dc/dce110/dce110_transform.c | 2 -
+ .../drm/amd/dal/dc/dce110/dce110_transform_scl.c | 230 ++++-----------
+ .../gpu/drm/amd/dal/dc/dce110/dce110_transform_v.c | 316 ++++++++-------------
+ drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c | 16 +-
+ drivers/gpu/drm/amd/dal/dc/dce80/dce80_transform.c | 2 -
+ .../gpu/drm/amd/dal/dc/dce80/dce80_transform_scl.c | 132 +--------
+ drivers/gpu/drm/amd/dal/dc/inc/core_status.h | 1 +
+ drivers/gpu/drm/amd/dal/dc/inc/core_types.h | 8 +-
+ drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h | 9 +-
+ drivers/gpu/drm/amd/dal/dc/inc/resource.h | 3 +
+ drivers/gpu/drm/amd/dal/dc/inc/transform.h | 5 -
+ drivers/gpu/drm/amd/dal/include/scaler_types.h | 149 +---------
+ 19 files changed, 521 insertions(+), 901 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c
+index bcc6f68..1d1cd89 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c
+@@ -175,13 +175,14 @@ static void init_hw(struct dc *dc)
+ for (i = 0; i < dc->res_pool.pipe_count; i++) {
+ xfm = dc->res_pool.transforms[i];
+
+- dc->hwss.enable_display_power_gating(
+- dc->ctx, i, bp,
+- PIPE_GATING_CONTROL_INIT);
+- dc->hwss.enable_display_power_gating(
+- dc->ctx, i, bp,
+- PIPE_GATING_CONTROL_DISABLE);
+-
++ if (i != DCE110_UNDERLAY_IDX) {
++ dc->hwss.enable_display_power_gating(
++ dc->ctx, i, bp,
++ PIPE_GATING_CONTROL_INIT);
++ dc->hwss.enable_display_power_gating(
++ dc->ctx, i, bp,
++ PIPE_GATING_CONTROL_DISABLE);
++ }
+ xfm->funcs->transform_power_up(xfm);
+ dc->hwss.enable_display_pipe_clock_gating(
+ dc->ctx,
+@@ -392,6 +393,7 @@ ctx_fail:
+
+ static void destruct(struct dc *dc)
+ {
++ destruct_val_ctx(&dc->current_context);
+ destroy_links(dc);
+ dc->res_pool.funcs->destruct(&dc->res_pool);
+ dal_logger_destroy(&dc->ctx->logger);
+@@ -452,6 +454,7 @@ bool dc_validate_resources(
+ result = dc->res_pool.funcs->validate_with_context(
+ dc, set, set_count, context);
+
++ destruct_val_ctx(context);
+ dm_free(dc->ctx, context);
+ context_alloc_fail:
+
+@@ -678,10 +681,8 @@ void dc_flip_surface_addrs(
+ */
+ surface->public.address = flip_addrs[i].address;
+ surface->public.flip_immediate = flip_addrs[i].flip_immediate;
+-
+- dc->hwss.update_plane_addrs(
+- dc, &dc->current_context.res_ctx, surface);
+ }
++ dc->hwss.update_plane_addrs(dc, &dc->current_context.res_ctx);
+ }
+
+ enum dc_irq_source dc_interrupt_to_irq_source(
+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 18cddfd..e7a4b3e 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
+@@ -243,17 +243,17 @@ static void calculate_viewport(
+ /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio
+ * num_pixels = clip.num_pix * scl_ratio
+ */
+- pipe_ctx->viewport.x = src.x + (clip.x - dst.x) * src.width / dst.width;
+- pipe_ctx->viewport.width = clip.width * src.width / dst.width;
++ pipe_ctx->scl_data.viewport.x = src.x + (clip.x - dst.x) * src.width / dst.width;
++ pipe_ctx->scl_data.viewport.width = clip.width * src.width / dst.width;
+
+- pipe_ctx->viewport.y = src.y + (clip.y - dst.y) * src.height / dst.height;
+- pipe_ctx->viewport.height = clip.height * src.height / dst.height;
++ pipe_ctx->scl_data.viewport.y = src.y + (clip.y - dst.y) * src.height / dst.height;
++ pipe_ctx->scl_data.viewport.height = clip.height * src.height / dst.height;
+
+ /* Minimum viewport such that 420/422 chroma vp is non 0 */
+- if (pipe_ctx->viewport.width < 2)
+- pipe_ctx->viewport.width = 2;
+- if (pipe_ctx->viewport.height < 2)
+- pipe_ctx->viewport.height = 2;
++ if (pipe_ctx->scl_data.viewport.width < 2)
++ pipe_ctx->scl_data.viewport.width = 2;
++ if (pipe_ctx->scl_data.viewport.height < 2)
++ pipe_ctx->scl_data.viewport.height = 2;
+ }
+
+ static void calculate_overscan(
+@@ -262,40 +262,40 @@ static void calculate_overscan(
+ {
+ struct core_stream *stream = pipe_ctx->stream;
+
+- pipe_ctx->overscan.left = stream->public.dst.x;
++ pipe_ctx->scl_data.overscan.left = stream->public.dst.x;
+ if (stream->public.src.x < surface->clip_rect.x)
+- pipe_ctx->overscan.left += (surface->clip_rect.x
++ pipe_ctx->scl_data.overscan.left += (surface->clip_rect.x
+ - stream->public.src.x) * stream->public.dst.width
+ / stream->public.src.width;
+
+- pipe_ctx->overscan.right = stream->public.timing.h_addressable
++ pipe_ctx->scl_data.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)
+- pipe_ctx->overscan.right = stream->public.timing.h_addressable -
++ pipe_ctx->scl_data.overscan.right = stream->public.timing.h_addressable -
+ dal_fixed31_32_floor(dal_fixed31_32_div(
+ dal_fixed31_32_from_int(
+- pipe_ctx->viewport.width),
+- pipe_ctx->ratios.horz)) -
+- pipe_ctx->overscan.left;
++ pipe_ctx->scl_data.viewport.width),
++ pipe_ctx->scl_data.ratios.horz)) -
++ pipe_ctx->scl_data.overscan.left;
+
+
+- pipe_ctx->overscan.top = stream->public.dst.y;
++ pipe_ctx->scl_data.overscan.top = stream->public.dst.y;
+ if (stream->public.src.y < surface->clip_rect.y)
+- pipe_ctx->overscan.top += (surface->clip_rect.y
++ pipe_ctx->scl_data.overscan.top += (surface->clip_rect.y
+ - stream->public.src.y) * stream->public.dst.height
+ / stream->public.src.height;
+
+- pipe_ctx->overscan.bottom = stream->public.timing.v_addressable
++ pipe_ctx->scl_data.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)
+- pipe_ctx->overscan.bottom = stream->public.timing.v_addressable -
++ pipe_ctx->scl_data.overscan.bottom = stream->public.timing.v_addressable -
+ dal_fixed31_32_floor(dal_fixed31_32_div(
+ dal_fixed31_32_from_int(
+- pipe_ctx->viewport.height),
+- pipe_ctx->ratios.vert)) -
+- pipe_ctx->overscan.top;
++ pipe_ctx->scl_data.viewport.height),
++ pipe_ctx->scl_data.ratios.vert)) -
++ pipe_ctx->scl_data.overscan.top;
+
+
+ /* TODO: Add timing overscan to finalize overscan calculation*/
+@@ -311,32 +311,32 @@ static void calculate_scaling_ratios(
+ const uint32_t out_w = stream->public.dst.width;
+ const uint32_t out_h = stream->public.dst.height;
+
+- pipe_ctx->ratios.horz = dal_fixed31_32_from_fraction(
++ pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction(
+ surface->src_rect.width,
+ surface->dst_rect.width);
+- pipe_ctx->ratios.vert = dal_fixed31_32_from_fraction(
++ pipe_ctx->scl_data.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)
+- pipe_ctx->ratios.horz.value *= 2;
++ pipe_ctx->scl_data.ratios.horz.value *= 2;
+ else if (surface->stereo_format
+ == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM)
+- pipe_ctx->ratios.vert.value *= 2;
++ pipe_ctx->scl_data.ratios.vert.value *= 2;
+
+- pipe_ctx->ratios.vert.value = div64_s64(pipe_ctx->ratios.vert.value * in_h,
++ pipe_ctx->scl_data.ratios.vert.value = div64_s64(pipe_ctx->scl_data.ratios.vert.value * in_h,
+ out_h);
+- pipe_ctx->ratios.horz.value = div64_s64(pipe_ctx->ratios.horz.value * in_w,
++ pipe_ctx->scl_data.ratios.horz.value = div64_s64(pipe_ctx->scl_data.ratios.horz.value * in_w,
+ out_w);
+
+- pipe_ctx->ratios.horz_c = pipe_ctx->ratios.horz;
+- pipe_ctx->ratios.vert_c = pipe_ctx->ratios.vert;
++ pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz;
++ pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert;
+
+- 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;
++ if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12) {
++ pipe_ctx->scl_data.ratios.horz_c.value /= 2;
++ pipe_ctx->scl_data.ratios.vert_c.value /= 2;
++ } else if (pipe_ctx->scl_data.format == PIXEL_FORMAT_422BPP16) {
++ pipe_ctx->scl_data.ratios.horz_c.value /= 2;
+ }
+ }
+
+@@ -348,7 +348,7 @@ void build_scaling_params(
+ * overscan calculation requires scaling ratios and viewport
+ * and lb depth/taps calculation requires overscan. Call sequence
+ * is therefore important */
+- pipe_ctx->format = convert_pixel_format_to_dalsurface(surface->format);
++ pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(surface->format);
+
+ calculate_viewport(surface, pipe_ctx);
+
+@@ -357,25 +357,25 @@ void build_scaling_params(
+ calculate_overscan(surface, pipe_ctx);
+
+ /* Check if scaling is required update taps if not */
+- if (dal_fixed31_32_u2d19(pipe_ctx->ratios.horz) == 1 << 19)
+- pipe_ctx->taps.h_taps = 1;
++ if (dal_fixed31_32_u2d19(pipe_ctx->scl_data.ratios.horz) == 1 << 19)
++ pipe_ctx->scl_data.taps.h_taps = 1;
+ else
+- pipe_ctx->taps.h_taps = surface->scaling_quality.h_taps;
++ pipe_ctx->scl_data.taps.h_taps = surface->scaling_quality.h_taps;
+
+- if (dal_fixed31_32_u2d19(pipe_ctx->ratios.horz_c) == 1 << 19)
+- pipe_ctx->taps.h_taps_c = 1;
++ if (dal_fixed31_32_u2d19(pipe_ctx->scl_data.ratios.horz_c) == 1 << 19)
++ pipe_ctx->scl_data.taps.h_taps_c = 1;
+ else
+- pipe_ctx->taps.h_taps_c = surface->scaling_quality.h_taps_c;
++ pipe_ctx->scl_data.taps.h_taps_c = surface->scaling_quality.h_taps_c;
+
+- if (dal_fixed31_32_u2d19(pipe_ctx->ratios.vert) == 1 << 19)
+- pipe_ctx->taps.v_taps = 1;
++ if (dal_fixed31_32_u2d19(pipe_ctx->scl_data.ratios.vert) == 1 << 19)
++ pipe_ctx->scl_data.taps.v_taps = 1;
+ else
+- pipe_ctx->taps.v_taps = surface->scaling_quality.v_taps;
++ pipe_ctx->scl_data.taps.v_taps = surface->scaling_quality.v_taps;
+
+- if (dal_fixed31_32_u2d19(pipe_ctx->ratios.vert_c) == 1 << 19)
+- pipe_ctx->taps.v_taps_c = 1;
++ if (dal_fixed31_32_u2d19(pipe_ctx->scl_data.ratios.vert_c) == 1 << 19)
++ pipe_ctx->scl_data.taps.v_taps_c = 1;
+ else
+- pipe_ctx->taps.v_taps_c = surface->scaling_quality.v_taps_c;
++ pipe_ctx->scl_data.taps.v_taps_c = surface->scaling_quality.v_taps_c;
+
+ dal_logger_write(pipe_ctx->stream->ctx->logger,
+ LOG_MAJOR_DCP,
+@@ -385,14 +385,14 @@ void build_scaling_params(
+ "y:%d\n dst_rect:\nheight:%d width:%d x:%d "
+ "y:%d\n",
+ __func__,
+- 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,
++ pipe_ctx->scl_data.overscan.bottom,
++ pipe_ctx->scl_data.overscan.left,
++ pipe_ctx->scl_data.overscan.right,
++ pipe_ctx->scl_data.overscan.top,
++ pipe_ctx->scl_data.viewport.height,
++ pipe_ctx->scl_data.viewport.width,
++ pipe_ctx->scl_data.viewport.x,
++ pipe_ctx->scl_data.viewport.y,
+ surface->dst_rect.height,
+ surface->dst_rect.width,
+ surface->dst_rect.x,
+@@ -439,13 +439,15 @@ bool attach_surfaces_to_context(
+ return false;
+ }
+
++
++ for (i = 0; i < surface_count; i++)
++ dc_surface_retain(surfaces[i]);
++ /* Release after retain to account for surfaces remaining the same */
+ for (i = 0; i < target_status->surface_count; i++)
+ dc_surface_release(target_status->surfaces[i]);
+-
+- for (i = 0; i < surface_count; i++) {
++ for (i = 0; i < surface_count; 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++) {
+@@ -503,7 +505,7 @@ static void fill_display_configs(
+ const struct validate_context *context,
+ struct dc_pp_display_configuration *pp_display_cfg)
+ {
+- uint8_t i, j;
++ uint8_t i, j, k;
+ uint8_t num_cfgs = 0;
+
+ for (i = 0; i < context->target_count; i++) {
+@@ -516,10 +518,10 @@ static void fill_display_configs(
+ &pp_display_cfg->disp_configs[num_cfgs];
+ const struct pipe_ctx *pipe_ctx = NULL;
+
+- for (j = 0; j < MAX_PIPES; j++)
++ for (k = 0; k < MAX_PIPES; k++)
+ if (stream ==
+- context->res_ctx.pipe_ctx[j].stream) {
+- pipe_ctx = &context->res_ctx.pipe_ctx[j];
++ context->res_ctx.pipe_ctx[k].stream) {
++ pipe_ctx = &context->res_ctx.pipe_ctx[k];
+ break;
+ }
+
+@@ -1272,6 +1274,18 @@ static void set_vendor_info_packet(struct core_stream *stream,
+ info_packet->valid = true;
+ }
+
++void destruct_val_ctx(struct validate_context *context)
++{
++ int i, j;
++
++ for (i = 0; i < context->target_count; i++) {
++ 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;
++ }
++}
++
+ void build_info_frame(struct pipe_ctx *pipe_ctx)
+ {
+ enum signal_type signal = SIGNAL_TYPE_NONE;
+diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
+index 6b778d8..dc9f157 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
+@@ -65,19 +65,7 @@ static void construct(
+
+ static void destruct(struct core_target *core_target)
+ {
+- int i, j;
+- struct validate_context *context =
+- &core_target->ctx->dc->current_context;
+-
+- 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;
+- }
++ int i;
+
+ for (i = 0; i < core_target->public.stream_count; i++) {
+ dc_stream_release(
+@@ -148,30 +136,45 @@ target_alloc_fail:
+ return NULL;
+ }
+
+-static bool validate_surface_address(
+- struct dc_plane_address address)
++static int8_t acquire_first_free_underlay(
++ struct resource_context *res_ctx,
++ struct core_stream *stream)
+ {
+- bool is_valid_address = false;
+-
+- switch (address.type) {
+- case PLN_ADDR_TYPE_GRAPHICS:
+- if (address.grph.addr.quad_part != 0)
+- is_valid_address = true;
+- break;
+- case PLN_ADDR_TYPE_GRPH_STEREO:
+- if ((address.grph_stereo.left_addr.quad_part != 0) &&
+- (address.grph_stereo.right_addr.quad_part != 0)) {
+- is_valid_address = true;
++ BREAK_TO_DEBUGGER();
++ if (!res_ctx->pipe_ctx[3].stream) {
++ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[DCE110_UNDERLAY_IDX];
++
++ pipe_ctx->tg = res_ctx->pool.timing_generators[DCE110_UNDERLAY_IDX];
++ pipe_ctx->mi = res_ctx->pool.mis[DCE110_UNDERLAY_IDX];
++ /*pipe_ctx->ipp = res_ctx->pool.ipps[DCE110_UNDERLAY_IDX];*/
++ pipe_ctx->xfm = res_ctx->pool.transforms[DCE110_UNDERLAY_IDX];
++ pipe_ctx->opp = res_ctx->pool.opps[DCE110_UNDERLAY_IDX];
++ pipe_ctx->dis_clk = res_ctx->pool.display_clock;
++ pipe_ctx->pipe_idx = DCE110_UNDERLAY_IDX;
++
++ if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) {
++ dm_error("DC: failed to blank crtc!\n");
++ BREAK_TO_DEBUGGER();
++ } else
++ pipe_ctx->flags.blanked = true;
++
++ pipe_ctx->tg->funcs->program_timing(
++ pipe_ctx->tg,
++ &stream->public.timing,
++ true);
++
++ if (!pipe_ctx->tg->funcs->enable_crtc(pipe_ctx->tg)) {
++ BREAK_TO_DEBUGGER();
+ }
+- break;
+- case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
+- default:
+- /* not supported */
+- BREAK_TO_DEBUGGER();
+- break;
+- }
+
+- return is_valid_address;
++ pipe_ctx->tg->funcs->set_blank_color(
++ pipe_ctx->tg,
++ COLOR_SPACE_SRGB_FULL_RANGE);/* TODO unhardcode*/
++
++ pipe_ctx->stream = stream;
++ return DCE110_UNDERLAY_IDX;
++ }
++ return -1;
+ }
+
+ bool dc_commit_surfaces_to_target(
+@@ -184,7 +187,7 @@ 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 dc_target_status *target_status = NULL;
+ struct validate_context *context;
+ int current_enabled_surface_count = 0;
+ int new_enabled_surface_count = 0;
+@@ -196,7 +199,7 @@ bool dc_commit_surfaces_to_target(
+ for (i = 0; i < context->target_count; i++)
+ if (target == context->targets[i])
+ break;
+- status = &context->target_status[i];
++ target_status = &context->target_status[i];
+ if (!dal_adapter_service_is_in_accelerated_mode(
+ dc->res_pool.adapter_srv)
+ || i == context->target_count) {
+@@ -204,14 +207,23 @@ bool dc_commit_surfaces_to_target(
+ goto unexpected_fail;
+ }
+
+- for (i = 0; i < status->surface_count; i++)
+- if (status->surfaces[i]->visible)
++ for (i = 0; i < target_status->surface_count; i++)
++ if (target_status->surfaces[i]->visible)
+ current_enabled_surface_count++;
+
+ for (i = 0; i < new_surface_count; i++)
+ if (new_surfaces[i]->visible)
+ new_enabled_surface_count++;
+
++ /* TODO unhack mpo */
++ if (new_surface_count == 2 && target_status->surface_count < 2)
++ acquire_first_free_underlay(&context->res_ctx,
++ DC_STREAM_TO_CORE(dc_target->streams[0]));
++ else if (new_surface_count < 2 && target_status->surface_count == 2) {
++ context->res_ctx.pipe_ctx[DCE110_UNDERLAY_IDX].stream = NULL;
++ context->res_ctx.pipe_ctx[DCE110_UNDERLAY_IDX].surface = NULL;
++ }
++
+ dal_logger_write(dc->ctx->logger,
+ LOG_MAJOR_INTERFACE_TRACE,
+ LOG_MINOR_COMPONENT_DC,
+@@ -280,24 +292,20 @@ bool dc_commit_surfaces_to_target(
+ dc_surface->dst_rect.width,
+ dc_surface->dst_rect.height);
+
+- if (surface->public.gamma_correction)
+- gamma = DC_GAMMA_TO_CORE(
++ if (surface->public.gamma_correction)
++ gamma = DC_GAMMA_TO_CORE(
+ surface->public.gamma_correction);
+
+- dc->hwss.set_gamma_correction(
+- pipe_ctx->ipp,
+- pipe_ctx->opp,
+- gamma, surface);
+-
+- dc->hwss.set_plane_config(dc, surface, pipe_ctx);
++ dc->hwss.set_gamma_correction(
++ pipe_ctx->ipp,
++ pipe_ctx->opp,
++ gamma, surface);
+
+- if (validate_surface_address(dc_surface->address))
+- dc->hwss.update_plane_addrs(
+- dc, &context->res_ctx, surface);
++ dc->hwss.set_plane_config(
++ dc, pipe_ctx, &context->res_ctx);
+ }
+
+- if (current_enabled_surface_count == 0 && new_enabled_surface_count > 0)
+- dc_target_enable_memory_requests(dc_target);
++ dc->hwss.update_plane_addrs(dc, &context->res_ctx);
+
+ /* Lower display clock if necessary */
+ if (prev_disp_clk > context->bw_results.dispclk_khz) {
+@@ -311,11 +319,9 @@ bool dc_commit_surfaces_to_target(
+ return true;
+
+ unexpected_fail:
+- for (i = 0; i < new_surface_count; i++) {
+- status->surfaces[i] = NULL;
+- }
+- status->surface_count = 0;
+
++ destruct_val_ctx(context);
++ dm_free(dc->ctx, context);
+ return false;
+ }
+
+@@ -350,7 +356,8 @@ void dc_target_enable_memory_requests(struct dc_target *dc_target)
+ if (!tg->funcs->set_blank(tg, false)) {
+ dm_error("DC: failed to unblank crtc!\n");
+ BREAK_TO_DEBUGGER();
+- }
++ } else
++ res_ctx->pipe_ctx[j].flags.blanked = false;
+ }
+ }
+ }
+@@ -373,7 +380,8 @@ void dc_target_disable_memory_requests(struct dc_target *dc_target)
+ if (!tg->funcs->set_blank(tg, true)) {
+ dm_error("DC: failed to blank crtc!\n");
+ BREAK_TO_DEBUGGER();
+- }
++ } else
++ res_ctx->pipe_ctx[j].flags.blanked = true;
+ }
+ }
+ }
+@@ -408,6 +416,9 @@ bool dc_target_set_cursor_attributes(
+ struct input_pixel_processor *ipp =
+ res_ctx->pipe_ctx[j].ipp;
+
++ if (j == DCE110_UNDERLAY_IDX)
++ continue;
++
+ if (res_ctx->pipe_ctx[j].stream !=
+ DC_STREAM_TO_CORE(target->public.streams[i]))
+ continue;
+@@ -451,6 +462,9 @@ bool dc_target_set_cursor_position(
+ struct input_pixel_processor *ipp =
+ res_ctx->pipe_ctx[j].ipp;
+
++ if (j == DCE110_UNDERLAY_IDX)
++ continue;
++
+ if (res_ctx->pipe_ctx[j].stream !=
+ DC_STREAM_TO_CORE(target->public.streams[i]))
+ continue;
+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 4e73ad1..d01a116 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
+@@ -86,7 +86,7 @@ static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
+ .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+ },
+ {
+- .dcfe = (mmDCFEV_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
++ .dcfe = (mmDCFEV_CLOCK_CONTROL - mmDCFE_CLOCK_CONTROL),
+ .blnd = (mmBLNDV_CONTROL - mmBLND_CONTROL),
+ .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+ }
+@@ -375,7 +375,10 @@ static void dce110_set_blender_mode(
+ break;
+ case BLENDER_MODE_CURRENT_PIPE:
+ default:
+- feedthrough = 1;
++ if (controller_id == DCE110_UNDERLAY_IDX)
++ feedthrough = 0;
++ else
++ feedthrough = 1;
+ blnd_mode = 0;
+ break;
+ }
+@@ -453,7 +456,7 @@ static bool dce110_enable_display_power_gating(
+ else
+ cntl = ASIC_PIPE_DISABLE;
+
+- if (!(power_gating == PIPE_GATING_CONTROL_INIT && controller_id != 0))
++ if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0)
+ bp_result = dcb->funcs->enable_disp_power_gating(
+ dcb, controller_id + 1, cntl);
+
+@@ -523,16 +526,19 @@ static bool set_gamma_ramp(
+
+ build_prescale_params(prescale_params, surface);
+
+- ipp->funcs->ipp_program_prescale(ipp, prescale_params);
++ if (ipp)
++ ipp->funcs->ipp_program_prescale(ipp, prescale_params);
+
+ if (ramp) {
+ calculate_regamma_params(regamma_params,
+ temp_params, ramp, surface);
+ opp->funcs->opp_program_regamma_pwl(opp, regamma_params);
+- ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_sRGB);
++ if (ipp)
++ ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_sRGB);
+ opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER);
+ } else {
+- ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
++ if (ipp)
++ ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
+ opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS);
+ }
+
+@@ -772,6 +778,8 @@ static enum dc_status apply_single_controller_ctx_to_hw(
+ * programming, otherwise CRTC will be hung in bad state
+ */
+ pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
++ pipe_ctx->flags.blanked = true;
++
+
+ /*
+ * only disable stream in case it was ever enabled
+@@ -949,6 +957,8 @@ static void disable_vga_and_power_gate_all_controllers(
+ * powergating. */
+ enable_display_pipe_clock_gating(ctx,
+ true);
++ if (i == DCE110_UNDERLAY_IDX)
++ continue;
+ dc->hwss.enable_display_power_gating(ctx, i, dcb,
+ PIPE_GATING_CONTROL_ENABLE);
+ }
+@@ -1138,7 +1148,8 @@ static void set_displaymarks(
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+ uint32_t total_dest_line_time_ns;
+
+- if (pipe_ctx->stream == NULL)
++ if (pipe_ctx->stream == NULL
++ || pipe_ctx->pipe_idx == DCE110_UNDERLAY_IDX)
+ continue;
+
+ total_dest_line_time_ns = compute_pstate_blackout_duration(
+@@ -1304,38 +1315,6 @@ static bool setup_line_buffer_pixel_depth(
+ return false;
+ }
+
+-static void hw_sequencer_build_scaler_parameter_plane(
+- const struct pipe_ctx *pipe_ctx,
+- struct scaler_data *scaler_data)
+-{
+- /*TODO: per pipe not per stream*/
+- /*TODO: get from feature from adapterservice*/
+- scaler_data->flags.bits.SHOW_COLOURED_BORDER = false;
+-
+- scaler_data->flags.bits.SHOULD_PROGRAM_ALPHA = 1;
+-
+- scaler_data->flags.bits.SHOULD_PROGRAM_VIEWPORT = 0;
+-
+- scaler_data->flags.bits.SHOULD_UNLOCK = 0;
+-
+- scaler_data->flags.bits.INTERLACED = 0;
+-
+- scaler_data->dal_pixel_format = pipe_ctx->format;
+-
+- scaler_data->taps = pipe_ctx->taps;
+-
+- scaler_data->viewport = pipe_ctx->viewport;
+-
+- scaler_data->overscan = pipe_ctx->overscan;
+-
+- scaler_data->ratios = &pipe_ctx->ratios;
+-
+- /*TODO rotation and adjustment */
+- scaler_data->h_sharpness = 0;
+- scaler_data->v_sharpness = 0;
+-
+-}
+-
+ static void set_default_colors(struct pipe_ctx *pipe_ctx)
+ {
+ struct default_adjustment default_adjust = { 0 };
+@@ -1344,7 +1323,7 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx)
+ 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 = pipe_ctx->format;
++ default_adjust.surface_pixel_format = pipe_ctx->scl_data.format;
+
+ /* display color depth */
+ default_adjust.color_depth =
+@@ -1360,28 +1339,17 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx)
+ pipe_ctx->opp, &default_adjust);
+ }
+
+-static void program_scaler(
+- const struct core_surface *surface,
+- const struct pipe_ctx *pipe_ctx)
++static void program_scaler(const struct pipe_ctx *pipe_ctx)
+ {
+- struct scaler_data scaler_data = { { 0 } };
+-
+- hw_sequencer_build_scaler_parameter_plane(
+- pipe_ctx,
+- &scaler_data);
+-
+ setup_line_buffer_pixel_depth(
+ pipe_ctx,
+ LB_PIXEL_DEPTH_24BPP,
+ false);
+
+ pipe_ctx->tg->funcs->set_overscan_blank_color(
+- pipe_ctx->tg, surface->public.color_space);
+-
+- pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm, &scaler_data);
++ pipe_ctx->tg, pipe_ctx->surface->public.color_space);
+
+- pipe_ctx->xfm->funcs->transform_update_viewport(
+- pipe_ctx->xfm, &scaler_data.viewport, false);
++ pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm, &pipe_ctx->scl_data);
+ }
+
+ /**
+@@ -1390,14 +1358,17 @@ static void program_scaler(
+ */
+ static void set_plane_config(
+ const struct dc *dc,
+- struct core_surface *surface,
+- struct pipe_ctx *pipe_ctx)
++ struct pipe_ctx *pipe_ctx,
++ struct resource_context *res_ctx)
+ {
++ int i;
+ 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;
++ struct core_surface *surface = pipe_ctx->surface;
++ enum blender_mode blender_mode = BLENDER_MODE_CURRENT_PIPE;
+
+ dc->hwss.pipe_control_lock(
+ ctx, pipe_ctx->pipe_idx, PIPE_LOCK_CONTROL_MODE, false);
+@@ -1419,11 +1390,19 @@ static void set_plane_config(
+
+ set_default_colors(pipe_ctx);
+
+- /* program Scaler */
+- program_scaler(surface, pipe_ctx);
++ program_scaler(pipe_ctx);
++
++ for (i = pipe_ctx->pipe_idx + 1; i < MAX_PIPES; i++)
++ if (res_ctx->pipe_ctx[i].stream == pipe_ctx->stream) {
++ if (surface->public.visible)
++ blender_mode = BLENDER_MODE_BLENDING;
++ else
++ blender_mode = BLENDER_MODE_OTHER_PIPE;
++ break;
++ }
+
+ dc->hwss.set_blender_mode(
+- ctx, pipe_ctx->pipe_idx, BLENDER_MODE_CURRENT_PIPE);
++ ctx, pipe_ctx->pipe_idx, blender_mode);
+
+ mi->funcs->mem_input_program_surface_config(
+ mi,
+@@ -1431,28 +1410,20 @@ static void set_plane_config(
+ &surface->public.tiling_info,
+ &surface->public.plane_size,
+ surface->public.rotation);
+-
+- dc->hwss.pipe_control_lock(
+- ctx,
+- pipe_ctx->pipe_idx,
+- PIPE_LOCK_CONTROL_GRAPHICS |
+- PIPE_LOCK_CONTROL_SCL |
+- PIPE_LOCK_CONTROL_BLENDER |
+- PIPE_LOCK_CONTROL_SURFACE,
+- false);
+ }
+
+-static void update_plane_addrs(
+- struct dc *dc,
+- struct resource_context *res_ctx,
+- const struct core_surface *surface)
++static void update_plane_addrs(struct dc *dc, struct resource_context *res_ctx)
+ {
+- uint8_t j;
++ int j;
+
+- for (j = 0; j < MAX_PIPES; j++) {
++ /* Go through pipes in reverse order to avoid underflow on unlock */
++ for (j = MAX_PIPES - 1; j >= 0; j--) {
+ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[j];
++ struct core_surface *surface = pipe_ctx->surface;
+
+- if (pipe_ctx->surface != surface)
++ if (surface == NULL ||
++ surface->status.requested_address.grph.addr.quad_part
++ == surface->public.address.grph.addr.quad_part)
+ continue;
+
+ dc->hwss.pipe_control_lock(
+@@ -1466,13 +1437,24 @@ static void update_plane_addrs(
+ &surface->public.address,
+ surface->public.flip_immediate);
+
+- dc->hwss.pipe_control_lock(
+- dc->ctx,
+- j,
+- PIPE_LOCK_CONTROL_SURFACE,
+- false);
++ surface->status.requested_address = surface->public.address;
+
+- break;
++ dc->hwss.pipe_control_lock(
++ dc->ctx,
++ pipe_ctx->pipe_idx,
++ PIPE_LOCK_CONTROL_GRAPHICS |
++ PIPE_LOCK_CONTROL_SCL |
++ PIPE_LOCK_CONTROL_BLENDER |
++ PIPE_LOCK_CONTROL_SURFACE,
++ false);
++
++ if (pipe_ctx->flags.blanked) {
++ if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, false)) {
++ dm_error("DC: failed to unblank crtc!\n");
++ BREAK_TO_DEBUGGER();
++ } else
++ pipe_ctx->flags.blanked = false;
++ }
+ }
+ }
+
+@@ -1483,6 +1465,9 @@ static void reset_single_pipe_hw_ctx(
+ {
+ struct dc_bios *dcb;
+
++ if (pipe_ctx->pipe_idx == DCE110_UNDERLAY_IDX)
++ return;
++
+ dcb = dal_adapter_service_get_bios_parser(
+ context->res_ctx.pool.adapter_srv);
+ if (pipe_ctx->audio) {
+@@ -1493,8 +1478,13 @@ static void reset_single_pipe_hw_ctx(
+ }
+
+ core_link_disable_stream(pipe_ctx);
+-
+- pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
++ if (!pipe_ctx->flags.blanked) {
++ if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) {
++ dm_error("DC: failed to blank crtc!\n");
++ BREAK_TO_DEBUGGER();
++ } else
++ pipe_ctx->flags.blanked = true;
++ }
+ pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg);
+ pipe_ctx->mi->funcs->free_mem_input(
+ pipe_ctx->mi, context->target_count);
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.c
+index 4b9042f..8babd01 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.c
+@@ -57,22 +57,16 @@ struct opp_funcs funcs = {
+
+ .opp_set_regamma_mode = dce110_opp_set_regamma_mode,
+
+- .opp_destroy = dce110_opp_destroy,
++ .opp_destroy = dce110_opp_destroy
+ };
+
+ bool dce110_opp_v_construct(struct dce110_opp *opp110,
+- struct dc_context *ctx,
+- uint32_t inst,
+- const struct dce110_opp_reg_offsets *offsets)
++ struct dc_context *ctx)
+ {
+ opp110->base.funcs = &funcs;
+
+ opp110->base.ctx = ctx;
+
+- opp110->base.inst = inst;
+-
+- opp110->offsets = *offsets;
+-
+ return true;
+ }
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.h
+index 9543a70..1936ba4 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.h
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.h
+@@ -34,9 +34,7 @@
+ struct gamma_parameters;
+
+ bool dce110_opp_v_construct(struct dce110_opp *opp110,
+- struct dc_context *ctx,
+- uint32_t inst,
+- const struct dce110_opp_reg_offsets *offsets);
++ struct dc_context *ctx);
+
+ /* underlay callbacks */
+ void dce110_opp_v_set_csc_default(
+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 26fc104..26e9df5 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
+@@ -35,11 +35,13 @@
+ #include "dce110/dce110_timing_generator_v.h"
+ #include "dce110/dce110_link_encoder.h"
+ #include "dce110/dce110_mem_input.h"
++#include "dce110/dce110_mem_input_v.h"
+ #include "dce110/dce110_ipp.h"
+ #include "dce110/dce110_transform.h"
+ #include "dce110/dce110_transform_v.h"
+ #include "dce110/dce110_stream_encoder.h"
+ #include "dce110/dce110_opp.h"
++#include "dce110/dce110_opp_v.h"
+ #include "dce110/dce110_clock_source.h"
+
+ #include "dce/dce_11_0_d.h"
+@@ -307,14 +309,8 @@ static struct timing_generator *dce110_timing_generator_create(
+ if (!tg110)
+ return NULL;
+
+- if (instance == 3) {
+- /* This is the Underlay instance. */
+- if (dce110_timing_generator_v_construct(tg110, as, ctx))
+- return &tg110->base;
+- } else {
+- if (dce110_timing_generator_construct(tg110, as, ctx, instance, offsets))
+- return &tg110->base;
+- }
++ if (dce110_timing_generator_construct(tg110, as, ctx, instance, offsets))
++ return &tg110->base;
+
+ BREAK_TO_DEBUGGER();
+ dm_free(ctx, tg110);
+@@ -378,14 +374,8 @@ static struct transform *dce110_transform_create(
+ if (!transform)
+ return NULL;
+
+- if (inst == 3) {
+- /* Underlay */
+- if (dce110_transform_v_construct(transform, ctx))
+- return &transform->base;
+- } else {
+- if (dce110_transform_construct(transform, ctx, inst, offsets))
+- return &transform->base;
+- }
++ if (dce110_transform_construct(transform, ctx, inst, offsets))
++ return &transform->base;
+
+ BREAK_TO_DEBUGGER();
+ dm_free(ctx, transform);
+@@ -683,6 +673,18 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx)
+ return DC_OK;
+ }
+
++static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx)
++{
++ if (pipe_ctx->pipe_idx != DCE110_UNDERLAY_IDX)
++ return true;
++ if (pipe_ctx->surface && pipe_ctx->surface->public.format <
++ SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
++ return false;
++ if (!pipe_ctx->surface)
++ return false;
++ return true;
++}
++
+ static enum dc_status validate_mapped_resource(
+ const struct dc *dc,
+ struct validate_context *context)
+@@ -706,8 +708,11 @@ static enum dc_status validate_mapped_resource(
+ if (context->res_ctx.pipe_ctx[k].stream != stream)
+ continue;
+
++ if (!is_surface_pixel_format_supported(pipe_ctx))
++ return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED;
++
+ if (!pipe_ctx->tg->funcs->validate_timing(
+- pipe_ctx->tg, &stream->public.timing))
++ pipe_ctx->tg, &stream->public.timing))
+ return DC_FAIL_CONTROLLER_VALIDATE;
+
+ status = build_pipe_hw_param(pipe_ctx);
+@@ -762,7 +767,7 @@ enum dc_status dce110_validate_bandwidth(
+ if (pipe_ctx->stream == NULL)
+ continue;
+
+- if (pipe_ctx->ratios.vert.value == 0) {
++ if (pipe_ctx->scl_data.ratios.vert.value == 0) {
+ disp->graphics_scale_ratio = bw_int_to_fixed(1);
+ disp->graphics_h_taps = 2;
+ disp->graphics_v_taps = 2;
+@@ -778,17 +783,17 @@ enum dc_status dce110_validate_bandwidth(
+ } 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;
++ pipe_ctx->scl_data.ratios.vert.value);
++ disp->graphics_h_taps = pipe_ctx->scl_data.taps.h_taps;
++ disp->graphics_v_taps = pipe_ctx->scl_data.taps.v_taps;
+
+ /* TODO: remove when bw formula accepts taps per
+ * display
+ */
+- 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;
++ if (max_vtaps < pipe_ctx->scl_data.taps.v_taps)
++ max_vtaps = pipe_ctx->scl_data.taps.v_taps;
++ if (max_htaps < pipe_ctx->scl_data.taps.h_taps)
++ max_htaps = pipe_ctx->scl_data.taps.h_taps;
+ }
+
+ disp->graphics_src_width =
+@@ -1004,10 +1009,16 @@ enum dc_status dce110_validate_with_context(
+ == context->targets[i]) {
+ unchanged = true;
+ set_target_unchanged(context, i);
++ attach_surfaces_to_context(
++ (struct dc_surface **)dc->current_context.
++ target_status[j].surfaces,
++ dc->current_context.target_status[j].surface_count,
++ &context->targets[i]->public,
++ context);
+ context->target_status[i] =
+ dc->current_context.target_status[j];
+ }
+- if (!unchanged)
++ if (!unchanged || set[i].surface_count != 0)
+ if (!attach_surfaces_to_context(
+ (struct dc_surface **)set[i].surfaces,
+ set[i].surface_count,
+@@ -1045,6 +1056,29 @@ static struct resource_funcs dce110_res_pool_funcs = {
+ .validate_bandwidth = dce110_validate_bandwidth
+ };
+
++static void underlay_create(struct dc_context *ctx, struct resource_pool *pool)
++{
++ struct dce110_timing_generator *dce110_tgv = dm_alloc(ctx, sizeof (*dce110_tgv));
++ struct dce110_transform *dce110_xfmv = dm_alloc(ctx, sizeof (*dce110_xfmv));
++ struct dce110_mem_input *dce110_miv = dm_alloc(ctx, sizeof (*dce110_miv));
++ struct dce110_opp *dce110_oppv = dm_alloc(ctx, sizeof (*dce110_oppv));
++
++ dce110_opp_v_construct(dce110_oppv, ctx);
++ dce110_timing_generator_v_construct(dce110_tgv, pool->adapter_srv, ctx);
++ dce110_mem_input_v_construct(dce110_miv, ctx);
++ dce110_transform_v_construct(dce110_xfmv, ctx);
++
++ pool->opps[pool->pipe_count] = &dce110_oppv->base;
++ pool->timing_generators[pool->pipe_count] = &dce110_tgv->base;
++ pool->mis[pool->pipe_count] = &dce110_miv->base;
++ pool->transforms[pool->pipe_count] = &dce110_xfmv->base;
++
++ pool->transforms[pool->pipe_count]->funcs->transform_set_scaler_filter(
++ pool->transforms[pool->pipe_count],
++ pool->scaler_filter);
++ pool->pipe_count++;
++}
++
+ bool dce110_construct_resource_pool(
+ struct adapter_service *as,
+ uint8_t num_virtual_links,
+@@ -1177,6 +1211,8 @@ bool dce110_construct_resource_pool(
+ goto controller_create_fail;
+ }
+ }
++ /* TODO: failure? */
++ underlay_create(ctx, pool);
+
+ audio_init_data.as = as;
+ audio_init_data.ctx = ctx;
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
+index 2654a96..dba972f 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
+@@ -47,8 +47,6 @@ static struct transform_funcs dce110_transform_funcs = {
+ dce110_transform_set_scaler,
+ .transform_set_scaler_bypass =
+ dce110_transform_set_scaler_bypass,
+- .transform_update_viewport =
+- dce110_transform_update_viewport,
+ .transform_set_scaler_filter =
+ dce110_transform_set_scaler_filter,
+ .transform_set_gamut_remap =
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
+index 7c15a13..4a5d54c 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
+@@ -64,16 +64,14 @@ static void disable_enhanced_sharpness(struct dce110_transform *xfm110)
+ SCL_REG(mmSCL_F_SHARP_CONTROL), value);
+ }
+
+-/**
+-* Function:
+-* void setup_scaling_configuration
+-*
+-* Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
+-* Input: data
+-*
+-* Output:
+- void
+-*/
++/*
++ * @Function:
++ * void setup_scaling_configuration
++ * @Purpose: setup scaling mode : bypass, RGb, YCbCr and number of taps
++ * @Input: data
++ *
++ * @Output: void
++ */
+ static bool setup_scaling_configuration(
+ struct dce110_transform *xfm110,
+ const struct scaler_data *data)
+@@ -82,45 +80,44 @@ static bool setup_scaling_configuration(
+ uint32_t addr;
+ uint32_t value;
+
++ addr = SCL_REG(mmSCL_BYPASS_CONTROL);
++ value = dm_read_reg(ctx, addr);
++ set_reg_field_value(
++ value,
++ 0,
++ SCL_BYPASS_CONTROL,
++ SCL_BYPASS_MODE);
++ dm_write_reg(ctx, addr, value);
++
+ if (data->taps.h_taps + data->taps.v_taps <= 2) {
+ dce110_transform_set_scaler_bypass(&xfm110->base);
+ return false;
+ }
+
+- {
+- addr = SCL_REG(mmSCL_MODE);
+- value = dm_read_reg(ctx, addr);
+-
+- if (data->dal_pixel_format <= PIXEL_FORMAT_GRPH_END)
+- set_reg_field_value(value, 1, SCL_MODE, SCL_MODE);
+- else
+- set_reg_field_value(value, 2, SCL_MODE, SCL_MODE);
+-
+- set_reg_field_value(value, 1, SCL_MODE, SCL_PSCL_EN);
++ addr = SCL_REG(mmSCL_MODE);
++ value = dm_read_reg(ctx, addr);
++ if (data->format <= PIXEL_FORMAT_GRPH_END)
++ set_reg_field_value(value, 1, SCL_MODE, SCL_MODE);
++ else
++ set_reg_field_value(value, 2, SCL_MODE, SCL_MODE);
++ set_reg_field_value(value, 1, SCL_MODE, SCL_PSCL_EN);
++ dm_write_reg(ctx, addr, value);
+
+- dm_write_reg(ctx, addr, value);
+- }
+- {
+- addr = SCL_REG(mmSCL_TAP_CONTROL);
+- value = dm_read_reg(ctx, addr);
+
+- set_reg_field_value(value, data->taps.h_taps - 1,
+- SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
++ addr = SCL_REG(mmSCL_TAP_CONTROL);
++ value = dm_read_reg(ctx, addr);
++ set_reg_field_value(value, data->taps.h_taps - 1,
++ SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
++ set_reg_field_value(value, data->taps.v_taps - 1,
++ SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
++ dm_write_reg(ctx, addr, value);
+
+- set_reg_field_value(value, data->taps.v_taps - 1,
+- SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
+
+- dm_write_reg(ctx, addr, value);
+- }
+- {
+- addr = SCL_REG(mmSCL_CONTROL);
+- value = dm_read_reg(ctx, addr);
+- /* 1 - Replaced out of bound pixels with edge */
+- set_reg_field_value(value, 1, SCL_CONTROL, SCL_BOUNDARY_MODE);
+-
+- /* 1 - Replaced out of bound pixels with the edge pixel. */
+- dm_write_reg(ctx, addr, value);
+- }
++ addr = SCL_REG(mmSCL_CONTROL);
++ value = dm_read_reg(ctx, addr);
++ /* 1 - Replaced out of bound pixels with edge */
++ set_reg_field_value(value, 1, SCL_CONTROL, SCL_BOUNDARY_MODE);
++ dm_write_reg(ctx, addr, value);
+
+ return true;
+ }
+@@ -425,7 +422,7 @@ static bool program_multi_taps_filter(
+
+ if (horizontal) {
+ filter_params.taps = data->taps.h_taps;
+- filter_params.sharpness = data->h_sharpness;
++ filter_params.sharpness = 0; /* TODO */
+ filter_params.flags.bits.HORIZONTAL = 1;
+
+ src_size = data->viewport.width;
+@@ -434,12 +431,12 @@ static bool program_multi_taps_filter(
+ dal_fixed31_32_div(
+ dal_fixed31_32_from_int(
+ data->viewport.width),
+- data->ratios->horz));
++ data->ratios.horz));
+
+ filter_type = FILTER_TYPE_RGB_Y_HORIZONTAL;
+ } else {
+ filter_params.taps = data->taps.v_taps;
+- filter_params.sharpness = data->v_sharpness;
++ filter_params.sharpness = 0; /* TODO */
+ filter_params.flags.bits.HORIZONTAL = 0;
+
+ src_size = data->viewport.height;
+@@ -448,7 +445,7 @@ static bool program_multi_taps_filter(
+ dal_fixed31_32_div(
+ dal_fixed31_32_from_int(
+ data->viewport.height),
+- data->ratios->vert));
++ data->ratios.vert));
+
+ filter_type = FILTER_TYPE_RGB_Y_VERTICAL;
+ }
+@@ -478,20 +475,18 @@ static bool program_multi_taps_filter(
+ filter_data,
+ filter_data_size);
+
+- /* 4. Program the alpha if necessary */
+- if (data->flags.bits.SHOULD_PROGRAM_ALPHA) {
+- if (horizontal)
+- filter_type = FILTER_TYPE_ALPHA_HORIZONTAL;
+- else
+- filter_type = FILTER_TYPE_ALPHA_VERTICAL;
+-
+- program_filter(
+- xfm110,
+- filter_type,
+- &filter_params,
+- filter_data,
+- filter_data_size);
+- }
++ /* 4. Program the alpha*/
++ if (horizontal)
++ filter_type = FILTER_TYPE_ALPHA_HORIZONTAL;
++ else
++ filter_type = FILTER_TYPE_ALPHA_VERTICAL;
++
++ program_filter(
++ xfm110,
++ filter_type,
++ &filter_params,
++ filter_data,
++ filter_data_size);
+
+ return true;
+ }
+@@ -542,18 +537,16 @@ static void calculate_inits(
+ {
+ struct fixed31_32 h_init;
+ struct fixed31_32 v_init;
+- struct fixed31_32 v_init_bot;
+
+- inits->bottom_enable = 0;
+ inits->h_int_scale_ratio =
+- dal_fixed31_32_u2d19(data->ratios->horz) << 5;
++ dal_fixed31_32_u2d19(data->ratios.horz) << 5;
+ inits->v_int_scale_ratio =
+- dal_fixed31_32_u2d19(data->ratios->vert) << 5;
++ dal_fixed31_32_u2d19(data->ratios.vert) << 5;
+
+ h_init =
+ dal_fixed31_32_div_int(
+ dal_fixed31_32_add(
+- data->ratios->horz,
++ data->ratios.horz,
+ dal_fixed31_32_from_int(data->taps.h_taps + 1)),
+ 2);
+ inits->h_init.integer = dal_fixed31_32_floor(h_init);
+@@ -562,28 +555,11 @@ static void calculate_inits(
+ v_init =
+ dal_fixed31_32_div_int(
+ dal_fixed31_32_add(
+- data->ratios->vert,
++ data->ratios.vert,
+ dal_fixed31_32_from_int(data->taps.v_taps + 1)),
+ 2);
+ inits->v_init.integer = dal_fixed31_32_floor(v_init);
+ inits->v_init.fraction = dal_fixed31_32_u0d19(v_init) << 5;
+-
+- if (data->flags.bits.INTERLACED) {
+- v_init_bot =
+- dal_fixed31_32_add(
+- dal_fixed31_32_div_int(
+- dal_fixed31_32_add(
+- data->ratios->vert,
+- dal_fixed31_32_from_int(
+- data->taps.v_taps + 1)),
+- 2),
+- data->ratios->vert);
+- inits->v_init_bottom.integer = dal_fixed31_32_floor(v_init_bot);
+- inits->v_init_bottom.fraction =
+- dal_fixed31_32_u0d19(v_init_bot) << 5;
+-
+- inits->bottom_enable = 1;
+- }
+ }
+
+ static void program_scl_ratios_inits(
+@@ -637,22 +613,6 @@ static void program_scl_ratios_inits(
+ SCL_V_INIT_FRAC);
+ dm_write_reg(xfm110->base.ctx, addr, value);
+
+- if (inits->bottom_enable) {
+- addr = SCL_REG(mmSCL_VERT_FILTER_INIT_BOT);
+- value = 0;
+- set_reg_field_value(
+- value,
+- inits->v_init_bottom.integer,
+- SCL_VERT_FILTER_INIT_BOT,
+- SCL_V_INIT_INT_BOT);
+- set_reg_field_value(
+- value,
+- inits->v_init_bottom.fraction,
+- SCL_VERT_FILTER_INIT_BOT,
+- SCL_V_INIT_FRAC_BOT);
+- dm_write_reg(xfm110->base.ctx, addr, value);
+- }
+-
+ addr = SCL_REG(mmSCL_AUTOMATIC_MODE_CONTROL);
+ value = 0;
+ set_reg_field_value(
+@@ -668,38 +628,6 @@ static void program_scl_ratios_inits(
+ dm_write_reg(xfm110->base.ctx, addr, value);
+ }
+
+-static void get_viewport(
+- struct dce110_transform *xfm110,
+- struct rect *current_view_port)
+-{
+- uint32_t value_start;
+- uint32_t value_size;
+-
+- if (current_view_port == NULL)
+- return;
+-
+- value_start = dm_read_reg(xfm110->base.ctx, SCL_REG(mmVIEWPORT_START));
+- value_size = dm_read_reg(xfm110->base.ctx, SCL_REG(mmVIEWPORT_SIZE));
+-
+- current_view_port->x = get_reg_field_value(
+- value_start,
+- VIEWPORT_START,
+- VIEWPORT_X_START);
+- current_view_port->y = get_reg_field_value(
+- value_start,
+- VIEWPORT_START,
+- VIEWPORT_Y_START);
+- current_view_port->height = get_reg_field_value(
+- value_size,
+- VIEWPORT_SIZE,
+- VIEWPORT_HEIGHT);
+- current_view_port->width = get_reg_field_value(
+- value_size,
+- VIEWPORT_SIZE,
+- VIEWPORT_WIDTH);
+-}
+-
+-
+ bool dce110_transform_set_scaler(
+ struct transform *xfm,
+ const struct scaler_data *data)
+@@ -708,18 +636,6 @@ bool dce110_transform_set_scaler(
+ bool is_scaling_required;
+ struct dc_context *ctx = xfm->ctx;
+
+- {
+- uint32_t addr = SCL_REG(mmSCL_BYPASS_CONTROL);
+- uint32_t value = dm_read_reg(xfm->ctx, addr);
+-
+- set_reg_field_value(
+- value,
+- 0,
+- SCL_BYPASS_CONTROL,
+- SCL_BYPASS_MODE);
+- dm_write_reg(xfm->ctx, addr, value);
+- }
+-
+ disable_enhanced_sharpness(xfm110);
+
+ /* 3. Program overscan */
+@@ -764,6 +680,9 @@ bool dce110_transform_set_scaler(
+ program_two_taps_filter(xfm110, true, false);
+ }
+
++ /* 7. Program the viewport */
++ program_viewport(xfm110, &data->viewport);
++
+ return true;
+ }
+
+@@ -780,35 +699,6 @@ void dce110_transform_set_scaler_bypass(struct transform *xfm)
+ dm_write_reg(xfm->ctx, SCL_REG(mmSCL_MODE), sclv_mode);
+ }
+
+-bool dce110_transform_update_viewport(
+- struct transform *xfm,
+- const struct rect *view_port,
+- bool is_fbc_attached)
+-{
+- struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+- bool program_req = false;
+- struct rect current_view_port;
+-
+- if (view_port == NULL)
+- return program_req;
+-
+- get_viewport(xfm110, &current_view_port);
+-
+- if (current_view_port.x != view_port->x ||
+- current_view_port.y != view_port->y ||
+- current_view_port.height != view_port->height ||
+- current_view_port.width != view_port->width)
+- program_req = true;
+-
+- if (program_req) {
+- /*underlay viewport is programmed with scaler
+- *program_viewport function pointer is not exposed*/
+- program_viewport(xfm110, view_port);
+- }
+-
+- return program_req;
+-}
+-
+ void dce110_transform_set_scaler_filter(
+ struct transform *xfm,
+ struct scaler_filter *filter)
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.c
+index 6491435..aef17b3 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_v.c
+@@ -39,7 +39,6 @@
+
+
+ struct sclv_ratios_inits {
+- uint32_t chroma_enable;
+ uint32_t h_int_scale_ratio_luma;
+ uint32_t h_int_scale_ratio_chroma;
+ uint32_t v_int_scale_ratio_luma;
+@@ -48,10 +47,6 @@ struct sclv_ratios_inits {
+ struct init_int_and_frac h_init_chroma;
+ struct init_int_and_frac v_init_luma;
+ struct init_int_and_frac v_init_chroma;
+- struct init_int_and_frac h_init_lumabottom;
+- struct init_int_and_frac h_init_chromabottom;
+- struct init_int_and_frac v_init_lumabottom;
+- struct init_int_and_frac v_init_chromabottom;
+ };
+
+ /*
+@@ -80,14 +75,13 @@ static void calculate_viewport(
+ scl_data->viewport.width - scl_data->viewport.width % 2;
+ luma_viewport->height =
+ scl_data->viewport.height - scl_data->viewport.height % 2;
++ chroma_viewport->x = luma_viewport->x;
++ chroma_viewport->y = luma_viewport->y;
++ chroma_viewport->height = luma_viewport->height;
++ chroma_viewport->width = luma_viewport->width;
+
+
+- if (scl_data->dal_pixel_format == PIXEL_FORMAT_422BPP16) {
+- luma_viewport->width += luma_viewport->width % 2;
+-
+- chroma_viewport->x = luma_viewport->x / 2;
+- chroma_viewport->width = luma_viewport->width / 2;
+- } else if (scl_data->dal_pixel_format == PIXEL_FORMAT_420BPP12) {
++ if (scl_data->format == PIXEL_FORMAT_420BPP12) {
+ luma_viewport->height += luma_viewport->height % 2;
+ luma_viewport->width += luma_viewport->width % 2;
+ /*for 420 video chroma is 1/4 the area of luma, scaled
+@@ -169,24 +163,8 @@ static void program_viewport(
+ VIEWPORT_WIDTH_C);
+ dm_write_reg(ctx, addr, value);
+ }
+- /* TODO: add stereo support */
+ }
+
+-
+-/*
+- * Until and For MPO video play story, to reduce time for implementation,
+- * below limits are applied for now: 2_TAPS only
+- * Use auto-calculated filter values
+- * Following routines will be empty for now:
+- *
+- * programSclRatiosInits -- calcualate scaler ratio manually
+- * calculateInits --- calcualate scaler ratio manually
+- * programFilter -- multi-taps
+- * GetOptimalNumberOfTaps -- will hard coded to 2 TAPS
+- * GetNextLowerNumberOfTaps -- will hard coded to 2TAPS
+- * validateRequestedScaleRatio - used by GetOptimalNumberOfTaps internally
+- */
+-
+ /*
+ * Function:
+ * void setup_scaling_configuration
+@@ -218,8 +196,8 @@ static bool setup_scaling_configuration(
+ set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C);
+ set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C);
+ is_scaling_needed = true;
+- } else if (data->dal_pixel_format != PIXEL_FORMAT_420BPP12 &&
+- data->dal_pixel_format != PIXEL_FORMAT_422BPP16) {
++ } else if (data->format != PIXEL_FORMAT_420BPP12 &&
++ data->format != PIXEL_FORMAT_422BPP16) {
+ set_reg_field_value(
+ value,
+ get_reg_field_value(value, SCLV_MODE, SCL_MODE),
+@@ -236,39 +214,25 @@ static bool setup_scaling_configuration(
+ }
+ dm_write_reg(ctx, mmSCLV_MODE, value);
+
+- {
+- value = dm_read_reg(ctx, mmSCLV_TAP_CONTROL);
+-
+- set_reg_field_value(value, data->taps.h_taps - 1,
+- SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
+-
+- set_reg_field_value(value, data->taps.v_taps - 1,
+- SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
+-
+- set_reg_field_value(value, data->taps.h_taps_c - 1,
+- SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
+-
+- set_reg_field_value(value, data->taps.v_taps_c - 1,
+- SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
+-
+- dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);
+- }
+-
+- {
+- /*
+- * we can ignore this register because we are ok with hw
+- * default 0 -- change to 1 according to dal2 code
+- */
+- value = dm_read_reg(ctx, mmSCLV_CONTROL);
+- /*
+- * 0 - Replaced out of bound pixels with black pixel
+- * (or any other required color)
+- */
+- set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
+-
+- /* 1 - Replaced out of bound pixels with the edge pixel. */
+- dm_write_reg(ctx, mmSCLV_CONTROL, value);
+- }
++ value = 0;
++ set_reg_field_value(value, data->taps.h_taps - 1,
++ SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
++ set_reg_field_value(value, data->taps.v_taps - 1,
++ SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
++ set_reg_field_value(value, data->taps.h_taps_c - 1,
++ SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
++ set_reg_field_value(value, data->taps.v_taps_c - 1,
++ SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
++ dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);
++
++ value = 0;
++ /*
++ * 0 - Replaced out of bound pixels with black pixel
++ * (or any other required color)
++ * 1 - Replaced out of bound pixels with the edge pixel
++ */
++ set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
++ dm_write_reg(ctx, mmSCLV_CONTROL, value);
+
+ return is_scaling_needed;
+ }
+@@ -379,17 +343,20 @@ static void calculate_inits(
+ struct rect *luma_viewport,
+ struct rect *chroma_viewport)
+ {
+- if (data->dal_pixel_format == PIXEL_FORMAT_420BPP12 ||
+- data->dal_pixel_format == PIXEL_FORMAT_422BPP16)
+- inits->chroma_enable = true;
+-
+- /* TODO: implement rest of this function properly */
+- if (inits->chroma_enable) {
+- inits->h_int_scale_ratio_luma = 0x1000000;
+- inits->v_int_scale_ratio_luma = 0x1000000;
+- inits->h_int_scale_ratio_chroma = 0x800000;
+- inits->v_int_scale_ratio_chroma = 0x800000;
+- }
++ inits->h_int_scale_ratio_luma =
++ dal_fixed31_32_u2d19(data->ratios.horz) << 5;
++ inits->v_int_scale_ratio_luma =
++ dal_fixed31_32_u2d19(data->ratios.vert) << 5;
++ inits->h_int_scale_ratio_chroma =
++ dal_fixed31_32_u2d19(data->ratios.horz_c) << 5;
++ inits->v_int_scale_ratio_chroma =
++ dal_fixed31_32_u2d19(data->ratios.vert_c) << 5;
++
++ inits->h_init_luma.integer = 1;
++ inits->v_init_luma.integer = 1;
++ inits->h_init_chroma.integer = 1;
++ inits->v_init_chroma.integer = 1;
++
+ }
+
+ static void program_scl_ratios_inits(
+@@ -398,7 +365,7 @@ static void program_scl_ratios_inits(
+ {
+ struct dc_context *ctx = xfm110->base.ctx;
+ uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
+- uint32_t value = dm_read_reg(ctx, addr);
++ uint32_t value = 0;
+
+ set_reg_field_value(
+ value,
+@@ -408,7 +375,7 @@ static void program_scl_ratios_inits(
+ dm_write_reg(ctx, addr, value);
+
+ addr = mmSCLV_VERT_FILTER_SCALE_RATIO;
+- value = dm_read_reg(ctx, addr);
++ value = 0;
+ set_reg_field_value(
+ value,
+ inits->v_int_scale_ratio_luma,
+@@ -416,8 +383,9 @@ static void program_scl_ratios_inits(
+ SCL_V_SCALE_RATIO);
+ dm_write_reg(ctx, addr, value);
+
++
+ addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C;
+- value = dm_read_reg(ctx, addr);
++ value = 0;
+ set_reg_field_value(
+ value,
+ inits->h_int_scale_ratio_chroma,
+@@ -426,13 +394,71 @@ static void program_scl_ratios_inits(
+ dm_write_reg(ctx, addr, value);
+
+ addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C;
+- value = dm_read_reg(ctx, addr);
++ value = 0;
+ set_reg_field_value(
+ value,
+ inits->v_int_scale_ratio_chroma,
+ SCLV_VERT_FILTER_SCALE_RATIO_C,
+ SCL_V_SCALE_RATIO_C);
+ dm_write_reg(ctx, addr, value);
++
++
++ addr = mmSCLV_HORZ_FILTER_INIT;
++ value = 0;
++ set_reg_field_value(
++ value,
++ inits->h_init_luma.fraction,
++ SCLV_HORZ_FILTER_INIT,
++ SCL_H_INIT_FRAC);
++ set_reg_field_value(
++ value,
++ inits->h_init_luma.integer,
++ SCLV_HORZ_FILTER_INIT,
++ SCL_H_INIT_INT);
++ dm_write_reg(ctx, addr, value);
++
++ addr = mmSCLV_VERT_FILTER_INIT;
++ value = 0;
++ set_reg_field_value(
++ value,
++ inits->v_init_luma.fraction,
++ SCLV_VERT_FILTER_INIT,
++ SCL_V_INIT_FRAC);
++ set_reg_field_value(
++ value,
++ inits->v_init_luma.integer,
++ SCLV_VERT_FILTER_INIT,
++ SCL_V_INIT_INT);
++ dm_write_reg(ctx, addr, value);
++
++
++ addr = mmSCLV_HORZ_FILTER_INIT_C;
++ value = 0;
++ set_reg_field_value(
++ value,
++ inits->h_init_chroma.fraction,
++ SCLV_HORZ_FILTER_INIT_C,
++ SCL_H_INIT_FRAC_C);
++ set_reg_field_value(
++ value,
++ inits->h_init_chroma.integer,
++ SCLV_HORZ_FILTER_INIT_C,
++ SCL_H_INIT_INT_C);
++ dm_write_reg(ctx, addr, value);
++
++ addr = mmSCLV_VERT_FILTER_INIT_C;
++ value = 0;
++ set_reg_field_value(
++ value,
++ inits->v_init_chroma.fraction,
++ SCLV_VERT_FILTER_INIT_C,
++ SCL_V_INIT_FRAC_C);
++ set_reg_field_value(
++ value,
++ inits->v_init_chroma.integer,
++ SCLV_VERT_FILTER_INIT_C,
++ SCL_V_INIT_INT_C);
++ dm_write_reg(ctx, addr, value);
+ }
+
+ static void dce110_transform_v_set_scalerv_bypass(struct transform *xfm)
+@@ -447,34 +473,32 @@ static void dce110_transform_v_set_scalerv_bypass(struct transform *xfm)
+ dm_write_reg(xfm->ctx, addr, value);
+ }
+
+-/* TODO: sync this one with DAL2 */
+ static bool dce110_transform_v_set_scaler(
+ struct transform *xfm,
+ const struct scaler_data *data)
+ {
+ struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+- bool is_scaling_required;
++ bool is_scaling_required = false;
++ bool filter_updated = false;
+ struct rect luma_viewport = {0};
+ struct rect chroma_viewport = {0};
+ struct dc_context *ctx = xfm->ctx;
+
+- /* 1. Lock Scaler TODO: enable?*/
+- /*set_scaler_update_lock(xfm, true);*/
+
+- /* 2. Calculate viewport, viewport programming should happen after init
++ /* 1. Calculate viewport, viewport programming should happen after init
+ * calculations as they may require an adjustment in the viewport.
+ */
+
+ calculate_viewport(data, &luma_viewport, &chroma_viewport);
+
+- /* 3. Program overscan */
++ /* 2. Program overscan */
+ program_overscan(xfm110, &data->overscan);
+
+- /* 4. Program taps and configuration */
++ /* 3. Program taps and configuration */
+ is_scaling_required = setup_scaling_configuration(xfm110, data);
+
+ if (is_scaling_required) {
+- /* 5. Calculate and program ratio, filter initialization */
++ /* 4. Calculate and program ratio, filter initialization */
+
+ struct sclv_ratios_inits inits = { 0 };
+
+@@ -489,7 +513,7 @@ static bool dce110_transform_v_set_scaler(
+
+ /*scaler coeff of 2-TAPS use hardware auto calculated value*/
+
+- /* 6. Program vertical filters */
++ /* 5. Program vertical filters */
+ if (data->taps.v_taps > 2) {
+ program_two_taps_filter_vert(xfm110, false);
+
+@@ -500,10 +524,11 @@ static bool dce110_transform_v_set_scaler(
+ "Failed vertical taps programming\n");
+ return false;
+ }
++ filter_updated = true;
+ } else
+ program_two_taps_filter_vert(xfm110, true);
+
+- /* 7. Program horizontal filters */
++ /* 6. Program horizontal filters */
+ if (data->taps.h_taps > 2) {
+ program_two_taps_filter_horz(xfm110, false);
+
+@@ -514,23 +539,16 @@ static bool dce110_transform_v_set_scaler(
+ "Failed horizontal taps programming\n");
+ return false;
+ }
++ filter_updated = true;
+ } else
+ program_two_taps_filter_horz(xfm110, true);
+ }
+
+- /* 8. Program the viewport */
+- if (data->flags.bits.SHOULD_PROGRAM_VIEWPORT)
+- program_viewport(xfm110, &luma_viewport, &chroma_viewport);
+-
+- /* 9. Unlock the Scaler TODO: enable?
+- * Every call to "set_scaler_update_lock(xfm, TRUE)"
+- * must have a corresponding call to
+- * "set_scaler_update_lock(xfm, FALSE)" */
+-
+- /*set_scaler_update_lock(xfm, false);*/
++ /* 7. Program the viewport */
++ program_viewport(xfm110, &luma_viewport, &chroma_viewport);
+
+- /* TODO: investigate purpose/need of SHOULD_UNLOCK */
+- if (data->flags.bits.SHOULD_UNLOCK == false)
++ /* 8. Set bit to flip to new coefficient memory */
++ if (filter_updated)
+ set_coeff_update_complete(xfm110);
+
+ return true;
+@@ -554,104 +572,6 @@ static bool dce110_transform_v_power_up_line_buffer(struct transform *xfm)
+ return true;
+ }
+
+-static void get_viewport(
+- struct dce110_transform *xfm110,
+- struct rect *current_view_port)
+-{
+- uint32_t value_start;
+- uint32_t value_size;
+-
+- if (current_view_port == NULL)
+- return;
+-
+- value_start = dm_read_reg(xfm110->base.ctx, mmSCLV_VIEWPORT_START);
+- value_size = dm_read_reg(xfm110->base.ctx, mmSCLV_VIEWPORT_SIZE);
+-
+- current_view_port->x = get_reg_field_value(
+- value_start,
+- SCLV_VIEWPORT_START,
+- VIEWPORT_X_START);
+- current_view_port->y = get_reg_field_value(
+- value_start,
+- SCLV_VIEWPORT_START,
+- VIEWPORT_Y_START);
+- current_view_port->height = get_reg_field_value(
+- value_size,
+- SCLV_VIEWPORT_SIZE,
+- VIEWPORT_HEIGHT);
+- current_view_port->width = get_reg_field_value(
+- value_size,
+- SCLV_VIEWPORT_SIZE,
+- VIEWPORT_WIDTH);
+-}
+-
+-static void program_luma_viewport(
+- struct dce110_transform *xfm110,
+- const struct rect *view_port)
+-{
+- struct dc_context *ctx = xfm110->base.ctx;
+- uint32_t value = 0;
+- uint32_t addr = 0;
+-
+- addr = mmSCLV_VIEWPORT_START;
+- value = dm_read_reg(ctx, addr);
+- set_reg_field_value(
+- value,
+- view_port->x,
+- SCLV_VIEWPORT_START,
+- VIEWPORT_X_START);
+- set_reg_field_value(
+- value,
+- view_port->y,
+- SCLV_VIEWPORT_START,
+- VIEWPORT_Y_START);
+- dm_write_reg(ctx, addr, value);
+-
+- addr = mmSCLV_VIEWPORT_SIZE;
+- value = dm_read_reg(ctx, addr);
+- set_reg_field_value(
+- value,
+- view_port->height,
+- SCLV_VIEWPORT_SIZE,
+- VIEWPORT_HEIGHT);
+- set_reg_field_value(
+- value,
+- view_port->width,
+- SCLV_VIEWPORT_SIZE,
+- VIEWPORT_WIDTH);
+- dm_write_reg(ctx, addr, value);
+-
+- /* TODO: add stereo support */
+-}
+-
+-static bool dce110_transform_v_update_viewport(
+- struct transform *xfm,
+- const struct rect *view_port,
+- bool is_fbc_attached)
+-{
+- struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+- bool program_req = false;
+- struct rect current_view_port;
+-
+- if (view_port == NULL)
+- return program_req;
+-
+- get_viewport(xfm110, &current_view_port);
+-
+- if (current_view_port.x != view_port->x ||
+- current_view_port.y != view_port->y ||
+- current_view_port.height != view_port->height ||
+- current_view_port.width != view_port->width)
+- program_req = true;
+-
+- if (program_req) {
+- /*underlay viewport is programmed with scaler
+- *program_viewport function pointer is not exposed*/
+- program_luma_viewport(xfm110, view_port);
+- }
+-
+- return program_req;
+-}
+
+ static struct transform_funcs dce110_transform_v_funcs = {
+ .transform_power_up =
+@@ -660,8 +580,6 @@ static struct transform_funcs dce110_transform_v_funcs = {
+ dce110_transform_v_set_scaler,
+ .transform_set_scaler_bypass =
+ dce110_transform_v_set_scalerv_bypass,
+- .transform_update_viewport =
+- dce110_transform_v_update_viewport,
+ .transform_set_scaler_filter =
+ dce110_transform_set_scaler_filter,
+ .transform_set_gamut_remap =
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c
+index c7bfa28..ed143f4 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_resource.c
+@@ -764,7 +764,7 @@ enum dc_status dce80_validate_bandwidth(
+ if (pipe_ctx->stream == NULL)
+ continue;
+
+- if (pipe_ctx->ratios.vert.value == 0) {
++ if (pipe_ctx->scl_data.ratios.vert.value == 0) {
+ disp->graphics_scale_ratio = bw_int_to_fixed(1);
+ disp->graphics_h_taps = 2;
+ disp->graphics_v_taps = 2;
+@@ -780,17 +780,17 @@ enum dc_status dce80_validate_bandwidth(
+ } 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;
++ pipe_ctx->scl_data.ratios.vert.value);
++ disp->graphics_h_taps = pipe_ctx->scl_data.taps.h_taps;
++ disp->graphics_v_taps = pipe_ctx->scl_data.taps.v_taps;
+
+ /* TODO: remove when bw formula accepts taps per
+ * display
+ */
+- 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;
++ if (max_vtaps < pipe_ctx->scl_data.taps.v_taps)
++ max_vtaps = pipe_ctx->scl_data.taps.v_taps;
++ if (max_htaps < pipe_ctx->scl_data.taps.h_taps)
++ max_htaps = pipe_ctx->scl_data.taps.h_taps;
+ }
+
+ disp->graphics_src_width =
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_transform.c b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_transform.c
+index 5654738..204893e 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_transform.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_transform.c
+@@ -47,8 +47,6 @@ static struct transform_funcs dce80_transform_funcs = {
+ dce80_transform_set_scaler,
+ .transform_set_scaler_bypass =
+ dce80_transform_set_scaler_bypass,
+- .transform_update_viewport =
+- dce80_transform_update_viewport,
+ .transform_set_scaler_filter =
+ dce80_transform_set_scaler_filter,
+ .transform_set_gamut_remap =
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_transform_scl.c b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_transform_scl.c
+index 62a3a04..c9b3af5 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce80/dce80_transform_scl.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce80/dce80_transform_scl.c
+@@ -91,7 +91,7 @@ static bool setup_scaling_configuration(
+ addr = SCL_REG(mmSCL_MODE);
+ value = dm_read_reg(ctx, addr);
+
+- if (data->dal_pixel_format <= PIXEL_FORMAT_GRPH_END)
++ if (data->format <= PIXEL_FORMAT_GRPH_END)
+ set_reg_field_value(value, 1, SCL_MODE, SCL_MODE);
+ else
+ set_reg_field_value(value, 2, SCL_MODE, SCL_MODE);
+@@ -422,7 +422,7 @@ static bool program_multi_taps_filter(
+
+ if (horizontal) {
+ filter_params.taps = data->taps.h_taps;
+- filter_params.sharpness = data->h_sharpness;
++ filter_params.sharpness = 0; /* TODO */
+ filter_params.flags.bits.HORIZONTAL = 1;
+
+ src_size = data->viewport.width;
+@@ -431,12 +431,12 @@ static bool program_multi_taps_filter(
+ dal_fixed31_32_div(
+ dal_fixed31_32_from_int(
+ data->viewport.width),
+- data->ratios->horz));
++ data->ratios.horz));
+
+ filter_type = FILTER_TYPE_RGB_Y_HORIZONTAL;
+ } else {
+ filter_params.taps = data->taps.v_taps;
+- filter_params.sharpness = data->v_sharpness;
++ filter_params.sharpness = 0; /* TODO */
+ filter_params.flags.bits.HORIZONTAL = 0;
+
+ src_size = data->viewport.height;
+@@ -445,7 +445,7 @@ static bool program_multi_taps_filter(
+ dal_fixed31_32_div(
+ dal_fixed31_32_from_int(
+ data->viewport.height),
+- data->ratios->vert));
++ data->ratios.vert));
+
+ filter_type = FILTER_TYPE_RGB_Y_VERTICAL;
+ }
+@@ -475,21 +475,6 @@ static bool program_multi_taps_filter(
+ filter_data,
+ filter_data_size);
+
+- /* 4. Program the alpha if necessary */
+- if (data->flags.bits.SHOULD_PROGRAM_ALPHA) {
+- if (horizontal)
+- filter_type = FILTER_TYPE_ALPHA_HORIZONTAL;
+- else
+- filter_type = FILTER_TYPE_ALPHA_VERTICAL;
+-
+- program_filter(
+- xfm80,
+- filter_type,
+- &filter_params,
+- filter_data,
+- filter_data_size);
+- }
+-
+ return true;
+ }
+
+@@ -539,18 +524,16 @@ static void calculate_inits(
+ {
+ struct fixed31_32 h_init;
+ struct fixed31_32 v_init;
+- struct fixed31_32 v_init_bot;
+
+- inits->bottom_enable = 0;
+ inits->h_int_scale_ratio =
+- dal_fixed31_32_u2d19(data->ratios->horz) << 5;
++ dal_fixed31_32_u2d19(data->ratios.horz) << 5;
+ inits->v_int_scale_ratio =
+- dal_fixed31_32_u2d19(data->ratios->vert) << 5;
++ dal_fixed31_32_u2d19(data->ratios.vert) << 5;
+
+ h_init =
+ dal_fixed31_32_div_int(
+ dal_fixed31_32_add(
+- data->ratios->horz,
++ data->ratios.horz,
+ dal_fixed31_32_from_int(data->taps.h_taps + 1)),
+ 2);
+ inits->h_init.integer = dal_fixed31_32_floor(h_init);
+@@ -559,28 +542,11 @@ static void calculate_inits(
+ v_init =
+ dal_fixed31_32_div_int(
+ dal_fixed31_32_add(
+- data->ratios->vert,
++ data->ratios.vert,
+ dal_fixed31_32_from_int(data->taps.v_taps + 1)),
+ 2);
+ inits->v_init.integer = dal_fixed31_32_floor(v_init);
+ inits->v_init.fraction = dal_fixed31_32_u0d19(v_init) << 5;
+-
+- if (data->flags.bits.INTERLACED) {
+- v_init_bot =
+- dal_fixed31_32_add(
+- dal_fixed31_32_div_int(
+- dal_fixed31_32_add(
+- data->ratios->vert,
+- dal_fixed31_32_from_int(
+- data->taps.v_taps + 1)),
+- 2),
+- data->ratios->vert);
+- inits->v_init_bottom.integer = dal_fixed31_32_floor(v_init_bot);
+- inits->v_init_bottom.fraction =
+- dal_fixed31_32_u0d19(v_init_bot) << 5;
+-
+- inits->bottom_enable = 1;
+- }
+ }
+
+ static void program_scl_ratios_inits(
+@@ -634,22 +600,6 @@ static void program_scl_ratios_inits(
+ SCL_V_INIT_FRAC);
+ dm_write_reg(xfm80->base.ctx, addr, value);
+
+- if (inits->bottom_enable) {
+- addr = SCL_REG(mmSCL_VERT_FILTER_INIT_BOT);
+- value = 0;
+- set_reg_field_value(
+- value,
+- inits->v_init_bottom.integer,
+- SCL_VERT_FILTER_INIT_BOT,
+- SCL_V_INIT_INT_BOT);
+- set_reg_field_value(
+- value,
+- inits->v_init_bottom.fraction,
+- SCL_VERT_FILTER_INIT_BOT,
+- SCL_V_INIT_FRAC_BOT);
+- dm_write_reg(xfm80->base.ctx, addr, value);
+- }
+-
+ addr = SCL_REG(mmSCL_AUTOMATIC_MODE_CONTROL);
+ value = 0;
+ set_reg_field_value(
+@@ -665,38 +615,6 @@ static void program_scl_ratios_inits(
+ dm_write_reg(xfm80->base.ctx, addr, value);
+ }
+
+-static void get_viewport(
+- struct dce80_transform *xfm80,
+- struct rect *current_view_port)
+-{
+- uint32_t value_start;
+- uint32_t value_size;
+-
+- if (current_view_port == NULL)
+- return;
+-
+- value_start = dm_read_reg(xfm80->base.ctx, SCL_REG(mmVIEWPORT_START));
+- value_size = dm_read_reg(xfm80->base.ctx, SCL_REG(mmVIEWPORT_SIZE));
+-
+- current_view_port->x = get_reg_field_value(
+- value_start,
+- VIEWPORT_START,
+- VIEWPORT_X_START);
+- current_view_port->y = get_reg_field_value(
+- value_start,
+- VIEWPORT_START,
+- VIEWPORT_Y_START);
+- current_view_port->height = get_reg_field_value(
+- value_size,
+- VIEWPORT_SIZE,
+- VIEWPORT_HEIGHT);
+- current_view_port->width = get_reg_field_value(
+- value_size,
+- VIEWPORT_SIZE,
+- VIEWPORT_WIDTH);
+-}
+-
+-
+ bool dce80_transform_set_scaler(
+ struct transform *xfm,
+ const struct scaler_data *data)
+@@ -761,6 +679,9 @@ bool dce80_transform_set_scaler(
+ program_two_taps_filter(xfm80, true, false);
+ }
+
++ /* 7. Program the viewport */
++ program_viewport(xfm80, &data->viewport);
++
+ return true;
+ }
+
+@@ -776,35 +697,6 @@ void dce80_transform_set_scaler_bypass(struct transform *xfm)
+ dm_write_reg(xfm->ctx, SCL_REG(mmSCL_MODE), sclv_mode);
+ }
+
+-bool dce80_transform_update_viewport(
+- struct transform *xfm,
+- const struct rect *view_port,
+- bool is_fbc_attached)
+-{
+- struct dce80_transform *xfm80 = TO_DCE80_TRANSFORM(xfm);
+- bool program_req = false;
+- struct rect current_view_port;
+-
+- if (view_port == NULL)
+- return program_req;
+-
+- get_viewport(xfm80, &current_view_port);
+-
+- if (current_view_port.x != view_port->x ||
+- current_view_port.y != view_port->y ||
+- current_view_port.height != view_port->height ||
+- current_view_port.width != view_port->width)
+- program_req = true;
+-
+- if (program_req) {
+- /*underlay viewport is programmed with scaler
+- *program_viewport function pointer is not exposed*/
+- program_viewport(xfm80, view_port);
+- }
+-
+- return program_req;
+-}
+-
+ void dce80_transform_set_scaler_filter(
+ struct transform *xfm,
+ struct scaler_filter *filter)
+diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_status.h b/drivers/gpu/drm/amd/dal/dc/inc/core_status.h
+index b395ae5..f6621f6 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/core_status.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/core_status.h
+@@ -37,6 +37,7 @@ enum dc_status {
+ DC_FAIL_ATTACH_SURFACES,
+ DC_NO_DP_LINK_BANDWIDTH,
+ DC_EXCEED_DONGLE_MAX_CLK,
++ DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED,
+ DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */
+
+ DC_ERROR_UNEXPECTED = -1
+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 18bd2da..d638054 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
+@@ -29,6 +29,7 @@
+ #include "dc.h"
+ #include "bandwidth_calcs.h"
+ #include "ddc_service_types.h"
++#include "scaler_types.h"
+
+ struct core_stream;
+ /********* core_target *************/
+@@ -288,11 +289,7 @@ struct pipe_ctx {
+ 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 scaler_data scl_data;
+
+ struct stream_encoder *stream_enc;
+ struct display_clock *dis_clk;
+@@ -319,6 +316,7 @@ struct pipe_ctx {
+ uint8_t pipe_idx;
+
+ struct flags {
++ bool blanked;
+ bool unchanged;
+ bool timing_changed;
+ } flags;
+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 8b0afe1..014e83f 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
+@@ -44,14 +44,13 @@ struct hw_sequencer_funcs {
+ void (*reset_hw_ctx)(struct dc *dc, struct validate_context *context);
+
+ void (*set_plane_config)(
+- const struct dc *dc,
+- struct core_surface *surface,
+- struct pipe_ctx *pipe_ctx);
++ const struct dc *dc,
++ struct pipe_ctx *pipe_ctx,
++ struct resource_context *res_ctx);
+
+ void (*update_plane_addrs)(
+ struct dc *dc,
+- struct resource_context *res_ctx,
+- const struct core_surface *surface);
++ struct resource_context *res_ctx);
+
+ bool (*set_gamma_correction)(
+ struct input_pixel_processor *ipp,
+diff --git a/drivers/gpu/drm/amd/dal/dc/inc/resource.h b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
+index a7b0032..c2d6011 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/resource.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
+@@ -31,6 +31,7 @@
+
+ /* TODO unhardcode, 4 for CZ*/
+ #define MEMORY_TYPE_MULTIPLIER 4
++#define DCE110_UNDERLAY_IDX 3
+
+ bool dc_construct_resource_pool(struct adapter_service *adapter_serv,
+ struct dc *dc,
+@@ -79,4 +80,6 @@ enum dc_status map_resources(
+ const struct dc *dc,
+ struct validate_context *context);
+
++void destruct_val_ctx(struct validate_context *context);
++
+ #endif /* DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_ */
+diff --git a/drivers/gpu/drm/amd/dal/dc/inc/transform.h b/drivers/gpu/drm/amd/dal/dc/inc/transform.h
+index 1e5467c..efefedb 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/transform.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/transform.h
+@@ -133,11 +133,6 @@ struct transform_funcs {
+ void (*transform_set_scaler_bypass)(
+ struct transform *xfm);
+
+- bool (*transform_update_viewport)(
+- struct transform *xfm,
+- const struct rect *view_port,
+- bool is_fbc_attached);
+-
+ void (*transform_set_scaler_filter)(
+ struct transform *xfm,
+ struct scaler_filter *filter);
+diff --git a/drivers/gpu/drm/amd/dal/include/scaler_types.h b/drivers/gpu/drm/amd/dal/include/scaler_types.h
+index db52dbc..3947776 100644
+--- a/drivers/gpu/drm/amd/dal/include/scaler_types.h
++++ b/drivers/gpu/drm/amd/dal/include/scaler_types.h
+@@ -26,15 +26,8 @@
+ #ifndef __DAL_SCALER_TYPES_H__
+ #define __DAL_SCALER_TYPES_H__
+
+-#include "signal_types.h"
+-#include "fixed31_32.h"
+ #include "dc_types.h"
+
+-enum pixel_type {
+- PIXEL_TYPE_30BPP = 1,
+- PIXEL_TYPE_20BPP
+-};
+-
+ /*overscan or window*/
+ struct overscan_info {
+ uint32_t left;
+@@ -43,154 +36,42 @@ struct overscan_info {
+ uint32_t bottom;
+ };
+
+-struct mp_scaling_data {
+- struct rect viewport;
+- struct view dst_res;
++struct scaler_data {
+ struct overscan_info overscan;
+ struct scaling_taps taps;
++ struct rect viewport;
+ struct scaling_ratios ratios;
+-};
+
+-struct scaler_validation_params {
+- uint32_t INTERLACED:1;
+- uint32_t CHROMA_SUB_SAMPLING:1;
+-
+- uint32_t line_buffer_size;
+- uint32_t display_clock; /* in KHz */
+- uint32_t actual_pixel_clock; /* in KHz */
+- struct view source_view;
+- struct view dest_view;
+- enum signal_type signal_type;
+-
+- struct scaling_taps taps_requested;
+- enum pixel_format pixel_format;
+- enum dc_rotation_angle rotation;
++ enum pixel_format format;
+ };
+
+-struct adjustment_factor {
+- int32_t adjust; /* Actual adjustment value * lDivider */
+- uint32_t divider;
+-};
+-
+-struct sharpness_adjustment {
+- int32_t sharpness;
+- bool enable_sharpening;
+-};
+-
+-enum scaling_options {
+- SCALING_BYPASS = 0,
+- SCALING_ENABLE
+-};
+-
+-/* same as Hw register */
+-enum filter_type {
+- FILTER_TYPE_V_LOW_PASS = 0x0,
+- FILTER_TYPE_V_HIGH_PASS = 0x1,
+- FILTER_TYPE_H_LUMA = 0x2,
+- FILTER_TYPE_H_CHROMA = 0x3
+-};
+-
+-/* Validation Result enumeration */
+-enum scaler_validation_code {
+- SCALER_VALIDATION_OK = 0,
+- SCALER_VALIDATION_INVALID_INPUT_PARAMETERS,
+- SCALER_VALIDATION_SCALING_RATIO_NOT_SUPPORTED,
+- SCALER_VALIDATION_SOURCE_VIEW_WIDTH_EXCEEDING_LIMIT,
+- SCALER_VALIDATION_DISPLAY_CLOCK_BELOW_PIXEL_CLOCK,
+- SCALER_VALIDATION_FAILURE_PREDEFINED_TAPS_NUMBER
+-};
+-
+-
+-#define FILTER_TYPE_MASK 0x0000000FL
+-#define TWO_TAPS 2
+-
+ struct init_int_and_frac {
+ uint32_t integer;
+ uint32_t fraction;
+ };
+
+ struct scl_ratios_inits {
+- uint32_t bottom_enable;
+ uint32_t h_int_scale_ratio;
+ uint32_t v_int_scale_ratio;
+ struct init_int_and_frac h_init;
+ struct init_int_and_frac v_init;
+- struct init_int_and_frac v_init_bottom;
+-};
+-
+-union scaler_flags {
+- uint32_t raw;
+- struct {
+- uint32_t INTERLACED:1;
+- uint32_t DOUBLE_SCAN_MODE:1;
+- /* this one is legacy flag only used in DCE80 */
+- uint32_t RGB_COLOR_SPACE:1;
+- uint32_t PIPE_LOCK_REQ:1;
+- /* 4 */
+- uint32_t WIDE_DISPLAY:1;
+- uint32_t OTHER_PIPE:1;
+- uint32_t SHOULD_PROGRAM_VIEWPORT:1;
+- uint32_t SHOULD_UNLOCK:1;
+- /* 8 */
+- uint32_t SHOULD_PROGRAM_ALPHA:1;
+- uint32_t SHOW_COLOURED_BORDER:1;
+-
+- uint32_t RESERVED:22;
+- } bits;
+-};
+-
+-struct scaler_data {
+- struct view src_res;
+- struct view dst_res;
+- struct overscan_info overscan;
+- struct scaling_taps taps;
+- struct adjustment_factor scale_ratio_hp_factor;
+- struct adjustment_factor scale_ratio_lp_factor;
+- enum pixel_type pixel_type; /*legacy*/
+- struct sharpness_adjustment sharp_gain;
+-
+- union scaler_flags flags;
+- int32_t h_sharpness;
+- int32_t v_sharpness;
+-
+- struct view src_res_wide_display;
+- struct view dst_res_wide_display;
+-
+- /* it is here because of the HW bug in NI (UBTS #269539)
+- causes glitches in this VBI signal. It shouldn't change after
+- initialization, kind of a const */
+- const struct hw_crtc_timing *hw_crtc_timing;
+-
+- struct rect viewport;
+-
+- enum pixel_format dal_pixel_format;/*plane concept*/
+- /*stereoformat TODO*/
+- /*hwtotation TODO*/
+-
+- const struct scaling_ratios *ratios;
+-};
+-
+-enum bypass_type {
+- /* 00 - 00 - Manual Centering, Manual Replication */
+- BYPASS_TYPE_MANUAL = 0,
+- /* 01 - 01 - Auto-Centering, No Replication */
+- BYPASS_TYPE_AUTO_CENTER = 1,
+- /* 02 - 10 - Auto-Centering, Auto-Replication */
+- BYPASS_TYPE_AUTO_REPLICATION = 3
+ };
+
+-struct replication_factor {
+- uint32_t h_manual;
+- uint32_t v_manual;
++/* same as Hw register */
++enum filter_type {
++ FILTER_TYPE_V_LOW_PASS = 0x0,
++ FILTER_TYPE_V_HIGH_PASS = 0x1,
++ FILTER_TYPE_H_LUMA = 0x2,
++ FILTER_TYPE_H_CHROMA = 0x3
+ };
+
+ enum ram_filter_type {
+- FILTER_TYPE_RGB_Y_VERTICAL = 0, /* 0 - RGB/Y Vertical filter */
+- FILTER_TYPE_CBCR_VERTICAL = 1, /* 1 - CbCr Vertical filter */
+- FILTER_TYPE_RGB_Y_HORIZONTAL = 2, /* 1 - RGB/Y Horizontal filter */
+- FILTER_TYPE_CBCR_HORIZONTAL = 3, /* 3 - CbCr Horizontal filter */
+- FILTER_TYPE_ALPHA_VERTICAL = 4, /* 4 - Alpha Vertical filter. */
+- FILTER_TYPE_ALPHA_HORIZONTAL = 5, /* 5 - Alpha Horizontal filter. */
++ FILTER_TYPE_RGB_Y_VERTICAL = 0, /* 0 - RGB/Y Vertical filter */
++ FILTER_TYPE_CBCR_VERTICAL = 1, /* 1 - CbCr Vertical filter */
++ FILTER_TYPE_RGB_Y_HORIZONTAL = 2, /* 1 - RGB/Y Horizontal filter */
++ FILTER_TYPE_CBCR_HORIZONTAL = 3, /* 3 - CbCr Horizontal filter */
++ FILTER_TYPE_ALPHA_VERTICAL = 4, /* 4 - Alpha Vertical filter. */
++ FILTER_TYPE_ALPHA_HORIZONTAL = 5, /* 5 - Alpha Horizontal filter. */
+ };
+
+ #endif
+--
+2.7.4
+