drm/amd/display: break up plane disable and disconnect in set mode
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / core / dc.c
index 27e31bd..7921880 100644 (file)
@@ -35,7 +35,7 @@
 #include "clock_source.h"
 #include "dc_bios_types.h"
 
-#include "bandwidth_calcs.h"
+#include "dce_calcs.h"
 #include "bios_parser_interface.h"
 #include "include/irq_service_interface.h"
 #include "transform.h"
@@ -94,9 +94,10 @@ static bool create_links(
 
        for (i = 0; i < connectors_num; i++) {
                struct link_init_data link_init_params = {0};
-               struct core_link *link;
+               struct dc_link *link;
 
                link_init_params.ctx = dc->ctx;
+               /* next BIOS object table connector */
                link_init_params.connector_index = i;
                link_init_params.link_index = dc->link_count;
                link_init_params.dc = dc;
@@ -106,13 +107,11 @@ static bool create_links(
                        dc->links[dc->link_count] = link;
                        link->dc = dc;
                        ++dc->link_count;
-               } else {
-                       dm_error("DC: failed to create link!\n");
                }
        }
 
        for (i = 0; i < num_virtual_links; i++) {
-               struct core_link *link = dm_alloc(sizeof(*link));
+               struct dc_link *link = dm_alloc(sizeof(*link));
                struct encoder_init_data enc_init = {0};
 
                if (link == NULL) {
@@ -122,7 +121,7 @@ static bool create_links(
 
                link->ctx = dc->ctx;
                link->dc = dc;
-               link->public.connector_signal = SIGNAL_TYPE_VIRTUAL;
+               link->connector_signal = SIGNAL_TYPE_VIRTUAL;
                link->link_id.type = OBJECT_TYPE_CONNECTOR;
                link->link_id.id = CONNECTOR_ID_VIRTUAL;
                link->link_id.enum_id = ENUM_ID_1;
@@ -138,7 +137,7 @@ static bool create_links(
                enc_init.encoder.enum_id = ENUM_ID_1;
                virtual_link_encoder_construct(link->link_enc, &enc_init);
 
-               link->public.link_index = dc->link_count;
+               link->link_index = dc->link_count;
                dc->links[dc->link_count] = link;
                dc->link_count++;
        }
@@ -175,108 +174,100 @@ static bool stream_adjust_vmin_vmax(struct dc *dc,
        return ret;
 }
 
-
-static bool set_gamut_remap(struct dc *dc,
-                       const struct dc_stream **stream, int num_streams)
+static bool stream_get_crtc_position(struct dc *dc,
+               const struct dc_stream **stream, int num_streams,
+               unsigned int *v_pos, unsigned int *nom_v_pos)
 {
+       /* TODO: Support multiple streams */
        struct core_dc *core_dc = DC_TO_CORE(dc);
        struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]);
        int i = 0;
        bool ret = false;
-       struct pipe_ctx *pipes;
+       struct crtc_position position;
 
        for (i = 0; i < MAX_PIPES; i++) {
-               if (core_dc->current_context->res_ctx.pipe_ctx[i].stream
-                               == core_stream) {
+               struct pipe_ctx *pipe =
+                               &core_dc->current_context->res_ctx.pipe_ctx[i];
 
-                       pipes = &core_dc->current_context->res_ctx.pipe_ctx[i];
-                       core_dc->hwss.set_plane_config(core_dc, pipes,
-                                       &core_dc->current_context->res_ctx);
+               if (pipe->stream == core_stream && pipe->stream_enc) {
+                       core_dc->hwss.get_position(&pipe, 1, &position);
+
+                       *v_pos = position.vertical_count;
+                       *nom_v_pos = position.nominal_vcount;
                        ret = true;
                }
        }
-
        return ret;
 }
 
-/* This function is not expected to fail, proper implementation of
- * validation will prevent this from ever being called for unsupported
- * configurations.
- */
-static void stream_update_scaling(
-               const struct dc *dc,
-               const struct dc_stream *dc_stream,
-               const struct rect *src,
-               const struct rect *dst)
+static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream)
 {
-       struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
        struct core_dc *core_dc = DC_TO_CORE(dc);
-       struct validate_context *cur_ctx = core_dc->current_context;
-       int i;
-
-       if (src)
-               stream->public.src = *src;
-
-       if (dst)
-               stream->public.dst = *dst;
-
-       for (i = 0; i < cur_ctx->stream_count; i++) {
-               struct core_stream *cur_stream = cur_ctx->streams[i];
-
-               if (stream == cur_stream) {
-                       struct dc_stream_status *status = &cur_ctx->stream_status[i];
+       struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
+       int i = 0;
+       bool ret = false;
+       struct pipe_ctx *pipes;
 
-                       if (status->surface_count)
-                               if (!dc_commit_surfaces_to_stream(
-                                               &core_dc->public,
-                                               status->surfaces,
-                                               status->surface_count,
-                                               &cur_stream->public))
-                                       /* Need to debug validation */
-                                       BREAK_TO_DEBUGGER();
+       for (i = 0; i < MAX_PIPES; i++) {
+               if (core_dc->current_context->res_ctx.pipe_ctx[i].stream
+                               == core_stream) {
 
-                       return;
+                       pipes = &core_dc->current_context->res_ctx.pipe_ctx[i];
+                       core_dc->hwss.program_gamut_remap(pipes);
+                       ret = true;
                }
        }
-}
-
-static bool set_psr_enable(struct dc *dc, bool enable)
-{
-       struct core_dc *core_dc = DC_TO_CORE(dc);
-       int i;
-
-       for (i = 0; i < core_dc->link_count; i++)
-               dc_link_set_psr_enable(&core_dc->links[i]->public,
-                               enable);
 
-       return true;
+       return ret;
 }
 
-
-static bool setup_psr(struct dc *dc, const struct dc_stream *stream)
+static bool program_csc_matrix(struct dc *dc, const struct dc_stream *stream)
 {
        struct core_dc *core_dc = DC_TO_CORE(dc);
        struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
+       int i = 0;
+       bool ret = false;
        struct pipe_ctx *pipes;
-       int i;
-       unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index;
-
-       for (i = 0; i < core_dc->link_count; i++) {
-               if (core_stream->sink->link == core_dc->links[i])
-                       dc_link_setup_psr(&core_dc->links[i]->public,
-                                       stream);
-       }
 
        for (i = 0; i < MAX_PIPES; i++) {
                if (core_dc->current_context->res_ctx.pipe_ctx[i].stream
-                               == core_stream && i != underlay_idx) {
+                               == core_stream) {
+
                        pipes = &core_dc->current_context->res_ctx.pipe_ctx[i];
-                       core_dc->hwss.set_static_screen_control(&pipes, 1,
-                                       0x182);
+                       core_dc->hwss.program_csc_matrix(pipes,
+                       core_stream->public.output_color_space,
+                       core_stream->public.csc_color_matrix.matrix);
+                       ret = true;
                }
        }
 
-       return true;
+       return ret;
+}
+
+static void set_static_screen_events(struct dc *dc,
+               const struct dc_stream **stream,
+               int num_streams,
+               const struct dc_static_screen_events *events)
+{
+       struct core_dc *core_dc = DC_TO_CORE(dc);
+       int i = 0;
+       int j = 0;
+       struct pipe_ctx *pipes_affected[MAX_PIPES];
+       int num_pipes_affected = 0;
+
+       for (i = 0; i < num_streams; i++) {
+               struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[i]);
+
+               for (j = 0; j < MAX_PIPES; j++) {
+                       if (core_dc->current_context->res_ctx.pipe_ctx[j].stream
+                                       == core_stream) {
+                               pipes_affected[num_pipes_affected++] =
+                                               &core_dc->current_context->res_ctx.pipe_ctx[j];
+                       }
+               }
+       }
+
+       core_dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events);
 }
 
 static void set_drive_settings(struct dc *dc,
@@ -287,14 +278,14 @@ static void set_drive_settings(struct dc *dc,
        int i;
 
        for (i = 0; i < core_dc->link_count; i++) {
-               if (&core_dc->links[i]->public == link)
+               if (core_dc->links[i] == link)
                        break;
        }
 
        if (i >= core_dc->link_count)
                ASSERT_CRITICAL(false);
 
-       dc_link_dp_set_drive_settings(&core_dc->links[i]->public, lt_settings);
+       dc_link_dp_set_drive_settings(core_dc->links[i], lt_settings);
 }
 
 static void perform_link_training(struct dc *dc,
@@ -306,22 +297,17 @@ static void perform_link_training(struct dc *dc,
 
        for (i = 0; i < core_dc->link_count; i++)
                dc_link_dp_perform_link_training(
-                       &core_dc->links[i]->public,
+                       core_dc->links[i],
                        link_setting,
                        skip_video_pattern);
 }
 
 static void set_preferred_link_settings(struct dc *dc,
                struct dc_link_settings *link_setting,
-               const struct dc_link *link)
+               struct dc_link *link)
 {
-       struct core_link *core_link = DC_LINK_TO_CORE(link);
-
-       core_link->public.verified_link_cap.lane_count =
-                               link_setting->lane_count;
-       core_link->public.verified_link_cap.link_rate =
-                               link_setting->link_rate;
-       dp_retrain_link_dp_test(core_link, link_setting, false);
+       link->preferred_link_setting = *link_setting;
+       dp_retrain_link_dp_test(link, link_setting, false);
 }
 
 static void enable_hpd(const struct dc_link *link)
@@ -336,7 +322,7 @@ static void disable_hpd(const struct dc_link *link)
 
 
 static void set_test_pattern(
-               const struct dc_link *link,
+               struct dc_link *link,
                enum dp_test_pattern test_pattern,
                const struct link_training_settings *p_link_settings,
                const unsigned char *p_custom_pattern,
@@ -351,22 +337,64 @@ static void set_test_pattern(
                        cust_pattern_size);
 }
 
+void set_dither_option(const struct dc_stream *dc_stream,
+               enum dc_dither_option option)
+{
+       struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
+       struct bit_depth_reduction_params params;
+       struct dc_link *link = stream->status.link;
+       struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx;
+
+       memset(&params, 0, sizeof(params));
+       if (!stream)
+               return;
+       if (option > DITHER_OPTION_MAX)
+               return;
+       if (option == DITHER_OPTION_DEFAULT) {
+               switch (stream->public.timing.display_color_depth) {
+               case COLOR_DEPTH_666:
+                       stream->public.dither_option = DITHER_OPTION_SPATIAL6;
+                       break;
+               case COLOR_DEPTH_888:
+                       stream->public.dither_option = DITHER_OPTION_SPATIAL8;
+                       break;
+               case COLOR_DEPTH_101010:
+                       stream->public.dither_option = DITHER_OPTION_SPATIAL10;
+                       break;
+               default:
+                       option = DITHER_OPTION_DISABLE;
+               }
+       } else {
+               stream->public.dither_option = option;
+       }
+       resource_build_bit_depth_reduction_params(stream,
+                               &params);
+       stream->bit_depth_params = params;
+       pipes->opp->funcs->
+               opp_program_bit_depth_reduction(pipes->opp, &params);
+}
+
 static void allocate_dc_stream_funcs(struct core_dc *core_dc)
 {
-       core_dc->public.stream_funcs.stream_update_scaling = stream_update_scaling;
        if (core_dc->hwss.set_drr != NULL) {
                core_dc->public.stream_funcs.adjust_vmin_vmax =
                                stream_adjust_vmin_vmax;
        }
 
+       core_dc->public.stream_funcs.set_static_screen_events =
+                       set_static_screen_events;
+
+       core_dc->public.stream_funcs.get_crtc_position =
+                       stream_get_crtc_position;
+
        core_dc->public.stream_funcs.set_gamut_remap =
                        set_gamut_remap;
 
-       core_dc->public.stream_funcs.set_psr_enable =
-                       set_psr_enable;
+       core_dc->public.stream_funcs.program_csc_matrix =
+                       program_csc_matrix;
 
-       core_dc->public.stream_funcs.setup_psr =
-                       setup_psr;
+       core_dc->public.stream_funcs.set_dither_option =
+                       set_dither_option;
 
        core_dc->public.link_funcs.set_drive_settings =
                        set_drive_settings;
@@ -389,7 +417,8 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc)
 
 static void destruct(struct core_dc *dc)
 {
-       resource_validate_ctx_destruct(dc->current_context);
+       dc_release_validate_context(dc->current_context);
+       dc->current_context = NULL;
 
        destroy_links(dc);
 
@@ -407,13 +436,6 @@ static void destruct(struct core_dc *dc)
        if (dc->ctx->logger)
                dal_logger_destroy(&dc->ctx->logger);
 
-       dm_free(dc->current_context);
-       dc->current_context = NULL;
-       dm_free(dc->temp_flip_context);
-       dc->temp_flip_context = NULL;
-       dm_free(dc->scratch_val_ctx);
-       dc->scratch_val_ctx = NULL;
-
        dm_free(dc->ctx);
        dc->ctx = NULL;
 }
@@ -431,14 +453,14 @@ static bool construct(struct core_dc *dc,
        }
 
        dc->current_context = dm_alloc(sizeof(*dc->current_context));
-       dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context));
-       dc->scratch_val_ctx = dm_alloc(sizeof(*dc->scratch_val_ctx));
 
-       if (!dc->current_context || !dc->temp_flip_context) {
+       if (!dc->current_context) {
                dm_error("%s: failed to create validate ctx\n", __func__);
                goto val_ctx_fail;
        }
 
+       dc->current_context->ref_count++;
+
        dc_ctx->cgs_device = init_params->cgs_device;
        dc_ctx->driver_context = init_params->driver;
        dc_ctx->dc = &dc->public;
@@ -467,6 +489,7 @@ static bool construct(struct core_dc *dc,
        else {
                /* Create BIOS parser */
                struct bp_init_data bp_init_data;
+
                bp_init_data.ctx = dc_ctx;
                bp_init_data.bios = init_params->asic_id.atombios_base_address;
 
@@ -479,7 +502,7 @@ static bool construct(struct core_dc *dc,
                }
 
                dc_ctx->created_bios = true;
-       }
+               }
 
        /* Create I2C AUX */
        dc_ctx->i2caux = dal_i2caux_create(dc_ctx);
@@ -625,7 +648,8 @@ static bool is_validation_required(
                        return true;
 
                for (j = 0; j < set[i].surface_count; j++) {
-                       struct dc_surface temp_surf = { 0 };
+                       struct dc_surface temp_surf;
+                       memset(&temp_surf, 0, sizeof(temp_surf));
 
                        temp_surf = *context->stream_status[i].surfaces[j];
                        temp_surf.clip_rect = set[i].surfaces[j]->clip_rect;
@@ -640,7 +664,7 @@ static bool is_validation_required(
        return false;
 }
 
-bool dc_validate_resources(
+struct validate_context *dc_get_validate_context(
                const struct dc *dc,
                const struct dc_validation_set set[],
                uint8_t set_count)
@@ -649,18 +673,52 @@ bool dc_validate_resources(
        enum dc_status result = DC_ERROR_UNEXPECTED;
        struct validate_context *context;
 
-       if (!is_validation_required(core_dc, set, set_count))
-               return true;
-
        context = dm_alloc(sizeof(struct validate_context));
-       if(context == NULL)
+       if (context == NULL)
                goto context_alloc_fail;
 
+       ++context->ref_count;
+
+       if (!is_validation_required(core_dc, set, set_count)) {
+               dc_resource_validate_ctx_copy_construct(core_dc->current_context, context);
+               return context;
+       }
+
        result = core_dc->res_pool->funcs->validate_with_context(
-                                               core_dc, set, set_count, context);
+                       core_dc, set, set_count, context, core_dc->current_context);
 
-       resource_validate_ctx_destruct(context);
-       dm_free(context);
+context_alloc_fail:
+       if (result != DC_OK) {
+               dm_logger_write(core_dc->ctx->logger, LOG_WARNING,
+                               "%s:resource validation failed, dc_status:%d\n",
+                               __func__,
+                               result);
+
+               dc_release_validate_context(context);
+               context = NULL;
+       }
+
+       return context;
+
+}
+
+bool dc_validate_resources(
+               const struct dc *dc,
+               const struct dc_validation_set set[],
+               uint8_t set_count)
+{
+       struct core_dc *core_dc = DC_TO_CORE(dc);
+       enum dc_status result = DC_ERROR_UNEXPECTED;
+       struct validate_context *context;
+
+       context = dm_alloc(sizeof(struct validate_context));
+       if (context == NULL)
+               goto context_alloc_fail;
+
+       ++context->ref_count;
+
+       result = core_dc->res_pool->funcs->validate_with_context(
+                               core_dc, set, set_count, context, NULL);
 
 context_alloc_fail:
        if (result != DC_OK) {
@@ -670,8 +728,10 @@ context_alloc_fail:
                                result);
        }
 
-       return (result == DC_OK);
+       dc_release_validate_context(context);
+       context = NULL;
 
+       return result == DC_OK;
 }
 
 bool dc_validate_guaranteed(
@@ -686,11 +746,12 @@ bool dc_validate_guaranteed(
        if (context == NULL)
                goto context_alloc_fail;
 
+       ++context->ref_count;
+
        result = core_dc->res_pool->funcs->validate_guaranteed(
                                        core_dc, stream, context);
 
-       resource_validate_ctx_destruct(context);
-       dm_free(context);
+       dc_release_validate_context(context);
 
 context_alloc_fail:
        if (result != DC_OK) {
@@ -709,7 +770,7 @@ static void program_timing_sync(
 {
        int i, j;
        int group_index = 0;
-       int pipe_count = ctx->res_ctx.pool->pipe_count;
+       int pipe_count = core_dc->res_pool->pipe_count;
        struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL };
 
        for (i = 0; i < pipe_count; i++) {
@@ -777,6 +838,23 @@ static void program_timing_sync(
        }
 }
 
+static bool context_changed(
+               struct core_dc *dc,
+               struct validate_context *context)
+{
+       uint8_t i;
+
+       if (context->stream_count != dc->current_context->stream_count)
+               return true;
+
+       for (i = 0; i < dc->current_context->stream_count; i++) {
+               if (&dc->current_context->streams[i]->public != &context->streams[i]->public)
+                       return true;
+       }
+
+       return false;
+}
+
 static bool streams_changed(
                struct core_dc *dc,
                const struct dc_stream *streams[],
@@ -795,83 +873,93 @@ static bool streams_changed(
        return false;
 }
 
-bool dc_commit_streams(
+bool dc_enable_stereo(
        struct dc *dc,
+       struct validate_context *context,
        const struct dc_stream *streams[],
        uint8_t stream_count)
 {
+       bool ret = true;
+       int i, j;
+       struct pipe_ctx *pipe;
        struct core_dc *core_dc = DC_TO_CORE(dc);
-       struct dc_bios *dcb = core_dc->ctx->dc_bios;
-       enum dc_status result = DC_ERROR_UNEXPECTED;
-       struct validate_context *context;
-       struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } };
-       int i, j, k;
-
-       if (false == streams_changed(core_dc, streams, stream_count))
-               return DC_OK;
 
-       dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n",
-                               __func__, stream_count);
-
-       for (i = 0; i < stream_count; i++) {
-               const struct dc_stream *stream = streams[i];
-               const struct dc_stream_status *status = dc_stream_get_status(stream);
-               int j;
+#ifdef ENABLE_FBC
+       struct compressor *fbc_compressor = core_dc->fbc_compressor;
+#endif
 
-               dc_stream_log(stream,
-                               core_dc->ctx->logger,
-                               LOG_DC);
+       for (i = 0; i < MAX_PIPES; i++) {
+               if (context != NULL)
+                       pipe = &context->res_ctx.pipe_ctx[i];
+               else
+                       pipe = &core_dc->current_context->res_ctx.pipe_ctx[i];
+               for (j = 0 ; pipe && j < stream_count; j++)  {
+                       if (streams[j] && streams[j] == &pipe->stream->public &&
+                               core_dc->hwss.setup_stereo)
+                               core_dc->hwss.setup_stereo(pipe, core_dc);
+               }
+       }
 
-               set[i].stream = stream;
+#ifdef ENABLE_FBC
+       if (fbc_compressor != NULL &&
+           fbc_compressor->funcs->is_fbc_enabled_in_hw(core_dc->fbc_compressor,
+                                                       &pipe->tg->inst))
+               fbc_compressor->funcs->disable_fbc(fbc_compressor);
 
-               if (status) {
-                       set[i].surface_count = status->surface_count;
-                       for (j = 0; j < status->surface_count; j++)
-                               set[i].surfaces[j] = status->surfaces[j];
-               }
+#endif
+       return ret;
+}
 
-       }
 
-       context = dm_alloc(sizeof(struct validate_context));
-       if (context == NULL)
-               goto context_alloc_fail;
+/*
+ * Applies given context to HW and copy it into current context.
+ * It's up to the user to release the src context afterwards.
+ */
+static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *context)
+{
+       struct core_dc *core_dc = DC_TO_CORE(dc);
+       struct dc_bios *dcb = core_dc->ctx->dc_bios;
+       enum dc_status result = DC_ERROR_UNEXPECTED;
+       struct pipe_ctx *pipe;
+       int i, j, k, l;
+       const struct dc_stream *dc_streams[MAX_STREAMS] = {0};
 
-       result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, stream_count, context);
-       if (result != DC_OK){
-               dm_logger_write(core_dc->ctx->logger, LOG_ERROR,
-                                       "%s: Context validation failed! dc_status:%d\n",
-                                       __func__,
-                                       result);
-               BREAK_TO_DEBUGGER();
-               resource_validate_ctx_destruct(context);
-               goto fail;
-       }
+       for (i = 0; i < context->stream_count; i++)
+               dc_streams[i] =  &context->streams[i]->public;
 
-       if (!dcb->funcs->is_accelerated_mode(dcb)) {
+       if (!dcb->funcs->is_accelerated_mode(dcb))
                core_dc->hwss.enable_accelerated_mode(core_dc);
-       }
 
-       if (result == DC_OK) {
-               result = core_dc->hwss.apply_ctx_to_hw(core_dc, context);
+       for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
+               pipe = &context->res_ctx.pipe_ctx[i];
+               core_dc->hwss.wait_for_mpcc_disconnect(core_dc, core_dc->res_pool, pipe);
        }
+       result = core_dc->hwss.apply_ctx_to_hw(core_dc, context);
 
        program_timing_sync(core_dc, context);
 
        for (i = 0; i < context->stream_count; i++) {
-               const struct core_sink *sink = context->streams[i]->sink;
+               const struct dc_sink *sink = context->streams[i]->sink;
 
                for (j = 0; j < context->stream_status[i].surface_count; j++) {
-                       const struct dc_surface *dc_surface =
+                       const struct dc_surface *surface =
                                        context->stream_status[i].surfaces[j];
 
-                       for (k = 0; k < context->res_ctx.pool->pipe_count; k++) {
-                               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[k];
+                       core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context);
 
-                               if (dc_surface != &pipe->surface->public
-                                               || !dc_surface->visible)
-                                       continue;
+                       /*
+                        * enable stereo
+                        * TODO rework dc_enable_stereo call to work with validation sets?
+                        */
+                       for (k = 0; k < MAX_PIPES; k++) {
+                               pipe = &context->res_ctx.pipe_ctx[k];
 
-                               pipe->tg->funcs->set_blank(pipe->tg, false);
+                               for (l = 0 ; pipe && l < context->stream_count; l++)  {
+                                       if (context->streams[l] &&
+                                           context->streams[l] == pipe->stream &&
+                                           core_dc->hwss.setup_stereo)
+                                               core_dc->hwss.setup_stereo(pipe, core_dc);
+                               }
                        }
                }
 
@@ -883,169 +971,130 @@ bool dc_commit_streams(
                                context->streams[i]->public.timing.pix_clk_khz);
        }
 
-       resource_validate_ctx_destruct(core_dc->current_context);
+       dc_enable_stereo(dc, context, dc_streams, context->stream_count);
 
-       if (core_dc->temp_flip_context != core_dc->current_context) {
-               dm_free(core_dc->temp_flip_context);
-               core_dc->temp_flip_context = core_dc->current_context;
-       }
-       core_dc->current_context = context;
-       memset(core_dc->temp_flip_context, 0, sizeof(*core_dc->temp_flip_context));
+       dc_release_validate_context(core_dc->current_context);
 
-       return (result == DC_OK);
+       core_dc->current_context = context;
 
-fail:
-       dm_free(context);
+       dc_retain_validate_context(core_dc->current_context);
 
-context_alloc_fail:
        return (result == DC_OK);
 }
 
-bool dc_pre_update_surfaces_to_stream(
-               struct dc *dc,
-               const struct dc_surface *const *new_surfaces,
-               uint8_t new_surface_count,
-               const struct dc_stream *dc_stream)
+bool dc_commit_context(struct dc *dc, struct validate_context *context)
 {
-       int i, j;
+       enum dc_status result = DC_ERROR_UNEXPECTED;
        struct core_dc *core_dc = DC_TO_CORE(dc);
-       struct dc_stream_status *stream_status = NULL;
-       struct validate_context *context;
-       bool ret = true;
+       int i;
 
-       pre_surface_trace(dc, new_surfaces, new_surface_count);
+       if (false == context_changed(core_dc, context))
+               return DC_OK;
 
-       if (core_dc->current_context->stream_count == 0)
-               return false;
+       dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n",
+                               __func__, context->stream_count);
 
-       /* Cannot commit surface to a stream that is not commited */
-       for (i = 0; i < core_dc->current_context->stream_count; i++)
-               if (dc_stream == &core_dc->current_context->streams[i]->public)
-                       break;
+       for (i = 0; i < context->stream_count; i++) {
+               const struct dc_stream *stream = &context->streams[i]->public;
 
-       if (i == core_dc->current_context->stream_count)
-               return false;
+               dc_stream_log(stream,
+                               core_dc->ctx->logger,
+                               LOG_DC);
+       }
 
-       stream_status = &core_dc->current_context->stream_status[i];
+       result = dc_commit_context_no_check(dc, context);
 
-       if (new_surface_count == stream_status->surface_count) {
-               bool skip_pre = true;
+       return (result == DC_OK);
+}
 
-               for (i = 0; i < stream_status->surface_count; i++) {
-                       struct dc_surface temp_surf = { 0 };
 
-                       temp_surf = *stream_status->surfaces[i];
-                       temp_surf.clip_rect = new_surfaces[i]->clip_rect;
-                       temp_surf.dst_rect.x = new_surfaces[i]->dst_rect.x;
-                       temp_surf.dst_rect.y = new_surfaces[i]->dst_rect.y;
+bool dc_commit_streams(
+       struct dc *dc,
+       const struct dc_stream *streams[],
+       uint8_t stream_count)
+{
+       struct core_dc *core_dc = DC_TO_CORE(dc);
+       enum dc_status result = DC_ERROR_UNEXPECTED;
+       struct validate_context *context;
+       struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } };
+       int i;
 
-                       if (memcmp(&temp_surf, new_surfaces[i], sizeof(temp_surf)) != 0) {
-                               skip_pre = false;
-                               break;
-                       }
-               }
+       if (false == streams_changed(core_dc, streams, stream_count))
+               return DC_OK;
 
-               if (skip_pre)
-                       return true;
-       }
+       dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n",
+                               __func__, stream_count);
 
-       context = dm_alloc(sizeof(struct validate_context));
+       for (i = 0; i < stream_count; i++) {
+               const struct dc_stream *stream = streams[i];
+               const struct dc_stream_status *status = dc_stream_get_status(stream);
+               int j;
 
-       if (!context) {
-               dm_error("%s: failed to create validate ctx\n", __func__);
-               ret = false;
-               goto val_ctx_fail;
-       }
+               dc_stream_log(stream,
+                               core_dc->ctx->logger,
+                               LOG_DC);
 
-       resource_validate_ctx_copy_construct(core_dc->current_context, context);
+               set[i].stream = stream;
 
-       dm_logger_write(core_dc->ctx->logger, LOG_DC,
-                               "%s: commit %d surfaces to stream 0x%x\n",
-                               __func__,
-                               new_surface_count,
-                               dc_stream);
+               if (status) {
+                       set[i].surface_count = status->surface_count;
+                       for (j = 0; j < status->surface_count; j++)
+                               set[i].surfaces[j] = status->surfaces[j];
+               }
 
-       if (!resource_attach_surfaces_to_context(
-                       new_surfaces, new_surface_count, dc_stream, context)) {
-               BREAK_TO_DEBUGGER();
-               ret = false;
-               goto unexpected_fail;
        }
 
-       for (i = 0; i < new_surface_count; i++)
-               for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
-                       if (context->res_ctx.pipe_ctx[j].surface !=
-                                       DC_SURFACE_TO_CORE(new_surfaces[i]))
-                               continue;
+       context = dm_alloc(sizeof(struct validate_context));
+       if (context == NULL)
+               goto context_alloc_fail;
 
-                       resource_build_scaling_params(
-                               new_surfaces[i], &context->res_ctx.pipe_ctx[j]);
-               }
+       ++context->ref_count;
 
-       if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) {
+       result = core_dc->res_pool->funcs->validate_with_context(
+                       core_dc, set, stream_count, context, core_dc->current_context);
+       if (result != DC_OK){
+               dm_logger_write(core_dc->ctx->logger, LOG_ERROR,
+                                       "%s: Context validation failed! dc_status:%d\n",
+                                       __func__,
+                                       result);
                BREAK_TO_DEBUGGER();
-               ret = false;
-               goto unexpected_fail;
+               goto fail;
        }
 
-       core_dc->hwss.set_bandwidth(core_dc, context, false);
+       result = dc_commit_context_no_check(dc, context);
 
-       for (i = 0; i < new_surface_count; i++)
-               for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
-                       if (context->res_ctx.pipe_ctx[j].surface !=
-                                       DC_SURFACE_TO_CORE(new_surfaces[i]))
-                               continue;
-
-                       core_dc->hwss.prepare_pipe_for_context(
-                                       core_dc,
-                                       &context->res_ctx.pipe_ctx[j],
-                                       context);
-               }
-
-unexpected_fail:
-       resource_validate_ctx_destruct(context);
-       dm_free(context);
-val_ctx_fail:
+fail:
+       dc_release_validate_context(context);
 
