for (j = 0; j < dc->res_pool->pipe_count; j++) {
                struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
 
-               if (!pipe_ctx->top_pipe &&
-                       pipe_ctx->stream &&
-                       pipe_ctx->stream == stream) {
+               if (!pipe_ctx->top_pipe &&  !pipe_ctx->prev_odm_pipe && pipe_ctx->stream == stream) {
 
                        if (stream_update->periodic_interrupt0 &&
                                        dc->hwss.setup_periodic_interrupt)
 
                        if (stream_update->dither_option) {
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
-                               struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
+                               struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
 #endif
                                resource_build_bit_depth_reduction_params(pipe_ctx->stream,
                                                                        &pipe_ctx->stream->bit_depth_params);
                                                &stream->bit_depth_params,
                                                &stream->clamping);
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
-                               if (odm_pipe)
+                               while (odm_pipe) {
                                        odm_pipe->stream_res.opp->funcs->opp_program_fmt(odm_pipe->stream_res.opp,
                                                        &stream->bit_depth_params,
                                                        &stream->clamping);
+                                       odm_pipe = odm_pipe->next_odm_pipe;
+                               }
 #endif
                        }
 
 
                                controller_test_pattern, color_depth);
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
                else if (opp->funcs->opp_set_disp_pattern_generator) {
-                       struct pipe_ctx *bot_odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
+                       struct pipe_ctx *odm_pipe;
+                       int opp_cnt = 1;
 
-                       if (bot_odm_pipe) {
-                               struct output_pixel_processor *bot_opp = bot_odm_pipe->stream_res.opp;
+                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
+                               opp_cnt++;
 
-                               bot_opp->funcs->opp_program_bit_depth_reduction(bot_opp, ¶ms);
-                               width /= 2;
-                               bot_opp->funcs->opp_set_disp_pattern_generator(bot_opp,
+                       width /= opp_cnt;
+
+                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+                               struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
+
+                               odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms);
+                               odm_opp->funcs->opp_set_disp_pattern_generator(odm_opp,
                                        controller_test_pattern,
                                        color_depth,
                                        NULL,
                                color_depth);
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
                else if (opp->funcs->opp_set_disp_pattern_generator) {
-                       struct pipe_ctx *bot_odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
+                       struct pipe_ctx *odm_pipe;
+                       int opp_cnt = 1;
+
+                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
+                               opp_cnt++;
 
-                       if (bot_odm_pipe) {
-                               struct output_pixel_processor *bot_opp = bot_odm_pipe->stream_res.opp;
+                       width /= opp_cnt;
+                       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+                               struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
 
-                               bot_opp->funcs->opp_program_bit_depth_reduction(bot_opp, ¶ms);
-                               width /= 2;
-                               bot_opp->funcs->opp_set_disp_pattern_generator(bot_opp,
+                               odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms);
+                               odm_opp->funcs->opp_set_disp_pattern_generator(odm_opp,
                                        CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
                                        color_depth,
                                        NULL,
 
 
        for (i = 0; i < MAX_PIPES; i++) {
                if (pipes[i].stream != NULL &&
-                       !pipes[i].top_pipe &&
+                       !pipes[i].top_pipe && !pipes[i].prev_odm_pipe &&
                        pipes[i].stream->link != NULL &&
                        pipes[i].stream_res.stream_enc != NULL) {
                        udelay(100);
        struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
        struct dc *core_dc = pipe_ctx->stream->ctx->dc;
        struct dc_stream_state *stream = pipe_ctx->stream;
-       struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
+       struct pipe_ctx *odm_pipe;
+       int opp_cnt = 1;
+
+       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
+               opp_cnt++;
 
        if (enable) {
                struct dsc_config dsc_cfg;
                enum optc_dsc_mode optc_dsc_mode;
 
                /* Enable DSC hw block */
-               dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
+               dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
                dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
                dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
                dsc_cfg.color_depth = stream->timing.display_color_depth;
                dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
+               ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
+               dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
+
+               dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
+               dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
+               for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+                       struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
 
-               if (odm_pipe) {
-                       struct display_stream_compressor *bot_dsc = odm_pipe->stream_res.dsc;
-
-                       dsc_cfg.pic_width /= 2;
-                       ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % 2 == 0);
-                       dsc_cfg.dc_dsc_cfg.num_slices_h /= 2;
-                       dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
-                       bot_dsc->funcs->dsc_set_config(bot_dsc, &dsc_cfg, &dsc_optc_cfg);
-                       dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
-                       bot_dsc->funcs->dsc_enable(bot_dsc, odm_pipe->stream_res.opp->inst);
-               } else {
-                       dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
-                       dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
+                       odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
+                       odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
                }
+               dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
+               dsc_cfg.pic_width *= opp_cnt;
 
                optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
 
 
                /* disable DSC block */
                pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
-               if (odm_pipe)
+               for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
                        odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
        }
 }
 
 {
        int i;
        for (i = 0; i < MAX_PIPES; i++) {
-               if (res_ctx->pipe_ctx[i].stream == stream &&
-                               !res_ctx->pipe_ctx[i].top_pipe) {
+               if (res_ctx->pipe_ctx[i].stream == stream
+                               && !res_ctx->pipe_ctx[i].top_pipe
+                               && !res_ctx->pipe_ctx[i].prev_odm_pipe) {
                        return &res_ctx->pipe_ctx[i];
                        break;
                }
        return NULL;
 }
 
-static struct pipe_ctx *resource_get_tail_pipe_for_stream(
+static struct pipe_ctx *resource_get_tail_pipe(
                struct resource_context *res_ctx,
-               struct dc_stream_state *stream)
+               struct pipe_ctx *head_pipe)
 {
-       struct pipe_ctx *head_pipe, *tail_pipe;
-       head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
-
-       if (!head_pipe)
-               return NULL;
+       struct pipe_ctx *tail_pipe;
 
        tail_pipe = head_pipe->bottom_pipe;
 
  * A free_pipe for a stream is defined here as a pipe
  * that has no surface attached yet
  */
-static struct pipe_ctx *acquire_free_pipe_for_stream(
+static struct pipe_ctx *acquire_free_pipe_for_head(
                struct dc_state *context,
                const struct resource_pool *pool,
-               struct dc_stream_state *stream)
+               struct pipe_ctx *head_pipe)
 {
        int i;
        struct resource_context *res_ctx = &context->res_ctx;
 
-       struct pipe_ctx *head_pipe = NULL;
-
-       /* Find head pipe, which has the back end set up*/
-
-       head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
-
-       if (!head_pipe) {
-               ASSERT(0);
-               return NULL;
-       }
-
        if (!head_pipe->plane_state)
                return head_pipe;
 
        /* Re-use pipe already acquired for this stream if available*/
        for (i = pool->pipe_count - 1; i >= 0; i--) {
-               if (res_ctx->pipe_ctx[i].stream == stream &&
+               if (res_ctx->pipe_ctx[i].stream == head_pipe->stream &&
                                !res_ctx->pipe_ctx[i].plane_state) {
                        return &res_ctx->pipe_ctx[i];
                }
        if (!pool->funcs->acquire_idle_pipe_for_layer)
                return NULL;
 
-       return pool->funcs->acquire_idle_pipe_for_layer(context, pool, stream);
-
+       return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream);
 }
 
 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        for (i = 0; i < pool->pipe_count; i++) {
                struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i];
 
-               if (split_pipe->top_pipe && !dc_res_is_odm_head_pipe(split_pipe) &&
+               if (split_pipe->top_pipe &&
                                split_pipe->top_pipe->plane_state == split_pipe->plane_state) {
                        split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe;
                        if (split_pipe->bottom_pipe)
                return false;
        }
 
-       tail_pipe = resource_get_tail_pipe_for_stream(&context->res_ctx, stream);
-       ASSERT(tail_pipe);
+       /* retain new surface, but only once per stream */
+       dc_plane_state_retain(plane_state);
 
-       free_pipe = acquire_free_pipe_for_stream(context, pool, stream);
+       while (head_pipe) {
+               tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe);
+               ASSERT(tail_pipe);
 
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
-       if (!free_pipe) {
-               int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
-               if (pipe_idx >= 0)
-                       free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
-       }
-#endif
-       if (!free_pipe)
-               return false;
+               free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe);
 
-       /* retain new surfaces */
-       dc_plane_state_retain(plane_state);
-       free_pipe->plane_state = plane_state;
-
-       if (head_pipe != free_pipe) {
-               free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
-               free_pipe->stream_res.abm = tail_pipe->stream_res.abm;
-               free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
-               free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
-               free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
-               free_pipe->clock_source = tail_pipe->clock_source;
-               free_pipe->top_pipe = tail_pipe;
-               tail_pipe->bottom_pipe = free_pipe;
-       } else if (free_pipe->bottom_pipe && free_pipe->bottom_pipe->plane_state == NULL) {
-               ASSERT(free_pipe->bottom_pipe->stream_res.opp != free_pipe->stream_res.opp);
-               free_pipe->bottom_pipe->plane_state = plane_state;
-       }
+       #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+               if (!free_pipe) {
+                       int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
+                       if (pipe_idx >= 0)
+                               free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
+               }
+       #endif
+               if (!free_pipe) {
+                       dc_plane_state_release(plane_state);
+                       return false;
+               }
 
+               free_pipe->plane_state = plane_state;
+
+               if (head_pipe != free_pipe) {
+                       free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
+                       free_pipe->stream_res.abm = tail_pipe->stream_res.abm;
+                       free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
+                       free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
+                       free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
+                       free_pipe->clock_source = tail_pipe->clock_source;
+                       free_pipe->top_pipe = tail_pipe;
+                       tail_pipe->bottom_pipe = free_pipe;
+               }
+               head_pipe = head_pipe->next_odm_pipe;
+       }
        /* assign new surfaces*/
        stream_status->plane_states[stream_status->plane_count] = plane_state;
 
        return true;
 }
 
-struct pipe_ctx *dc_res_get_odm_bottom_pipe(struct pipe_ctx *pipe_ctx)
-{
-       struct pipe_ctx *bottom_pipe = pipe_ctx->bottom_pipe;
-
-       /* ODM should only be updated once per otg */
-       if (pipe_ctx->top_pipe)
-               return NULL;
-
-       while (bottom_pipe) {
-               if (bottom_pipe->stream_res.opp != pipe_ctx->stream_res.opp)
-                       break;
-               bottom_pipe = bottom_pipe->bottom_pipe;
-       }
-
-       return bottom_pipe;
-}
-
-bool dc_res_is_odm_head_pipe(struct pipe_ctx *pipe_ctx)
-{
-       struct pipe_ctx *top_pipe = pipe_ctx->top_pipe;
-
-       if (!top_pipe)
-               return false;
-       if (top_pipe && top_pipe->stream_res.opp == pipe_ctx->stream_res.opp)
-               return false;
-
-       return true;
-}
-
 bool dc_remove_plane_from_context(
                const struct dc *dc,
                struct dc_stream_state *stream,
                struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 
                if (pipe_ctx->plane_state == plane_state) {
-                       if (dc_res_is_odm_head_pipe(pipe_ctx)) {
-                               pipe_ctx->plane_state = NULL;
-                               pipe_ctx->bottom_pipe = NULL;
-                               continue;
-                       }
-
                        if (pipe_ctx->top_pipe)
                                pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
 
                         * For head pipe detach surfaces from pipe for tail
                         * pipe just zero it out
                         */
-                       if (!pipe_ctx->top_pipe) {
+                       if (!pipe_ctx->top_pipe)
                                pipe_ctx->plane_state = NULL;
-                               if (!dc_res_get_odm_bottom_pipe(pipe_ctx))
-                                       pipe_ctx->bottom_pipe = NULL;
-                       } else {
+                       else
                                memset(pipe_ctx, 0, sizeof(*pipe_ctx));
-                       }
                }
        }
 
        for (i = 0; i < MAX_PIPES; i++) {
                if (new_ctx->res_ctx.pipe_ctx[i].stream == stream &&
                                !new_ctx->res_ctx.pipe_ctx[i].top_pipe) {
-                       struct pipe_ctx *odm_pipe =
-                                       dc_res_get_odm_bottom_pipe(&new_ctx->res_ctx.pipe_ctx[i]);
-
                        del_pipe = &new_ctx->res_ctx.pipe_ctx[i];
 
                        ASSERT(del_pipe->stream_res.stream_enc);
                                dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);
 
                        memset(del_pipe, 0, sizeof(*del_pipe));
-                       if (odm_pipe)
-                               memset(odm_pipe, 0, sizeof(*odm_pipe));
 
                        break;
                }
 
                if (cur_pipe->bottom_pipe)
                        cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
+
+               if (cur_pipe->next_odm_pipe)
+                       cur_pipe->next_odm_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
+
+               if (cur_pipe->prev_odm_pipe)
+                       cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
        }
 
        for (i = 0; i < dst_ctx->stream_count; i++) {
 
        struct drr_params params = {0};
        unsigned int event_triggers = 0;
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
-       struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
+       struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
 #endif
 
        if (dc->hwss.disable_stream_gating) {
                &stream->bit_depth_params,
                &stream->clamping);
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
-       if (odm_pipe) {
+       while (odm_pipe) {
                odm_pipe->stream_res.opp->funcs->opp_set_dyn_expansion(
                                odm_pipe->stream_res.opp,
                                COLOR_SPACE_YCBCR601,
                                odm_pipe->stream_res.opp,
                                &stream->bit_depth_params,
                                &stream->clamping);
+               odm_pipe = odm_pipe->next_odm_pipe;
        }
 #endif
 
                if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
                        continue;
 
-               if (pipe_ctx->top_pipe)
+               if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe)
                        continue;
 
                status = apply_single_controller_ctx_to_hw(
 
                if (pipe_ctx->stream != stream)
                        continue;
 
-               if (!pipe_ctx->top_pipe)
+               if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe)
                        return pipe_ctx;
        }
        return NULL;
 
        struct dc_stream_state *stream = pipe_ctx->stream;
        struct drr_params params = {0};
        unsigned int event_triggers = 0;
-
-
-#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
-       struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
-#endif
+       struct pipe_ctx *odm_pipe;
+       int opp_cnt = 1;
+       int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
 
        /* by upper caller loop, pipe0 is parent pipe and be called first.
         * back end is set up by for pipe0. Other children pipe share back end
 
        /* TODO check if timing_changed, disable stream if timing changed */
 
-       if (odm_pipe) {
-               int opp_inst[2] = { pipe_ctx->stream_res.opp->inst, odm_pipe->stream_res.opp->inst };
+       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+               opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
+               opp_cnt++;
+       }
 
+       if (opp_cnt > 1)
                pipe_ctx->stream_res.tg->funcs->set_odm_combine(
                                pipe_ctx->stream_res.tg,
-                               opp_inst, 2,
+                               opp_inst, opp_cnt,
                                &pipe_ctx->stream->timing);
-       }
+
        /* HW program guide assume display already disable
         * by unplug sequence. OTG assume stop.
         */
                        pipe_ctx->stream->signal,
                        true);
 
-       if (odm_pipe)
+       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
                odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
                                odm_pipe->stream_res.opp,
                                true);
         */
        if (mpc->funcs->power_on_mpc_mem_pwr)
                mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true);
-       if ((pipe_ctx->top_pipe == NULL || dc_res_is_odm_head_pipe(pipe_ctx))
+       if (pipe_ctx->top_pipe == NULL
                        && mpc->funcs->set_output_gamma && stream->out_transfer_func) {
                if (stream->out_transfer_func->type == TF_TYPE_HWPWL)
                        params = &stream->out_transfer_func->pwl;
 
 static void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
 {
-       struct pipe_ctx *combine_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
+       struct pipe_ctx *odm_pipe;
+       int opp_cnt = 1;
+       int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
 
-       if (combine_pipe) {
-               int opp_inst[2] = { pipe_ctx->stream_res.opp->inst,
-                               combine_pipe->stream_res.opp->inst };
+       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+               opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
+               opp_cnt++;
+       }
 
+       if (opp_cnt > 1)
                pipe_ctx->stream_res.tg->funcs->set_odm_combine(
                                pipe_ctx->stream_res.tg,
-                               opp_inst, 2,
+                               opp_inst, opp_cnt,
                                &pipe_ctx->stream->timing);
-       } else
+       else
                pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
                                pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
 }
        struct dc_stream_state *stream = pipe_ctx->stream;
        enum dc_color_space color_space = stream->output_color_space;
        enum controller_dp_test_pattern test_pattern = CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR;
-       struct pipe_ctx *bot_odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
+       struct pipe_ctx *odm_pipe;
+       int odm_cnt = 1;
 
        int width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
        int height = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
        /* get opp dpg blank color */
        color_space_to_black_color(dc, color_space, &black_color);
 
-       if (bot_odm_pipe)
-               width = width / 2;
+       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
+               odm_cnt++;
+
+       width = width / odm_cnt;
 
        if (blank) {
                if (stream_res->abm)
                        width,
                        height);
 
-       if (bot_odm_pipe) {
-               bot_odm_pipe->stream_res.opp->funcs->opp_set_disp_pattern_generator(
-                               bot_odm_pipe->stream_res.opp,
+       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+               odm_pipe->stream_res.opp->funcs->opp_set_disp_pattern_generator(
+                               odm_pipe->stream_res.opp,
                                dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE ?
                                                CONTROLLER_DP_TEST_PATTERN_COLORRAMP : test_pattern,
                                stream->timing.display_color_depth,
                struct pipe_ctx *pipe_ctx,
                struct dc_state *context)
 {
-       if (pipe_ctx->top_pipe == NULL) {
+       if (pipe_ctx->top_pipe == NULL && !pipe_ctx->prev_odm_pipe) {
                bool blank = !is_pipe_tree_visible(pipe_ctx);
 
                pipe_ctx->stream_res.tg->funcs->program_global_sync(
 
                        pipe_ctx->stream_res.tg->funcs->set_vtg_params(
                                        pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
-
-                       dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
+                       if (pipe_ctx->prev_odm_pipe == NULL)
+                               dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
                }
 
                pipe_ctx->plane_res.hubp->funcs->hubp_setup(
 {
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        struct dce_hwseq *hws = dc->hwseq;
-       struct pipe_ctx *bot_odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
 
        if (pipe_ctx->stream_res.dsc) {
+               struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
+
                dcn20_dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, true);
-               if (bot_odm_pipe)
-                       dcn20_dsc_pg_control(hws, bot_odm_pipe->stream_res.dsc->inst, true);
+               while (odm_pipe) {
+                       dcn20_dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, true);
+                       odm_pipe = odm_pipe->next_odm_pipe;
+               }
        }
 #endif
 }
 {
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        struct dce_hwseq *hws = dc->hwseq;
-       struct pipe_ctx *bot_odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
 
        if (pipe_ctx->stream_res.dsc) {
+               struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
+
                dcn20_dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, false);
-               if (bot_odm_pipe)
-                       dcn20_dsc_pg_control(hws, bot_odm_pipe->stream_res.dsc->inst, false);
+               while (odm_pipe) {
+                       dcn20_dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, false);
+                       odm_pipe = odm_pipe->next_odm_pipe;
+               }
        }
 #endif
 }
        struct encoder_unblank_param params = { { 0 } };
        struct dc_stream_state *stream = pipe_ctx->stream;
        struct dc_link *link = stream->link;
-       params.odm = dc_res_get_odm_bottom_pipe(pipe_ctx);
+       struct pipe_ctx *odm_pipe;
 
+       params.opp_cnt = 1;
+       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+               params.opp_cnt++;
+       }
        /* only 3 items below are used by unblank */
        params.timing = pipe_ctx->stream->timing;
 
        params.link_settings.link_rate = link_settings->link_rate;
 
        if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
-               if (optc1_is_two_pixels_per_containter(&stream->timing) || params.odm)
+               if (optc1_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt)
                        params.timing.pix_clk_100hz /= 2;
                pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
-                               pipe_ctx->stream_res.stream_enc, params.odm);
+                               pipe_ctx->stream_res.stream_enc, params.opp_cnt);
                pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
        }
 
                if (!pipe_ctx_old->stream)
                        continue;
 
-               if (pipe_ctx_old->top_pipe)
+               if (pipe_ctx_old->top_pipe || pipe_ctx_old->prev_odm_pipe)
                        continue;
 
                if (!pipe_ctx->stream ||
 
        struct pixel_clk_params *pixel_clk_params)
 {
        const struct dc_stream_state *stream = pipe_ctx->stream;
-       bool odm_combine = dc_res_get_odm_bottom_pipe(pipe_ctx) != NULL;
+       struct pipe_ctx *odm_pipe;
+       int opp_cnt = 1;
+
+       for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
+               opp_cnt++;
 
        pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz;
        pixel_clk_params->encoder_object_id = stream->link->link_enc->id;
        if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
                pixel_clk_params->color_depth = COLOR_DEPTH_888;
 
-       if (optc1_is_two_pixels_per_containter(&stream->timing) || odm_combine)
+       if (opp_cnt == 4)
+               pixel_clk_params->requested_pix_clk_100hz /= 4;
+       else if (optc1_is_two_pixels_per_containter(&stream->timing) || opp_cnt == 2)
                pixel_clk_params->requested_pix_clk_100hz /= 2;
 
        if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
        for (i = 0; i < MAX_PIPES; i++) {
                if (new_ctx->res_ctx.pipe_ctx[i].stream == dc_stream && !new_ctx->res_ctx.pipe_ctx[i].top_pipe) {
                        pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
-                       break;
+
+                       if (pipe_ctx->stream_res.dsc)
+                               release_dsc(&new_ctx->res_ctx, dc->res_pool, &pipe_ctx->stream_res.dsc);
                }
        }
 
        if (!pipe_ctx)
                return DC_ERROR_UNEXPECTED;
-
-       if (pipe_ctx->stream_res.dsc) {
-               struct pipe_ctx *odm_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
-
-               release_dsc(&new_ctx->res_ctx, dc->res_pool, &pipe_ctx->stream_res.dsc);
-               if (odm_pipe)
-                       release_dsc(&new_ctx->res_ctx, dc->res_pool, &odm_pipe->stream_res.dsc);
-       }
-
-       return DC_OK;
+       else
+               return DC_OK;
 }
 #endif
 
        }
 }
 
