Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6cda9d12 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: Add support for DSC 4 4 2 Topology"

parents 0d7be4ee 6b1803a1
Loading
Loading
Loading
Loading
+115 −4
Original line number Diff line number Diff line
@@ -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

@@ -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;
@@ -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)
{
@@ -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];

@@ -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];

@@ -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);