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

Commit 7ae2fb11 authored by Jani Nikula's avatar Jani Nikula Committed by Tomi Valkeinen
Browse files

OMAP: DSS2: Taal: Add proper external TE support



Add gpio irq based external TE support with timeout.

Signed-off-by: default avatarJani Nikula <ext-jani.1.nikula@nokia.com>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@nokia.com>
parent d2b65787
Loading
Loading
Loading
Loading
+75 −18
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@
#include <linux/fb.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/mutex.h>
@@ -65,6 +64,8 @@
/* #define TAAL_USE_ESD_CHECK */
#define TAAL_ESD_CHECK_PERIOD	msecs_to_jiffies(5000)

static irqreturn_t taal_te_isr(int irq, void *data);
static void taal_te_timeout_work_callback(struct work_struct *work);
static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);

struct taal_data {
@@ -85,7 +86,15 @@ struct taal_data {

	bool te_enabled;
	bool use_ext_te;
	struct completion te_completion;

	atomic_t do_update;
	struct {
		u16 x;
		u16 y;
		u16 w;
		u16 h;
	} update_region;
	struct delayed_work te_timeout_work;

	bool use_dsi_bl;

@@ -346,16 +355,6 @@ static void taal_get_resolution(struct omap_dss_device *dssdev,
	}
}

static irqreturn_t taal_te_isr(int irq, void *data)
{
	struct omap_dss_device *dssdev = data;
	struct taal_data *td = dev_get_drvdata(&dssdev->dev);

	complete_all(&td->te_completion);

	return IRQ_HANDLED;
}

static ssize_t taal_num_errors_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
@@ -545,6 +544,8 @@ static int taal_probe(struct omap_dss_device *dssdev)

	mutex_init(&td->lock);

	atomic_set(&td->do_update, 0);

	td->esd_wq = create_singlethread_workqueue("taal_esd");
	if (td->esd_wq == NULL) {
		dev_err(&dssdev->dev, "can't create ESD workqueue\n");
@@ -606,9 +607,12 @@ static int taal_probe(struct omap_dss_device *dssdev)
			goto err_irq;
		}

		init_completion(&td->te_completion);
		INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work,
					taal_te_timeout_work_callback);

		td->use_ext_te = true;

		dev_dbg(&dssdev->dev, "Using GPIO TE\n");
	}

	r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
@@ -909,6 +913,47 @@ static void taal_framedone_cb(int err, void *data)
	dsi_bus_unlock();
}

static irqreturn_t taal_te_isr(int irq, void *data)
{
	struct omap_dss_device *dssdev = data;
	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
	int old;
	int r;

	old = atomic_cmpxchg(&td->do_update, 1, 0);

	if (old) {
		cancel_delayed_work(&td->te_timeout_work);

		r = omap_dsi_update(dssdev, TCH,
				td->update_region.x,
				td->update_region.y,
				td->update_region.w,
				td->update_region.h,
				taal_framedone_cb, dssdev);
		if (r)
			goto err;
	}

	return IRQ_HANDLED;
err:
	dev_err(&dssdev->dev, "start update failed\n");
	dsi_bus_unlock();
	return IRQ_HANDLED;
}

static void taal_te_timeout_work_callback(struct work_struct *work)
{
	struct taal_data *td = container_of(work, struct taal_data,
					te_timeout_work.work);
	struct omap_dss_device *dssdev = td->dssdev;

	dev_err(&dssdev->dev, "TE not received for 250ms!\n");

	atomic_set(&td->do_update, 0);
	dsi_bus_unlock();
}

static int taal_update(struct omap_dss_device *dssdev,
				    u16 x, u16 y, u16 w, u16 h)
{
@@ -933,10 +978,21 @@ static int taal_update(struct omap_dss_device *dssdev,
	if (r)
		goto err;

	if (td->te_enabled && td->use_ext_te) {
		td->update_region.x = x;
		td->update_region.y = y;
		td->update_region.w = w;
		td->update_region.h = h;
		barrier();
		schedule_delayed_work(&td->te_timeout_work,
				msecs_to_jiffies(250));
		atomic_set(&td->do_update, 1);
	} else {
		r = omap_dsi_update(dssdev, TCH, x, y, w, h,
				taal_framedone_cb, dssdev);
		if (r)
			goto err;
	}

	/* note: no bus_unlock here. unlock is in framedone_cb */
	mutex_unlock(&td->lock);
@@ -972,6 +1028,7 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
	else
		r = taal_dcs_write_0(DCS_TEAR_OFF);

	if (!td->use_ext_te)
		omapdss_dsi_enable_te(dssdev, enable);

	/* XXX for some reason, DSI TE breaks if we don't wait here.