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

Commit 3560bdca authored by Steve Cohen's avatar Steve Cohen
Browse files

disp: msm: sde: refactor sde_hw_interrupts to use offsets from catalog



Refactor the SDE interrupts module to use the offsets in the catalog.
This avoids hard-coding offsets for interrupts within a block's
address space so when that block's base address is relocated the
interrupts for that block are shifted as well.

Change-Id: I08f66c0e93bbe102dfe67350c97c5c7a4fb5039a
Signed-off-by: default avatarSteve Cohen <cohens@codeaurora.org>
parent df8c709d
Loading
Loading
Loading
Loading
+110 −23
Original line number Diff line number Diff line
@@ -1060,6 +1060,74 @@ static int _read_dt_entry(struct device_node *np,
	return rc;
}

static int _add_to_irq_offset_list(struct sde_mdss_cfg *sde_cfg,
		enum sde_intr_hwblk_type blk_type, u32 instance, u32 offset)
{
	struct sde_intr_irq_offsets *item = NULL;
	bool err = false;

	switch (blk_type) {
	case SDE_INTR_HWBLK_TOP:
		if (instance >= SDE_INTR_TOP_MAX)
			err = true;
		break;
	case SDE_INTR_HWBLK_INTF:
		if (instance >= INTF_MAX)
			err = true;
		break;
	case SDE_INTR_HWBLK_AD4:
		if (instance >= AD_MAX)
			err = true;
		break;
	case SDE_INTR_HWBLK_INTF_TEAR:
		if (instance >= INTF_MAX)
			err = true;
		break;
	case SDE_INTR_HWBLK_LTM:
		if (instance >= LTM_MAX)
			err = true;
		break;
	default:
		SDE_ERROR("invalid hwblk_type: %d", blk_type);
		return -EINVAL;
	}

	if (err) {
		SDE_ERROR("unable to map instance %d for blk type %d",
				instance, blk_type);
		return -EINVAL;
	}

	/* Check for existing list entry */
	item = sde_hw_intr_list_lookup(sde_cfg, blk_type, instance);
	if (IS_ERR_OR_NULL(item)) {
		SDE_DEBUG("adding intr type %d idx %d offset 0x%x\n",
				blk_type, instance, offset);
	} else if (item->base_offset == offset) {
		SDE_INFO("duplicate intr %d/%d offset 0x%x, skipping\n",
				blk_type, instance, offset);
		return 0;
	} else {
		SDE_ERROR("type %d, idx %d in list with offset 0x%x != 0x%x\n",
				blk_type, instance, item->base_offset, offset);
		return -EINVAL;
	}

	item = kzalloc(sizeof(*item), GFP_KERNEL);
	if (!item) {
		SDE_ERROR("memory allocation failed!\n");
		return -ENOMEM;
	}

	INIT_LIST_HEAD(&item->list);
	item->type = blk_type;
	item->instance_idx = instance;
	item->base_offset = offset;
	list_add_tail(&item->list, &sde_cfg->irq_offset_list);

	return 0;
}

static void _sde_sspp_setup_vig(struct sde_mdss_cfg *sde_cfg,
	struct sde_sspp_cfg *sspp, struct sde_sspp_sub_blks *sblk,
	bool *prop_exists, struct sde_prop_value *prop_value, u32 *vig_count)
