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

Commit af07b8a5 authored by Amine Najahi's avatar Amine Najahi Committed by Steve Cohen
Browse files

disp: msm: sde: add support for hardware based rounded corner



Add support for hardware based rounded corner part of
color processing framework.

Change-Id: I3e5f4dac6ffc759bb940215b7621ac716f255169
Signed-off-by: default avatarAmine Najahi <anajahi@codeaurora.org>
Signed-off-by: default avatarSteve Cohen <cohens@codeaurora.org>
parent 818651c2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \
	sde/sde_hw_qdss.o \
	sde_dsc_helper.o \
	sde_vdc_helper.o \
	sde/sde_hw_rc.o \

msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \
	sde/sde_encoder_phys_wb.o \
+162 −4
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@ static void dspp_ad_install_property(struct drm_crtc *crtc);

static void dspp_ltm_install_property(struct drm_crtc *crtc);

static void dspp_rc_install_property(struct drm_crtc *crtc);

static void dspp_vlut_install_property(struct drm_crtc *crtc);

static void dspp_gamut_install_property(struct drm_crtc *crtc);
@@ -112,6 +114,7 @@ do { \
	func[SDE_DSPP_IGC] = dspp_igc_install_property; \
	func[SDE_DSPP_HIST] = dspp_hist_install_property; \
	func[SDE_DSPP_DITHER] = dspp_dither_install_property; \
	func[SDE_DSPP_RC] = dspp_rc_install_property; \
} while (0)

typedef void (*lm_prop_install_func_t)(struct drm_crtc *crtc);
@@ -160,6 +163,7 @@ enum sde_cp_crtc_features {
	SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3,
	SDE_CP_CRTC_DSPP_LTM_VLUT,
	SDE_CP_CRTC_DSPP_SB,
	SDE_CP_CRTC_DSPP_RC_MASK,
	SDE_CP_CRTC_DSPP_MAX,
	/* DSPP features end */

@@ -172,11 +176,15 @@ enum sde_cp_crtc_features {
};

enum sde_cp_crtc_pu_features {
	SDE_CP_CRTC_DSPP_RC_PU,
	SDE_CP_CRTC_MAX_PU_FEATURES,
};

static enum sde_cp_crtc_pu_features
		sde_cp_crtc_pu_to_feature[SDE_CP_CRTC_MAX_PU_FEATURES];
		sde_cp_crtc_pu_to_feature[SDE_CP_CRTC_MAX_PU_FEATURES] = {
	[SDE_CP_CRTC_DSPP_RC_PU] =
		(enum sde_cp_crtc_pu_features) SDE_CP_CRTC_DSPP_RC_MASK,
};

static void _sde_cp_crtc_enable_hist_irq(struct sde_crtc *sde_crtc);

@@ -672,10 +680,122 @@ static int set_ltm_hist_crtl_feature(struct sde_hw_dspp *hw_dspp,
	return ret;
}

static int check_rc_mask_feature(struct sde_hw_dspp *hw_dspp,
				 struct sde_hw_cp_cfg *hw_cfg,
				 struct sde_crtc *sde_crtc)
{
	int ret = 0;

	if (!hw_dspp || !hw_cfg || !sde_crtc) {
		DRM_ERROR("invalid arguments");
		return -EINVAL;
	}

	if (!hw_dspp->ops.validate_rc_mask) {
		DRM_ERROR("invalid rc ops");
		return -EINVAL;
	}

	ret = hw_dspp->ops.validate_rc_mask(hw_dspp, hw_cfg);
	if (ret)
		DRM_ERROR("failed to validate rc mask %d", ret);

	return ret;
}

static int set_rc_mask_feature(struct sde_hw_dspp *hw_dspp,
			       struct sde_hw_cp_cfg *hw_cfg,
			       struct sde_crtc *sde_crtc)
{
	int ret = 0;

	if (!hw_dspp || !hw_cfg || !sde_crtc) {
		DRM_ERROR("invalid arguments\n");
		return -EINVAL;
	}

	if (!hw_dspp->ops.setup_rc_mask || !hw_dspp->ops.setup_rc_data) {
		DRM_ERROR("invalid rc ops\n");
		return -EINVAL;
	}

	DRM_DEBUG_DRIVER("dspp %d setup mask for rc instance %u\n",
			hw_dspp->idx, hw_dspp->cap->sblk->rc.idx);

	ret = hw_dspp->ops.setup_rc_mask(hw_dspp, hw_cfg);
	if (ret) {
		DRM_ERROR("failed to setup rc mask, ret %d\n", ret);
		goto exit;
	}

	/* rc data should be programmed once if dspp are in multi-pipe mode */
	if (hw_dspp->cap->sblk->rc.idx % hw_cfg->num_of_mixers == 0) {
		ret = hw_dspp->ops.setup_rc_data(hw_dspp, hw_cfg);
		if (ret) {
			DRM_ERROR("failed to setup rc data, ret %d\n", ret);
			goto exit;
		}
	}

exit:
	return ret;
}

static int set_rc_pu_feature(struct sde_hw_dspp *hw_dspp,
			     struct sde_hw_cp_cfg *hw_cfg,
			     struct sde_crtc *sde_crtc)
{
	int ret = 0;

	if (!hw_dspp || !hw_cfg || !sde_crtc) {
		DRM_ERROR("invalid arguments\n");
		return -EINVAL;
	}

	if (!hw_dspp->ops.setup_rc_pu_roi) {
		DRM_ERROR("invalid rc ops\n");
		return -EINVAL;
	}

	DRM_DEBUG_DRIVER("dspp %d setup pu roi for rc instance %u\n",
			hw_dspp->idx, hw_dspp->cap->sblk->rc.idx);

	ret = hw_dspp->ops.setup_rc_pu_roi(hw_dspp, hw_cfg);
	if (ret < 0)
		DRM_ERROR("failed to setup rc pu roi, ret %d\n", ret);

	return ret;
}

static int check_rc_pu_feature(struct sde_hw_dspp *hw_dspp,
			       struct sde_hw_cp_cfg *hw_cfg,
			       struct sde_crtc *sde_crtc)
{
	int ret = 0;

	if (!hw_dspp || !hw_cfg || !sde_crtc) {
		DRM_ERROR("invalid arguments\n");
		return -EINVAL;
	}

	if (!hw_dspp->ops.validate_rc_pu_roi) {
		SDE_ERROR("invalid rc ops");
		return -EINVAL;
	}

	ret = hw_dspp->ops.validate_rc_pu_roi(hw_dspp, hw_cfg);
	if (ret)
		SDE_ERROR("failed to validate rc pu roi, ret %d", ret);

	return ret;
}

feature_wrapper check_crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES];
#define setup_check_crtc_feature_wrappers(wrappers) \
memset(wrappers, 0, sizeof(wrappers))
do { \
	memset(wrappers, 0, sizeof(wrappers)); \
	wrappers[SDE_CP_CRTC_DSPP_RC_MASK] = check_rc_mask_feature; \
} while (0)

