summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Perez de Heredia <pedro.perez@digi.com>2012-02-26 13:21:54 +0100
committerPedro Perez de Heredia <pedro.perez@digi.com>2012-02-26 13:21:54 +0100
commitf2f651fb097fed944ca6f52ad4fc11cc7979c5f4 (patch)
tree58879373b84126b4348da1bdfa0249a1994d3582
parent80e108e8230ff1055aea30dfe9835f2b2e51e8f5 (diff)
ad9389 hdmi: fix monitor config problems (#42030)
This commit fixes some initialization/configuration problems that were happening with some screens due to the generation of multiple hot plug events. This commit disables the interrupts during a configurable period to avoid this reconfigurations that some screens doesnt tolerate well. Fixes #42030 for most screens. The NANNSPREE still doesnt work very well but that monitor presents a strange behavior (also in WinCE). Signed-off-by: Pedro Perez de Heredia <pedro.perez@digi.com>
-rw-r--r--arch/arm/mach-mx5/devices_ccwmx51.c1
-rw-r--r--arch/arm/mach-mx5/devices_ccwmx53.c1
-rw-r--r--drivers/video/mxc/ad9389.c35
-rw-r--r--include/video/ad9389.h2
4 files changed, 33 insertions, 6 deletions
diff --git a/arch/arm/mach-mx5/devices_ccwmx51.c b/arch/arm/mach-mx5/devices_ccwmx51.c
index cd14b659f692..c83a891d85a7 100644
--- a/arch/arm/mach-mx5/devices_ccwmx51.c
+++ b/arch/arm/mach-mx5/devices_ccwmx51.c
@@ -956,6 +956,7 @@ static struct ad9389_pdata hdmi_pdata = {
.vmode_to_var = &mxc_videomode_to_var,
.edid_addr = (0x7e >> 1),
.dispif = 0,
+ .debounce_ms = 500,
};
struct i2c_board_info ccwmx51_hdmi[] __initdata = {
diff --git a/arch/arm/mach-mx5/devices_ccwmx53.c b/arch/arm/mach-mx5/devices_ccwmx53.c
index b863447f07b7..5c91e9140002 100644
--- a/arch/arm/mach-mx5/devices_ccwmx53.c
+++ b/arch/arm/mach-mx5/devices_ccwmx53.c
@@ -732,6 +732,7 @@ static struct ad9389_pdata hdmi_pdata = {
.vmode_to_var = &mxc_videomode_to_var,
.edid_addr = (0x7e >> 1),
.dispif = 0,
+ .debounce_ms = 500,
};
struct i2c_board_info ccwmx53_hdmi[] __initdata = {
diff --git a/drivers/video/mxc/ad9389.c b/drivers/video/mxc/ad9389.c
index b5487d0aa031..aa7efa5a64f1 100644
--- a/drivers/video/mxc/ad9389.c
+++ b/drivers/video/mxc/ad9389.c
@@ -334,9 +334,10 @@ static void ad9389_fb_init(struct fb_info *info)
static struct fb_var_screeninfo var;
int ret = 0;
- dev_info(info->dev, "%s\n", __func__);
+ dev_dbg(info->dev, "%s\n", __func__);
if (!ad9389_disp_connected(client)) {
+ dev_dbg(info->dev, "%s, display disconnected\n", __func__);
ad9389_set_power_down(client, 1);
if(pdata->disp_disconnected)
pdata->disp_disconnected(ad9389);
@@ -346,7 +347,7 @@ static void ad9389_fb_init(struct fb_info *info)
if(pdata->disp_connected)
pdata->disp_connected(ad9389);
- dev_info(info->dev, "%s, display connected\n", __func__);
+ dev_dbg(info->dev, "%s, display connected\n", __func__);
memset(&var, 0, sizeof(var));
/* Disable Power down and set mute to on */
@@ -366,7 +367,7 @@ static void ad9389_fb_init(struct fb_info *info)
ad9389_write_reg(client, 0xba, 0x60);
ad9389_write_reg(client, 0x47, 0x80);
- mdelay(250);
+ mdelay(50);
ret = ad9389_read_edid(ad9389->client, ad9389->edid_data);
if (!ret) {
@@ -417,10 +418,25 @@ int ad9389_fb_event(struct notifier_block *nb, unsigned long val, void *v)
return 0;
}
+static void ad9389_timer(unsigned long handle)
+{
+ struct ad9389_dev *ad9389 = (void *)handle;
+ struct i2c_client *client = ad9389->client;
+
+ /* Just enable again the interrupt and stop the timer */
+ dev_dbg(&client->dev, "%s, enabling interrupts\n", __func__);
+
+ mutex_lock(&ad9389->irq_lock);
+ enable_irq(client->irq);
+ del_timer(&ad9389->timer);
+ mutex_unlock(&ad9389->irq_lock);
+}
+
static void ad9389_work(struct work_struct *work)
{
struct ad9389_dev *ad9389 = container_of(work, struct ad9389_dev, work);
struct i2c_client *client = ad9389->client;
+ struct ad9389_pdata *pdata = client->dev.platform_data;
unsigned char irq_reg1;
unsigned char irq_reg2;
@@ -428,7 +444,9 @@ static void ad9389_work(struct work_struct *work)
mutex_lock(&ad9389->irq_lock);
- /* Interrupts are disabled here... */
+ /* Disable interrupt */
+ disable_irq(client->irq);
+
irq_reg1 = ad9389_read_reg(client, 0x96);
irq_reg2 = ad9389_read_reg(client, 0x97);
@@ -456,10 +474,12 @@ static void ad9389_work(struct work_struct *work)
irq_reg2 = ad9389_read_reg(client, 0x97);
}
+ /* Fire debouncing timer */
+ mod_timer(&ad9389->timer, jiffies + msecs_to_jiffies(pdata->debounce_ms));
+
mutex_unlock(&ad9389->irq_lock);
}
-
static irqreturn_t ad9389_handler(int irq, void *dev_id)
{
struct ad9389_dev *dev = (struct ad9389_dev *) dev_id;
@@ -681,6 +701,8 @@ static int ad9389_probe(struct i2c_client *client,
mutex_unlock(&ad9389->irq_lock);
+ setup_timer(&ad9389->timer, ad9389_timer, (unsigned long)ad9389);
+
ad9389_fb_init(registered_fb[pdata->dispif]);
printk(KERN_INFO DRV_NAME ": device detected at address 0x%x, chip revision 0x%02x\n",
@@ -709,6 +731,7 @@ static int ad9389_remove(struct i2c_client *client)
struct ad9389_dev *ad9389 = i2c_get_clientdata(client);
free_irq(client->irq, ad9389);
+ del_timer_sync(&ad9389->timer);
flush_scheduled_work();
sysfs_remove_group(&client->dev.kobj, &ad9389_attr_group);
i2c_unregister_device(ad9389->edid_ram);
@@ -757,7 +780,7 @@ static int ad9389_resume(struct i2c_client *client)
ad9389_write_reg(client, 0xba, 0x60);
ad9389_write_reg(client, 0x47, 0x80);
- mdelay(250);
+ mdelay(50);
ret = ad9389_read_edid(ad9389->client, ad9389->edid_data);
if (!ret) {
diff --git a/include/video/ad9389.h b/include/video/ad9389.h
index 837cb5306fdc..9ed9807007ed 100644
--- a/include/video/ad9389.h
+++ b/include/video/ad9389.h
@@ -34,6 +34,7 @@ struct ad9389_dev {
struct mutex irq_lock;
struct i2c_client *client;
struct work_struct work;
+ struct timer_list timer;
struct i2c_client *edid_ram;
struct fb_info *fbi;
u8 *edid_data;
@@ -44,6 +45,7 @@ struct ad9389_pdata {
int dispif;
enum hdmi_mode mode;
void *data;
+ unsigned int debounce_ms;
unsigned char edid_addr;
/* function callbacks */