-static bool dcn20_split_stream_for_combine(
+static bool dcn20_split_stream_for_odm(
+               struct resource_context *res_ctx,
+               const struct resource_pool *pool,
+               struct pipe_ctx *prev_odm_pipe,
+               struct pipe_ctx *next_odm_pipe)
+{
+       int pipe_idx = next_odm_pipe->pipe_idx;
+       struct scaler_data *sd = &prev_odm_pipe->plane_res.scl_data;
+       struct pipe_ctx *sec_next_pipe = next_odm_pipe->next_odm_pipe;
+       int new_width;
+
+       *next_odm_pipe = *prev_odm_pipe;
+       next_odm_pipe->next_odm_pipe = sec_next_pipe;
+
+       next_odm_pipe->pipe_idx = pipe_idx;
+       next_odm_pipe->plane_res.mi = pool->mis[next_odm_pipe->pipe_idx];
+       next_odm_pipe->plane_res.hubp = pool->hubps[next_odm_pipe->pipe_idx];
+       next_odm_pipe->plane_res.ipp = pool->ipps[next_odm_pipe->pipe_idx];
+       next_odm_pipe->plane_res.xfm = pool->transforms[next_odm_pipe->pipe_idx];
+       next_odm_pipe->plane_res.dpp = pool->dpps[next_odm_pipe->pipe_idx];
+       next_odm_pipe->plane_res.mpcc_inst = pool->dpps[next_odm_pipe->pipe_idx]->inst;
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+       next_odm_pipe->stream_res.dsc = NULL;
+#endif
+       if (prev_odm_pipe->next_odm_pipe && prev_odm_pipe->next_odm_pipe != next_odm_pipe) {
+               ASSERT(!next_odm_pipe->next_odm_pipe);
+               next_odm_pipe->next_odm_pipe = prev_odm_pipe->next_odm_pipe;
+               next_odm_pipe->next_odm_pipe->prev_odm_pipe = next_odm_pipe;
+       }
+       prev_odm_pipe->next_odm_pipe = next_odm_pipe;
+       next_odm_pipe->prev_odm_pipe = prev_odm_pipe;
+       ASSERT(next_odm_pipe->top_pipe == NULL);
+
+       if (prev_odm_pipe->plane_state) {
+               /* HACTIVE halved for odm combine */
+               sd->h_active /= 2;
+               /* Copy scl_data to secondary pipe */
+               next_odm_pipe->plane_res.scl_data = *sd;
+
+               /* Calculate new vp and recout for left pipe */
+               /* Need at least 16 pixels width per side */
+               if (sd->recout.x + 16 >= sd->h_active)
+                       return false;
+               new_width = sd->h_active - sd->recout.x;
+               sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int(
+                               sd->ratios.horz, sd->recout.width - new_width));
+               sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int(
+                               sd->ratios.horz_c, sd->recout.width - new_width));
+               sd->recout.width = new_width;
+
+               /* Calculate new vp and recout for right pipe */
+               sd = &next_odm_pipe->plane_res.scl_data;
+               new_width = sd->recout.width + sd->recout.x - sd->h_active;
+               /* Need at least 16 pixels width per side */
+               if (new_width <= 16)
+                       return false;
+               sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int(
+                               sd->ratios.horz, sd->recout.width - new_width));
+               sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int(
+                               sd->ratios.horz_c, sd->recout.width - new_width));
+               sd->recout.width = new_width;
+               sd->viewport.x += dc_fixpt_floor(dc_fixpt_mul_int(
+                               sd->ratios.horz, sd->h_active - sd->recout.x));
+               sd->viewport_c.x += dc_fixpt_floor(dc_fixpt_mul_int(
+                               sd->ratios.horz_c, sd->h_active - sd->recout.x));
+               sd->recout.x = 0;
+       }
+       next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+       if (next_odm_pipe->stream->timing.flags.DSC == 1) {
+               acquire_dsc(res_ctx, pool, &next_odm_pipe->stream_res.dsc);
+               ASSERT(next_odm_pipe->stream_res.dsc);
+               if (next_odm_pipe->stream_res.dsc == NULL)
+                       return false;
+       }
+#endif
+
+       return true;
+}
+
+static void dcn20_split_stream_for_mpc(
                struct resource_context *res_ctx,
                const struct resource_pool *pool,
                struct pipe_ctx *primary_pipe,
-               struct pipe_ctx *secondary_pipe,
-               bool is_odm_combine)
+               struct pipe_ctx *secondary_pipe)
 {
        int pipe_idx = secondary_pipe->pipe_idx;
-       struct scaler_data *sd = &primary_pipe->plane_res.scl_data;
        struct pipe_ctx *sec_bot_pipe = secondary_pipe->bottom_pipe;
-       int new_width;
 
        *secondary_pipe = *primary_pipe;
        secondary_pipe->bottom_pipe = sec_bot_pipe;
        primary_pipe->bottom_pipe = secondary_pipe;
        secondary_pipe->top_pipe = primary_pipe;
 
-       if (is_odm_combine) {
-               if (primary_pipe->plane_state) {
-                       /* HACTIVE halved for odm combine */
-                       sd->h_active /= 2;
-                       /* Copy scl_data to secondary pipe */
-                       secondary_pipe->plane_res.scl_data = *sd;
-
-                       /* Calculate new vp and recout for left pipe */
-                       /* Need at least 16 pixels width per side */
-                       if (sd->recout.x + 16 >= sd->h_active)
-                               return false;
-                       new_width = sd->h_active - sd->recout.x;
-                       sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int(
-                                       sd->ratios.horz, sd->recout.width - new_width));
-                       sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int(
-                                       sd->ratios.horz_c, sd->recout.width - new_width));
-                       sd->recout.width = new_width;
-
-                       /* Calculate new vp and recout for right pipe */
-                       sd = &secondary_pipe->plane_res.scl_data;
-                       new_width = sd->recout.width + sd->recout.x - sd->h_active;
-                       /* Need at least 16 pixels width per side */
-                       if (new_width <= 16)
-                               return false;
-                       sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int(
-                                       sd->ratios.horz, sd->recout.width - new_width));
-                       sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int(
-                                       sd->ratios.horz_c, sd->recout.width - new_width));
-                       sd->recout.width = new_width;
-                       sd->viewport.x += dc_fixpt_floor(dc_fixpt_mul_int(
-                                       sd->ratios.horz, sd->h_active - sd->recout.x));
-                       sd->viewport_c.x += dc_fixpt_floor(dc_fixpt_mul_int(
-                                       sd->ratios.horz_c, sd->h_active - sd->recout.x));
-                       sd->recout.x = 0;
-               }
-               secondary_pipe->stream_res.opp = pool->opps[secondary_pipe->pipe_idx];
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-               if (secondary_pipe->stream->timing.flags.DSC == 1) {
-                       acquire_dsc(res_ctx, pool, &secondary_pipe->stream_res.dsc);
-                       ASSERT(secondary_pipe->stream_res.dsc);
-                       if (secondary_pipe->stream_res.dsc == NULL)
-                               return false;
-               }
-#endif
-       } else {
-               ASSERT(primary_pipe->plane_state);
-               resource_build_scaling_params(primary_pipe);
-               resource_build_scaling_params(secondary_pipe);
-       }
-
-       return true;
+       ASSERT(primary_pipe->plane_state);
+       resource_build_scaling_params(primary_pipe);
+       resource_build_scaling_params(secondary_pipe);
 }
 
 void dcn20_populate_dml_writeback_from_context(
                struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];
                struct dc_stream_state *stream = pipe_ctx->stream;
                struct dsc_config dsc_cfg;
