OMAP: DSS2: Taal: Add proper external TE support
Add gpio irq based external TE support with timeout. Signed-off-by: Jani Nikula <ext-jani.1.nikula@nokia.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
This commit is contained in:
Родитель
d2b6578738
Коммит
7ae2fb1192
|
@ -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;
|
||||
|
||||
r = omap_dsi_update(dssdev, TCH, x, y, w, h,
|
||||
taal_framedone_cb, 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,7 +1028,8 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
|
|||
else
|
||||
r = taal_dcs_write_0(DCS_TEAR_OFF);
|
||||
|
||||
omapdss_dsi_enable_te(dssdev, enable);
|
||||
if (!td->use_ext_te)
|
||||
omapdss_dsi_enable_te(dssdev, enable);
|
||||
|
||||
/* XXX for some reason, DSI TE breaks if we don't wait here.
|
||||
* Panel bug? Needs more studying */
|
||||
|
|
Загрузка…
Ссылка в новой задаче