stream->timing.h_border_right;
        int odm_slice_width = h_active / odm_slice_count;
        struct rect odm_rec;
+       bool is_two_pixels_per_container =
+                       pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing);
+
+       if ((odm_slice_width % 2) && is_two_pixels_per_container)
+               odm_slice_width++;
 
        odm_rec.x = odm_slice_width * odm_slice_idx;
        odm_rec.width = is_last_odm_slice ?
        int v_active = otg_master->stream->timing.v_addressable +
                otg_master->stream->timing.v_border_bottom +
                otg_master->stream->timing.v_border_top;
+       bool is_two_pixels_per_container = otg_master->stream_res.tg->funcs->is_two_pixels_per_container(&otg_master->stream->timing);
        int i;
 
        controller_test_pattern = convert_dp_to_controller_test_pattern(
        odm_cnt = resource_get_opp_heads_for_otg_master(otg_master, res_ctx, opp_heads);
 
        odm_slice_width = h_active / odm_cnt;
+       if ((odm_slice_width % 2) && is_two_pixels_per_container)
+               odm_slice_width++;
        last_odm_slice_width = h_active - odm_slice_width * (odm_cnt - 1);
 
        for (i = 0; i < odm_cnt; i++) {
 
        return dce110_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
 }
 
+/* "Container" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this:
+ *
+ * - In most of the formats (RGB or YCbCr 4:4:4, 4:2:2 uncompressed and DSC 4:2:2 Simple) pixel rate is the same as
+ *   container rate.
+ *
+ * - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be
+ *   halved to maintain the correct pixel rate.
+ *
+ * - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied
+ *   to it) and has to be treated the same as 4:2:0, i.e. target containter rate has to be halved in this case as well.
+ *
+ */
+bool dce110_is_two_pixels_per_container(const struct dc_crtc_timing *timing)
+{
+       return timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
+}
+
 void dce110_tg_wait_for_state(struct timing_generator *tg,
        enum crtc_state state)
 {
                .is_tg_enabled = dce110_is_tg_enabled,
                .configure_crc = dce110_configure_crc,
                .get_crc = dce110_get_crc,
+               .is_two_pixels_per_container = dce110_is_two_pixels_per_container,
 };
 
 void dce110_timing_generator_construct(
 
 bool dce110_get_crc(struct timing_generator *tg,
                    uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb);
 
+bool dce110_is_two_pixels_per_container(const struct dc_crtc_timing *timing);
+
 #endif /* __DC_TIMING_GENERATOR_DCE110_H__ */
 
                .tear_down_global_swap_lock =
                                dce110_timing_generator_v_tear_down_global_swap_lock,
                .enable_advanced_request =
-                               dce110_timing_generator_v_enable_advanced_request
+                               dce110_timing_generator_v_enable_advanced_request,
+               .is_two_pixels_per_container = dce110_is_two_pixels_per_container,
 };
 
 void dce110_timing_generator_v_construct(
 
                .is_tg_enabled = dce120_is_tg_enabled,
                .configure_crc = dce120_configure_crc,
                .get_crc = dce120_get_crc,
+               .is_two_pixels_per_container = dce110_is_two_pixels_per_container,
 };
 
 
 
                                dce80_timing_generator_enable_advanced_request,
                .configure_crc = dce110_configure_crc,
                .get_crc = dce110_get_crc,
+               .is_two_pixels_per_container = dce110_is_two_pixels_per_container,
 };
 
 void dce80_timing_generator_construct(
 
                        temp_pipe->stream = pipe->stream;
                        temp_pipe->plane_state = pipe->plane_state;
                        temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps;
-
+                       temp_pipe->stream_res = pipe->stream_res;
                        resource_build_scaling_params(temp_pipe);
                        break;
                }
 
 }
 
 static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
-               int opp_cnt)
+               int opp_cnt, bool is_two_pixels_per_container)
 {
-       bool hblank_halved = optc2_is_two_pixels_per_containter(&stream->timing);
+       bool hblank_halved = is_two_pixels_per_container;
        int flow_ctrl_cnt;
 
        if (opp_cnt >= 2)
        int i;
        struct mpc_dwb_flow_control flow_control;
        struct mpc *mpc = dc->res_pool->mpc;
-       bool rate_control_2x_pclk = (interlace || optc2_is_two_pixels_per_containter(&stream->timing));
+       bool is_two_pixels_per_container =
+                       pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing);
+       bool rate_control_2x_pclk = (interlace || is_two_pixels_per_container);
        unsigned int k1_div = PIXEL_RATE_DIV_NA;
        unsigned int k2_div = PIXEL_RATE_DIV_NA;
 
        rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
        flow_control.flow_ctrl_mode = 0;
        flow_control.flow_ctrl_cnt0 = 0x80;