feature_wrapper set_crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES];
#define setup_set_crtc_feature_wrappers(wrappers) \
@@ -718,15 +838,22 @@ do { \
	wrappers[SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF2] = set_ltm_queue_buf_feature; \
	wrappers[SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3] = set_ltm_queue_buf_feature; \
	wrappers[SDE_CP_CRTC_DSPP_LTM_HIST_CTL] = set_ltm_hist_crtl_feature; \
	wrappers[SDE_CP_CRTC_DSPP_RC_MASK] = set_rc_mask_feature; \
} while (0)

feature_wrapper set_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES];
#define setup_set_crtc_pu_feature_wrappers(wrappers) \
memset(wrappers, 0, sizeof(wrappers))
do { \
	memset(wrappers, 0, sizeof(wrappers)); \
	wrappers[SDE_CP_CRTC_DSPP_RC_PU] = set_rc_pu_feature; \
} while (0)

feature_wrapper check_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES];
#define setup_check_crtc_pu_feature_wrappers(wrappers) \
memset(wrappers, 0, sizeof(wrappers))
do { \
	memset(wrappers, 0, sizeof(wrappers)); \
	wrappers[SDE_CP_CRTC_DSPP_RC_PU] = check_rc_pu_feature; \
} while (0)

#define INIT_PROP_ATTACH(p, crtc, prop, node, feature, val) \
	do { \
@@ -1372,6 +1499,7 @@ static const int dspp_feature_to_sub_blk_tbl[SDE_CP_CRTC_MAX_FEATURES] = {
	[SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3] = SDE_DSPP_LTM,
	[SDE_CP_CRTC_DSPP_LTM_VLUT] = SDE_DSPP_LTM,
	[SDE_CP_CRTC_DSPP_SB] = SDE_DSPP_SB,
	[SDE_CP_CRTC_DSPP_RC_MASK] = SDE_DSPP_RC,
	[SDE_CP_CRTC_DSPP_MAX] = SDE_DSPP_MAX,
	[SDE_CP_CRTC_LM_GC] = SDE_DSPP_MAX,
};
@@ -2391,6 +2519,36 @@ static void dspp_ltm_install_property(struct drm_crtc *crtc)
	}
}