@@ -1948,6 +2016,11 @@ static int sde_intf_parse_dt(struct device_node *np,
		if (!prop_exists[INTF_LEN])
			intf->len = DEFAULT_SDE_HW_BLOCK_LEN;

		rc = _add_to_irq_offset_list(sde_cfg, SDE_INTR_HWBLK_INTF,
				intf->id, intf->base);
		if (rc)
			goto end;

		intf->prog_fetch_lines_worst_case =
				!prop_exists[INTF_PREFETCH] ?
				sde_cfg->perf.min_prefill_lines :
@@ -1979,6 +2052,14 @@ static int sde_intf_parse_dt(struct device_node *np,
			intf->te_irq_offset = PROP_VALUE_ACCESS(prop_value,
					INTF_TE_IRQ, i);

		if (intf->te_irq_offset) {
			rc = _add_to_irq_offset_list(sde_cfg,
					SDE_INTR_HWBLK_INTF_TEAR,
					intf->id, intf->te_irq_offset);
			if (rc)
				goto end;
		}

		if (sde_cfg->has_intf_te)
			set_bit(SDE_INTF_TE, &intf->features);
	}
@@ -2445,6 +2526,11 @@ static int sde_dspp_parse_dt(struct device_node *np,
			sblk->ad.version = PROP_VALUE_ACCESS(ad_prop_value,
				AD_VERSION, 0);
			set_bit(SDE_DSPP_AD, &dspp->features);
			rc = _add_to_irq_offset_list(sde_cfg,
					SDE_INTR_HWBLK_AD4, dspp->id,
					dspp->base + sblk->ad.base);
			if (rc)
				goto end;
		}

		sblk->ltm.id = SDE_DSPP_LTM;
@@ -2456,6 +2542,11 @@ static int sde_dspp_parse_dt(struct device_node *np,
			sblk->ltm.version = PROP_VALUE_ACCESS(ltm_prop_value,
				LTM_VERSION, 0);
			set_bit(SDE_DSPP_LTM, &dspp->features);
			rc = _add_to_irq_offset_list(sde_cfg,
					SDE_INTR_HWBLK_LTM, dspp->id,
					dspp->base + sblk->ltm.base);
			if (rc)
				goto end;
		}

	}
@@ -3373,6 +3464,21 @@ static int sde_top_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
	if (major_version < SDE_HW_MAJOR(SDE_HW_VER_500))
		set_bit(SDE_MDP_VSYNC_SEL, &cfg->mdp[0].features);

	rc = _add_to_irq_offset_list(cfg, SDE_INTR_HWBLK_TOP,
			SDE_INTR_TOP_INTR, cfg->mdp[0].base);
	if (rc)
		goto end;

	rc = _add_to_irq_offset_list(cfg, SDE_INTR_HWBLK_TOP,
			SDE_INTR_TOP_INTR2, cfg->mdp[0].base);
	if (rc)
		goto end;

	rc = _add_to_irq_offset_list(cfg, SDE_INTR_HWBLK_TOP,
			SDE_INTR_TOP_HIST_INTR, cfg->mdp[0].base);
	if (rc)
		goto end;

	if (prop_exists[SEC_SID_MASK]) {
		cfg->sec_sid_mask_count = prop_count[SEC_SID_MASK];
		for (i = 0; i < cfg->sec_sid_mask_count; i++)
@@ -4055,21 +4161,17 @@ static void _sde_hw_setup_uidle(struct sde_uidle_cfg *uidle_cfg)

static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
{
	int i, rc = 0;
	int rc = 0;

	if (!sde_cfg)
		return -EINVAL;

	/* default settings for *MOST* targets */
	sde_cfg->has_mixer_combined_alpha = true;
	for (i = 0; i < SDE_INTR_MAX; i++)
		set_bit(i, sde_cfg->mdss_irqs);

	/* target specific settings */
	if (IS_MSM8996_TARGET(hw_rev)) {
		sde_cfg->perf.min_prefill_lines = 21;
		clear_bit(SDE_INTR_LTM_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(SDE_INTR_LTM_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_decimation = true;
		sde_cfg->has_mixer_combined_alpha = false;
	} else if (IS_MSM8998_TARGET(hw_rev)) {
@@ -4077,8 +4179,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->perf.min_prefill_lines = 25;
		sde_cfg->vbif_qos_nlvl = 4;
		sde_cfg->ts_prefill_rev = 1;
		clear_bit(SDE_INTR_LTM_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(SDE_INTR_LTM_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_decimation = true;
		sde_cfg->has_cursor = true;
		sde_cfg->has_hdr = true;
@@ -4091,8 +4191,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->ts_prefill_rev = 2;
		sde_cfg->sui_misr_supported = true;
		sde_cfg->sui_block_xin_mask = 0x3F71;
		clear_bit(SDE_INTR_LTM_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(SDE_INTR_LTM_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_decimation = true;
		sde_cfg->has_hdr = true;
		sde_cfg->has_vig_p010 = true;
@@ -4101,8 +4199,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->perf.min_prefill_lines = 24;
		sde_cfg->vbif_qos_nlvl = 8;
		sde_cfg->ts_prefill_rev = 2;
		clear_bit(SDE_INTR_LTM_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(SDE_INTR_LTM_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_decimation = true;
		sde_cfg->has_hdr = true;
		sde_cfg->has_vig_p010 = true;
@@ -4125,8 +4221,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->has_sui_blendstage = true;
		sde_cfg->has_qos_fl_nocalc = true;
		sde_cfg->has_3d_merge_reset = true;
		clear_bit(SDE_INTR_LTM_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(SDE_INTR_LTM_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_decimation = true;
		sde_cfg->has_intf_te = true;
		sde_cfg->vbif_disable_inner_outer_shareable = true;
@@ -4137,8 +4231,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->ts_prefill_rev = 2;
		sde_cfg->ctl_rev = SDE_CTL_CFG_VERSION_1_0_0;
		sde_cfg->delay_prg_fetch_start = true;
		clear_bit(SDE_INTR_LTM_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(SDE_INTR_LTM_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_decimation = true;
		sde_cfg->has_hdr = true;
		sde_cfg->has_vig_p010 = true;
@@ -4158,8 +4250,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->has_sui_blendstage = true;
		sde_cfg->has_qos_fl_nocalc = true;
		sde_cfg->has_3d_merge_reset = true;
		clear_bit(SDE_INTR_LTM_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(SDE_INTR_LTM_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_hdr = true;
		sde_cfg->has_vig_p010 = true;
		sde_cfg->has_intf_te = true;
@@ -4196,8 +4286,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->has_sui_blendstage = true;
		sde_cfg->has_qos_fl_nocalc = true;
		sde_cfg->has_3d_merge_reset = true;
		clear_bit(SDE_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(SDE_INTR_AD4_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_hdr = true;
		sde_cfg->has_hdr_plus = true;
		set_bit(SDE_MDP_DHDR_MEMPOOL, &sde_cfg->mdp[0].features);
@@ -4230,8 +4318,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->has_sui_blendstage = true;
		sde_cfg->has_qos_fl_nocalc = true;
		sde_cfg->has_3d_merge_reset = true;
		clear_bit(SDE_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(SDE_INTR_AD4_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_hdr = true;
		sde_cfg->has_hdr_plus = true;
		set_bit(SDE_MDP_DHDR_MEMPOOL, &sde_cfg->mdp[0].features);
@@ -4291,8 +4377,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->sui_misr_supported = true;
		sde_cfg->sui_block_xin_mask = 0x3F71;
		sde_cfg->has_3d_merge_reset = true;
		clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_hdr = true;
		sde_cfg->has_hdr_plus = true;
		set_bit(SDE_MDP_DHDR_MEMPOOL, &sde_cfg->mdp[0].features);
@@ -4390,6 +4474,8 @@ void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg)
	if (!sde_cfg)
		return;

	sde_hw_catalog_irq_offset_list_delete(&sde_cfg->irq_offset_list);

	for (i = 0; i < sde_cfg->sspp_count; i++)
		kfree(sde_cfg->sspp[i].sblk);

@@ -4450,6 +4536,7 @@ struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 hw_rev)
		return ERR_PTR(-ENOMEM);

	sde_cfg->hwversion = hw_rev;
	INIT_LIST_HEAD(&sde_cfg->irq_offset_list);

	rc = _sde_hardware_pre_caps(sde_cfg, hw_rev);
	if (rc)
+42 −22
Original line number Diff line number Diff line
@@ -136,26 +136,30 @@ enum {
#define SSPP_SYS_CACHE_NO_ALLOC	BIT(4)

/**
 * SDE INTERRUPTS - maintains the possible hw irq's allowed by HW
 * The order in this enum must match the order of the irqs defined
 * by 'sde_irq_map'
 */
enum sde_intr_enum {
	SDE_INTR_SSPP_TOP0_INTR,
	SDE_INTR_SSPP_TOP0_INTR2,
	SDE_INTF_TEAR_1_INTR,
	SDE_INTF_TEAR_2_INTR,
	SDE_INTR_SSPP_TOP0_HIST_INTR,
	SDE_INTR_INTF_0_INTR,
	SDE_INTR_INTF_1_INTR,
	SDE_INTR_INTF_2_INTR,
	SDE_INTR_INTF_3_INTR,
	SDE_INTR_INTF_4_INTR,
	SDE_INTR_AD4_0_INTR,
	SDE_INTR_AD4_1_INTR,
	SDE_INTR_LTM_0_INTR,
	SDE_INTR_LTM_1_INTR,
	SDE_INTR_MAX
 * All INTRs relevant for a specific target should be enabled via
 * _add_to_irq_offset_list()
 */
enum sde_intr_hwblk_type {
	SDE_INTR_HWBLK_TOP,
	SDE_INTR_HWBLK_INTF,
	SDE_INTR_HWBLK_AD4,
	SDE_INTR_HWBLK_INTF_TEAR,
	SDE_INTR_HWBLK_LTM,
	SDE_INTR_HWBLK_MAX
};

enum sde_intr_top_intr {
	SDE_INTR_TOP_INTR = 1,
	SDE_INTR_TOP_INTR2,
	SDE_INTR_TOP_HIST_INTR,
	SDE_INTR_TOP_MAX
};

struct sde_intr_irq_offsets {
	struct list_head list;
	enum sde_intr_hwblk_type type;
	u32 instance_idx;
	u32 base_offset;
};

/**
@@ -1297,7 +1301,7 @@ struct sde_limit_cfg {
 * @has_cursor    indicates if hardware cursor is supported
 * @has_vig_p010  indicates if vig pipe supports p010 format
 * @inline_rot_formats	formats supported by the inline rotator feature
 * @mdss_irqs	  bitmap with the irqs supported by the target
 * @irq_offset_list     list of sde_intr_irq_offsets to initialize irq table
 */
struct sde_mdss_cfg {
	u32 hwversion;
@@ -1431,7 +1435,7 @@ struct sde_mdss_cfg {
	struct sde_format_extended *virt_vig_formats;
	struct sde_format_extended *inline_rot_formats;

	DECLARE_BITMAP(mdss_irqs, SDE_INTR_MAX);
	struct list_head irq_offset_list;
};

struct sde_mdss_hw_cfg_handler {
@@ -1485,6 +1489,22 @@ struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 hw_rev);
 */
void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg);

/**
 * sde_hw_catalog_irq_offset_list_delete - delete the irq_offset_list
 *                                         maintained by the catalog
 * @head:      pointer to the catalog's irq_offset_list
 */
static inline void sde_hw_catalog_irq_offset_list_delete(
		struct list_head *head)
{
	struct sde_intr_irq_offsets *item, *tmp;

	list_for_each_entry_safe(item, tmp, head, list) {
		list_del(&item->list);
		kfree(item);
	}
}

/**
 * sde_hw_sspp_multirect_enabled - check multirect enabled for the sspp
 * @cfg:          pointer to sspp cfg
+224 −448

File changed.

Preview size limit exceeded, changes collapsed.

+19 −0
Original line number Diff line number Diff line
@@ -314,4 +314,23 @@ struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr,
 * @intr: pointer to interrupts hw object
 */
void sde_hw_intr_destroy(struct sde_hw_intr *intr);

/**
 * sde_hw_intr_list_lookup(): get the list entry for a given intr
 * @sde_cfg: catalog containing the irq_offset_list
 * @type: the sde_intr_hwblk_type to lookup
 * @idx: the instance id to lookup for the specified hwblk_type
 * @return: pointer to sde_intr_irq_offsets list entry, or NULL if lookup fails
 */
static inline struct sde_intr_irq_offsets *sde_hw_intr_list_lookup(
	struct sde_mdss_cfg *sde_cfg, enum sde_intr_hwblk_type type, u32 idx)
{
	struct sde_intr_irq_offsets *item;

	list_for_each_entry(item, &sde_cfg->irq_offset_list, list) {
		if (type == item->type && idx == item->instance_idx)
			return item;
	}
	return NULL;
}
#endif