-       flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(stream, opp_cnt);
+       flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(stream, opp_cnt,
+                       is_two_pixels_per_container);
        if (mpc->funcs->set_out_rate_control) {
                for (i = 0; i < opp_cnt; ++i) {
                        mpc->funcs->set_out_rate_control(
        int h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
        int v_active = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
        int odm_slice_width, last_odm_slice_width, offset = 0;
+       bool is_two_pixels_per_container =
+                       pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing);
 
        if (stream->link->test_pattern_enabled)
                return;
        for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
                odm_cnt++;
        odm_slice_width = h_active / odm_cnt;
+       if ((odm_slice_width % 2) && is_two_pixels_per_container)
+               odm_slice_width++;
        last_odm_slice_width = h_active - odm_slice_width * (odm_cnt - 1);
 
        if (blank) {
        struct dc_link *link = stream->link;
        struct dce_hwseq *hws = link->dc->hwseq;
        struct pipe_ctx *odm_pipe;
+       bool is_two_pixels_per_container =
+                       pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing);
 
        params.opp_cnt = 1;
        for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
                                pipe_ctx->stream_res.hpo_dp_stream_enc,
                                pipe_ctx->stream_res.tg->inst);
        } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
-               if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1)
+               if (is_two_pixels_per_container || params.opp_cnt > 1)
                        params.timing.pix_clk_100hz /= 2;
                pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
                                pipe_ctx->stream_res.stream_enc, params.opp_cnt > 1);
 
 
        if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
                /*check whether it is half the rate*/
-               if (optc201_is_two_pixels_per_containter(&stream->timing))
+               if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing))
                        params.timing.pix_clk_100hz /= 2;
 
                pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms);
 
        unsigned int odm_combine_factor = 0;
        bool two_pix_per_container = false;
 
-       two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing);
+       two_pix_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing);
        odm_combine_factor = get_odm_config(pipe_ctx, NULL);
 
        if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) {
                return;
 
        odm_combine_factor = get_odm_config(pipe_ctx, NULL);
-       if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1)
+       if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&pipe_ctx->stream->timing) || odm_combine_factor > 1)
                pix_per_cycle = 2;
 
        if (pipe_ctx->stream_res.stream_enc->funcs->set_input_mode)
 
        unsigned int odm_combine_factor = 0;
        bool two_pix_per_container = false;
 
-       two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing);
+       two_pix_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing);
        odm_combine_factor = get_odm_config(pipe_ctx, NULL);
 
        if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) {
                return;
 
        odm_combine_factor = get_odm_config(pipe_ctx, NULL);
-       if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1
+       if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&pipe_ctx->stream->timing) || odm_combine_factor > 1
                || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx))
                pix_per_cycle = 2;
 
                                pipe_ctx->stream_res.hpo_dp_stream_enc,
                                pipe_ctx->stream_res.tg->inst);
        } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
-               if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1
+               if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing) || params.opp_cnt > 1
                        || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) {
                        params.timing.pix_clk_100hz /= 2;
                        pix_per_cycle = 2;
 
                   uint32_t *g_y,
                   uint32_t *b_cb);
 
-bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing);
-
 void optc1_set_vtg_params(struct timing_generator *optc,
                          const struct dc_crtc_timing *dc_crtc_timing,
                          bool program_fp2);
 
+bool optc1_is_two_pixels_per_container(const struct dc_crtc_timing *timing);
+
 #endif
 
                        uint32_t *num_of_input_segments,
                        uint32_t *seg0_src_sel,
                        uint32_t *seg1_src_sel);
+       bool (*is_two_pixels_per_container)(const struct dc_crtc_timing *timing);
 
        /**
         * Configure CRCs for the given timing generator. Return false if TG is
 
         * of stereo handled in explicit call
         */
 
-       if (optc1_is_two_pixels_per_containter(&patched_crtc_timing) || optc1->opp_count == 2)
+       if (optc->funcs->is_two_pixels_per_container(&patched_crtc_timing) || optc1->opp_count == 2)
                h_div = H_TIMING_DIV_BY2;
 
        if (REG(OPTC_DATA_FORMAT_CONTROL) && optc1->tg_mask->OPTC_DATA_FORMAT != 0) {
        return true;
 }
 