-       return ret;
+context_alloc_fail:
+       return (result == DC_OK);
 }
 
 bool dc_post_update_surfaces_to_stream(struct dc *dc)
 {
        int i;
        struct core_dc *core_dc = DC_TO_CORE(dc);
-       struct validate_context *context = dm_alloc(sizeof(struct validate_context));
-
-       if (!context) {
-               dm_error("%s: failed to create validate ctx\n", __func__);
-               return false;
-       }
-       resource_validate_ctx_copy_construct(core_dc->current_context, context);
+       struct validate_context *context = core_dc->current_context;
 
        post_surface_trace(dc);
 
-       for (i = 0; i < context->res_ctx.pool->pipe_count; i++)
-               if (context->res_ctx.pipe_ctx[i].stream == NULL) {
-                       context->res_ctx.pipe_ctx[i].pipe_idx = i;
-                       core_dc->hwss.power_down_front_end(
-                                       core_dc, &context->res_ctx.pipe_ctx[i]);
-               }
-       if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) {
-               BREAK_TO_DEBUGGER();
-               return false;
-       }
+       for (i = 0; i < core_dc->res_pool->pipe_count; i++)
+               if (context->res_ctx.pipe_ctx[i].stream == NULL
+                               || context->res_ctx.pipe_ctx[i].surface == NULL)
+                       core_dc->hwss.power_down_front_end(core_dc, i);
 
