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

Commit 92f4c23f authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm: enable support for custom power ioctl"

parents 418f3c07 6616a558
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@
#include "msm_gpu.h"
#include "msm_kms.h"
#include "sde_wb.h"
#include "sde_dbg.h"

/*
 * MSM driver version:
@@ -823,6 +824,8 @@ static int msm_open(struct drm_device *dev, struct drm_file *file)
	if (!ctx)
		return -ENOMEM;

	mutex_init(&ctx->power_lock);

	file->driver_priv = ctx;

	if (dev && dev->dev_private) {
@@ -859,6 +862,14 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file)
		priv->lastctx = NULL;
	mutex_unlock(&dev->struct_mutex);

	mutex_lock(&ctx->power_lock);
	if (ctx->enable_refcnt) {
		SDE_EVT32(ctx->enable_refcnt);
		sde_power_resource_enable(&priv->phandle,
				priv->pclient, false);
	}
	mutex_unlock(&ctx->power_lock);

	kfree(ctx);
}

@@ -1573,6 +1584,62 @@ int msm_ioctl_rmfb2(struct drm_device *dev, void *data,
}
EXPORT_SYMBOL(msm_ioctl_rmfb2);

/**
 * msm_ioctl_power_ctrl - enable/disable power vote on MDSS Hw
 * @dev: drm device for the ioctl
 * @data: data pointer for the ioctl
 * @file_priv: drm file for the ioctl call
 *
 */
static int msm_ioctl_power_ctrl(struct drm_device *dev, void *data,
			struct drm_file *file_priv)
{
	struct msm_file_private *ctx = file_priv->driver_priv;
	struct msm_drm_private *priv;
	struct drm_msm_power_ctrl *power_ctrl = data;
	bool vote_req = false;
	int old_cnt;
	int rc = 0;

	if (unlikely(!power_ctrl)) {
		DRM_ERROR("invalid ioctl data\n");
		return -EINVAL;
	}

	priv = dev->dev_private;

	mutex_lock(&ctx->power_lock);

	old_cnt = ctx->enable_refcnt;
	if (power_ctrl->enable) {
		if (!ctx->enable_refcnt)
			vote_req = true;
		ctx->enable_refcnt++;
	} else if (ctx->enable_refcnt) {
		ctx->enable_refcnt--;
		if (!ctx->enable_refcnt)
			vote_req = true;
	} else {
		pr_err("ignoring, unbalanced disable\n");
	}

	if (vote_req) {
		rc = sde_power_resource_enable(&priv->phandle,
				priv->pclient, power_ctrl->enable);

		if (rc)
			ctx->enable_refcnt = old_cnt;
	}

	pr_debug("pid %d enable %d, refcnt %d, vote_req %d\n",
			current->pid, power_ctrl->enable, ctx->enable_refcnt,
			vote_req);
	SDE_EVT32(current->pid, power_ctrl->enable, ctx->enable_refcnt,
			vote_req);
	mutex_unlock(&ctx->power_lock);
	return rc;
}

static const struct drm_ioctl_desc msm_ioctls[] = {
	DRM_IOCTL_DEF_DRV(MSM_GET_PARAM,    msm_ioctl_get_param,    DRM_AUTH|DRM_RENDER_ALLOW),
	DRM_IOCTL_DEF_DRV(MSM_GEM_NEW,      msm_ioctl_gem_new,      DRM_AUTH|DRM_RENDER_ALLOW),
@@ -1589,6 +1656,8 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
			  DRM_UNLOCKED|DRM_CONTROL_ALLOW),
	DRM_IOCTL_DEF_DRV(MSM_RMFB2, msm_ioctl_rmfb2,
			  DRM_CONTROL_ALLOW|DRM_UNLOCKED),
	DRM_IOCTL_DEF_DRV(MSM_POWER_CTRL, msm_ioctl_power_ctrl,
			DRM_RENDER_ALLOW),
};

static const struct vm_operations_struct vm_ops = {
+5 −5
Original line number Diff line number Diff line
@@ -74,11 +74,11 @@ struct msm_gem_vma;
#define TEARDOWN_DEADLOCK_RETRY_MAX 5

struct msm_file_private {
	/* currently we don't do anything useful with this.. but when
	 * per-context address spaces are supported we'd keep track of
	 * the context's page-tables here.
	 */
	int dummy;
	/* update the refcount when user driver calls power_ctrl IOCTL */
	unsigned short enable_refcnt;

	/* protects enable_refcnt */
	struct mutex power_lock;
};

enum msm_mdp_plane_property {
+27 −1
Original line number Diff line number Diff line
@@ -941,6 +941,26 @@ static bool sde_crtc_mode_fixup(struct drm_crtc *crtc,
	return true;
}

static int _sde_crtc_get_ctlstart_timeout(struct drm_crtc *crtc)
{
	struct drm_encoder *encoder;
	int rc = 0;

	if (!crtc || !crtc->dev)
		return 0;

	list_for_each_entry(encoder,
			&crtc->dev->mode_config.encoder_list, head) {
		if (encoder->crtc != crtc)
			continue;

		if (sde_encoder_get_intf_mode(encoder) == INTF_MODE_CMD)
			rc += sde_encoder_get_ctlstart_timeout_state(encoder);
	}

	return rc;
}

static void _sde_crtc_setup_blend_cfg(struct sde_crtc_mixer *mixer,
	struct sde_plane_state *pstate, struct sde_format *format)
{
@@ -3714,7 +3734,13 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
	if (unlikely(!sde_crtc->num_mixers))
		goto end;

	if (_sde_crtc_get_ctlstart_timeout(crtc)) {
		_sde_crtc_blend_setup(crtc, old_state, false);
		SDE_ERROR("border fill only commit after ctlstart timeout\n");
	} else {
		_sde_crtc_blend_setup(crtc, old_state, true);
	}

	_sde_crtc_dest_scaler_setup(crtc);

	/* cancel the idle notify delayed work */
+17 −0
Original line number Diff line number Diff line
@@ -3545,6 +3545,23 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc)
	return 0;
}

int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *drm_enc)
{
	struct sde_encoder_virt *sde_enc = NULL;
	int i, count = 0;

	if (!drm_enc)
		return 0;

	sde_enc = to_sde_encoder_virt(drm_enc);

	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		count += atomic_read(&sde_enc->phys_encs[i]->ctlstart_timeout);
		atomic_set(&sde_enc->phys_encs[i]->ctlstart_timeout, 0);
	}

	return count;
}
/**
 * _sde_encoder_trigger_flush - trigger flush for a physical encoder
 * drm_enc: Pointer to drm encoder structure
+7 −0
Original line number Diff line number Diff line
@@ -331,4 +331,11 @@ void sde_encoder_control_idle_pc(struct drm_encoder *enc, bool enable);
 */
int sde_encoder_in_cont_splash(struct drm_encoder *enc);

/**
 * sde_encoder_get_ctlstart_timeout_state - checks if ctl start timeout happened
 * @drm_enc:    Pointer to drm encoder structure
 * @Return:     non zero value if ctl start timeout occurred
 */
int sde_encoder_get_ctlstart_timeout_state(struct drm_encoder *enc);

#endif /* __SDE_ENCODER_H__ */
Loading