+/* "Container" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this:
+ *
+ * - In most of the formats (RGB or YCbCr 4:4:4, 4:2:2 uncompressed and DSC 4:2:2 Simple) pixel rate is the same as
+ *   container rate.
+ *
+ * - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be
+ *   halved to maintain the correct pixel rate.
+ *
+ * - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied
+ *   to it) and has to be treated the same as 4:2:0, i.e. target containter rate has to be halved in this case as well.
+ *
+ */
+bool optc1_is_two_pixels_per_container(const struct dc_crtc_timing *timing)
+{
+       bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
+
+       two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
+                       && !timing->dsc_cfg.ycbcr422_simple);
+       return two_pix;
+}
+
 static const struct timing_generator_funcs dcn10_tg_funcs = {
                .validate_timing = optc1_validate_timing,
                .program_timing = optc1_program_timing,
                .program_manual_trigger = optc1_program_manual_trigger,
                .setup_manual_trigger = optc1_setup_manual_trigger,
                .get_hw_timing = optc1_get_hw_timing,
+               .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
 };
 
 void dcn10_timing_generator_init(struct optc *optc1)
        optc1->min_h_sync_width = 4;
        optc1->min_v_sync_width = 1;
 }
-
-/* "Containter" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this:
- *
- * - In most of the formats (RGB or YCbCr 4:4:4, 4:2:2 uncompressed and DSC 4:2:2 Simple) pixel rate is the same as
- *   containter rate.
- *
- * - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be
- *   halved to maintain the correct pixel rate.
- *
- * - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied
- *   to it) and has to be treated the same as 4:2:0, i.e. target containter rate has to be halved in this case as well.
- *
- */
-bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
-{
-       bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
-
-       two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
-                       && !timing->dsc_cfg.ycbcr422_simple);
-       return two_pix;
-}
-
 
                OPTC_DSC_MODE, dsc_mode);
 }
 
-
-/*TEMP: Need to figure out inheritance model here.*/
-bool optc2_is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
-{
-       return optc1_is_two_pixels_per_containter(timing);
-}
-
 void optc2_set_odm_bypass(struct timing_generator *optc,
                const struct dc_crtc_timing *dc_crtc_timing)
 {
                        OPTC_SEG1_SRC_SEL, 0xf);
        REG_WRITE(OTG_H_TIMING_CNTL, 0);
 
-       h_div_2 = optc2_is_two_pixels_per_containter(dc_crtc_timing);
+       h_div_2 = optc->funcs->is_two_pixels_per_container(dc_crtc_timing);
        REG_UPDATE(OTG_H_TIMING_CNTL,
                        OTG_H_TIMING_DIV_BY2, h_div_2);
        REG_SET(OPTC_MEMORY_CONFIG, 0,
                .setup_manual_trigger = optc2_setup_manual_trigger,
                .get_hw_timing = optc1_get_hw_timing,
                .align_vblanks = optc2_align_vblanks,
+               .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
 };
 
 void dcn20_timing_generator_init(struct optc *optc1)
 
 void optc2_lock_doublebuffer_enable(struct timing_generator *optc);
 void optc2_setup_manual_trigger(struct timing_generator *optc);
 void optc2_program_manual_trigger(struct timing_generator *optc);
-bool optc2_is_two_pixels_per_containter(const struct dc_crtc_timing *timing);
 bool optc2_configure_crc(struct timing_generator *optc,
                          const struct crc_params *params);
 #endif /* __DC_OPTC_DCN20_H__ */
 
 #define FN(reg_name, field_name) \
        optc1->tg_shift->field_name, optc1->tg_mask->field_name
 
-/*TEMP: Need to figure out inheritance model here.*/
-bool optc201_is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
-{
-       return optc1_is_two_pixels_per_containter(timing);
-}
-
 static void optc201_triplebuffer_lock(struct timing_generator *optc)
 {
        struct optc *optc1 = DCN10TG_FROM_TG(optc);
                .program_manual_trigger = optc2_program_manual_trigger,
                .setup_manual_trigger = optc2_setup_manual_trigger,
                .get_hw_timing = optc1_get_hw_timing,
+               .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
 };
 
 void dcn201_timing_generator_init(struct optc *optc1)
 
        SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh)
 
 void dcn201_timing_generator_init(struct optc *optc);
-
-bool optc201_is_two_pixels_per_containter(const struct dc_crtc_timing *timing);
-
 #endif
 
                        OPTC_SEG3_SRC_SEL, 0xf
                        );
 