+       /* 3rd param should be true, temp w/a for RV*/
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+       core_dc->hwss.set_bandwidth(core_dc, context, core_dc->ctx->dce_version != DCN_VERSION_1_0);
+#else
        core_dc->hwss.set_bandwidth(core_dc, context, true);
-
-       resource_validate_ctx_destruct(core_dc->current_context);
-       core_dc->current_context = context;
-
+#endif
        return true;
 }
 
 bool dc_commit_surfaces_to_stream(
                struct dc *dc,
-               const struct dc_surface **new_surfaces,
+               struct dc_surface **new_surfaces,
                uint8_t new_surface_count,
                const struct dc_stream *dc_stream)
 {
@@ -1054,20 +1103,28 @@ bool dc_commit_surfaces_to_stream(
        struct dc_plane_info plane_info[MAX_SURFACES];
        struct dc_scaling_info scaling_info[MAX_SURFACES];
        int i;
+       struct dc_stream_update *stream_update =
+                       dm_alloc(sizeof(struct dc_stream_update));
 
-       if (!dc_pre_update_surfaces_to_stream(
-                       dc, new_surfaces, new_surface_count, dc_stream))
+       if (!stream_update) {
+               BREAK_TO_DEBUGGER();
                return false;
+       }
 
        memset(updates, 0, sizeof(updates));
        memset(flip_addr, 0, sizeof(flip_addr));
        memset(plane_info, 0, sizeof(plane_info));
        memset(scaling_info, 0, sizeof(scaling_info));
 
+       stream_update->src = dc_stream->src;
+       stream_update->dst = dc_stream->dst;
+       stream_update->out_transfer_func = dc_stream->out_transfer_func;
+
        for (i = 0; i < new_surface_count; i++) {
                updates[i].surface = new_surfaces[i];
                updates[i].gamma =
                        (struct dc_gamma *)new_surfaces[i]->gamma_correction;
+               updates[i].in_transfer_func = new_surfaces[i]->in_transfer_func;
                flip_addr[i].address = new_surfaces[i]->address;
                flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate;
                plane_info[i].color_space = new_surfaces[i]->color_space;
@@ -1078,6 +1135,7 @@ bool dc_commit_surfaces_to_stream(
                plane_info[i].stereo_format = new_surfaces[i]->stereo_format;
                plane_info[i].tiling_info = new_surfaces[i]->tiling_info;
                plane_info[i].visible = new_surfaces[i]->visible;
+               plane_info[i].per_pixel_alpha = new_surfaces[i]->per_pixel_alpha;
                plane_info[i].dcc = new_surfaces[i]->dcc;
                scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality;
                scaling_info[i].src_rect = new_surfaces[i]->src_rect;
@@ -1088,9 +1146,34 @@ bool dc_commit_surfaces_to_stream(
                updates[i].plane_info = &plane_info[i];
                updates[i].scaling_info = &scaling_info[i];
        }
-       dc_update_surfaces_for_stream(dc, updates, new_surface_count, dc_stream);
 
-       return dc_post_update_surfaces_to_stream(dc);
+       dc_update_surfaces_and_stream(
+                       dc,
+                       updates,
+                       new_surface_count,
+                       dc_stream, stream_update);
+
+       dc_post_update_surfaces_to_stream(dc);
+
+       dm_free(stream_update);
+       return true;
+}
+
+void dc_retain_validate_context(struct validate_context *context)
+{
+       ASSERT(context->ref_count > 0);
+       ++context->ref_count;
+}
+
+void dc_release_validate_context(struct validate_context *context)
+{
+       ASSERT(context->ref_count > 0);
+       --context->ref_count;
+
+       if (context->ref_count == 0) {
+               dc_resource_validate_ctx_destruct(context);
+               dm_free(context);
+       }
 }
 
 static bool is_surface_in_context(
@@ -1099,10 +1182,10 @@ static bool is_surface_in_context(
 {
        int j;
 
-       for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
+       for (j = 0; j < MAX_PIPES; j++) {
                const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
 
-               if (surface == &pipe_ctx->surface->public) {
+               if (surface == pipe_ctx->surface) {
                        return true;
                }
        }
@@ -1113,8 +1196,13 @@ static bool is_surface_in_context(
 static unsigned int pixel_format_to_bpp(enum surface_pixel_format format)
 {
        switch (format) {
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+               return 12;
        case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
        case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
                return 16;
        case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
        case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
@@ -1132,13 +1220,17 @@ static unsigned int pixel_format_to_bpp(enum surface_pixel_format format)
 }
 
 static enum surface_update_type get_plane_info_update_type(
-               const struct dc_surface_update *u)
+               const struct dc_surface_update *u,
+               int surface_index)
 {
-       struct dc_plane_info temp_plane_info = { { { { 0 } } } };
+       struct dc_plane_info temp_plane_info;
+       memset(&temp_plane_info, 0, sizeof(temp_plane_info));
 
        if (!u->plane_info)
                return UPDATE_TYPE_FAST;
 
+       temp_plane_info = *u->plane_info;
+
        /* Copy all parameters that will cause a full update
         * from current surface, the rest of the parameters
         * from provided plane configuration.
@@ -1154,10 +1246,11 @@ static enum surface_update_type get_plane_info_update_type(
        temp_plane_info.rotation = u->surface->rotation;
        temp_plane_info.stereo_format = u->surface->stereo_format;
        temp_plane_info.tiling_info = u->surface->tiling_info;
-       temp_plane_info.visible = u->surface->visible;
 
-       /* Special Validation parameters */
-       temp_plane_info.format = u->plane_info->format;
+       if (surface_index == 0)
+               temp_plane_info.visible = u->plane_info->visible;
+       else
+               temp_plane_info.visible = u->surface->visible;
 
        if (memcmp(u->plane_info, &temp_plane_info,
                        sizeof(struct dc_plane_info)) != 0)
@@ -1174,52 +1267,32 @@ static enum surface_update_type get_plane_info_update_type(
 static enum surface_update_type  get_scaling_info_update_type(
                const struct dc_surface_update *u)
 {
-       struct dc_scaling_info temp_scaling_info = { { 0 } };
-
        if (!u->scaling_info)
                return UPDATE_TYPE_FAST;
 
-       /* Copy all parameters that will cause a full update
-        * from current surface, the rest of the parameters
-        * from provided plane configuration.
-        * Perform memory compare and special validation
-        * for those that can cause fast/medium updates
-        */
-
-       /* Full Update Parameters */
-       temp_scaling_info.dst_rect = u->surface->dst_rect;
-       temp_scaling_info.src_rect = u->surface->src_rect;
-       temp_scaling_info.scaling_quality = u->surface->scaling_quality;
-
-       /* Special validation required */
-       temp_scaling_info.clip_rect = u->scaling_info->clip_rect;
-
-       if (memcmp(u->scaling_info, &temp_scaling_info,
-                       sizeof(struct dc_scaling_info)) != 0)
+       if (u->scaling_info->src_rect.width != u->surface->src_rect.width
+                       || u->scaling_info->src_rect.height != u->surface->src_rect.height
+                       || u->scaling_info->clip_rect.width != u->surface->clip_rect.width
+                       || u->scaling_info->clip_rect.height != u->surface->clip_rect.height
+                       || u->scaling_info->dst_rect.width != u->surface->dst_rect.width
+                       || u->scaling_info->dst_rect.height != u->surface->dst_rect.height)
                return UPDATE_TYPE_FULL;
 
-       /* Check Clip rectangles if not equal
-        * difference is in offsets == > UPDATE_TYPE_FAST
-        * difference is in dimensions == > UPDATE_TYPE_FULL
-        */
-       if (memcmp(&u->scaling_info->clip_rect,
-                       &u->surface->clip_rect, sizeof(struct rect)) != 0) {
-               if ((u->scaling_info->clip_rect.height ==
-                       u->surface->clip_rect.height) &&
-                       (u->scaling_info->clip_rect.width ==
-                       u->surface->clip_rect.width)) {
-                       return UPDATE_TYPE_FAST;
-               } else {
-                       return UPDATE_TYPE_FULL;
-               }
-       }
+       if (u->scaling_info->src_rect.x != u->surface->src_rect.x
+                       || u->scaling_info->src_rect.y != u->surface->src_rect.y
+                       || u->scaling_info->clip_rect.x != u->surface->clip_rect.x
+                       || u->scaling_info->clip_rect.y != u->surface->clip_rect.y
+                       || u->scaling_info->dst_rect.x != u->surface->dst_rect.x
+                       || u->scaling_info->dst_rect.y != u->surface->dst_rect.y)
+               return UPDATE_TYPE_MED;
 
        return UPDATE_TYPE_FAST;
 }
 
 static enum surface_update_type det_surface_update(
                const struct core_dc *dc,
-               const struct dc_surface_update *u)
+               const struct dc_surface_update *u,
+               int surface_index)
 {
        const struct validate_context *context = dc->current_context;
        enum surface_update_type type = UPDATE_TYPE_FAST;
@@ -1228,7 +1301,7 @@ static enum surface_update_type det_surface_update(
        if (!is_surface_in_context(context, u->surface))
                return UPDATE_TYPE_FULL;
 
-       type = get_plane_info_update_type(u);
+       type = get_plane_info_update_type(u, surface_index);
        if (overall_type < type)
                overall_type = type;
 
@@ -1237,7 +1310,6 @@ static enum surface_update_type det_surface_update(
                overall_type = type;
 
        if (u->in_transfer_func ||
-               u->out_transfer_func ||
                u->hdr_static_metadata) {
                if (overall_type < UPDATE_TYPE_MED)
                        overall_type = UPDATE_TYPE_MED;
@@ -1250,18 +1322,22 @@ enum surface_update_type dc_check_update_surfaces_for_stream(
                struct dc *dc,
                struct dc_surface_update *updates,
                int surface_count,
+               struct dc_stream_update *stream_update,
                const struct dc_stream_status *stream_status)
 {
        struct core_dc *core_dc = DC_TO_CORE(dc);
        int i;
        enum surface_update_type overall_type = UPDATE_TYPE_FAST;
 
-       if (stream_status->surface_count != surface_count)
+       if (stream_status == NULL || stream_status->surface_count != surface_count)
+               return UPDATE_TYPE_FULL;
+
+       if (stream_update)
                return UPDATE_TYPE_FULL;
 
        for (i = 0 ; i < surface_count; i++) {
                enum surface_update_type type =
-                               det_surface_update(core_dc, &updates[i]);
+                               det_surface_update(core_dc, &updates[i], i);
 
                if (type == UPDATE_TYPE_FULL)
                        return type;
@@ -1275,167 +1351,221 @@ enum surface_update_type dc_check_update_surfaces_for_stream(
 
 enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL;
 
-void dc_update_surfaces_for_stream(struct dc *dc,
-               struct dc_surface_update *updates, int surface_count,
-               const struct dc_stream *dc_stream)
+void dc_update_surfaces_and_stream(struct dc *dc,
+               struct dc_surface_update *srf_updates, int surface_count,
+               const struct dc_stream *dc_stream,
+               struct dc_stream_update *stream_update)
 {
        struct core_dc *core_dc = DC_TO_CORE(dc);
        struct validate_context *context;
        int i, j;
-
        enum surface_update_type update_type;
        const struct dc_stream_status *stream_status;
+       struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
+       struct dc_context *dc_ctx = core_dc->ctx;
+
+       /* Currently this function do not result in any HW programming
+        * when called with 0 surface. But proceeding will cause
+        * SW state to be updated in validate_context. So we might as
+        * well make it not do anything at all until the hw programming
+        * is implemented properly to handle 0 surface case.
+        * TODO: fix hw programming then remove this early return
+        */
+       if (surface_count == 0)
+               return;
 
        stream_status = dc_stream_get_status(dc_stream);
        ASSERT(stream_status);
        if (!stream_status)
                return; /* Cannot commit surface to stream that is not committed */
 
+#ifdef ENABLE_FBC
+       if (srf_updates->flip_addr) {
+               if (srf_updates->flip_addr->address.grph.addr.low_part == 0)
+                       ASSERT(0);
+       }
+#endif
+       context = core_dc->current_context;
+
+       /* update current stream with the new updates */
+       if (stream_update) {
+               if ((stream_update->src.height != 0) &&
+                               (stream_update->src.width != 0))
+                       stream->public.src = stream_update->src;
+
+               if ((stream_update->dst.height != 0) &&
+                               (stream_update->dst.width != 0))
+                       stream->public.dst = stream_update->dst;
+
+               if (stream_update->out_transfer_func &&
+                               stream_update->out_transfer_func !=
+                                               dc_stream->out_transfer_func) {
+                       if (dc_stream->out_transfer_func != NULL)
+                               dc_transfer_func_release(dc_stream->out_transfer_func);
+                       dc_transfer_func_retain(stream_update->out_transfer_func);
+                       stream->public.out_transfer_func =
+                               stream_update->out_transfer_func;
+               }
+       }
+
+       /* do not perform surface update if surface has invalid dimensions
+        * (all zero) and no scaling_info is provided
+        */
+       if (surface_count > 0 &&
+                       srf_updates->surface->src_rect.width == 0 &&
+                       srf_updates->surface->src_rect.height == 0 &&
+                       srf_updates->surface->dst_rect.width == 0 &&
+                       srf_updates->surface->dst_rect.height == 0 &&
+                       !srf_updates->scaling_info) {
+               ASSERT(false);
+               return;
+       }
+
        update_type = dc_check_update_surfaces_for_stream(
-                       dc, updates, surface_count, stream_status);
+                       dc, srf_updates, surface_count, stream_update, stream_status);
 
        if (update_type >= update_surface_trace_level)
-               update_surface_trace(dc, updates, surface_count);
+               update_surface_trace(dc, srf_updates, surface_count);
 
        if (update_type >= UPDATE_TYPE_FULL) {
-               const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 };
+               struct dc_surface *new_surfaces[MAX_SURFACES] = {0};
 
                for (i = 0; i < surface_count; i++)
-                       new_surfaces[i] = updates[i].surface;
+                       new_surfaces[i] = srf_updates[i].surface;
 
                /* initialize scratch memory for building context */
-               context = core_dc->temp_flip_context;
-               resource_validate_ctx_copy_construct(
+               context = dm_alloc(sizeof(*context));
+               if (context == NULL)
+                               goto context_alloc_fail;
+
+               ++context->ref_count;
+
+               dc_resource_validate_ctx_copy_construct(
                                core_dc->current_context, context);
 
                /* add surface to context */
                if (!resource_attach_surfaces_to_context(
-                               new_surfaces, surface_count, dc_stream, context)) {
+                               new_surfaces, surface_count, dc_stream,
+                               context, core_dc->res_pool)) {
                        BREAK_TO_DEBUGGER();
-                       return;
+                       goto fail;
                }
-       } else {
-               context = core_dc->current_context;
        }
+
+       /* save update parameters into surface */
        for (i = 0; i < surface_count; i++) {
-               /* save update param into surface */
-               struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface);
-               struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
-
-               if (updates[i].flip_addr) {
-                       surface->public.address = updates[i].flip_addr->address;
-                       surface->public.flip_immediate =
-                                       updates[i].flip_addr->flip_immediate;
+               struct dc_surface *surface = srf_updates[i].surface;
+
+               if (srf_updates[i].flip_addr) {
+                       surface->address = srf_updates[i].flip_addr->address;
+                       surface->flip_immediate =
+                                       srf_updates[i].flip_addr->flip_immediate;
                }
 
-               if (updates[i].scaling_info) {
-                       surface->public.scaling_quality =
-                                       updates[i].scaling_info->scaling_quality;
-                       surface->public.dst_rect =
-                                       updates[i].scaling_info->dst_rect;
-                       surface->public.src_rect =
-                                       updates[i].scaling_info->src_rect;
-                       surface->public.clip_rect =
-                                       updates[i].scaling_info->clip_rect;
+               if (srf_updates[i].scaling_info) {
+                       surface->scaling_quality =
+                                       srf_updates[i].scaling_info->scaling_quality;
+                       surface->dst_rect =
+                                       srf_updates[i].scaling_info->dst_rect;
+                       surface->src_rect =
+                                       srf_updates[i].scaling_info->src_rect;
+                       surface->clip_rect =
+                                       srf_updates[i].scaling_info->clip_rect;
                }
 
-               if (updates[i].plane_info) {
-                       surface->public.color_space =
-                                       updates[i].plane_info->color_space;
-                       surface->public.format =
-                                       updates[i].plane_info->format;
-                       surface->public.plane_size =
-                                       updates[i].plane_info->plane_size;
-                       surface->public.rotation =
-                                       updates[i].plane_info->rotation;
-                       surface->public.horizontal_mirror =
-                                       updates[i].plane_info->horizontal_mirror;
-                       surface->public.stereo_format =
-                                       updates[i].plane_info->stereo_format;
-                       surface->public.tiling_info =
-                                       updates[i].plane_info->tiling_info;
-                       surface->public.visible =
-                                       updates[i].plane_info->visible;
-                       surface->public.dcc =
-                                       updates[i].plane_info->dcc;
+               if (srf_updates[i].plane_info) {
+                       surface->color_space =
+                                       srf_updates[i].plane_info->color_space;
+                       surface->format =
+                                       srf_updates[i].plane_info->format;
+                       surface->plane_size =
+                                       srf_updates[i].plane_info->plane_size;
+                       surface->rotation =
+                                       srf_updates[i].plane_info->rotation;
+                       surface->horizontal_mirror =
+                                       srf_updates[i].plane_info->horizontal_mirror;
+                       surface->stereo_format =
+                                       srf_updates[i].plane_info->stereo_format;
+                       surface->tiling_info =
+                                       srf_updates[i].plane_info->tiling_info;
+                       surface->visible =
+                                       srf_updates[i].plane_info->visible;
+                       surface->per_pixel_alpha =
+                                       srf_updates[i].plane_info->per_pixel_alpha;
+                       surface->dcc =
+                                       srf_updates[i].plane_info->dcc;
                }
 
-               /* not sure if we still need this */
-               if (update_type == UPDATE_TYPE_FULL) {
-                       for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
+               if (update_type >= UPDATE_TYPE_MED) {
+                       for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
                                struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
 
                                if (pipe_ctx->surface != surface)
                                        continue;
 
-                               resource_build_scaling_params(updates[i].surface, pipe_ctx);
+                               resource_build_scaling_params(pipe_ctx);
                        }
                }
 
-               if (updates[i].gamma &&
-                       updates[i].gamma != surface->public.gamma_correction) {
-                       if (surface->public.gamma_correction != NULL)
-                               dc_gamma_release(&surface->public.
-                                               gamma_correction);
+               if (srf_updates[i].gamma &&
+                       srf_updates[i].gamma != surface->gamma_correction) {
+                       if (surface->gamma_correction != NULL)
+                               dc_gamma_release(&surface->gamma_correction);
 
-                       dc_gamma_retain(updates[i].gamma);
-                       surface->public.gamma_correction =
-                                               updates[i].gamma;
+                       dc_gamma_retain(srf_updates[i].gamma);
+                       surface->gamma_correction = srf_updates[i].gamma;
                }
 
-               if (updates[i].in_transfer_func &&
-                       updates[i].in_transfer_func != surface->public.in_transfer_func) {
-                       if (surface->public.in_transfer_func != NULL)
+               if (srf_updates[i].in_transfer_func &&
+                       srf_updates[i].in_transfer_func != surface->in_transfer_func) {
+                       if (surface->in_transfer_func != NULL)
                                dc_transfer_func_release(
-                                               surface->public.
+                                               surface->
                                                in_transfer_func);
 
                        dc_transfer_func_retain(
-                                       updates[i].in_transfer_func);
-                       surface->public.in_transfer_func =
-                                       updates[i].in_transfer_func;
+                                       srf_updates[i].in_transfer_func);
+                       surface->in_transfer_func =
+                                       srf_updates[i].in_transfer_func;
                }
 
-               if (updates[i].out_transfer_func &&
-                       updates[i].out_transfer_func != dc_stream->out_transfer_func) {
-                       if (dc_stream->out_transfer_func != NULL)
-                               dc_transfer_func_release(dc_stream->out_transfer_func);
-                       dc_transfer_func_retain(updates[i].out_transfer_func);
-                       stream->public.out_transfer_func = updates[i].out_transfer_func;
+               if (srf_updates[i].hdr_static_metadata)
+                       surface->hdr_static_ctx =
+                               *(srf_updates[i].hdr_static_metadata);
+       }
+
+       if (update_type == UPDATE_TYPE_FULL) {
+               if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) {
+                       BREAK_TO_DEBUGGER();
+                       goto fail;
+               } else {
+                       core_dc->hwss.set_bandwidth(core_dc, context, false);
+                       context_clock_trace(dc, context);
                }
-               if (updates[i].hdr_static_metadata)
-                       surface->public.hdr_static_ctx =
-                               *(updates[i].hdr_static_metadata);
        }
 
-       if (update_type == UPDATE_TYPE_FULL &&
-                       !core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) {
-               BREAK_TO_DEBUGGER();
-               return;
+       if (update_type > UPDATE_TYPE_FAST) {
+               for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
+                       struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+
+                       core_dc->hwss.wait_for_mpcc_disconnect(core_dc, core_dc->res_pool, pipe_ctx);
+               }
        }
 
-       if (!surface_count)  /* reset */
+       if (surface_count == 0)
                core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context);
 
+       /* Lock pipes for provided surfaces, or all active if full update*/
        for (i = 0; i < surface_count; i++) {
-               struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface);
+               struct dc_surface *surface = srf_updates[i].surface;
 
-               for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
+               for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
                        struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
-                       struct pipe_ctx *cur_pipe_ctx;
-                       bool is_new_pipe_surface = true;
 
-                       if (pipe_ctx->surface != surface)
+                       if (update_type != UPDATE_TYPE_FULL && pipe_ctx->surface != surface)
+                               continue;
+                       if (!pipe_ctx->surface || pipe_ctx->top_pipe)
                                continue;
-
-                       if (update_type >= UPDATE_TYPE_MED) {
-                               /* only apply for top pipe */
-                               if (!pipe_ctx->top_pipe) {
-                                       core_dc->hwss.apply_ctx_for_surface(core_dc,
-                                                        surface, context);
-                                       context_timing_trace(dc, &context->res_ctx);
-                               }
-                       }
 
                        if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) {
                                core_dc->hwss.pipe_control_lock(
@@ -1443,58 +1573,109 @@ void dc_update_surfaces_for_stream(struct dc *dc,
                                                pipe_ctx,
                                                true);
                        }
+               }
+               if (update_type == UPDATE_TYPE_FULL)
+                       break;
+       }
+
+       /* Full fe update*/
+       for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+               struct pipe_ctx *cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j];
+               bool is_new_pipe_surface = cur_pipe_ctx->surface != pipe_ctx->surface;
+               struct dc_cursor_position position = { 0 };
+
+               if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->surface)
+                       continue;
+
+               if (!pipe_ctx->top_pipe)
+                       core_dc->hwss.apply_ctx_for_surface(
+                                       core_dc, pipe_ctx->surface, context);
 
-                       if (updates[i].flip_addr)
+               /* TODO: this is a hack w/a for switching from mpo to pipe split */
+               dc_stream_set_cursor_position(&pipe_ctx->stream->public, &position);
+
+               if (is_new_pipe_surface) {
+                       core_dc->hwss.update_plane_addr(core_dc, pipe_ctx);
+                       core_dc->hwss.set_input_transfer_func(
+                                       pipe_ctx, pipe_ctx->surface);
+                       core_dc->hwss.set_output_transfer_func(
+                                       pipe_ctx, pipe_ctx->stream);
+               }
+       }
+
+       if (update_type > UPDATE_TYPE_FAST)
+               context_timing_trace(dc, &context->res_ctx);
+
+       /* Perform requested Updates */
+       for (i = 0; i < surface_count; i++) {
+               struct dc_surface *surface = srf_updates[i].surface;
+
+               if (update_type == UPDATE_TYPE_MED)
+                       core_dc->hwss.apply_ctx_for_surface(
+                                       core_dc, surface, context);
+
+               for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
+                       struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+
+                       if (pipe_ctx->surface != surface)
+                               continue;
+
+                       if (srf_updates[i].flip_addr)
                                core_dc->hwss.update_plane_addr(core_dc, pipe_ctx);
 
                        if (update_type == UPDATE_TYPE_FAST)
                                continue;
 
-                       cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j];
-                       if (cur_pipe_ctx->surface == pipe_ctx->surface)
-                               is_new_pipe_surface = false;
-
-                       if (is_new_pipe_surface ||
-                                       updates[i].in_transfer_func)
+                       if (srf_updates[i].in_transfer_func)
                                core_dc->hwss.set_input_transfer_func(
                                                pipe_ctx, pipe_ctx->surface);
 
-                       if (is_new_pipe_surface ||
-                                       updates[i].out_transfer_func)
+                       if (stream_update != NULL &&
+                                       stream_update->out_transfer_func != NULL) {
                                core_dc->hwss.set_output_transfer_func(
-                                               pipe_ctx,
-                                               pipe_ctx->surface,
-                                               pipe_ctx->stream);
+                                               pipe_ctx, pipe_ctx->stream);
+                       }
 
-                       if (updates[i].hdr_static_metadata) {
+                       if (srf_updates[i].hdr_static_metadata) {
                                resource_build_info_frame(pipe_ctx);
                                core_dc->hwss.update_info_frame(pipe_ctx);
                        }
                }
        }
 
-       for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) {
+       /* Unlock pipes */
+       for (i = core_dc->res_pool->pipe_count - 1; i >= 0; i--) {
                struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 
                for (j = 0; j < surface_count; j++) {
-                       if (updates[j].surface == &pipe_ctx->surface->public) {
-                               if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) {
-                                       core_dc->hwss.pipe_control_lock(
-                                                       core_dc,
-                                                       pipe_ctx,
-                                                       false);
-                               }
-                               break;
+                       if (update_type != UPDATE_TYPE_FULL &&
+                           srf_updates[j].surface != pipe_ctx->surface)
+                               continue;
+                       if (!pipe_ctx->surface || pipe_ctx->top_pipe)
+                               continue;
+
+                       if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) {
+                               core_dc->hwss.pipe_control_lock(
+                                               core_dc,
+                                               pipe_ctx,
+                                               false);
                        }
+                       break;
                }
        }
 
        if (core_dc->current_context != context) {
-               resource_validate_ctx_destruct(core_dc->current_context);
-               core_dc->temp_flip_context = core_dc->current_context;
-
+               dc_release_validate_context(core_dc->current_context);
                core_dc->current_context = context;
        }
+       return;
+
+fail:
+       dc_release_validate_context(context);
+
+context_alloc_fail:
+       DC_ERROR("Failed to allocate new validate context!\n");
 }
 
 uint8_t dc_get_current_stream_count(const struct dc *dc)
@@ -1511,10 +1692,10 @@ struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i)
        return NULL;
 }
 
-const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index)
+struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index)
 {
        struct core_dc *core_dc = DC_TO_CORE(dc);
-       return &core_dc->links[link_index]->public;
+       return core_dc->links[link_index];
 }
 
 const struct graphics_object_id dc_get_link_id_at_index(
@@ -1524,18 +1705,11 @@ const struct graphics_object_id dc_get_link_id_at_index(
        return core_dc->links[link_index]->link_id;
 }
 
-const struct ddc_service *dc_get_ddc_at_index(
-       struct dc *dc, uint32_t link_index)
-{
-       struct core_dc *core_dc = DC_TO_CORE(dc);
-       return core_dc->links[link_index]->ddc;
-}
-
 enum dc_irq_source dc_get_hpd_irq_source_at_index(
        struct dc *dc, uint32_t link_index)
 {
        struct core_dc *core_dc = DC_TO_CORE(dc);
-       return core_dc->links[link_index]->public.irq_source_hpd;
+       return core_dc->links[link_index]->irq_source_hpd;
 }
 
 const struct audio **dc_get_audios(struct dc *dc)
@@ -1544,32 +1718,6 @@ const struct audio **dc_get_audios(struct dc *dc)
        return (const struct audio **)core_dc->res_pool->audios;
 }
 
-void dc_flip_surface_addrs(
-               struct dc *dc,
-               const struct dc_surface *const surfaces[],
-               struct dc_flip_addrs flip_addrs[],
-               uint32_t count)
-{
-       struct core_dc *core_dc = DC_TO_CORE(dc);
-       int i, j;
-
-       for (i = 0; i < count; i++) {
-               struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
-
-               surface->public.address = flip_addrs[i].address;
-               surface->public.flip_immediate = flip_addrs[i].flip_immediate;
-
-               for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
-                       struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j];
-
-                       if (pipe_ctx->surface != surface)
-                               continue;
-
-                       core_dc->hwss.update_plane_addr(core_dc, pipe_ctx);
-               }
-       }
-}
-
 enum dc_irq_source dc_interrupt_to_irq_source(
                struct dc *dc,
                uint32_t src_id,
@@ -1581,7 +1729,12 @@ enum dc_irq_source dc_interrupt_to_irq_source(
 
 void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable)
 {
-       struct core_dc *core_dc = DC_TO_CORE(dc);
+       struct core_dc *core_dc;
+
+       if (dc == NULL)
+               return;
+       core_dc = DC_TO_CORE(dc);
+
        dal_irq_service_set(core_dc->res_pool->irqs, src, enable);
 }
 
@@ -1593,21 +1746,16 @@ void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
 
 void dc_set_power_state(
        struct dc *dc,
-       enum dc_acpi_cm_power_state power_state,
-       enum dc_video_power_state video_power_state)
+       enum dc_acpi_cm_power_state power_state)
 {
        struct core_dc *core_dc = DC_TO_CORE(dc);
-
-       core_dc->previous_power_state = core_dc->current_power_state;
-       core_dc->current_power_state = video_power_state;
+       int ref_count;
 
        switch (power_state) {
        case DC_ACPI_CM_POWER_STATE_D0:
                core_dc->hwss.init_hw(core_dc);
                break;
        default:
-               /* NULL means "reset/release all DC streams" */
-               dc_commit_streams(dc, NULL, 0);
 
                core_dc->hwss.power_down(core_dc);
 
@@ -1615,10 +1763,13 @@ void dc_set_power_state(
                 * clean state, and dc hw programming optimizations will not
                 * cause any trouble.
                 */
+
+               /* Preserve refcount */
+               ref_count = core_dc->current_context->ref_count;
+               dc_resource_validate_ctx_destruct(core_dc->current_context);
                memset(core_dc->current_context, 0,
                                sizeof(*core_dc->current_context));
-
-               core_dc->current_context->res_ctx.pool = core_dc->res_pool;
+               core_dc->current_context->ref_count = ref_count;
 
                break;
        }
@@ -1635,7 +1786,7 @@ void dc_resume(const struct dc *dc)
                core_link_resume(core_dc->links[i]);
 }
 
-bool dc_read_dpcd(
+bool dc_read_aux_dpcd(
                struct dc *dc,
                uint32_t link_index,
                uint32_t address,
@@ -1644,59 +1795,103 @@ bool dc_read_dpcd(
 {
        struct core_dc *core_dc = DC_TO_CORE(dc);
 
-       struct core_link *link = core_dc->links[link_index];
+       struct dc_link *link = core_dc->links[link_index];
        enum ddc_result r = dal_ddc_service_read_dpcd_data(
                        link->ddc,
+                       false,
+                       I2C_MOT_UNDEF,
                        address,
                        data,
                        size);
        return r == DDC_RESULT_SUCESSFULL;
 }
 
-bool dc_query_ddc_data(
+bool dc_write_aux_dpcd(
                struct dc *dc,
                uint32_t link_index,
                uint32_t address,
-               uint8_t *write_buf,
-               uint32_t write_size,
-               uint8_t *read_buf,
-               uint32_t read_size) {
-
+               const uint8_t *data,
+               uint32_t size)
+{
        struct core_dc *core_dc = DC_TO_CORE(dc);
+       struct dc_link *link = core_dc->links[link_index];
 
-       struct core_link *link = core_dc->links[link_index];
-
-       bool result = dal_ddc_service_query_ddc_data(
+       enum ddc_result r = dal_ddc_service_write_dpcd_data(
                        link->ddc,
+                       false,
+                       I2C_MOT_UNDEF,
                        address,
-                       write_buf,
-                       write_size,
-                       read_buf,
-                       read_size);
-
-       return result;
+                       data,
+                       size);
+       return r == DDC_RESULT_SUCESSFULL;
 }
 
+bool dc_read_aux_i2c(
+               struct dc *dc,
+               uint32_t link_index,
+               enum i2c_mot_mode mot,
+               uint32_t address,
+               uint8_t *data,
+               uint32_t size)
+{
+       struct core_dc *core_dc = DC_TO_CORE(dc);
+
+               struct dc_link *link = core_dc->links[link_index];
+               enum ddc_result r = dal_ddc_service_read_dpcd_data(
+                       link->ddc,
+                       true,
+                       mot,
+                       address,
+                       data,
+                       size);
+               return r == DDC_RESULT_SUCESSFULL;
+}
 
-bool dc_write_dpcd(
+bool dc_write_aux_i2c(
                struct dc *dc,
                uint32_t link_index,
+               enum i2c_mot_mode mot,
                uint32_t address,
                const uint8_t *data,
                uint32_t size)
 {
        struct core_dc *core_dc = DC_TO_CORE(dc);
-
-       struct core_link *link = core_dc->links[link_index];
+       struct dc_link *link = core_dc->links[link_index];
 
        enum ddc_result r = dal_ddc_service_write_dpcd_data(
                        link->ddc,
+                       true,
+                       mot,
                        address,
                        data,
                        size);
        return r == DDC_RESULT_SUCESSFULL;
 }
 
+bool dc_query_ddc_data(
+               struct dc *dc,
+               uint32_t link_index,
+               uint32_t address,
+               uint8_t *write_buf,
+               uint32_t write_size,
+               uint8_t *read_buf,
+               uint32_t read_size) {
+
+       struct core_dc *core_dc = DC_TO_CORE(dc);
+
+       struct dc_link *link = core_dc->links[link_index];
+
+       bool result = dal_ddc_service_query_ddc_data(
+                       link->ddc,
+                       address,
+                       write_buf,
+                       write_size,
+                       read_buf,
+                       read_size);
+
+       return result;
+}
+
 bool dc_submit_i2c(
                struct dc *dc,
                uint32_t link_index,
@@ -1704,7 +1899,7 @@ bool dc_submit_i2c(
 {
        struct core_dc *core_dc = DC_TO_CORE(dc);
 
-       struct core_link *link = core_dc->links[link_index];
+       struct dc_link *link = core_dc->links[link_index];
        struct ddc_service *ddc = link->ddc;
 
        return dal_i2caux_submit_i2c_command(
@@ -1713,10 +1908,8 @@ bool dc_submit_i2c(
                cmd);
 }
 
-static bool link_add_remote_sink_helper(struct core_link *core_link, struct dc_sink *sink)
+static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink)
 {
-       struct dc_link *dc_link = &core_link->public;
-
        if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
                BREAK_TO_DEBUGGER();
                return false;
@@ -1731,14 +1924,13 @@ static bool link_add_remote_sink_helper(struct core_link *core_link, struct dc_s
 }
 
 struct dc_sink *dc_link_add_remote_sink(
-               const struct dc_link *link,
+               struct dc_link *link,
                const uint8_t *edid,
                int len,
                struct dc_sink_init_data *init_data)
 {
        struct dc_sink *dc_sink;
        enum dc_edid_status edid_status;
-       struct core_link *core_link = DC_LINK_TO_LINK(link);
 
        if (len > MAX_EDID_BUFFER_SIZE) {
                dm_error("Max EDID buffer size breached!\n");
@@ -1764,12 +1956,12 @@ struct dc_sink *dc_link_add_remote_sink(
        dc_sink->dc_edid.length = len;
 
        if (!link_add_remote_sink_helper(
-                       core_link,
+                       link,
                        dc_sink))
                goto fail_add_sink;
 
        edid_status = dm_helpers_parse_edid_caps(
-                       core_link->ctx,
+                       link->ctx,
                        &dc_sink->dc_edid,
                        &dc_sink->edid_caps);
 
@@ -1784,45 +1976,74 @@ fail_add_sink:
        return NULL;
 }
 
-void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink)
+void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink)
 {
-       struct core_link *core_link = DC_LINK_TO_LINK(link);
-       struct dc_link *dc_link = &core_link->public;
-
-       dc_link->local_sink = sink;
+       link->local_sink = sink;
 
        if (sink == NULL) {
-               dc_link->type = dc_connection_none;
+               link->type = dc_connection_none;
        } else {
-               dc_link->type = dc_connection_single;
+               link->type = dc_connection_single;
        }
 }
 
-void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink *sink)
+void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink)
 {
        int i;
-       struct core_link *core_link = DC_LINK_TO_LINK(link);
-       struct dc_link *dc_link = &core_link->public;
 
        if (!link->sink_count) {
                BREAK_TO_DEBUGGER();
                return;
        }
 
-       for (i = 0; i < dc_link->sink_count; i++) {
-               if (dc_link->remote_sinks[i] == sink) {
+       for (i = 0; i < link->sink_count; i++) {
+               if (link->remote_sinks[i] == sink) {
                        dc_sink_release(sink);
-                       dc_link->remote_sinks[i] = NULL;
+                       link->remote_sinks[i] = NULL;
 
                        /* shrink array to remove empty place */
-                       while (i < dc_link->sink_count - 1) {
-                               dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1];
+                       while (i < link->sink_count - 1) {
+                               link->remote_sinks[i] = link->remote_sinks[i+1];
                                i++;
                        }
-
-                       dc_link->sink_count--;
+                       link->remote_sinks[i] = NULL;
+                       link->sink_count--;
                        return;
                }
        }
 }
 
+bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data)
+{
+       int i;
+       struct core_dc *core_dc = DC_TO_CORE(dc);
+       struct mem_input *mi = NULL;
+
+       for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
+               if (core_dc->res_pool->mis[i] != NULL) {
+                       mi = core_dc->res_pool->mis[i];
+                       break;
+               }
+       }
+       if (mi == NULL) {
+               dm_error("no mem_input!\n");
+               return false;
+       }
+
+       if (core_dc->hwss.update_dchub)
+               core_dc->hwss.update_dchub(core_dc->hwseq, dh_data);
+       else
+               ASSERT(core_dc->hwss.update_dchub);
+
+
+       return true;
+
+}
+
+void dc_log_hw_state(struct dc *dc)
+{
+       struct core_dc *core_dc = DC_TO_CORE(dc);
+
+       if (core_dc->hwss.log_hw_state)
+               core_dc->hwss.log_hw_state(core_dc);
+}