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

Commit 91399a54 authored by Dhaval Patel's avatar Dhaval Patel
Browse files

drm/msm/sde: add sysfs for vsync_event



Register sysfs device node for vsync_event notification
on each crtc. It allows multiple clients to poll for
vsync event on each display.

Change-Id: I3665ca75084da954f5ef23dd39844f7606364e95
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent b14f1bf3
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
@@ -610,6 +610,38 @@ static void _sde_crtc_deinit_events(struct sde_crtc *sde_crtc)
		return;
}

static ssize_t vsync_event_show(struct device *device,
	struct device_attribute *attr, char *buf)
{
	struct drm_crtc *crtc;
	struct sde_crtc *sde_crtc;

	if (!device || !buf) {
		SDE_ERROR("invalid input param(s)\n");
		return -EAGAIN;
	}

	crtc = dev_get_drvdata(device);
	sde_crtc = to_sde_crtc(crtc);
	return scnprintf(buf, PAGE_SIZE, "VSYNC=%llu\n",
			ktime_to_ns(sde_crtc->vblank_last_cb_time));
}

static DEVICE_ATTR_RO(vsync_event);
static struct attribute *sde_crtc_dev_attrs[] = {
	&dev_attr_vsync_event.attr,
	NULL
};

static const struct attribute_group sde_crtc_attr_group = {
	.attrs = sde_crtc_dev_attrs,
};

static const struct attribute_group *sde_crtc_attr_groups[] = {
	&sde_crtc_attr_group,
	NULL,
};

static void sde_crtc_destroy(struct drm_crtc *crtc)
{
	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
@@ -619,6 +651,11 @@ static void sde_crtc_destroy(struct drm_crtc *crtc)
	if (!crtc)
		return;

	if (sde_crtc->vsync_event_sf)
		sysfs_put(sde_crtc->vsync_event_sf);
	if (sde_crtc->sysfs_dev)
		device_unregister(sde_crtc->sysfs_dev);

	if (sde_crtc->blob_info)
		drm_property_unreference_blob(sde_crtc->blob_info);
	msm_property_destroy(&sde_crtc->property_info);
@@ -2306,6 +2343,10 @@ static void sde_crtc_vblank_cb(void *data)
		sde_crtc->vblank_cb_time = ktime_get();
	else
		sde_crtc->vblank_cb_count++;

	sde_crtc->vblank_last_cb_time = ktime_get();
	sysfs_notify_dirent(sde_crtc->vsync_event_sf);

	_sde_crtc_complete_flip(crtc, NULL);
	drm_crtc_handle_vblank(crtc);
	DRM_DEBUG_VBL("crtc%d\n", crtc->base.id);
@@ -5888,6 +5929,41 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane)
	return crtc;
}

int sde_crtc_post_init(struct drm_device *dev, struct drm_crtc *crtc)
{
	struct sde_crtc *sde_crtc;
	int rc = 0;

	if (!dev || !dev->primary || !dev->primary->kdev || !crtc) {
		SDE_ERROR("invalid input param(s)\n");
		rc = -EINVAL;
		goto end;
	}

	sde_crtc = to_sde_crtc(crtc);
	sde_crtc->sysfs_dev = device_create_with_groups(
		dev->primary->kdev->class, dev->primary->kdev, 0, crtc,
		sde_crtc_attr_groups, "sde-crtc-%d", crtc->index);
	if (IS_ERR_OR_NULL(sde_crtc->sysfs_dev)) {
		SDE_ERROR("crtc:%d sysfs create failed rc:%ld\n", crtc->index,
			PTR_ERR(sde_crtc->sysfs_dev));
		if (!sde_crtc->sysfs_dev)
			rc = -EINVAL;
		else
			rc = PTR_ERR(sde_crtc->sysfs_dev);
		goto end;
	}

	sde_crtc->vsync_event_sf = sysfs_get_dirent(
		sde_crtc->sysfs_dev->kobj.sd, "vsync_event");
	if (!sde_crtc->vsync_event_sf)
		SDE_ERROR("crtc:%d vsync_event sysfs create failed\n",
						crtc->base.id);

end:
	return rc;
}

static int _sde_crtc_event_enable(struct sde_kms *kms,
		struct drm_crtc *crtc_drm, u32 event)
{
+14 −0
Original line number Diff line number Diff line
@@ -183,6 +183,9 @@ struct sde_crtc_event {
 * @vblank_cb_count : count of vblank callback since last reset
 * @play_count    : frame count between crtc enable and disable
 * @vblank_cb_time  : ktime at vblank count reset
 * @vblank_last_cb_time  : ktime at last vblank notification
 * @sysfs_dev  : sysfs device node for crtc
 * @vsync_event_sf : vsync event notifier sysfs device
 * @vblank_requested : whether the user has requested vblank events
 * @suspend         : whether or not a suspend operation is in progress
 * @enabled       : whether the SDE CRTC is currently enabled. updated in the
@@ -246,6 +249,9 @@ struct sde_crtc {
	u32 vblank_cb_count;
	u64 play_count;
	ktime_t vblank_cb_time;
	ktime_t vblank_last_cb_time;
	struct device *sysfs_dev;
	struct kernfs_node *vsync_event_sf;
	bool vblank_requested;
	bool suspend;
	bool enabled;
@@ -544,6 +550,14 @@ void sde_crtc_complete_commit(struct drm_crtc *crtc,
 */
struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane);

/**
 * sde_crtc_post_init - update crtc object with post initialization. It
 *      can update the debugfs, sysfs, entires.
 * @dev: sde device
 * @crtc: Pointer to drm crtc structure
 */
int sde_crtc_post_init(struct drm_device *dev, struct drm_crtc *crtc);

/**
 * sde_crtc_cancel_pending_flip - complete flip for clients on lastclose
 * @crtc: Pointer to drm crtc object
+4 −0
Original line number Diff line number Diff line
@@ -1507,6 +1507,7 @@ static int sde_kms_postinit(struct msm_kms *kms)
{
	struct sde_kms *sde_kms = to_sde_kms(kms);
	struct drm_device *dev;
	struct drm_crtc *crtc;
	int rc;

	if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev) {
@@ -1520,6 +1521,9 @@ static int sde_kms_postinit(struct msm_kms *kms)
	if (rc)
		SDE_ERROR("sde_debugfs init failed: %d\n", rc);

	drm_for_each_crtc(crtc, dev)
		sde_crtc_post_init(dev, crtc);

	return rc;
}