Loading drivers/gpu/drm/msm/sde/sde_encoder.c +115 −4 Original line number Diff line number Diff line Loading @@ -67,7 +67,7 @@ #define MAX_PHYS_ENCODERS_PER_VIRTUAL \ (MAX_H_TILES_PER_DISPLAY * NUM_PHYS_ENCODER_TYPES) #define MAX_CHANNELS_PER_ENC 2 #define MAX_CHANNELS_PER_ENC 4 #define MISR_BUFF_SIZE 256 Loading Loading @@ -420,7 +420,8 @@ bool sde_encoder_is_dsc_merge(struct drm_encoder *drm_enc) return false; topology = sde_connector_get_topology_name(drm_conn); if (topology == SDE_RM_TOPOLOGY_DUALPIPE_DSCMERGE) if (topology == SDE_RM_TOPOLOGY_DUALPIPE_DSCMERGE || topology == SDE_RM_TOPOLOGY_QUADPIPE_DSCMERGE) return true; return false; Loading Loading @@ -1182,6 +1183,113 @@ static int _sde_encoder_dsc_n_lm_1_enc_1_intf(struct sde_encoder_virt *sde_enc) return 0; } static int _sde_encoder_dsc_4_lm_4_enc_2_intf(struct sde_encoder_virt *sde_enc, struct sde_encoder_kickoff_params *params) { int this_frame_slices; int intf_ip_w, enc_ip_w; int ich_res, dsc_common_mode; struct sde_encoder_phys *enc_master = sde_enc->cur_master; const struct sde_rect *roi = &sde_enc->cur_conn_roi; struct sde_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; struct sde_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC]; struct msm_display_dsc_info dsc[MAX_CHANNELS_PER_ENC]; struct msm_mode_info mode_info; bool half_panel_partial_update; int i, rc; memset(hw_dsc, 0, sizeof(struct sde_hw_dsc *)*MAX_CHANNELS_PER_ENC); memset(hw_pp, 0, sizeof(struct sde_hw_pingpong *)*MAX_CHANNELS_PER_ENC); for (i = 0; i < params->num_channels; i++) { hw_pp[i] = sde_enc->hw_pp[i]; hw_dsc[i] = sde_enc->hw_dsc[i]; if (!hw_pp[i] || !hw_dsc[i]) { SDE_ERROR_ENC(sde_enc, "invalid params for DSC\n"); return -EINVAL; } } rc = _sde_encoder_get_mode_info(&sde_enc->base, &mode_info); if (rc) { SDE_ERROR_ENC(sde_enc, "failed to get mode info\n"); return -EINVAL; } half_panel_partial_update = hweight_long(params->affected_displays) == 1; dsc_common_mode = 0; if (!half_panel_partial_update) dsc_common_mode |= DSC_MODE_SPLIT_PANEL | DSC_MODE_MULTIPLEX; if (enc_master->intf_mode == INTF_MODE_VIDEO) dsc_common_mode |= DSC_MODE_VIDEO; memcpy(&dsc[0], &mode_info.comp_info.dsc_info, sizeof(dsc[0])); memcpy(&dsc[1], &mode_info.comp_info.dsc_info, sizeof(dsc[1])); memcpy(&dsc[2], &mode_info.comp_info.dsc_info, sizeof(dsc[2])); memcpy(&dsc[3], &mode_info.comp_info.dsc_info, sizeof(dsc[3])); /* * Since both DSC use same pic dimension, set same pic dimension * to both DSC structures. */ _sde_encoder_dsc_update_pic_dim(&dsc[0], roi->w, roi->h); _sde_encoder_dsc_update_pic_dim(&dsc[1], roi->w, roi->h); _sde_encoder_dsc_update_pic_dim(&dsc[2], roi->w, roi->h); _sde_encoder_dsc_update_pic_dim(&dsc[3], roi->w, roi->h); this_frame_slices = roi->w / dsc[0].slice_width; intf_ip_w = this_frame_slices * dsc[0].slice_width; if (!half_panel_partial_update) intf_ip_w /= 2; /* * In this topology when both interfaces are active, they have same * load so intf_ip_w will be same. */ _sde_encoder_dsc_pclk_param_calc(&dsc[0], intf_ip_w); _sde_encoder_dsc_pclk_param_calc(&dsc[1], intf_ip_w); _sde_encoder_dsc_pclk_param_calc(&dsc[2], intf_ip_w); _sde_encoder_dsc_pclk_param_calc(&dsc[3], intf_ip_w); /* * In this topology, since there is no dsc_merge, uncompressed input * to encoder and interface is same. */ enc_ip_w = intf_ip_w; _sde_encoder_dsc_initial_line_calc(&dsc[0], enc_ip_w); _sde_encoder_dsc_initial_line_calc(&dsc[1], enc_ip_w); _sde_encoder_dsc_initial_line_calc(&dsc[2], enc_ip_w); _sde_encoder_dsc_initial_line_calc(&dsc[3], enc_ip_w); /* * __is_ich_reset_override_needed should be called only after * updating pic dimension, mdss_panel_dsc_update_pic_dim. */ ich_res = _sde_encoder_dsc_ich_reset_override_needed( half_panel_partial_update, &dsc[0]); SDE_DEBUG_ENC(sde_enc, "pic_w: %d pic_h: %d mode:%d\n", roi->w, roi->h, dsc_common_mode); _sde_encoder_dsc_pipe_cfg(hw_dsc[0], hw_pp[0], &dsc[0], dsc_common_mode, ich_res, true); _sde_encoder_dsc_pipe_cfg(hw_dsc[1], hw_pp[1], &dsc[1], dsc_common_mode, ich_res, true); _sde_encoder_dsc_pipe_cfg(hw_dsc[2], hw_pp[2], &dsc[2], dsc_common_mode, ich_res, true); _sde_encoder_dsc_pipe_cfg(hw_dsc[3], hw_pp[3], &dsc[3], dsc_common_mode, ich_res, true); return 0; } static int _sde_encoder_dsc_2_lm_2_enc_2_intf(struct sde_encoder_virt *sde_enc, struct sde_encoder_kickoff_params *params) { Loading @@ -1198,7 +1306,7 @@ static int _sde_encoder_dsc_2_lm_2_enc_2_intf(struct sde_encoder_virt *sde_enc, bool half_panel_partial_update; int i, rc; for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { for (i = 0; i < params->num_channels; i++) { hw_pp[i] = sde_enc->hw_pp[i]; hw_dsc[i] = sde_enc->hw_dsc[i]; Loading Loading @@ -1292,7 +1400,7 @@ static int _sde_encoder_dsc_2_lm_2_enc_1_intf(struct sde_encoder_virt *sde_enc, bool half_panel_partial_update; int i, rc; for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { for (i = 0; i < params->num_channels; i++) { hw_pp[i] = sde_enc->hw_pp[i]; hw_dsc[i] = sde_enc->hw_dsc[i]; Loading Loading @@ -1438,6 +1546,9 @@ static int _sde_encoder_dsc_setup(struct sde_encoder_virt *sde_enc, case SDE_RM_TOPOLOGY_QUADPIPE_3DMERGE_DSC: ret = _sde_encoder_dsc_2_lm_2_enc_2_intf(sde_enc, params); break; case SDE_RM_TOPOLOGY_QUADPIPE_DSCMERGE: ret = _sde_encoder_dsc_4_lm_4_enc_2_intf(sde_enc, params); break; default: SDE_ERROR_ENC(sde_enc, "No DSC support for topology %d", topology); Loading Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +115 −4 Original line number Diff line number Diff line Loading @@ -67,7 +67,7 @@ #define MAX_PHYS_ENCODERS_PER_VIRTUAL \ (MAX_H_TILES_PER_DISPLAY * NUM_PHYS_ENCODER_TYPES) #define MAX_CHANNELS_PER_ENC 2 #define MAX_CHANNELS_PER_ENC 4 #define MISR_BUFF_SIZE 256 Loading Loading @@ -420,7 +420,8 @@ bool sde_encoder_is_dsc_merge(struct drm_encoder *drm_enc) return false; topology = sde_connector_get_topology_name(drm_conn); if (topology == SDE_RM_TOPOLOGY_DUALPIPE_DSCMERGE) if (topology == SDE_RM_TOPOLOGY_DUALPIPE_DSCMERGE || topology == SDE_RM_TOPOLOGY_QUADPIPE_DSCMERGE) return true; return false; Loading Loading @@ -1182,6 +1183,113 @@ static int _sde_encoder_dsc_n_lm_1_enc_1_intf(struct sde_encoder_virt *sde_enc) return 0; } static int _sde_encoder_dsc_4_lm_4_enc_2_intf(struct sde_encoder_virt *sde_enc, struct sde_encoder_kickoff_params *params) { int this_frame_slices; int intf_ip_w, enc_ip_w; int ich_res, dsc_common_mode; struct sde_encoder_phys *enc_master = sde_enc->cur_master; const struct sde_rect *roi = &sde_enc->cur_conn_roi; struct sde_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; struct sde_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC]; struct msm_display_dsc_info dsc[MAX_CHANNELS_PER_ENC]; struct msm_mode_info mode_info; bool half_panel_partial_update; int i, rc; memset(hw_dsc, 0, sizeof(struct sde_hw_dsc *)*MAX_CHANNELS_PER_ENC); memset(hw_pp, 0, sizeof(struct sde_hw_pingpong *)*MAX_CHANNELS_PER_ENC); for (i = 0; i < params->num_channels; i++) { hw_pp[i] = sde_enc->hw_pp[i]; hw_dsc[i] = sde_enc->hw_dsc[i]; if (!hw_pp[i] || !hw_dsc[i]) { SDE_ERROR_ENC(sde_enc, "invalid params for DSC\n"); return -EINVAL; } } rc = _sde_encoder_get_mode_info(&sde_enc->base, &mode_info); if (rc) { SDE_ERROR_ENC(sde_enc, "failed to get mode info\n"); return -EINVAL; } half_panel_partial_update = hweight_long(params->affected_displays) == 1; dsc_common_mode = 0; if (!half_panel_partial_update) dsc_common_mode |= DSC_MODE_SPLIT_PANEL | DSC_MODE_MULTIPLEX; if (enc_master->intf_mode == INTF_MODE_VIDEO) dsc_common_mode |= DSC_MODE_VIDEO; memcpy(&dsc[0], &mode_info.comp_info.dsc_info, sizeof(dsc[0])); memcpy(&dsc[1], &mode_info.comp_info.dsc_info, sizeof(dsc[1])); memcpy(&dsc[2], &mode_info.comp_info.dsc_info, sizeof(dsc[2])); memcpy(&dsc[3], &mode_info.comp_info.dsc_info, sizeof(dsc[3])); /* * Since both DSC use same pic dimension, set same pic dimension * to both DSC structures. */ _sde_encoder_dsc_update_pic_dim(&dsc[0], roi->w, roi->h); _sde_encoder_dsc_update_pic_dim(&dsc[1], roi->w, roi->h); _sde_encoder_dsc_update_pic_dim(&dsc[2], roi->w, roi->h); _sde_encoder_dsc_update_pic_dim(&dsc[3], roi->w, roi->h); this_frame_slices = roi->w / dsc[0].slice_width; intf_ip_w = this_frame_slices * dsc[0].slice_width; if (!half_panel_partial_update) intf_ip_w /= 2; /* * In this topology when both interfaces are active, they have same * load so intf_ip_w will be same. */ _sde_encoder_dsc_pclk_param_calc(&dsc[0], intf_ip_w); _sde_encoder_dsc_pclk_param_calc(&dsc[1], intf_ip_w); _sde_encoder_dsc_pclk_param_calc(&dsc[2], intf_ip_w); _sde_encoder_dsc_pclk_param_calc(&dsc[3], intf_ip_w); /* * In this topology, since there is no dsc_merge, uncompressed input * to encoder and interface is same. */ enc_ip_w = intf_ip_w; _sde_encoder_dsc_initial_line_calc(&dsc[0], enc_ip_w); _sde_encoder_dsc_initial_line_calc(&dsc[1], enc_ip_w); _sde_encoder_dsc_initial_line_calc(&dsc[2], enc_ip_w); _sde_encoder_dsc_initial_line_calc(&dsc[3], enc_ip_w); /* * __is_ich_reset_override_needed should be called only after * updating pic dimension, mdss_panel_dsc_update_pic_dim. */ ich_res = _sde_encoder_dsc_ich_reset_override_needed( half_panel_partial_update, &dsc[0]); SDE_DEBUG_ENC(sde_enc, "pic_w: %d pic_h: %d mode:%d\n", roi->w, roi->h, dsc_common_mode); _sde_encoder_dsc_pipe_cfg(hw_dsc[0], hw_pp[0], &dsc[0], dsc_common_mode, ich_res, true); _sde_encoder_dsc_pipe_cfg(hw_dsc[1], hw_pp[1], &dsc[1], dsc_common_mode, ich_res, true); _sde_encoder_dsc_pipe_cfg(hw_dsc[2], hw_pp[2], &dsc[2], dsc_common_mode, ich_res, true); _sde_encoder_dsc_pipe_cfg(hw_dsc[3], hw_pp[3], &dsc[3], dsc_common_mode, ich_res, true); return 0; } static int _sde_encoder_dsc_2_lm_2_enc_2_intf(struct sde_encoder_virt *sde_enc, struct sde_encoder_kickoff_params *params) { Loading @@ -1198,7 +1306,7 @@ static int _sde_encoder_dsc_2_lm_2_enc_2_intf(struct sde_encoder_virt *sde_enc, bool half_panel_partial_update; int i, rc; for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { for (i = 0; i < params->num_channels; i++) { hw_pp[i] = sde_enc->hw_pp[i]; hw_dsc[i] = sde_enc->hw_dsc[i]; Loading Loading @@ -1292,7 +1400,7 @@ static int _sde_encoder_dsc_2_lm_2_enc_1_intf(struct sde_encoder_virt *sde_enc, bool half_panel_partial_update; int i, rc; for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { for (i = 0; i < params->num_channels; i++) { hw_pp[i] = sde_enc->hw_pp[i]; hw_dsc[i] = sde_enc->hw_dsc[i]; Loading Loading @@ -1438,6 +1546,9 @@ static int _sde_encoder_dsc_setup(struct sde_encoder_virt *sde_enc, case SDE_RM_TOPOLOGY_QUADPIPE_3DMERGE_DSC: ret = _sde_encoder_dsc_2_lm_2_enc_2_intf(sde_enc, params); break; case SDE_RM_TOPOLOGY_QUADPIPE_DSCMERGE: ret = _sde_encoder_dsc_4_lm_4_enc_2_intf(sde_enc, params); break; default: SDE_ERROR_ENC(sde_enc, "No DSC support for topology %d", topology); Loading