-       h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing);
+       h_div = optc->funcs->is_two_pixels_per_container(dc_crtc_timing);
        REG_UPDATE(OTG_H_TIMING_CNTL,
                        OTG_H_TIMING_DIV_MODE, h_div);
 
                .setup_manual_trigger = optc2_setup_manual_trigger,
                .get_hw_timing = optc1_get_hw_timing,
                .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear,
+               .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
 };
 
 void dcn30_timing_generator_init(struct optc *optc1)
 
                .setup_manual_trigger = optc301_setup_manual_trigger,
                .get_hw_timing = optc1_get_hw_timing,
                .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear,
+               .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
 };
 
 void dcn301_timing_generator_init(struct optc *optc1)
 
                .setup_manual_trigger = optc2_setup_manual_trigger,
                .get_hw_timing = optc1_get_hw_timing,
                .init_odm = optc3_init_odm,
+               .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
 };
 
 void dcn31_timing_generator_init(struct optc *optc1)
 
                        OPTC_SEG3_SRC_SEL, 0xf
                        );
 
-       h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing);
+       h_div = optc->funcs->is_two_pixels_per_container(dc_crtc_timing);
        REG_UPDATE(OTG_H_TIMING_CNTL,
                        OTG_H_TIMING_DIV_MODE, h_div);
 
                .set_odm_bypass = optc314_set_odm_bypass,
                .set_odm_combine = optc314_set_odm_combine,
                .set_h_timing_div_manual_mode = optc314_set_h_timing_div_manual_mode,
+               .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
 };
 
 void dcn314_timing_generator_init(struct optc *optc1)
 
                        OPTC_SEG3_SRC_SEL, 0xf
                        );
 
-       h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing);
+       h_div = optc->funcs->is_two_pixels_per_container(dc_crtc_timing);
        REG_UPDATE(OTG_H_TIMING_CNTL,
                        OTG_H_TIMING_DIV_MODE, h_div);
 
                .program_manual_trigger = optc2_program_manual_trigger,
                .setup_manual_trigger = optc2_setup_manual_trigger,
                .get_hw_timing = optc1_get_hw_timing,
+               .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
 };
 
 void dcn32_timing_generator_init(struct optc *optc1)
 
                .get_hw_timing = optc1_get_hw_timing,
                .init_odm = optc3_init_odm,
                .set_long_vtotal = optc35_set_long_vtotal,
+               .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
 };
 
 void dcn35_timing_generator_init(struct optc *optc1)
 
        struct optc *optc1 = DCN10TG_FROM_TG(optc);
        uint32_t h_active = timing->h_addressable +
                        timing->h_border_left + timing->h_border_right;
-       uint32_t odm_segment_width = h_active / opp_cnt;
-       uint32_t odm_segment_width_last =
-                       h_active - odm_segment_width * (opp_cnt - 1);
        uint32_t odm_mem_bit_map = decide_odm_mem_bit_map(
                        opp_id, opp_cnt, h_active);
+       uint32_t odm_segment_width;
+       uint32_t odm_segment_width_last;
+       bool is_two_pixels_per_container = optc->funcs->is_two_pixels_per_container(timing);
+
+       odm_segment_width = h_active / opp_cnt;
+       if ((odm_segment_width % 2) && is_two_pixels_per_container)
+               odm_segment_width++;
+       odm_segment_width_last =
+                       h_active - odm_segment_width * (opp_cnt - 1);
 
        REG_SET(OPTC_MEMORY_CONFIG, 0,
                OPTC_MEM_SEL, odm_mem_bit_map);
                        OPTC_SEG3_SRC_SEL, 0xf
                        );
 
-       h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing);
+       h_div = optc->funcs->is_two_pixels_per_container(dc_crtc_timing);
        REG_UPDATE(OTG_H_TIMING_CNTL,
                        OTG_H_TIMING_DIV_MODE, h_div);
 
                .program_manual_trigger = optc2_program_manual_trigger,
                .setup_manual_trigger = optc2_setup_manual_trigger,
                .get_hw_timing = optc1_get_hw_timing,
+               .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
 };
 
 void dcn401_timing_generator_init(struct optc *optc1)
 
 
        if (opp_cnt == 4)
                pixel_clk_params->requested_pix_clk_100hz /= 4;
-       else if (optc2_is_two_pixels_per_containter(&stream->timing) || opp_cnt == 2)
+       else if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing) || opp_cnt == 2)
                pixel_clk_params->requested_pix_clk_100hz /= 2;
        else if (hws->funcs.is_dp_dig_pixel_rate_div_policy) {
                if (hws->funcs.is_dp_dig_pixel_rate_div_policy(pipe_ctx))