+               struct pipe_ctx *odm_pipe;
+               int opp_cnt = 1;
+
+               for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
+                       opp_cnt++;
 
                /* Only need to validate top pipe */
-               if (pipe_ctx->top_pipe || !stream || !stream->timing.flags.DSC)
+               if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe || !stream || !stream->timing.flags.DSC)
                        continue;
 
-               dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left
-                               + stream->timing.h_border_right;
+               dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left
+                               + stream->timing.h_border_right) / opp_cnt;
                dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top
                                + stream->timing.v_border_bottom;
-               if (dc_res_get_odm_bottom_pipe(pipe_ctx))
-                       dsc_cfg.pic_width /= 2;
                dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
                dsc_cfg.color_depth = stream->timing.display_color_depth;
                dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
+               dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
 
                if (!pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg))
                        return false;
                 * if this primary pipe has a bottom pipe in prev. state
                 * and if the bottom pipe is still available (which it should be),
                 * pick that pipe as secondary
+                * Same logic applies for ODM pipes. Since mpo is not allowed with odm
+                * check in else case.
                 */
                if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) {
                        preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx;
                                secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
                                secondary_pipe->pipe_idx = preferred_pipe_idx;
                        }
+               } else if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) {
+                       preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe->pipe_idx;
+                       if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
+                               secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
+                               secondary_pipe->pipe_idx = preferred_pipe_idx;
+                       }
                }
 
                /*
        if (!pipes)
                return false;
 
+       /* merge previously split odm pipes since mode support needs to make the decision */
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+               struct pipe_ctx *odm_pipe = pipe->next_odm_pipe;
+
+               if (pipe->prev_odm_pipe)
+                       continue;
+
+               pipe->next_odm_pipe = NULL;
+               while (odm_pipe) {
+                       struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe;
+
+                       odm_pipe->plane_state = NULL;
+                       odm_pipe->stream = NULL;
+                       odm_pipe->top_pipe = NULL;
+                       odm_pipe->bottom_pipe = NULL;
+                       odm_pipe->prev_odm_pipe = NULL;
+                       odm_pipe->next_odm_pipe = NULL;
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+                       if (odm_pipe->stream_res.dsc)
+                               release_dsc(&context->res_ctx, dc->res_pool, &odm_pipe->stream_res.dsc);
+#endif
+                       /* Clear plane_res and stream_res */
+                       memset(&odm_pipe->plane_res, 0, sizeof(odm_pipe->plane_res));
+                       memset(&odm_pipe->stream_res, 0, sizeof(odm_pipe->stream_res));
+                       odm_pipe = next_odm_pipe;
+               }
+               if (pipe->plane_state)
+                       resource_build_scaling_params(pipe);
+       }
+
+       /* merge previously mpc split pipes since mode support needs to make the decision */
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
                struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe;
                if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state)
                        continue;
 
