Commit 2b162fd3 authored by Dmytro Laktyushkin's avatar Dmytro Laktyushkin Committed by Alex Deucher

drm/amd/display: update optc odm interface for more than 2 opps

Current optc odm interface only accepts 2 opps, we need to
expand this to allow 4 to 1 odm combine.
Signed-off-by: default avatarDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Reviewed-by: default avatarCharlene Liu <Charlene.Liu@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 1071a0ec
...@@ -287,7 +287,7 @@ void optc1_program_timing( ...@@ -287,7 +287,7 @@ void optc1_program_timing(
h_div_2 = optc1_is_two_pixels_per_containter(&patched_crtc_timing); h_div_2 = optc1_is_two_pixels_per_containter(&patched_crtc_timing);
REG_UPDATE(OTG_H_TIMING_CNTL, REG_UPDATE(OTG_H_TIMING_CNTL,
OTG_H_TIMING_DIV_BY2, h_div_2 || optc1->comb_opp_id != 0xf); OTG_H_TIMING_DIV_BY2, h_div_2 || optc1->opp_count == 2);
} }
...@@ -1513,7 +1513,6 @@ void dcn10_timing_generator_init(struct optc *optc1) ...@@ -1513,7 +1513,6 @@ void dcn10_timing_generator_init(struct optc *optc1)
optc1->min_v_blank_interlace = 5; optc1->min_v_blank_interlace = 5;
optc1->min_h_sync_width = 8; optc1->min_h_sync_width = 8;
optc1->min_v_sync_width = 1; optc1->min_v_sync_width = 1;
optc1->comb_opp_id = 0xf;
} }
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
......
...@@ -494,7 +494,7 @@ struct optc { ...@@ -494,7 +494,7 @@ struct optc {
const struct dcn_optc_shift *tg_shift; const struct dcn_optc_shift *tg_shift;
const struct dcn_optc_mask *tg_mask; const struct dcn_optc_mask *tg_mask;
int comb_opp_id; int opp_count;
uint32_t max_h_total; uint32_t max_h_total;
uint32_t max_v_total; uint32_t max_v_total;
......
...@@ -545,12 +545,14 @@ enum dc_status dcn20_enable_stream_timing( ...@@ -545,12 +545,14 @@ enum dc_status dcn20_enable_stream_timing(
/* TODO check if timing_changed, disable stream if timing changed */ /* TODO check if timing_changed, disable stream if timing changed */
if (odm_pipe) if (odm_pipe) {
int opp_inst[2] = { pipe_ctx->stream_res.opp->inst, odm_pipe->stream_res.opp->inst };
pipe_ctx->stream_res.tg->funcs->set_odm_combine( pipe_ctx->stream_res.tg->funcs->set_odm_combine(
pipe_ctx->stream_res.tg, pipe_ctx->stream_res.tg,
odm_pipe->stream_res.opp->inst, opp_inst, 2,
pipe_ctx->stream->timing.h_addressable/2, &pipe_ctx->stream->timing);
pipe_ctx->stream->timing.pixel_encoding); }
/* HW program guide assume display already disable /* HW program guide assume display already disable
* by unplug sequence. OTG assume stop. * by unplug sequence. OTG assume stop.
*/ */
...@@ -822,13 +824,15 @@ static void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pip ...@@ -822,13 +824,15 @@ static void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pip
{ {
struct pipe_ctx *combine_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx); struct pipe_ctx *combine_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx);
if (combine_pipe) if (combine_pipe) {
int opp_inst[2] = { pipe_ctx->stream_res.opp->inst,
combine_pipe->stream_res.opp->inst };
pipe_ctx->stream_res.tg->funcs->set_odm_combine( pipe_ctx->stream_res.tg->funcs->set_odm_combine(
pipe_ctx->stream_res.tg, pipe_ctx->stream_res.tg,
combine_pipe->stream_res.opp->inst, opp_inst, 2,
pipe_ctx->plane_res.scl_data.h_active, &pipe_ctx->stream->timing);
pipe_ctx->stream->timing.pixel_encoding); } else
else
pipe_ctx->stream_res.tg->funcs->set_odm_bypass( pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing); pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
} }
......
...@@ -224,7 +224,6 @@ void optc2_set_odm_bypass(struct timing_generator *optc, ...@@ -224,7 +224,6 @@ void optc2_set_odm_bypass(struct timing_generator *optc,
struct optc *optc1 = DCN10TG_FROM_TG(optc); struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t h_div_2 = 0; uint32_t h_div_2 = 0;
optc1->comb_opp_id = 0xf;
REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0,
OPTC_NUM_OF_INPUT_SEGMENT, 0, OPTC_NUM_OF_INPUT_SEGMENT, 0,
OPTC_SEG0_SRC_SEL, optc->inst, OPTC_SEG0_SRC_SEL, optc->inst,
...@@ -236,13 +235,16 @@ void optc2_set_odm_bypass(struct timing_generator *optc, ...@@ -236,13 +235,16 @@ void optc2_set_odm_bypass(struct timing_generator *optc,
OTG_H_TIMING_DIV_BY2, h_div_2); OTG_H_TIMING_DIV_BY2, h_div_2);
REG_SET(OPTC_MEMORY_CONFIG, 0, REG_SET(OPTC_MEMORY_CONFIG, 0,
OPTC_MEM_SEL, 0); OPTC_MEM_SEL, 0);
optc1->opp_count = 1;
} }
void optc2_set_odm_combine(struct timing_generator *optc, int combine_opp_id, void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int mpcc_hactive, enum dc_pixel_encoding pixel_encoding) struct dc_crtc_timing *timing)
{ {
struct optc *optc1 = DCN10TG_FROM_TG(optc); struct optc *optc1 = DCN10TG_FROM_TG(optc);
/* 2 pieces of memory required for up to 5120 displays, 4 for up to 8192 */ /* 2 pieces of memory required for up to 5120 displays, 4 for up to 8192 */
int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right)
/ opp_cnt;
int memory_mask = mpcc_hactive <= 2560 ? 0x3 : 0xf; int memory_mask = mpcc_hactive <= 2560 ? 0x3 : 0xf;
uint32_t data_fmt = 0; uint32_t data_fmt = 0;
...@@ -257,23 +259,24 @@ void optc2_set_odm_combine(struct timing_generator *optc, int combine_opp_id, ...@@ -257,23 +259,24 @@ void optc2_set_odm_combine(struct timing_generator *optc, int combine_opp_id,
REG_SET(OPTC_MEMORY_CONFIG, 0, REG_SET(OPTC_MEMORY_CONFIG, 0,
OPTC_MEM_SEL, memory_mask << (optc->inst * 4)); OPTC_MEM_SEL, memory_mask << (optc->inst * 4));
if (pixel_encoding == PIXEL_ENCODING_YCBCR422) if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
data_fmt = 1; data_fmt = 1;
else if (pixel_encoding == PIXEL_ENCODING_YCBCR420) else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
data_fmt = 2; data_fmt = 2;
REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt); REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt);
ASSERT(opp_cnt == 2);
REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0,
OPTC_NUM_OF_INPUT_SEGMENT, 1, OPTC_NUM_OF_INPUT_SEGMENT, 1,
OPTC_SEG0_SRC_SEL, optc->inst, OPTC_SEG0_SRC_SEL, opp_id[0],
OPTC_SEG1_SRC_SEL, combine_opp_id); OPTC_SEG1_SRC_SEL, opp_id[1]);
REG_UPDATE(OPTC_WIDTH_CONTROL, REG_UPDATE(OPTC_WIDTH_CONTROL,
OPTC_SEGMENT_WIDTH, mpcc_hactive); OPTC_SEGMENT_WIDTH, mpcc_hactive);
REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_BY2, 1); REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_BY2, 1);
optc1->comb_opp_id = combine_opp_id; optc1->opp_count = opp_cnt;
} }
void optc2_get_optc_source(struct timing_generator *optc, void optc2_get_optc_source(struct timing_generator *optc,
...@@ -538,6 +541,5 @@ void dcn20_timing_generator_init(struct optc *optc1) ...@@ -538,6 +541,5 @@ void dcn20_timing_generator_init(struct optc *optc1)
optc1->min_v_blank_interlace = 5; optc1->min_v_blank_interlace = 5;
optc1->min_h_sync_width = 4;// Minimum HSYNC = 8 pixels asked By HW in the first place for no actual reason. Oculus Rift S will not light up with 8 as it's hsyncWidth is 6. Changing it to 4 to fix that issue. optc1->min_h_sync_width = 4;// Minimum HSYNC = 8 pixels asked By HW in the first place for no actual reason. Oculus Rift S will not light up with 8 as it's hsyncWidth is 6. Changing it to 4 to fix that issue.
optc1->min_v_sync_width = 1; optc1->min_v_sync_width = 1;
optc1->comb_opp_id = 0xf;
} }
...@@ -96,8 +96,8 @@ void optc2_set_dsc_config(struct timing_generator *optc, ...@@ -96,8 +96,8 @@ void optc2_set_dsc_config(struct timing_generator *optc,
void optc2_set_odm_bypass(struct timing_generator *optc, void optc2_set_odm_bypass(struct timing_generator *optc,
const struct dc_crtc_timing *dc_crtc_timing); const struct dc_crtc_timing *dc_crtc_timing);
void optc2_set_odm_combine(struct timing_generator *optc, int combine_opp_id, void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int mpcc_hactive, enum dc_pixel_encoding pixel_encoding); struct dc_crtc_timing *timing);
void optc2_get_optc_source(struct timing_generator *optc, void optc2_get_optc_source(struct timing_generator *optc,
uint32_t *num_of_src_opp, uint32_t *num_of_src_opp,
......
...@@ -267,9 +267,9 @@ struct timing_generator_funcs { ...@@ -267,9 +267,9 @@ struct timing_generator_funcs {
uint32_t dsc_bytes_per_pixel, uint32_t dsc_bytes_per_pixel,
uint32_t dsc_slice_width); uint32_t dsc_slice_width);
#endif #endif
void (*set_odm_bypass)(struct timing_generator *tg, const struct dc_crtc_timing *dc_crtc_timing); void (*set_odm_bypass)(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing);
void (*set_odm_combine)(struct timing_generator *tg, int combine_opp_id, void (*set_odm_combine)(struct timing_generator *optc, int *opp_id, int opp_cnt,
int mpcc_hactive, enum dc_pixel_encoding pixel_encoding); struct dc_crtc_timing *timing);
void (*set_gsl)(struct timing_generator *optc, const struct gsl_params *params); void (*set_gsl)(struct timing_generator *optc, const struct gsl_params *params);
void (*set_gsl_source_select)(struct timing_generator *optc, void (*set_gsl_source_select)(struct timing_generator *optc,
int group_idx, int group_idx,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment