diff options
author | Pedro Perez de Heredia <pedro.perez@digi.com> | 2012-02-26 13:21:54 +0100 |
---|---|---|
committer | Pedro Perez de Heredia <pedro.perez@digi.com> | 2012-02-26 13:21:54 +0100 |
commit | f2f651fb097fed944ca6f52ad4fc11cc7979c5f4 (patch) | |
tree | 58879373b84126b4348da1bdfa0249a1994d3582 | |
parent | 80e108e8230ff1055aea30dfe9835f2b2e51e8f5 (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.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-mx5/devices_ccwmx53.c | 1 | ||||
-rw-r--r-- | drivers/video/mxc/ad9389.c | 35 | ||||
-rw-r--r-- | include/video/ad9389.h | 2 |
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 */ |