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

Commit d4776e3a 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 restore functionality after idle power collapse" into msm-4.9

parents 55a9ced3 82916e00
Loading
Loading
Loading
Loading
+54 −2
Original line number Diff line number Diff line
@@ -2190,21 +2190,62 @@ static int _sde_crtc_vblank_no_lock(struct sde_crtc *sde_crtc, bool en)
	return 0;
}

static void sde_crtc_handle_power_event(u32 event_type, void *arg)
{
	struct drm_crtc *crtc = arg;
	struct sde_crtc *sde_crtc;
	struct drm_encoder *encoder;

	if (!crtc) {
		SDE_ERROR("invalid crtc\n");
		return;
	}
	sde_crtc = to_sde_crtc(crtc);

	mutex_lock(&sde_crtc->crtc_lock);

	SDE_EVT32(DRMID(crtc), event_type);

	if (event_type == SDE_POWER_EVENT_POST_ENABLE) {
		/* restore encoder; crtc will be programmed during commit */
		drm_for_each_encoder(encoder, crtc->dev) {
			if (encoder->crtc != crtc)
				continue;

			sde_encoder_virt_restore(encoder);
		}

	} else if (event_type == SDE_POWER_EVENT_POST_DISABLE) {
		struct drm_plane *plane;

		/*
		 * set revalidate flag in planes, so it will be re-programmed
		 * in the next frame update
		 */
		drm_atomic_crtc_for_each_plane(plane, crtc)
			sde_plane_set_revalidate(plane, true);
	}

	mutex_unlock(&sde_crtc->crtc_lock);
}

static void sde_crtc_disable(struct drm_crtc *crtc)
{
	struct sde_crtc *sde_crtc;
	struct sde_crtc_state *cstate;
	struct drm_encoder *encoder;
	struct msm_drm_private *priv;
	unsigned long flags;
	struct sde_crtc_irq_info *node = NULL;
	int ret;

	if (!crtc || !crtc->dev || !crtc->state) {
	if (!crtc || !crtc->dev || !crtc->dev->dev_private || !crtc->state) {
		SDE_ERROR("invalid crtc\n");
		return;
	}
	sde_crtc = to_sde_crtc(crtc);
	cstate = to_sde_crtc_state(crtc->state);
	priv = crtc->dev->dev_private;

	SDE_DEBUG("crtc%d\n", crtc->base.id);

@@ -2244,6 +2285,10 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
		cstate->rsc_update = false;
	}

	if (sde_crtc->power_event)
		sde_power_handle_unregister_event(&priv->phandle,
				sde_crtc->power_event);

	memset(sde_crtc->mixers, 0, sizeof(sde_crtc->mixers));
	sde_crtc->num_mixers = 0;

@@ -2265,14 +2310,16 @@ static void sde_crtc_enable(struct drm_crtc *crtc)
{
	struct sde_crtc *sde_crtc;
	struct drm_encoder *encoder;
	struct msm_drm_private *priv;
	unsigned long flags;
	struct sde_crtc_irq_info *node = NULL;
	int ret;

	if (!crtc) {
	if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
		SDE_ERROR("invalid crtc\n");
		return;
	}
	priv = crtc->dev->dev_private;

	SDE_DEBUG("crtc%d\n", crtc->base.id);
	SDE_EVT32(DRMID(crtc));
@@ -2295,6 +2342,11 @@ static void sde_crtc_enable(struct drm_crtc *crtc)
				sde_crtc->name, node->event);
	}
	spin_unlock_irqrestore(&sde_crtc->spin_lock, flags);

	sde_crtc->power_event = sde_power_handle_register_event(
		&priv->phandle,
		SDE_POWER_EVENT_POST_ENABLE | SDE_POWER_EVENT_POST_DISABLE,
		sde_crtc_handle_power_event, crtc, sde_crtc->name);
}

struct plane_state {
+3 −0
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ struct sde_crtc_event {
 * @event_free_list : List of available event structures
 * @event_lock    : Spinlock around event handling code
 * @misr_enable   : boolean entry indicates misr enable/disable status.
 * @power_event   : registered power event handle
 */
struct sde_crtc {
	struct drm_crtc base;
@@ -187,6 +188,8 @@ struct sde_crtc {
	struct list_head event_free_list;
	spinlock_t event_lock;
	bool misr_enable;

	struct sde_power_event *power_event;
};

#define to_sde_crtc(x) container_of(x, struct sde_crtc, base)
+59 −25
Original line number Diff line number Diff line
@@ -1169,34 +1169,79 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
	}
}

static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
static void _sde_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
{
	struct sde_encoder_virt *sde_enc = NULL;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	int i = 0;
	int ret = 0;

	if (!drm_enc) {
		SDE_ERROR("invalid encoder\n");
		return;
	} else if (!drm_enc->dev) {
		SDE_ERROR("invalid dev\n");
		return;
	} else if (!drm_enc->dev->dev_private) {
		SDE_ERROR("invalid dev_private\n");
	if (!drm_enc || !drm_enc->dev || !drm_enc->dev->dev_private) {
		SDE_ERROR("invalid parameters\n");
		return;
	}
	priv = drm_enc->dev->dev_private;

	sde_enc = to_sde_encoder_virt(drm_enc);
	priv = drm_enc->dev->dev_private;
	sde_kms = to_sde_kms(priv->kms);
	if (!sde_enc || !sde_enc->cur_master) {
		SDE_ERROR("invalid sde encoder/master\n");
		return;
	}

	sde_kms = to_sde_kms(priv->kms);
	if (!sde_kms) {
		SDE_ERROR("invalid sde_kms\n");
		return;
	}

	if (sde_enc->cur_master->hw_mdptop &&
			sde_enc->cur_master->hw_mdptop->ops.reset_ubwc)
		sde_enc->cur_master->hw_mdptop->ops.reset_ubwc(
				sde_enc->cur_master->hw_mdptop,
				sde_kms->catalog);

	if (_sde_is_dsc_enabled(sde_enc)) {
		ret = _sde_encoder_dsc_setup(sde_enc);
		if (ret)
			SDE_ERROR_ENC(sde_enc, "failed to setup DSC:%d\n", ret);
	}
}

void sde_encoder_virt_restore(struct drm_encoder *drm_enc)
{
	struct sde_encoder_virt *sde_enc = NULL;
	int i;

	if (!drm_enc) {
		SDE_ERROR("invalid encoder\n");
		return;
	}
	sde_enc = to_sde_encoder_virt(drm_enc);

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

		if (phys && (phys != sde_enc->cur_master) && phys->ops.restore)
			phys->ops.restore(phys);
	}

	if (sde_enc->cur_master && sde_enc->cur_master->ops.restore)
		sde_enc->cur_master->ops.restore(sde_enc->cur_master);

	_sde_encoder_virt_enable_helper(drm_enc);
}

static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
{
	struct sde_encoder_virt *sde_enc = NULL;
	int i, ret = 0;

	if (!drm_enc) {
		SDE_ERROR("invalid encoder\n");
		return;
	}
	sde_enc = to_sde_encoder_virt(drm_enc);

	SDE_DEBUG_ENC(sde_enc, "\n");
	SDE_EVT32(DRMID(drm_enc));

@@ -1230,21 +1275,10 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
			phys->ops.enable(phys);
	}

	if (sde_enc->cur_master && sde_enc->cur_master->ops.enable)
	if (sde_enc->cur_master->ops.enable)
		sde_enc->cur_master->ops.enable(sde_enc->cur_master);

	if (sde_enc->cur_master && sde_enc->cur_master->hw_mdptop &&
			sde_enc->cur_master->hw_mdptop->ops.reset_ubwc)
		sde_enc->cur_master->hw_mdptop->ops.reset_ubwc(
				sde_enc->cur_master->hw_mdptop,
				sde_kms->catalog);

	if (_sde_is_dsc_enabled(sde_enc)) {
		ret = _sde_encoder_dsc_setup(sde_enc);
		if (ret)
			SDE_ERROR_ENC(sde_enc, "failed to setup DSC: %d\n",
					ret);
	}
	_sde_encoder_virt_enable_helper(drm_enc);
}

static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
+6 −0
Original line number Diff line number Diff line
@@ -126,6 +126,12 @@ int sde_encoder_wait_for_commit_done(struct drm_encoder *drm_encoder);
 */
enum sde_intf_mode sde_encoder_get_intf_mode(struct drm_encoder *encoder);

/**
 * sde_encoder_virt_restore - restore the encoder configs
 * @encoder:	encoder pointer
 */
void sde_encoder_virt_restore(struct drm_encoder *encoder);

/**
 * enum sde_encoder_property - property tags for sde enoder
 * @SDE_ENCODER_PROPERTY_INLINE_ROTATE_REFILL: # of prefill line, 0 to disable
+2 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ struct sde_encoder_virt_ops {
 *				SDE_ENC_ERR_NEEDS_HW_RESET state
 * @irq_control:		Handler to enable/disable all the encoder IRQs
 * @update_split_role:		Update the split role of the phys enc
 * @restore:			Restore all the encoder configs.
 */

struct sde_encoder_phys_ops {
@@ -157,6 +158,7 @@ struct sde_encoder_phys_ops {
	void (*irq_control)(struct sde_encoder_phys *phys, bool enable);
	void (*update_split_role)(struct sde_encoder_phys *phys_enc,
			enum sde_enc_split_role role);
	void (*restore)(struct sde_encoder_phys *phys);
};

/**
Loading