-               /* merge previously split pipe since mode support needs to make the decision */
                pipe->bottom_pipe = hsplit_pipe->bottom_pipe;
                if (hsplit_pipe->bottom_pipe)
                        hsplit_pipe->bottom_pipe->top_pipe = pipe;
                hsplit_pipe->stream = NULL;
                hsplit_pipe->top_pipe = NULL;
                hsplit_pipe->bottom_pipe = NULL;
-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
-               if (hsplit_pipe->stream_res.dsc && hsplit_pipe->stream_res.dsc != pipe->stream_res.dsc)
-                       release_dsc(&context->res_ctx, dc->res_pool, &hsplit_pipe->stream_res.dsc);
-#endif
+
                /* Clear plane_res and stream_res */
                memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res));
                memset(&hsplit_pipe->stream_res, 0, sizeof(hsplit_pipe->stream_res));
                if (!pipe->top_pipe && !pipe->plane_state && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) {
                        hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe);
                        ASSERT(hsplit_pipe);
-                       if (!dcn20_split_stream_for_combine(
+                       if (!dcn20_split_stream_for_odm(
                                        &context->res_ctx, dc->res_pool,
-                                       pipe, hsplit_pipe,
-                                       true))
+                                       pipe, hsplit_pipe))
                                goto validate_fail;
                        pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx;
                        dcn20_build_mapped_resource(dc, context, pipe->stream);
                                if (!hsplit_pipe)
                                        continue;
 
