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

Commit 7c26baf6 authored by Abhijit Kulkarni's avatar Abhijit Kulkarni
Browse files

drm/msm/sde: add support to configure 3d merge block



3d merge programming has been modified in sdm855. This change adds
support to program the merge_3d block. The merge 3d block is tied to
the pingpong buffer selected, this change adds additional support in
pingpong block to program the 3d merged block.

Change-Id: I9bc015ce4694bb0fa89881b1f955852cdee973c1
Signed-off-by: default avatarSteve Cohen <cohens@codeaurora.org>
Signed-off-by: default avatarAbhijit Kulkarni <kabhijit@codeaurora.org>
parent c244a5fa
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
@@ -247,6 +247,7 @@ enum {
	DITHER_OFF,
	DITHER_LEN,
	DITHER_VER,
	PP_MERGE_3D_ID,
	PP_PROP_MAX,
};

@@ -595,6 +596,7 @@ static struct sde_prop_type pp_prop[] = {
	{DITHER_OFF, "qcom,sde-dither-off", false, PROP_TYPE_U32_ARRAY},
	{DITHER_LEN, "qcom,sde-dither-size", false, PROP_TYPE_U32},
	{DITHER_VER, "qcom,sde-dither-version", false, PROP_TYPE_U32},
	{PP_MERGE_3D_ID, "qcom,sde-pp-merge-3d-id", false, PROP_TYPE_U32_ARRAY},
};

static struct sde_prop_type dsc_prop[] = {
@@ -654,6 +656,11 @@ static struct sde_prop_type reg_dma_prop[REG_DMA_PROP_MAX] = {
		PROP_TYPE_U32},
};

static struct sde_prop_type merge_3d_prop[] = {
	{HW_OFF, "qcom,sde-merge-3d-off", false, PROP_TYPE_U32_ARRAY},
	{HW_LEN, "qcom,sde-merge-3d-size", false, PROP_TYPE_U32},
};

static struct sde_prop_type inline_rot_prop[INLINE_ROT_PROP_MAX] = {
	{INLINE_ROT_XIN, "qcom,sde-inline-rot-xin", false,
							PROP_TYPE_U32_ARRAY},
@@ -2782,6 +2789,12 @@ static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg)
		sblk->dither.len = PROP_VALUE_ACCESS(prop_value, DITHER_LEN, 0);
		sblk->dither.version = PROP_VALUE_ACCESS(prop_value, DITHER_VER,
								0);

		if (prop_exists[PP_MERGE_3D_ID]) {
			set_bit(SDE_PINGPONG_MERGE_3D, &pp->features);
			pp->merge_3d_id = PROP_VALUE_ACCESS(prop_value,
					PP_MERGE_3D_ID, i) + 1;
		}
	}

end:
@@ -3246,6 +3259,51 @@ static int sde_perf_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
	return rc;
}

static int sde_parse_merge_3d_dt(struct device_node *np,
		struct sde_mdss_cfg *sde_cfg)
{
	int rc, prop_count[HW_PROP_MAX], off_count, i;
	struct sde_prop_value *prop_value = NULL;
	bool prop_exists[HW_PROP_MAX];
	struct sde_merge_3d_cfg *merge_3d;

	prop_value = kcalloc(HW_PROP_MAX, sizeof(struct sde_prop_value),
			GFP_KERNEL);
	if (!prop_value) {
		rc = -ENOMEM;
		goto fail;
	}

	rc = _validate_dt_entry(np, merge_3d_prop, ARRAY_SIZE(merge_3d_prop),
		prop_count, &off_count);
	if (rc)
		goto error;

	sde_cfg->merge_3d_count = off_count;

	rc = _read_dt_entry(np, merge_3d_prop, ARRAY_SIZE(merge_3d_prop),
			prop_count,
			prop_exists, prop_value);
	if (rc)
		goto error;

	for (i = 0; i < off_count; i++) {
		merge_3d = sde_cfg->merge_3d + i;
		merge_3d->base = PROP_VALUE_ACCESS(prop_value, HW_OFF, i);
		merge_3d->id = MERGE_3D_0 + i;
		snprintf(merge_3d->name, SDE_HW_BLK_NAME_LEN, "merge_3d_%u",
				merge_3d->id -  MERGE_3D_0);
		merge_3d->len = PROP_VALUE_ACCESS(prop_value, HW_LEN, 0);
	}

	return 0;
error:
	sde_cfg->merge_3d_count = 0;
	kfree(prop_value);
fail:
	return rc;
}

static int sde_hardware_format_caps(struct sde_mdss_cfg *sde_cfg,
	uint32_t hw_rev)
{
@@ -3513,6 +3571,10 @@ struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 hw_rev)
	if (rc)
		goto end;

	rc = sde_parse_merge_3d_dt(np, sde_cfg);
	if (rc)
		goto end;

	return sde_cfg;

end:
+19 −0
Original line number Diff line number Diff line
@@ -221,6 +221,7 @@ enum {
 * @SDE_PINGPONG_SLAVE      PP block is a suitable slave for split fifo
 * @SDE_PINGPONG_DSC,       Display stream compression blocks
 * @SDE_PINGPONG_DITHER,    Dither blocks
 * @SDE_PINGPONG_MERGE_3D,  Separate MERGE_3D block exists
 * @SDE_PINGPONG_MAX
 */
enum {
@@ -230,6 +231,7 @@ enum {
	SDE_PINGPONG_SLAVE,
	SDE_PINGPONG_DSC,
	SDE_PINGPONG_DITHER,
	SDE_PINGPONG_MERGE_3D,
	SDE_PINGPONG_MAX
};

@@ -693,16 +695,19 @@ struct sde_ds_cfg {
 * @base               register offset of this block
 * @features           bit mask identifying sub-blocks/features
 * @sblk               sub-blocks information
 * @merge_3d_id        merge_3d block id
 */
struct sde_pingpong_cfg  {
	SDE_HW_BLK_INFO;
	const struct sde_pingpong_sub_blks *sblk;
	int merge_3d_id;
};

/**
 * struct sde_dsc_cfg - information of DSC blocks
 * @id                 enum identifying this block
 * @base               register offset of this block
 * @len:               length of hardware block
 * @features           bit mask identifying sub-blocks/features
 */
struct sde_dsc_cfg {
@@ -759,6 +764,17 @@ struct sde_wb_cfg {
	enum sde_clk_ctrl_type clk_ctrl;
};

/**
 * struct sde_merge_3d_cfg - information of merge_3d blocks
 * @id                 enum identifying this block
 * @base               register offset of this block
 * @len:               length of hardware block
 * @features           bit mask identifying sub-blocks/features
 */
struct sde_merge_3d_cfg {
	SDE_HW_BLK_INFO;
};

/**
 * struct sde_rot_vbif_cfg - inline rotator vbif configs
 * @xin_id             xin client id
@@ -1049,6 +1065,9 @@ struct sde_mdss_cfg {

	u32 ad_count;

	u32 merge_3d_count;
	struct sde_merge_3d_cfg merge_3d[MAX_BLOCKS];

	/* Add additional block data structures here */

	struct sde_perf_cfg perf;
+1 −0
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ enum sde_hw_blk_type {
	SDE_HW_BLK_WB,
	SDE_HW_BLK_DSC,
	SDE_HW_BLK_ROT,
	SDE_HW_BLK_MERGE_3D,
	SDE_HW_BLK_MAX,
};

+96 −2
Original line number Diff line number Diff line
@@ -45,6 +45,81 @@ static u32 dither_depth_map[DITHER_DEPTH_MAP_INDEX] = {
	0, 0, 0, 0, 0, 1, 2, 3, 3
};

#define MERGE_3D_MODE 0x004

static struct sde_merge_3d_cfg *_merge_3d_offset(enum sde_merge_3d idx,
		struct sde_mdss_cfg *m,
		void __iomem *addr,
		struct sde_hw_blk_reg_map *b)
{
	int i;

	for (i = 0; i < m->merge_3d_count; i++) {
		if (idx == m->merge_3d[i].id) {
			b->base_off = addr;
			b->blk_off = m->merge_3d[i].base;
			b->length = m->merge_3d[i].len;
			b->hwversion = m->hwversion;
			b->log_mask = SDE_DBG_MASK_PINGPONG;
			return &m->merge_3d[i];
		}
	}

	return ERR_PTR(-EINVAL);
}

static void _sde_hw_merge_3d_setup_blend_mode(struct sde_hw_merge_3d *ctx,
			enum sde_3d_blend_mode cfg)
{
	struct sde_hw_blk_reg_map *c;
	u32 mode = 0;

	if (!ctx)
		return;

	c = &ctx->hw;
	if (cfg) {
		mode = BIT(0);
		mode |= (cfg - 0x1) << 1;
	}

	SDE_REG_WRITE(c, MERGE_3D_MODE, mode);
}

static void _setup_merge_3d_ops(struct sde_hw_merge_3d_ops *ops,
	const struct sde_merge_3d_cfg *hw_cap)
{
	ops->setup_blend_mode = _sde_hw_merge_3d_setup_blend_mode;
}

static struct sde_hw_merge_3d *_sde_pp_merge_3d_init(enum sde_merge_3d idx,
		void __iomem *addr,
		struct sde_mdss_cfg *m)
{
	struct sde_hw_merge_3d *c;
	struct sde_merge_3d_cfg *cfg;

	if (idx < MERGE_3D_0)
		return NULL;

	c = kzalloc(sizeof(*c), GFP_KERNEL);
	if (!c)
		return ERR_PTR(-ENOMEM);

	cfg = _merge_3d_offset(idx, m, addr, &c->hw);
	if (IS_ERR_OR_NULL(cfg)) {
		pr_err("invalid merge_3d cfg%d\n", idx);
		kfree(c);
		return ERR_PTR(-EINVAL);
	}

	c->idx = idx;
	c->caps = cfg;
	_setup_merge_3d_ops(&c->ops, c->caps);

	return c;
}

static struct sde_pingpong_cfg *_pingpong_offset(enum sde_pingpong pp,
		struct sde_mdss_cfg *m,
		void __iomem *addr,
@@ -340,6 +415,13 @@ static u32 sde_hw_pp_get_line_count(struct sde_hw_pingpong *pp)
	return line;
}

static void sde_hw_pp_setup_3d_merge_mode(struct sde_hw_pingpong *pp,
					enum sde_3d_blend_mode cfg)
{
	if (pp->merge_3d && pp->merge_3d->ops.setup_blend_mode)
		pp->merge_3d->ops.setup_blend_mode(pp->merge_3d, cfg);
}

static void _setup_pingpong_ops(struct sde_hw_pingpong_ops *ops,
	const struct sde_pingpong_cfg *hw_cap)
{
@@ -367,6 +449,8 @@ static void _setup_pingpong_ops(struct sde_hw_pingpong_ops *ops,
		ops->setup_dither = NULL;
		break;
	}
	if (test_bit(SDE_PINGPONG_MERGE_3D, &hw_cap->features))
		ops->setup_3d_mode = sde_hw_pp_setup_3d_merge_mode;
};

static struct sde_hw_blk_ops sde_hw_ops = {
@@ -394,6 +478,14 @@ struct sde_hw_pingpong *sde_hw_pingpong_init(enum sde_pingpong idx,

	c->idx = idx;
	c->caps = cfg;
	if (test_bit(SDE_PINGPONG_MERGE_3D, &cfg->features)) {
		c->merge_3d = _sde_pp_merge_3d_init(cfg->merge_3d_id, addr, m);
			if (IS_ERR(c->merge_3d)) {
				SDE_ERROR("invalid merge_3d block %d\n", idx);
				return ERR_PTR(-ENOMEM);
			}
	}

	_setup_pingpong_ops(&c->ops, c->caps);

	rc = sde_hw_blk_init(&c->base, SDE_HW_BLK_PINGPONG, idx, &sde_hw_ops);
@@ -415,7 +507,9 @@ struct sde_hw_pingpong *sde_hw_pingpong_init(enum sde_pingpong idx,

void sde_hw_pingpong_destroy(struct sde_hw_pingpong *pp)
{
	if (pp)
	if (pp) {
		sde_hw_blk_destroy(&pp->base);
		kfree(pp->merge_3d);
		kfree(pp);
	}
}
+30 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <uapi/drm/msm_drm_pp.h>

struct sde_hw_pingpong;
struct sde_hw_merge_3d;

struct sde_hw_tear_check {
	/*
@@ -142,6 +143,32 @@ struct sde_hw_pingpong_ops {
	 * Obtain current vertical line counter
	 */
	u32 (*get_line_count)(struct sde_hw_pingpong *pp);

	/**
	 * Programs the 3d blend configuration
	 */
	void (*setup_3d_mode)(struct sde_hw_pingpong *pp,
			enum sde_3d_blend_mode cfg);
};

struct sde_hw_merge_3d_ops {
	/**
	 * setup the 3d blend mode configuration
	 */
	void (*setup_blend_mode)(struct sde_hw_merge_3d *id,
			enum sde_3d_blend_mode cfg);
};

struct sde_hw_merge_3d {
	struct sde_hw_blk base;
	struct sde_hw_blk_reg_map hw;

	/* merge_3d */
	enum sde_merge_3d idx;
	const struct sde_merge_3d_cfg *caps;

	/* ops */
	struct sde_hw_merge_3d_ops ops;
};

struct sde_hw_pingpong {
@@ -152,6 +179,9 @@ struct sde_hw_pingpong {
	enum sde_pingpong idx;
	const struct sde_pingpong_cfg *caps;

	/* associated 3d_merge */
	struct sde_hw_merge_3d *merge_3d;

	/* ops */
	struct sde_hw_pingpong_ops ops;
};