static void dspp_rc_install_property(struct drm_crtc *crtc)
{
	char feature_name[256];
	struct sde_kms *kms = NULL;
	struct sde_mdss_cfg *catalog = NULL;
	u32 version;

	if (!crtc) {
		DRM_ERROR("invalid arguments");
		return;
	}

	kms = get_kms(crtc);
	catalog = kms->catalog;
	version = catalog->dspp[0].sblk->rc.version >> 16;
	switch (version) {
	case 1:
		snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d",
				"SDE_DSPP_RC_MASK_V", version);
		sde_cp_crtc_install_blob_property(crtc, feature_name,
				SDE_CP_CRTC_DSPP_RC_MASK,
				sizeof(struct drm_msm_rc_mask_cfg));

		break;
	default:
		DRM_ERROR("version %d not supported\n", version);
		break;
	}
}

static void lm_gc_install_property(struct drm_crtc *crtc)
{
	char feature_name[256];
+8 −0
Original line number Diff line number Diff line
@@ -755,6 +755,9 @@ static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc,
		}

		sde_kms_rect_merge_rectangles(&sde_conn_state->rois, &conn_roi);
		SDE_DEBUG("conn_roi x:%u, y:%u, w:%u, h:%u\n",
				conn_roi.x, conn_roi.y,
				conn_roi.w, conn_roi.h);
		SDE_EVT32_VERBOSE(DRMID(crtc), DRMID(conn),
				conn_roi.x, conn_roi.y,
				conn_roi.w, conn_roi.h);
@@ -5003,8 +5006,13 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
		sde_crtc_install_dest_scale_properties(sde_crtc, catalog,
				info);

	if (catalog->dspp_count && catalog->rc_count)
		sde_kms_info_add_keyint(info, "rc_mem_size",
				catalog->dspp[0].sblk->rc.mem_total_size);

	msm_property_install_blob(&sde_crtc->property_info, "capabilities",
		DRM_MODE_PROP_IMMUTABLE, CRTC_PROP_INFO);

	msm_property_set_blob(&sde_crtc->property_info, &sde_crtc->blob_info,
			info->data, SDE_KMS_INFO_DATALEN(info),
			CRTC_PROP_INFO);
+44 −3
Original line number Diff line number Diff line
@@ -383,6 +383,14 @@ enum {
	LTM_PROP_MAX,
};

enum {
	RC_OFF,
	RC_LEN,
	RC_VERSION,
	RC_MEM_TOTAL_SIZE,
	RC_PROP_MAX,
};

enum {
	MIXER_OFF,
	MIXER_LEN,
@@ -699,6 +707,13 @@ static struct sde_prop_type ltm_prop[] = {
	{LTM_VERSION, "qcom,sde-dspp-ltm-version", false, PROP_TYPE_U32},
};

static struct sde_prop_type rc_prop[] = {
	{RC_OFF, "qcom,sde-dspp-rc-off", false, PROP_TYPE_U32_ARRAY},
	{RC_LEN, "qcom,sde-dspp-rc-size", false, PROP_TYPE_U32},
	{RC_VERSION, "qcom,sde-dspp-rc-version", false, PROP_TYPE_U32},
	{RC_MEM_TOTAL_SIZE, "qcom,sde-dspp-rc-mem-size", false, PROP_TYPE_U32},
};

static struct sde_prop_type ds_top_prop[] = {
	{DS_TOP_OFF, "qcom,sde-dest-scaler-top-off", false, PROP_TYPE_U32},
	{DS_TOP_LEN, "qcom,sde-dest-scaler-top-size", false, PROP_TYPE_U32},
@@ -2471,8 +2486,8 @@ static int sde_dspp_parse_dt(struct device_node *np,
						struct sde_mdss_cfg *sde_cfg)
{
	int rc = 0, i;
	u32 off_count, ad_off_count, ltm_off_count;
	struct sde_dt_props *props, *ad_props, *ltm_props;
	u32 off_count, ad_off_count, ltm_off_count, rc_off_count;
	struct sde_dt_props *props, *ad_props, *ltm_props, *rc_props;
	struct sde_dt_props *blocks_props = NULL;
	struct sde_dspp_cfg *dspp;
	struct sde_dspp_sub_blks *sblk;
@@ -2506,6 +2521,14 @@ static int sde_dspp_parse_dt(struct device_node *np,
		goto put_ad_props;
	}