-                               if (!dcn20_split_stream_for_combine(
+                               if (context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) {
+                                       if (!dcn20_split_stream_for_odm(
+                                                       &context->res_ctx, dc->res_pool,
+                                                       pipe, hsplit_pipe))
+                                               goto validate_fail;
+                               } else
+                                       dcn20_split_stream_for_mpc(
                                                &context->res_ctx, dc->res_pool,
-                                               pipe, hsplit_pipe,
-                                               context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]))
-                                       goto validate_fail;
+                                               pipe, hsplit_pipe);
                                pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx;
                        }
                } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) {
 
                uint64_t m_vid_l = n_vid;
 
                /* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */
-               if (is_two_pixels_per_containter(¶m->timing) || param->odm) {
+               if (is_two_pixels_per_containter(¶m->timing) || param->opp_cnt) {
                        /*this logic should be the same in get_pixel_clock_parameters() */
                        n_multiply = 1;
                }
 
 
        struct pipe_ctx *top_pipe;
        struct pipe_ctx *bottom_pipe;
+       struct pipe_ctx *next_odm_pipe;
+       struct pipe_ctx *prev_odm_pipe;
 
 #ifdef CONFIG_DRM_AMD_DC_DCN1_0
        struct _vcs_dpi_display_dlg_regs_st dlg_regs;
 
        struct dc_link_settings link_settings;
        struct dc_crtc_timing timing;
 #ifdef CONFIG_DRM_AMD_DC_DCN2_0
-       bool odm;
+       int opp_cnt;
 #endif
 };
 
 
 
 unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format);
 
-struct pipe_ctx *dc_res_get_odm_bottom_pipe(struct pipe_ctx *pipe_ctx);
-bool dc_res_is_odm_head_pipe(struct pipe_ctx *pipe_ctx);
-
 #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */