Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: use even ODM slice width for two pixels per container

[why]
When optc uses two pixel per container, each ODM slice width must be an
even number.

[how]
If ODM slice width is odd number increase it by 1.

Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Acked-by: Wayne Lin <wayne.lin@amd.com>
Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Wenjing Liu and committed by
Alex Deucher
e6a901a0 a8baec46

+103 -64
+8
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
··· 827 827 stream->timing.h_border_right; 828 828 int odm_slice_width = h_active / odm_slice_count; 829 829 struct rect odm_rec; 830 + bool is_two_pixels_per_container = 831 + pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); 832 + 833 + if ((odm_slice_width % 2) && is_two_pixels_per_container) 834 + odm_slice_width++; 830 835 831 836 odm_rec.x = odm_slice_width * odm_slice_idx; 832 837 odm_rec.width = is_last_odm_slice ? ··· 1469 1464 int v_active = otg_master->stream->timing.v_addressable + 1470 1465 otg_master->stream->timing.v_border_bottom + 1471 1466 otg_master->stream->timing.v_border_top; 1467 + bool is_two_pixels_per_container = otg_master->stream_res.tg->funcs->is_two_pixels_per_container(&otg_master->stream->timing); 1472 1468 int i; 1473 1469 1474 1470 controller_test_pattern = convert_dp_to_controller_test_pattern( ··· 1483 1477 odm_cnt = resource_get_opp_heads_for_otg_master(otg_master, res_ctx, opp_heads); 1484 1478 1485 1479 odm_slice_width = h_active / odm_cnt; 1480 + if ((odm_slice_width % 2) && is_two_pixels_per_container) 1481 + odm_slice_width++; 1486 1482 last_odm_slice_width = h_active - odm_slice_width * (odm_cnt - 1); 1487 1483 1488 1484 for (i = 0; i < odm_cnt; i++) {
+18
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
··· 2015 2015 return dce110_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE); 2016 2016 } 2017 2017 2018 + /* "Container" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this: 2019 + * 2020 + * - 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 2021 + * container rate. 2022 + * 2023 + * - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be 2024 + * halved to maintain the correct pixel rate. 2025 + * 2026 + * - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied 2027 + * 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. 2028 + * 2029 + */ 2030 + bool dce110_is_two_pixels_per_container(const struct dc_crtc_timing *timing) 2031 + { 2032 + return timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; 2033 + } 2034 + 2018 2035 void dce110_tg_wait_for_state(struct timing_generator *tg, 2019 2036 enum crtc_state state) 2020 2037 { ··· 2256 2239 .is_tg_enabled = dce110_is_tg_enabled, 2257 2240 .configure_crc = dce110_configure_crc, 2258 2241 .get_crc = dce110_get_crc, 2242 + .is_two_pixels_per_container = dce110_is_two_pixels_per_container, 2259 2243 }; 2260 2244 2261 2245 void dce110_timing_generator_construct(
+2
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
··· 288 288 bool dce110_get_crc(struct timing_generator *tg, 289 289 uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb); 290 290 291 + bool dce110_is_two_pixels_per_container(const struct dc_crtc_timing *timing); 292 + 291 293 #endif /* __DC_TIMING_GENERATOR_DCE110_H__ */
+2 -1
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
··· 682 682 .tear_down_global_swap_lock = 683 683 dce110_timing_generator_v_tear_down_global_swap_lock, 684 684 .enable_advanced_request = 685 - dce110_timing_generator_v_enable_advanced_request 685 + dce110_timing_generator_v_enable_advanced_request, 686 + .is_two_pixels_per_container = dce110_is_two_pixels_per_container, 686 687 }; 687 688 688 689 void dce110_timing_generator_v_construct(
+1
drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
··· 1197 1197 .is_tg_enabled = dce120_is_tg_enabled, 1198 1198 .configure_crc = dce120_configure_crc, 1199 1199 .get_crc = dce120_get_crc, 1200 + .is_two_pixels_per_container = dce110_is_two_pixels_per_container, 1200 1201 }; 1201 1202 1202 1203
+1
drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
··· 220 220 dce80_timing_generator_enable_advanced_request, 221 221 .configure_crc = dce110_configure_crc, 222 222 .get_crc = dce110_get_crc, 223 + .is_two_pixels_per_container = dce110_is_two_pixels_per_container, 223 224 }; 224 225 225 226 void dce80_timing_generator_construct(
+1 -1
drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
··· 941 941 temp_pipe->stream = pipe->stream; 942 942 temp_pipe->plane_state = pipe->plane_state; 943 943 temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps; 944 - 944 + temp_pipe->stream_res = pipe->stream_res; 945 945 resource_build_scaling_params(temp_pipe); 946 946 break; 947 947 }
+14 -5
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
··· 758 758 } 759 759 760 760 static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream, 761 - int opp_cnt) 761 + int opp_cnt, bool is_two_pixels_per_container) 762 762 { 763 - bool hblank_halved = optc2_is_two_pixels_per_containter(&stream->timing); 763 + bool hblank_halved = is_two_pixels_per_container; 764 764 int flow_ctrl_cnt; 765 765 766 766 if (opp_cnt >= 2) ··· 827 827 int i; 828 828 struct mpc_dwb_flow_control flow_control; 829 829 struct mpc *mpc = dc->res_pool->mpc; 830 - bool rate_control_2x_pclk = (interlace || optc2_is_two_pixels_per_containter(&stream->timing)); 830 + bool is_two_pixels_per_container = 831 + pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); 832 + bool rate_control_2x_pclk = (interlace || is_two_pixels_per_container); 831 833 unsigned int k1_div = PIXEL_RATE_DIV_NA; 832 834 unsigned int k2_div = PIXEL_RATE_DIV_NA; 833 835 ··· 915 913 rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1; 916 914 flow_control.flow_ctrl_mode = 0; 917 915 flow_control.flow_ctrl_cnt0 = 0x80; 918 - flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(stream, opp_cnt); 916 + flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(stream, opp_cnt, 917 + is_two_pixels_per_container); 919 918 if (mpc->funcs->set_out_rate_control) { 920 919 for (i = 0; i < opp_cnt; ++i) { 921 920 mpc->funcs->set_out_rate_control( ··· 1207 1204 int h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; 1208 1205 int v_active = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top; 1209 1206 int odm_slice_width, last_odm_slice_width, offset = 0; 1207 + bool is_two_pixels_per_container = 1208 + pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); 1210 1209 1211 1210 if (stream->link->test_pattern_enabled) 1212 1211 return; ··· 1219 1214 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) 1220 1215 odm_cnt++; 1221 1216 odm_slice_width = h_active / odm_cnt; 1217 + if ((odm_slice_width % 2) && is_two_pixels_per_container) 1218 + odm_slice_width++; 1222 1219 last_odm_slice_width = h_active - odm_slice_width * (odm_cnt - 1); 1223 1220 1224 1221 if (blank) { ··· 2643 2636 struct dc_link *link = stream->link; 2644 2637 struct dce_hwseq *hws = link->dc->hwseq; 2645 2638 struct pipe_ctx *odm_pipe; 2639 + bool is_two_pixels_per_container = 2640 + pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); 2646 2641 2647 2642 params.opp_cnt = 1; 2648 2643 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { ··· 2661 2652 pipe_ctx->stream_res.hpo_dp_stream_enc, 2662 2653 pipe_ctx->stream_res.tg->inst); 2663 2654 } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { 2664 - if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1) 2655 + if (is_two_pixels_per_container || params.opp_cnt > 1) 2665 2656 params.timing.pix_clk_100hz /= 2; 2666 2657 pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine( 2667 2658 pipe_ctx->stream_res.stream_enc, params.opp_cnt > 1);
+1 -1
drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
··· 604 604 605 605 if (dc_is_dp_signal(pipe_ctx->stream->signal)) { 606 606 /*check whether it is half the rate*/ 607 - if (optc201_is_two_pixels_per_containter(&stream->timing)) 607 + if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing)) 608 608 params.timing.pix_clk_100hz /= 2; 609 609 610 610 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, &params);
+2 -2
drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
··· 302 302 unsigned int odm_combine_factor = 0; 303 303 bool two_pix_per_container = false; 304 304 305 - two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing); 305 + two_pix_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); 306 306 odm_combine_factor = get_odm_config(pipe_ctx, NULL); 307 307 308 308 if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { ··· 341 341 return; 342 342 343 343 odm_combine_factor = get_odm_config(pipe_ctx, NULL); 344 - if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1) 344 + if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&pipe_ctx->stream->timing) || odm_combine_factor > 1) 345 345 pix_per_cycle = 2; 346 346 347 347 if (pipe_ctx->stream_res.stream_enc->funcs->set_input_mode)
+3 -3
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
··· 1143 1143 unsigned int odm_combine_factor = 0; 1144 1144 bool two_pix_per_container = false; 1145 1145 1146 - two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing); 1146 + two_pix_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); 1147 1147 odm_combine_factor = get_odm_config(pipe_ctx, NULL); 1148 1148 1149 1149 if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { ··· 1182 1182 return; 1183 1183 1184 1184 odm_combine_factor = get_odm_config(pipe_ctx, NULL); 1185 - if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1 1185 + if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&pipe_ctx->stream->timing) || odm_combine_factor > 1 1186 1186 || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) 1187 1187 pix_per_cycle = 2; 1188 1188 ··· 1246 1246 pipe_ctx->stream_res.hpo_dp_stream_enc, 1247 1247 pipe_ctx->stream_res.tg->inst); 1248 1248 } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { 1249 - if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1 1249 + if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing) || params.opp_cnt > 1 1250 1250 || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) { 1251 1251 params.timing.pix_clk_100hz /= 2; 1252 1252 pix_per_cycle = 2;
+2 -2
drivers/gpu/drm/amd/display/dc/inc/hw/optc.h
··· 212 212 uint32_t *g_y, 213 213 uint32_t *b_cb); 214 214 215 - bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing); 216 - 217 215 void optc1_set_vtg_params(struct timing_generator *optc, 218 216 const struct dc_crtc_timing *dc_crtc_timing, 219 217 bool program_fp2); 218 + 219 + bool optc1_is_two_pixels_per_container(const struct dc_crtc_timing *timing); 220 220 221 221 #endif
+1
drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
··· 276 276 uint32_t *num_of_input_segments, 277 277 uint32_t *seg0_src_sel, 278 278 uint32_t *seg1_src_sel); 279 + bool (*is_two_pixels_per_container)(const struct dc_crtc_timing *timing); 279 280 280 281 /** 281 282 * Configure CRCs for the given timing generator. Return false if TG is
+23 -23
drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c
··· 297 297 * of stereo handled in explicit call 298 298 */ 299 299 300 - if (optc1_is_two_pixels_per_containter(&patched_crtc_timing) || optc1->opp_count == 2) 300 + if (optc->funcs->is_two_pixels_per_container(&patched_crtc_timing) || optc1->opp_count == 2) 301 301 h_div = H_TIMING_DIV_BY2; 302 302 303 303 if (REG(OPTC_DATA_FORMAT_CONTROL) && optc1->tg_mask->OPTC_DATA_FORMAT != 0) { ··· 1548 1548 return true; 1549 1549 } 1550 1550 1551 + /* "Container" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this: 1552 + * 1553 + * - 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 1554 + * container rate. 1555 + * 1556 + * - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be 1557 + * halved to maintain the correct pixel rate. 1558 + * 1559 + * - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied 1560 + * 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. 1561 + * 1562 + */ 1563 + bool optc1_is_two_pixels_per_container(const struct dc_crtc_timing *timing) 1564 + { 1565 + bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; 1566 + 1567 + two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 1568 + && !timing->dsc_cfg.ycbcr422_simple); 1569 + return two_pix; 1570 + } 1571 + 1551 1572 static const struct timing_generator_funcs dcn10_tg_funcs = { 1552 1573 .validate_timing = optc1_validate_timing, 1553 1574 .program_timing = optc1_program_timing, ··· 1615 1594 .program_manual_trigger = optc1_program_manual_trigger, 1616 1595 .setup_manual_trigger = optc1_setup_manual_trigger, 1617 1596 .get_hw_timing = optc1_get_hw_timing, 1597 + .is_two_pixels_per_container = optc1_is_two_pixels_per_container, 1618 1598 }; 1619 1599 1620 1600 void dcn10_timing_generator_init(struct optc *optc1) ··· 1631 1609 optc1->min_h_sync_width = 4; 1632 1610 optc1->min_v_sync_width = 1; 1633 1611 } 1634 - 1635 - /* "Containter" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this: 1636 - * 1637 - * - 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 1638 - * containter rate. 1639 - * 1640 - * - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be 1641 - * halved to maintain the correct pixel rate. 1642 - * 1643 - * - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied 1644 - * 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. 1645 - * 1646 - */ 1647 - bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) 1648 - { 1649 - bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; 1650 - 1651 - two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 1652 - && !timing->dsc_cfg.ycbcr422_simple); 1653 - return two_pix; 1654 - } 1655 -
+2 -8
drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c
··· 158 158 OPTC_DSC_MODE, dsc_mode); 159 159 } 160 160 161 - 162 - /*TEMP: Need to figure out inheritance model here.*/ 163 - bool optc2_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) 164 - { 165 - return optc1_is_two_pixels_per_containter(timing); 166 - } 167 - 168 161 void optc2_set_odm_bypass(struct timing_generator *optc, 169 162 const struct dc_crtc_timing *dc_crtc_timing) 170 163 { ··· 170 177 OPTC_SEG1_SRC_SEL, 0xf); 171 178 REG_WRITE(OTG_H_TIMING_CNTL, 0); 172 179 173 - h_div_2 = optc2_is_two_pixels_per_containter(dc_crtc_timing); 180 + h_div_2 = optc->funcs->is_two_pixels_per_container(dc_crtc_timing); 174 181 REG_UPDATE(OTG_H_TIMING_CNTL, 175 182 OTG_H_TIMING_DIV_BY2, h_div_2); 176 183 REG_SET(OPTC_MEMORY_CONFIG, 0, ··· 553 560 .setup_manual_trigger = optc2_setup_manual_trigger, 554 561 .get_hw_timing = optc1_get_hw_timing, 555 562 .align_vblanks = optc2_align_vblanks, 563 + .is_two_pixels_per_container = optc1_is_two_pixels_per_container, 556 564 }; 557 565 558 566 void dcn20_timing_generator_init(struct optc *optc1)
-1
drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.h
··· 118 118 void optc2_lock_doublebuffer_enable(struct timing_generator *optc); 119 119 void optc2_setup_manual_trigger(struct timing_generator *optc); 120 120 void optc2_program_manual_trigger(struct timing_generator *optc); 121 - bool optc2_is_two_pixels_per_containter(const struct dc_crtc_timing *timing); 122 121 bool optc2_configure_crc(struct timing_generator *optc, 123 122 const struct crc_params *params); 124 123 #endif /* __DC_OPTC_DCN20_H__ */
+1 -6
drivers/gpu/drm/amd/display/dc/optc/dcn201/dcn201_optc.c
··· 38 38 #define FN(reg_name, field_name) \ 39 39 optc1->tg_shift->field_name, optc1->tg_mask->field_name 40 40 41 - /*TEMP: Need to figure out inheritance model here.*/ 42 - bool optc201_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) 43 - { 44 - return optc1_is_two_pixels_per_containter(timing); 45 - } 46 - 47 41 static void optc201_triplebuffer_lock(struct timing_generator *optc) 48 42 { 49 43 struct optc *optc1 = DCN10TG_FROM_TG(optc); ··· 179 185 .program_manual_trigger = optc2_program_manual_trigger, 180 186 .setup_manual_trigger = optc2_setup_manual_trigger, 181 187 .get_hw_timing = optc1_get_hw_timing, 188 + .is_two_pixels_per_container = optc1_is_two_pixels_per_container, 182 189 }; 183 190 184 191 void dcn201_timing_generator_init(struct optc *optc1)
-3
drivers/gpu/drm/amd/display/dc/optc/dcn201/dcn201_optc.h
··· 68 68 SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh) 69 69 70 70 void dcn201_timing_generator_init(struct optc *optc); 71 - 72 - bool optc201_is_two_pixels_per_containter(const struct dc_crtc_timing *timing); 73 - 74 71 #endif
+2 -1
drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c
··· 206 206 OPTC_SEG3_SRC_SEL, 0xf 207 207 ); 208 208 209 - h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing); 209 + h_div = optc->funcs->is_two_pixels_per_container(dc_crtc_timing); 210 210 REG_UPDATE(OTG_H_TIMING_CNTL, 211 211 OTG_H_TIMING_DIV_MODE, h_div); 212 212 ··· 376 376 .setup_manual_trigger = optc2_setup_manual_trigger, 377 377 .get_hw_timing = optc1_get_hw_timing, 378 378 .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear, 379 + .is_two_pixels_per_container = optc1_is_two_pixels_per_container, 379 380 }; 380 381 381 382 void dcn30_timing_generator_init(struct optc *optc1)
+1
drivers/gpu/drm/amd/display/dc/optc/dcn301/dcn301_optc.c
··· 168 168 .setup_manual_trigger = optc301_setup_manual_trigger, 169 169 .get_hw_timing = optc1_get_hw_timing, 170 170 .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear, 171 + .is_two_pixels_per_container = optc1_is_two_pixels_per_container, 171 172 }; 172 173 173 174 void dcn301_timing_generator_init(struct optc *optc1)
+1
drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c
··· 292 292 .setup_manual_trigger = optc2_setup_manual_trigger, 293 293 .get_hw_timing = optc1_get_hw_timing, 294 294 .init_odm = optc3_init_odm, 295 + .is_two_pixels_per_container = optc1_is_two_pixels_per_container, 295 296 }; 296 297 297 298 void dcn31_timing_generator_init(struct optc *optc1)
+2 -1
drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c
··· 175 175 OPTC_SEG3_SRC_SEL, 0xf 176 176 ); 177 177 178 - h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing); 178 + h_div = optc->funcs->is_two_pixels_per_container(dc_crtc_timing); 179 179 REG_UPDATE(OTG_H_TIMING_CNTL, 180 180 OTG_H_TIMING_DIV_MODE, h_div); 181 181 ··· 255 255 .set_odm_bypass = optc314_set_odm_bypass, 256 256 .set_odm_combine = optc314_set_odm_combine, 257 257 .set_h_timing_div_manual_mode = optc314_set_h_timing_div_manual_mode, 258 + .is_two_pixels_per_container = optc1_is_two_pixels_per_container, 258 259 }; 259 260 260 261 void dcn314_timing_generator_init(struct optc *optc1)
+2 -1
drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
··· 239 239 OPTC_SEG3_SRC_SEL, 0xf 240 240 ); 241 241 242 - h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing); 242 + h_div = optc->funcs->is_two_pixels_per_container(dc_crtc_timing); 243 243 REG_UPDATE(OTG_H_TIMING_CNTL, 244 244 OTG_H_TIMING_DIV_MODE, h_div); 245 245 ··· 361 361 .program_manual_trigger = optc2_program_manual_trigger, 362 362 .setup_manual_trigger = optc2_setup_manual_trigger, 363 363 .get_hw_timing = optc1_get_hw_timing, 364 + .is_two_pixels_per_container = optc1_is_two_pixels_per_container, 364 365 }; 365 366 366 367 void dcn32_timing_generator_init(struct optc *optc1)
+1
drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
··· 438 438 .get_hw_timing = optc1_get_hw_timing, 439 439 .init_odm = optc3_init_odm, 440 440 .set_long_vtotal = optc35_set_long_vtotal, 441 + .is_two_pixels_per_container = optc1_is_two_pixels_per_container, 441 442 }; 442 443 443 444 void dcn35_timing_generator_init(struct optc *optc1)
+11 -4
drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
··· 107 107 struct optc *optc1 = DCN10TG_FROM_TG(optc); 108 108 uint32_t h_active = timing->h_addressable + 109 109 timing->h_border_left + timing->h_border_right; 110 - uint32_t odm_segment_width = h_active / opp_cnt; 111 - uint32_t odm_segment_width_last = 112 - h_active - odm_segment_width * (opp_cnt - 1); 113 110 uint32_t odm_mem_bit_map = decide_odm_mem_bit_map( 114 111 opp_id, opp_cnt, h_active); 112 + uint32_t odm_segment_width; 113 + uint32_t odm_segment_width_last; 114 + bool is_two_pixels_per_container = optc->funcs->is_two_pixels_per_container(timing); 115 + 116 + odm_segment_width = h_active / opp_cnt; 117 + if ((odm_segment_width % 2) && is_two_pixels_per_container) 118 + odm_segment_width++; 119 + odm_segment_width_last = 120 + h_active - odm_segment_width * (opp_cnt - 1); 115 121 116 122 REG_SET(OPTC_MEMORY_CONFIG, 0, 117 123 OPTC_MEM_SEL, odm_mem_bit_map); ··· 283 277 OPTC_SEG3_SRC_SEL, 0xf 284 278 ); 285 279 286 - h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing); 280 + h_div = optc->funcs->is_two_pixels_per_container(dc_crtc_timing); 287 281 REG_UPDATE(OTG_H_TIMING_CNTL, 288 282 OTG_H_TIMING_DIV_MODE, h_div); 289 283 ··· 467 461 .program_manual_trigger = optc2_program_manual_trigger, 468 462 .setup_manual_trigger = optc2_setup_manual_trigger, 469 463 .get_hw_timing = optc1_get_hw_timing, 464 + .is_two_pixels_per_container = optc1_is_two_pixels_per_container, 470 465 }; 471 466 472 467 void dcn401_timing_generator_init(struct optc *optc1)
+1 -1
drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
··· 1251 1251 1252 1252 if (opp_cnt == 4) 1253 1253 pixel_clk_params->requested_pix_clk_100hz /= 4; 1254 - else if (optc2_is_two_pixels_per_containter(&stream->timing) || opp_cnt == 2) 1254 + else if (pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing) || opp_cnt == 2) 1255 1255 pixel_clk_params->requested_pix_clk_100hz /= 2; 1256 1256 else if (hws->funcs.is_dp_dig_pixel_rate_div_policy) { 1257 1257 if (hws->funcs.is_dp_dig_pixel_rate_div_policy(pipe_ctx))