	/* Parse RC dtsi entries */
	rc_props = sde_get_dt_props(np, RC_PROP_MAX, rc_prop,
			ARRAY_SIZE(rc_prop), &rc_off_count);
	if (IS_ERR_OR_NULL(rc_props)) {
		rc = PTR_ERR(rc_props);
		goto put_ltm_props;
	}

	/* get DSPP feature dt properties if they exist */
	snp = of_get_child_by_name(np, dspp_prop[DSPP_BLOCKS].prop_name);
	if (snp) {
@@ -2514,7 +2537,7 @@ static int sde_dspp_parse_dt(struct device_node *np,
				NULL);
		if (IS_ERR_OR_NULL(blocks_props)) {
			rc = PTR_ERR(blocks_props);
			goto put_ltm_props;
			goto put_rc_props;
		}
	}

@@ -2571,10 +2594,28 @@ static int sde_dspp_parse_dt(struct device_node *np,
				goto end;
		}

		sblk->rc.id = SDE_DSPP_RC;
		sde_cfg->rc_count = rc_off_count;
		if (rc_props && (i < rc_off_count) &&
		    rc_props->exists[RC_OFF]) {
			sblk->rc.base = PROP_VALUE_ACCESS(rc_props->values,
					RC_OFF, i);
			sblk->rc.len = PROP_VALUE_ACCESS(rc_props->values,
					RC_LEN, 0);
			sblk->rc.version = PROP_VALUE_ACCESS(rc_props->values,
					RC_VERSION, 0);
			sblk->rc.mem_total_size = PROP_VALUE_ACCESS(
					rc_props->values, RC_MEM_TOTAL_SIZE,
					0);
			sblk->rc.idx = i;
			set_bit(SDE_DSPP_RC, &dspp->features);
		}
	}

end:
	sde_put_dt_props(blocks_props);
put_rc_props:
	sde_put_dt_props(rc_props);
put_ltm_props:
	sde_put_dt_props(ltm_props);
put_ad_props:
+18 −0
Original line number Diff line number Diff line
@@ -755,6 +755,20 @@ struct sde_lm_sub_blks {
	struct sde_pp_blk gc;
};

/**
 * struct sde_dspp_rc: Pixel processing rounded corner sub-blk information
 * @info: HW register and features supported by this sub-blk.
 * @version: HW Algorithm version.
 * @idx: HW block instance id.
 * @mem_total_size: data memory size.
 */
struct sde_dspp_rc {
	SDE_HW_SUBBLK_INFO;
	u32 version;
	u32 idx;
	u32 mem_total_size;
};

struct sde_dspp_sub_blks {
	struct sde_pp_blk igc;
	struct sde_pp_blk pcc;
@@ -768,6 +782,7 @@ struct sde_dspp_sub_blks {
	struct sde_pp_blk ad;
	struct sde_pp_blk ltm;
	struct sde_pp_blk vlut;
	struct sde_dspp_rc rc;
};

struct sde_pingpong_sub_blks {
@@ -1426,6 +1441,7 @@ struct sde_limit_cfg {
 * @has_vig_p010  indicates if vig pipe supports p010 format
 * @inline_rot_formats	formats supported by the inline rotator feature
 * @irq_offset_list     list of sde_intr_irq_offsets to initialize irq table
 * @rc_count	number of rounded corner hardware instances
 */
struct sde_mdss_cfg {
	u32 hwversion;
@@ -1536,6 +1552,7 @@ struct sde_mdss_cfg {

	u32 ad_count;
	u32 ltm_count;
	u32 rc_count;

	u32 merge_3d_count;
	struct sde_merge_3d_cfg merge_3d[MAX_BLOCKS];
@@ -1583,6 +1600,7 @@ struct sde_mdss_hw_cfg_handler {
#define BLK_WB(s) ((s)->wb)
#define BLK_AD(s) ((s)->ad)
#define BLK_LTM(s) ((s)->ltm)
#define BLK_RC(s) ((s)->rc)

/**
 * sde_hw_set_preference: populate the individual hw lm preferences,
Loading