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

Commit b121756b authored by Amine Najahi's avatar Amine Najahi Committed by Gerrit - the friendly Code Review server
Browse files

disp: msm: sde: adjust DSC encoders to support all 4LM topologies



Add support for all 4LM topologies in new DCE encoder framework.
This change also aligns with the new way of checking topology
information.

Change-Id: I5358d60634070bdb26059056db884ad4161c073e
Signed-off-by: default avatarAmine Najahi <anajahi@codeaurora.org>
parent 707ce010
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -364,6 +364,9 @@ struct msm_roi_caps {
 * @det_thresh_flatness:     Flatness threshold.
 * @extra_width:             Extra width required in timing calculations.
 * @pps_delay_ms:            Post PPS command delay in milliseconds.
 * @dsc_4hsmerge_en:         Using DSC 4HS merge topology
 * @dsc_4hsmerge_padding     4HS merge DSC pair padding value in bytes
 * @dsc_4hsmerge_alignment   4HS merge DSC alignment value in bytes
 */
struct msm_display_dsc_info {
	struct drm_dsc_config config;
@@ -382,6 +385,9 @@ struct msm_display_dsc_info {
	int det_thresh_flatness;
	u32 extra_width;
	u32 pps_delay_ms;
	bool dsc_4hsmerge_en;
	u32 dsc_4hsmerge_padding;
	u32 dsc_4hsmerge_alignment;
};


+8 −20
Original line number Diff line number Diff line
@@ -678,25 +678,6 @@ static int _sde_crtc_set_roi_v1(struct drm_crtc_state *state,
	return 0;
}

static bool _sde_crtc_setup_is_3dmux_dsc(struct drm_crtc_state *state)
{
	int i;
	struct sde_crtc_state *cstate;
	bool is_3dmux_dsc = false;

	cstate = to_sde_crtc_state(state);

	for (i = 0; i < cstate->num_connectors; i++) {
		struct drm_connector *conn = cstate->connectors[i];

		if (sde_connector_get_topology_name(conn) ==
				SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC)
			is_3dmux_dsc = true;
	}

	return is_3dmux_dsc;
}

static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc,
		struct drm_crtc_state *state)
{
@@ -836,6 +817,7 @@ static int _sde_crtc_check_autorefresh(struct drm_crtc *crtc,
static int _sde_crtc_set_lm_roi(struct drm_crtc *crtc,
		struct drm_crtc_state *state, int lm_idx)
{
	struct sde_kms *sde_kms;
	struct sde_crtc *sde_crtc;
	struct sde_crtc_state *crtc_state;
	const struct sde_rect *crtc_roi;
@@ -845,6 +827,12 @@ static int _sde_crtc_set_lm_roi(struct drm_crtc *crtc,
	if (!crtc || !state || lm_idx >= ARRAY_SIZE(crtc_state->lm_bounds))
		return -EINVAL;

	sde_kms = _sde_crtc_get_kms(crtc);
	if (!sde_kms || !sde_kms->catalog) {
		SDE_ERROR("invalid parameters\n");
		return -EINVAL;
	}

	sde_crtc = to_sde_crtc(crtc);
	crtc_state = to_sde_crtc_state(state);
	crtc_roi = &crtc_state->crtc_roi;
@@ -864,7 +852,7 @@ static int _sde_crtc_set_lm_roi(struct drm_crtc *crtc,
	 * hence, crtc roi must match the mixer dimensions.
	 */
	if (crtc_state->num_ds_enabled ||
		_sde_crtc_setup_is_3dmux_dsc(state)) {
		sde_rm_topology_is_3dmux_dsc(&sde_kms->rm, state)) {
		if (memcmp(lm_roi, lm_bounds, sizeof(struct sde_rect))) {
			SDE_ERROR("Unsupported: Dest scaler/3d mux DSC + PU\n");
			return -EINVAL;
+23 −19
Original line number Diff line number Diff line
@@ -71,12 +71,6 @@
/* Maximum number of VSYNC wait attempts for RSC state transition */
#define MAX_RSC_WAIT	5

#define TOPOLOGY_DUALPIPE_MERGE_MODE(x) \
		(((x) == SDE_RM_TOPOLOGY_DUALPIPE_DSCMERGE) || \
		((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE) || \
		((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_VDC) || \
		((x) == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC))

/**
 * enum sde_enc_rc_events - events for resource control state machine
 * @SDE_ENC_RC_EVENT_KICKOFF:
@@ -2220,6 +2214,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
	struct sde_kms *sde_kms;
	struct drm_connector *conn;
	int i = 0, ret;
	int num_lm, num_intf, num_pp_per_intf;

	if (!drm_enc) {
		SDE_ERROR("invalid encoder\n");
@@ -2281,17 +2276,25 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
	/* assign the reserved HW blocks to this encoder */
	_sde_encoder_virt_populate_hw_res(drm_enc);

	/* determine left HW PP block to map to INTF */
	num_lm = sde_enc->mode_info.topology.num_lm;
	num_intf = sde_enc->mode_info.topology.num_intf;
	num_pp_per_intf = num_lm / num_intf;
	if (!num_pp_per_intf)
		num_pp_per_intf = 1;

	/* perform mode_set on phys_encs */
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];

		if (phys) {
			if (!sde_enc->hw_pp[i] && sde_enc->topology.num_intf) {
				SDE_ERROR_ENC(sde_enc,
				    "invalid pingpong block for the encoder\n");
			if (!sde_enc->hw_pp[i * num_pp_per_intf] &&
				sde_enc->topology.num_intf) {
				SDE_ERROR_ENC(sde_enc, "invalid hw_pp[%d]\n",
						i * num_pp_per_intf);
				return;
			}
			phys->hw_pp = sde_enc->hw_pp[i];
			phys->hw_pp = sde_enc->hw_pp[i * num_pp_per_intf];
			phys->connector = conn->state->connector;
			if (phys->ops.mode_set)
				phys->ops.mode_set(phys, mode, adj_mode);
@@ -2498,6 +2501,7 @@ static void _sde_encoder_virt_enable_helper(struct drm_encoder *drm_enc)

static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys)
{
	struct sde_kms *sde_kms;
	void *dither_cfg = NULL;
	int ret = 0, i = 0;
	size_t len = 0;
@@ -2507,11 +2511,16 @@ static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys)
	struct sde_encoder_virt *sde_enc;
	struct sde_hw_pingpong *hw_pp;
	u32 bpp, bpc;
	int num_lm;

	if (!phys || !phys->connector || !phys->hw_pp ||
			!phys->hw_pp->ops.setup_dither || !phys->parent)
		return;

	sde_kms = sde_encoder_get_kms(phys->parent);
	if (!sde_kms)
		return;

	topology = sde_connector_get_topology_name(phys->connector);
	if ((topology == SDE_RM_TOPOLOGY_PPSPLIT) &&
			(phys->split_role == ENC_ROLE_SLAVE))
@@ -2538,17 +2547,12 @@ static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys)
	if (ret && ret == -ENODATA)
		return;

	if (TOPOLOGY_DUALPIPE_MERGE_MODE(topology)) {
		for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
	num_lm = sde_rm_topology_get_num_lm(&sde_kms->rm, topology);
	for (i = 0; i < num_lm; i++) {
		hw_pp = sde_enc->hw_pp[i];
		phys->hw_pp->ops.setup_dither(hw_pp,
				dither_cfg, len);
	}

	} else {
		phys->hw_pp->ops.setup_dither(phys->hw_pp,
				dither_cfg, len);
	}
}

void sde_encoder_virt_restore(struct drm_encoder *drm_enc)
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,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 SDE_ENCODER_FRAME_EVENT_DONE			BIT(0)
#define SDE_ENCODER_FRAME_EVENT_ERROR			BIT(1)
+25 −13
Original line number Diff line number Diff line
@@ -313,7 +313,8 @@ static int _dce_dsc_setup_single(struct sde_encoder_virt *sde_enc,
		unsigned long affected_displays, int index,
		const struct sde_rect *roi, int dsc_common_mode,
		bool merge_3d, bool disable_merge_3d, bool mode_3d,
		bool half_panel_partial_update, int ich_res)
		bool dsc_4hsmerge, bool half_panel_partial_update,
		int ich_res)
{
	struct sde_hw_ctl *hw_ctl;
	struct sde_hw_dsc *hw_dsc;
@@ -345,8 +346,9 @@ static int _dce_dsc_setup_single(struct sde_encoder_virt *sde_enc,
		return -EINVAL;
	}

	SDE_EVT32(DRMID(&sde_enc->base), roi->w, roi->h, dsc_common_mode,
			index, active, merge_3d, disable_merge_3d);
	SDE_EVT32(DRMID(&sde_enc->base), roi->w, roi->h,
			dsc_common_mode, index, active, merge_3d,
			disable_merge_3d, dsc_4hsmerge);

	_dce_dsc_pipe_cfg(hw_dsc, hw_pp, dsc, dsc_common_mode, ich_res,
			hw_dsc_pp, mode_3d, disable_merge_3d, active,
@@ -401,15 +403,15 @@ static int _dce_dsc_setup_helper(struct sde_encoder_virt *sde_enc,
	const struct sde_rm_topology_def *def;
	const struct sde_rect *roi;
	enum sde_3d_blend_mode mode_3d;
	bool half_panel_partial_update, dsc_merge, merge_3d;
	bool half_panel_partial_update, dsc_merge, merge_3d, dsc_4hsmerge;
	bool disable_merge_3d = false;
	int this_frame_slices;
	int intf_ip_w, enc_ip_w;
	int num_intf, num_dsc, num_lm;
	int ich_res;
	int dsc_pic_width;
	int dsc_common_mode = 0;
	int i;
	int rc = 0;
	int i, rc = 0;

	sde_kms = sde_encoder_get_kms(&sde_enc->base);

@@ -420,33 +422,43 @@ static int _dce_dsc_setup_helper(struct sde_encoder_virt *sde_enc,
	enc_master = sde_enc->cur_master;
	roi = &sde_enc->cur_conn_roi;
	dsc = &sde_enc->mode_info.comp_info.dsc_info;
	num_lm = def->num_lm;
	num_dsc = def->num_comp_enc;
	num_intf = def->num_intf;
	mode_3d = (topology == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC) ?
			BLEND_3D_H_ROW_INT : BLEND_3D_NONE;
	num_lm = def->num_lm;
	mode_3d = (num_lm > num_dsc) ? BLEND_3D_H_ROW_INT : BLEND_3D_NONE;
	merge_3d = (mode_3d != BLEND_3D_NONE) ? true : false;

	half_panel_partial_update = _dce_check_half_panel_update(num_lm,
			affected_displays);
	merge_3d = (mode_3d != BLEND_3D_NONE) ? true : false;
	dsc_merge = ((num_dsc > num_intf) && !half_panel_partial_update) ?
			true : false;
	disable_merge_3d = (merge_3d && half_panel_partial_update) ?
			false : true;
	dsc_4hsmerge = (dsc_merge && num_dsc == 4 && num_intf == 1) ?
			true : false;

	/*
	 * If this encoder is driving more than one DSC encoder, they
	 * operate in tandem, same pic dimension needs to be used by
	 * each of them.(pp-split is assumed to be not supported)
	 *
	 * If encoder is driving more than 2 DSCs, each DSC pair will operate
	 * on half of the picture in tandem.
	 */
	_dce_dsc_update_pic_dim(dsc, roi->w, roi->h);
	if (num_dsc > 2) {
		dsc_pic_width = roi->w / 2;
		dsc->dsc_4hsmerge_en = dsc_4hsmerge;
	} else
		dsc_pic_width = roi->w;

	_dce_dsc_update_pic_dim(dsc, dsc_pic_width, roi->h);

	this_frame_slices = roi->w / dsc->config.slice_width;
	intf_ip_w = this_frame_slices * dsc->config.slice_width;
	enc_ip_w = intf_ip_w;

	if (!half_panel_partial_update)
		intf_ip_w /= def->num_intf;
		intf_ip_w /= num_intf;
	if (!half_panel_partial_update && (num_dsc > 1))
		dsc_common_mode |= DSC_MODE_SPLIT_PANEL;
	if (dsc_merge) {
@@ -478,7 +490,7 @@ static int _dce_dsc_setup_helper(struct sde_encoder_virt *sde_enc,
	for (i = 0; i < num_dsc; i++) {
		rc = _dce_dsc_setup_single(sde_enc, dsc, affected_displays, i,
				roi, dsc_common_mode, merge_3d,
				disable_merge_3d, mode_3d,
				disable_merge_3d, mode_3d, dsc_4hsmerge,
				half_panel_partial_update, ich_res);
		if (rc)
			break;
Loading