Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCH] video: mb862xx-i2c: fix for reliable decoder register access
From: Anatolij Gustschin @ 2011-09-01 15:53 UTC (permalink / raw)
  To: linux-fbdev

Increase delay when polling for tx status. This fixes
the unreliable video decoder i2c register access.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
 drivers/video/mb862xx/mb862xx-i2c.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c
index b953099..934081d 100644
--- a/drivers/video/mb862xx/mb862xx-i2c.c
+++ b/drivers/video/mb862xx/mb862xx-i2c.c
@@ -23,7 +23,7 @@ static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
 	u32 reg;
 
 	do {
-		udelay(1);
+		udelay(10);
 		reg = inreg(i2c, GC_I2C_BCR);
 		if (reg & (I2C_INT | I2C_BER))
 			break;
-- 
1.7.1


^ permalink raw reply related

* Re: [PATCH] fb: avoid possible deadlock caused by fb_set_suspend
From: Florian Tobias Schandinat @ 2011-09-01 15:42 UTC (permalink / raw)
  To: Guennadi Liakhovetski
  Cc: Bruno Prémont, lethal, linux-fbdev, francis.moro, torvalds,
	linux-kernel, Herton Ronaldo Krzesinski, stable
In-Reply-To: <20110618111934.26203dbf@neptune.home>

ping

Guennadi, I really want this issue fixed. Please have a look at Bruno's patch
otherwise your driver might remain or get even more broken...

I am scheduling Herton's patch for the next merge window.


Regards,

Florian Tobias Schandinat


On 06/18/2011 09:19 AM, Bruno Prémont wrote:
> Guennadi, could you have a look at (completely untested) patch which avoids
> possible deadlock due to inverted lock taking order on hotplug as well
> as "readding" lock_fb_info() for fb_set_suspend() call after Herton's
> patch to fb_set_suspend().
> 
> Thanks,
> Bruno
> 
> 
> On Sat, 18 June 2011 Bruno Prémont <bonbons@linux-vserver.org> wrote:
>> On Fri, 17 June 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de> wrote:
>>> From: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
>>>
>>> A lock ordering issue can cause deadlocks: in framebuffer/console code,
>>> all needed struct fb_info locks are taken before acquire_console_sem(),
>>> in places which need to take console semaphore.
>>>
>>> But fb_set_suspend is always called with console semaphore held, and
>>> inside it we call lock_fb_info which gets the fb_info lock, inverse
>>> locking order of what the rest of the code does. This causes a real
>>> deadlock issue, when we write to state fb sysfs attribute (which calls
>>> fb_set_suspend) while a framebuffer is being unregistered by
>>> remove_conflicting_framebuffers, as can be shown by following show
>>> blocked state trace on a test program which loads i915 and runs another
>>> forked processes writing to state attribute:
>>>
>>> Test process with semaphore held and trying to get fb_info lock:
>>
>> ...
>>
>>> fb-test2 which reproduces above is available on kernel.org bug #26232.
>>> To solve this issue, avoid calling lock_fb_info inside fb_set_suspend,
>>> and move it out to where needed (callers of fb_set_suspend must call
>>> lock_fb_info before if needed). So far, the only place which needs to
>>> call lock_fb_info is store_fbstate, all other places which calls
>>> fb_set_suspend are suspend/resume hooks that should not need the lock as
>>> they should be run only when processes are already frozen in
>>> suspend/resume.
>>
>> From a quick look through FB drivers in 2.6.39 I've found one that would need
>> more work:
>> - drivers/video/sh_mobile_hdmi.c: sh_hdmi_edid_work_fn()
>>   Should get changed to
>>   a) right locking order in case (hdmi->hp_state = HDMI_HOTPLUG_CONNECTED)
>>   b) lock fb_info in the other case
>>   For this one fb_set_suspend() does get call in a hotplug worker,
>>   thus independently on suspend/resume process.
>>
>> The rest does match the suspend/resume hook pattern mentioned.
>>
>> Bruno
>>
>>
>>> References: https://bugzilla.kernel.org/show_bug.cgi?id&232
>>> Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
>>> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
>>> Cc: stable@kernel.org
>>> ---
>>>  drivers/video/fbmem.c   |    3 ---
>>>  drivers/video/fbsysfs.c |    3 +++
>>>  2 files changed, 3 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
>>> index 5aac00e..ad93629 100644
>>> --- a/drivers/video/fbmem.c
>>> +++ b/drivers/video/fbmem.c
>>> @@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state)
>>>  {
>>>  	struct fb_event event;
>>>  
>>> -	if (!lock_fb_info(info))
>>> -		return;
>>>  	event.info = info;
>>>  	if (state) {
>>>  		fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
>>> @@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state)
>>>  		info->state = FBINFO_STATE_RUNNING;
>>>  		fb_notifier_call_chain(FB_EVENT_RESUME, &event);
>>>  	}
>>> -	unlock_fb_info(info);
>>>  }
>>>  
>>>  /**
>>> diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
>>> index 04251ce..67afa9c 100644
>>> --- a/drivers/video/fbsysfs.c
>>> +++ b/drivers/video/fbsysfs.c
>>> @@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device,
>>>  
>>>  	state = simple_strtoul(buf, &last, 0);
>>>  
>>> +	if (!lock_fb_info(fb_info))
>>> +		return -ENODEV;
>>>  	console_lock();
>>>  	fb_set_suspend(fb_info, (int)state);
>>>  	console_unlock();
>>> +	unlock_fb_info(fb_info);
>>>  
>>>  	return count;
>>>  }
> 
> 
> diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
> index 2b9e56a..b1a13ab 100644
> --- a/drivers/video/sh_mobile_hdmi.c
> +++ b/drivers/video/sh_mobile_hdmi.c
> @@ -1151,27 +1151,27 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
>  
>  		ch = info->par;
>  
> -		console_lock();
> +		if (lock_fb_info(info)) {
> +			console_lock();
>  
> -		/* HDMI plug in */
> -		if (!sh_hdmi_must_reconfigure(hdmi) &&
> -		    info->state = FBINFO_STATE_RUNNING) {
> -			/*
> -			 * First activation with the default monitor - just turn
> -			 * on, if we run a resume here, the logo disappears
> -			 */
> -			if (lock_fb_info(info)) {
> +			/* HDMI plug in */
> +			if (!sh_hdmi_must_reconfigure(hdmi) &&
> +			    info->state = FBINFO_STATE_RUNNING) {
> +				/*
> +				 * First activation with the default monitor - just turn
> +				 * on, if we run a resume here, the logo disappears
> +				 */
>  				info->var.width = hdmi->var.width;
>  				info->var.height = hdmi->var.height;
>  				sh_hdmi_display_on(hdmi, info);
> -				unlock_fb_info(info);
> +			} else {
> +				/* New monitor or have to wake up */
> +				fb_set_suspend(info, 0);
>  			}
> -		} else {
> -			/* New monitor or have to wake up */
> -			fb_set_suspend(info, 0);
> -		}
>  
> -		console_unlock();
> +			console_unlock();
> +			unlock_fb_info(info);
> +		}
>  	} else {
>  		ret = 0;
>  		if (!hdmi->info)
> @@ -1181,12 +1181,15 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
>  		fb_destroy_modedb(hdmi->monspec.modedb);
>  		hdmi->monspec.modedb = NULL;
>  
> -		console_lock();
> +		if (lock_fb_info(info)) {
> +			console_lock();
>  
> -		/* HDMI disconnect */
> -		fb_set_suspend(hdmi->info, 1);
> +			/* HDMI disconnect */
> +			fb_set_suspend(hdmi->info, 1);
>  
> -		console_unlock();
> +			console_unlock();
> +			unlock_fb_info(info);
> +		}
>  		pm_runtime_put(hdmi->dev);
>  	}
>  
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


^ permalink raw reply

* Re: [PATCH] fbdev: fix parsing of standard timings
From: Tomi Valkeinen @ 2011-09-01 13:27 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1314362328-30456-1-git-send-email-tomi.valkeinen@ti.com>

On Thu, 2011-09-01 at 13:10 +0000, Florian Tobias Schandinat wrote:
> On 08/30/2011 05:31 AM, Tomi Valkeinen wrote:
> > Hi Florian,
> > 
> > On Fri, 2011-08-26 at 18:02 +0000, Florian Tobias Schandinat wrote:
> >> Hi Tomi,
> >>
> >> On 08/26/2011 12:38 PM, Tomi Valkeinen wrote:
> >>> The standard timings parses uses 1:1 dimensions when the ratio in the
> >>> EDID data is 0. However, for EDID 1.3 and later the dimensions are 16:10
> >>> when the ratio is 0.
> >>>
> >>> Pass the version and revision numbers to get_std_timing() which can then
> >>> make the right decision about dimensions.
> >>>
> >>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> >>
> >> Thanks, looks good to me.
> >> I'd be happy if someone with access to the original EDID specs could confirm
> >> this and add his reviewed by.
> >> I also think adding a comment explaining this change would be helpful.
> > 
> > You can see the same thing done in
> > drivers/gpu/drm/drm_edid.c:drm_mode_std(). Although they seem to check
> > only revision, which looks a bit risky to me.
> > 
> > The specs seem to be available by just googling them, although I don't
> > know if it's legal to distribute them or not...
> > 
> > I've added your comment, I agree it's good. Patch below.
> 
> Looks like your googling is better than mine, I only found references to it.

=). Try "e-edid standard pdf" or "edid standard pdf".

> Anyway, I've applied this patch.

Thanks!

 Tomi



^ permalink raw reply

* Re: [PATCH] fbdev: fix parsing of standard timings
From: Florian Tobias Schandinat @ 2011-09-01 13:10 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1314362328-30456-1-git-send-email-tomi.valkeinen@ti.com>

On 08/30/2011 05:31 AM, Tomi Valkeinen wrote:
> Hi Florian,
> 
> On Fri, 2011-08-26 at 18:02 +0000, Florian Tobias Schandinat wrote:
>> Hi Tomi,
>>
>> On 08/26/2011 12:38 PM, Tomi Valkeinen wrote:
>>> The standard timings parses uses 1:1 dimensions when the ratio in the
>>> EDID data is 0. However, for EDID 1.3 and later the dimensions are 16:10
>>> when the ratio is 0.
>>>
>>> Pass the version and revision numbers to get_std_timing() which can then
>>> make the right decision about dimensions.
>>>
>>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>>
>> Thanks, looks good to me.
>> I'd be happy if someone with access to the original EDID specs could confirm
>> this and add his reviewed by.
>> I also think adding a comment explaining this change would be helpful.
> 
> You can see the same thing done in
> drivers/gpu/drm/drm_edid.c:drm_mode_std(). Although they seem to check
> only revision, which looks a bit risky to me.
> 
> The specs seem to be available by just googling them, although I don't
> know if it's legal to distribute them or not...
> 
> I've added your comment, I agree it's good. Patch below.

Looks like your googling is better than mine, I only found references to it.
Anyway, I've applied this patch.


Thanks,

Florian Tobias Schandinat

> 
>  Tomi
> 
> 
>>From 82c630291ad39d45009352fce1b23b4d0f44f92d Mon Sep 17 00:00:00 2001
> From: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Date: Thu, 25 Aug 2011 15:36:40 +0300
> Subject: [PATCH] fbdev: fix parsing of standard timings
> 
> The standard timings parses uses 1:1 dimensions when the ratio in the
> EDID data is 0. However, for EDID 1.3 and later the dimensions are 16:10
> when the ratio is 0.
> 
> Pass the version and revision numbers to get_std_timing() which can then
> make the right decision about dimensions.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---
>  drivers/video/fbmon.c |   21 +++++++++++++++------
>  1 files changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
> index 4f57485..cef6557 100644
> --- a/drivers/video/fbmon.c
> +++ b/drivers/video/fbmon.c
> @@ -493,7 +493,8 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
>  	return num;
>  }
>  
> -static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
> +static int get_std_timing(unsigned char *block, struct fb_videomode *mode,
> +		int ver, int rev)
>  {
>  	int xres, yres = 0, refresh, ratio, i;
>  
> @@ -504,7 +505,11 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
>  	ratio = (block[1] & 0xc0) >> 6;
>  	switch (ratio) {
>  	case 0:
> -		yres = xres;
> +		/* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */
> +		if (ver < 1 || (ver = 1 && rev < 3))
> +			yres = xres;
> +		else
> +			yres = (xres * 10)/16;
>  		break;
>  	case 1:
>  		yres = (xres * 3)/4;
> @@ -533,12 +538,12 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
>  }
>  
>  static int get_dst_timing(unsigned char *block,
> -			  struct fb_videomode *mode)
> +			  struct fb_videomode *mode, int ver, int rev)
>  {
>  	int j, num = 0;
>  
>  	for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
> -		num += get_std_timing(block, &mode[num]);
> +		num += get_std_timing(block, &mode[num], ver, rev);
>  
>  	return num;
>  }
> @@ -599,6 +604,10 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
>  	struct fb_videomode *mode, *m;
>  	unsigned char *block;
>  	int num = 0, i, first = 1;
> +	int ver, rev;
> +
> +	ver = edid[EDID_STRUCT_VERSION];
> +	rev = edid[EDID_STRUCT_REVISION];
>  
>  	mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
>  	if (mode = NULL)
> @@ -632,12 +641,12 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
>  	DPRINTK("   Standard Timings\n");
>  	block = edid + STD_TIMING_DESCRIPTIONS_START;
>  	for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
> -		num += get_std_timing(block, &mode[num]);
> +		num += get_std_timing(block, &mode[num], ver, rev);
>  
>  	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
>  	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
>  		if (block[0] = 0x00 && block[1] = 0x00 && block[3] = 0xfa)
> -			num += get_dst_timing(block + 5, &mode[num]);
> +			num += get_dst_timing(block + 5, &mode[num], ver, rev);
>  	}
>  
>  	/* Yikes, EDID data is totally useless */


^ permalink raw reply

* Re: [PATCH RESEND] video: nuc900fb: remove include of mach/clkdev.h
From: Florian Tobias Schandinat @ 2011-09-01 13:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1314836018.2208.3.camel@phoenix>

On 09/01/2011 12:13 AM, Axel Lin wrote:
> Since commit aa3831cf9d29cfeaebd8c2169378b74111364487
> "ARM: Consolidate the clkdev header files",
> the header file arch/arm/mach-nuc93x/include/mach/clkdev.h is removed.
> 
> This patch fixes below build error:
> 
> drivers/video/nuc900fb.c:42:25: error: mach/clkdev.h: No such file or directory
> make[2]: *** [drivers/video/nuc900fb.o] Error 1
> make[1]: *** [drivers/video] Error 2
> make: *** [drivers] Error 2
> 
> Signed-off-by: Axel Lin <axel.lin@gmail.com>

Applied.
I'm wondering whether this build regression was unavoidable...


Thanks,

Florian Tobias Schandinat


> ---
>  drivers/video/nuc900fb.c |    1 -
>  1 files changed, 0 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
> index 0fff5978..37dd850 100644
> --- a/drivers/video/nuc900fb.c
> +++ b/drivers/video/nuc900fb.c
> @@ -39,7 +39,6 @@
>  #include <mach/regs-clock.h>
>  #include <mach/regs-ldm.h>
>  #include <mach/fb.h>
> -#include <mach/clkdev.h>
>  
>  #include "nuc900fb.h"
>  


^ permalink raw reply

* Re: [PATCH RESEND] video: mxsfb: add missing include of linux/module.h
From: Florian Tobias Schandinat @ 2011-09-01 13:01 UTC (permalink / raw)
  To: Axel Lin; +Cc: linux-kernel, Sascha Hauer, Paul Mundt, linux-fbdev
In-Reply-To: <1314835919.2208.1.camel@phoenix>

On 09/01/2011 12:11 AM, Axel Lin wrote:
> Include linux/module.h to fix below build error:
> 
>                  from drivers/video/mxsfb.c:42:
> arch/arm/mach-mxs/include/mach/memory.h:22:1: warning: this is the location of the previous definition
> drivers/video/mxsfb.c:574: error: 'THIS_MODULE' undeclared here (not in a function)
> drivers/video/mxsfb.c:893: warning: data definition has no type or storage class
> drivers/video/mxsfb.c:893: warning: type defaults to 'int' in declaration of 'MODULE_DEVICE_TABLE'
> drivers/video/mxsfb.c:893: warning: parameter names (without types) in function declaration
> drivers/video/mxsfb.c:917: error: expected declaration specifiers or '...' before string constant
> drivers/video/mxsfb.c:917: warning: data definition has no type or storage class
> drivers/video/mxsfb.c:917: warning: type defaults to 'int' in declaration of 'MODULE_DESCRIPTION'
> drivers/video/mxsfb.c:917: warning: function declaration isn't a prototype
> drivers/video/mxsfb.c:918: error: expected declaration specifiers or '...' before string constant
> drivers/video/mxsfb.c:918: warning: data definition has no type or storage class
> drivers/video/mxsfb.c:918: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR'
> drivers/video/mxsfb.c:918: warning: function declaration isn't a prototype
> drivers/video/mxsfb.c:919: error: expected declaration specifiers or '...' before string constant
> drivers/video/mxsfb.c:919: warning: data definition has no type or storage class
> drivers/video/mxsfb.c:919: warning: type defaults to 'int' in declaration of 'MODULE_LICENSE'
> drivers/video/mxsfb.c:919: warning: function declaration isn't a prototype
> make[2]: *** [drivers/video/mxsfb.o] Error 1
> make[1]: *** [drivers/video] Error 2
> make: *** [drivers] Error 2
> 
> Signed-off-by: Axel Lin <axel.lin@gmail.com>

Applied.


Thanks,

Florian Tobias Schandinat

> ---
>  drivers/video/mxsfb.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
> index 0b2f2dd..d837d63 100644
> --- a/drivers/video/mxsfb.c
> +++ b/drivers/video/mxsfb.c
> @@ -39,6 +39,7 @@
>   * the required value in the imx_fb_videomode structure.
>   */
>  
> +#include <linux/module.h>
>  #include <linux/kernel.h>
>  #include <linux/platform_device.h>
>  #include <linux/clk.h>


^ permalink raw reply

* [PATCH RESEND] video: nuc900fb: remove include of mach/clkdev.h
From: Axel Lin @ 2011-09-01  0:13 UTC (permalink / raw)
  To: linux-arm-kernel

Since commit aa3831cf9d29cfeaebd8c2169378b74111364487
"ARM: Consolidate the clkdev header files",
the header file arch/arm/mach-nuc93x/include/mach/clkdev.h is removed.

This patch fixes below build error:

drivers/video/nuc900fb.c:42:25: error: mach/clkdev.h: No such file or directory
make[2]: *** [drivers/video/nuc900fb.o] Error 1
make[1]: *** [drivers/video] Error 2
make: *** [drivers] Error 2

Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
 drivers/video/nuc900fb.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index 0fff5978..37dd850 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -39,7 +39,6 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-ldm.h>
 #include <mach/fb.h>
-#include <mach/clkdev.h>
 
 #include "nuc900fb.h"
 
-- 
1.7.4.1




^ permalink raw reply related

* [PATCH RESEND] video: mxsfb: add missing include of linux/module.h
From: Axel Lin @ 2011-09-01  0:11 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sascha Hauer, Paul Mundt, linux-fbdev, Florian Tobias Schandinat

Include linux/module.h to fix below build error:

                 from drivers/video/mxsfb.c:42:
arch/arm/mach-mxs/include/mach/memory.h:22:1: warning: this is the location of the previous definition
drivers/video/mxsfb.c:574: error: 'THIS_MODULE' undeclared here (not in a function)
drivers/video/mxsfb.c:893: warning: data definition has no type or storage class
drivers/video/mxsfb.c:893: warning: type defaults to 'int' in declaration of 'MODULE_DEVICE_TABLE'
drivers/video/mxsfb.c:893: warning: parameter names (without types) in function declaration
drivers/video/mxsfb.c:917: error: expected declaration specifiers or '...' before string constant
drivers/video/mxsfb.c:917: warning: data definition has no type or storage class
drivers/video/mxsfb.c:917: warning: type defaults to 'int' in declaration of 'MODULE_DESCRIPTION'
drivers/video/mxsfb.c:917: warning: function declaration isn't a prototype
drivers/video/mxsfb.c:918: error: expected declaration specifiers or '...' before string constant
drivers/video/mxsfb.c:918: warning: data definition has no type or storage class
drivers/video/mxsfb.c:918: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR'
drivers/video/mxsfb.c:918: warning: function declaration isn't a prototype
drivers/video/mxsfb.c:919: error: expected declaration specifiers or '...' before string constant
drivers/video/mxsfb.c:919: warning: data definition has no type or storage class
drivers/video/mxsfb.c:919: warning: type defaults to 'int' in declaration of 'MODULE_LICENSE'
drivers/video/mxsfb.c:919: warning: function declaration isn't a prototype
make[2]: *** [drivers/video/mxsfb.o] Error 1
make[1]: *** [drivers/video] Error 2
make: *** [drivers] Error 2

Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
 drivers/video/mxsfb.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 0b2f2dd..d837d63 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -39,6 +39,7 @@
  * the required value in the imx_fb_videomode structure.
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
-- 
1.7.4.1




^ permalink raw reply related

* Re: [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
From: Tomi Valkeinen @ 2011-08-31 18:09 UTC (permalink / raw)
  To: Andy Doan; +Cc: linux-omap, linux-fbdev, archit, mythripk
In-Reply-To: <4E5E4C9B.2010504@linaro.org>

On Wed, 2011-08-31 at 10:00 -0500, Andy Doan wrote:
> On 08/31/2011 08:23 AM, Tomi Valkeinen wrote:
> > Add i2c bus number for DVI output. The driver uses this to detect if a
> > panel is connected and to read EDID.
> >
> > Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> > ---
> >   arch/arm/mach-omap2/board-omap3beagle.c |    1 +
> >   arch/arm/mach-omap2/board-omap4panda.c  |    1 +
> >   2 files changed, 2 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> > index 3ae16b4..13244e9 100644
> > --- a/arch/arm/mach-omap2/board-omap3beagle.c
> > +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> > @@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
> >   	.name = "generic",
> >   	.platform_enable = beagle_enable_dvi,
> >   	.platform_disable = beagle_disable_dvi,
> > +	.i2c_bus_num = 3,
> >   };
> >
> >   static struct omap_dss_device beagle_dvi_device = {
> > diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
> > index 9aaa960..d5760e3 100644
> > --- a/arch/arm/mach-omap2/board-omap4panda.c
> > +++ b/arch/arm/mach-omap2/board-omap4panda.c
> > @@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
> >   	.name			= "generic",
> >   	.platform_enable	= omap4_panda_enable_dvi,
> >   	.platform_disable	= omap4_panda_disable_dvi,
> > +	.i2c_bus_num = 3,
> >   };
> >
> >   struct omap_dss_device omap4_panda_dvi_device = {
> 
> Can you add a similar patch for board-overo.c? I've tested earlier 
> versions of this patch series on a Tide+Tobi successfully. Here's a copy 
> of my patch:
> 
>    http://tinyurl.com/3cek5m7

Sure. I only added the boards I know have the ddc i2c on bus 3 (i.e.
those I was able to test).

 Tomi



^ permalink raw reply

* Re: [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
From: Andy Doan @ 2011-08-31 15:00 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev, archit, mythripk
In-Reply-To: <1314797003-17638-12-git-send-email-tomi.valkeinen@ti.com>

On 08/31/2011 08:23 AM, Tomi Valkeinen wrote:
> Add i2c bus number for DVI output. The driver uses this to detect if a
> panel is connected and to read EDID.
>
> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> ---
>   arch/arm/mach-omap2/board-omap3beagle.c |    1 +
>   arch/arm/mach-omap2/board-omap4panda.c  |    1 +
>   2 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> index 3ae16b4..13244e9 100644
> --- a/arch/arm/mach-omap2/board-omap3beagle.c
> +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> @@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
>   	.name = "generic",
>   	.platform_enable = beagle_enable_dvi,
>   	.platform_disable = beagle_disable_dvi,
> +	.i2c_bus_num = 3,
>   };
>
>   static struct omap_dss_device beagle_dvi_device = {
> diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
> index 9aaa960..d5760e3 100644
> --- a/arch/arm/mach-omap2/board-omap4panda.c
> +++ b/arch/arm/mach-omap2/board-omap4panda.c
> @@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
>   	.name			= "generic",
>   	.platform_enable	= omap4_panda_enable_dvi,
>   	.platform_disable	= omap4_panda_disable_dvi,
> +	.i2c_bus_num = 3,
>   };
>
>   struct omap_dss_device omap4_panda_dvi_device = {

Can you add a similar patch for board-overo.c? I've tested earlier 
versions of this patch series on a Tide+Tobi successfully. Here's a copy 
of my patch:

   http://tinyurl.com/3cek5m7


^ permalink raw reply

* [PATCH 12/12] OMAPFB: find best mode from edid
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

Use the new read_edid() function to get EDID information from the
display (when available), and use the information to use a suitable mode
at initialization time.

Hot-plug is not yet supported, so the timings selected at init time will
stay even if the monitor would be changed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/omapfb/omapfb-main.c |  109 +++++++++++++++++++++++++++---
 1 files changed, 99 insertions(+), 10 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index cd2cae8e..c84cc29 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2276,6 +2276,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
 	return r;
 }
 
+static void fb_videomode_to_omap_timings(struct fb_videomode *m,
+		struct omap_video_timings *t)
+{
+	t->x_res = m->xres;
+	t->y_res = m->yres;
+	t->pixel_clock = PICOS2KHZ(m->pixclock);
+	t->hsw = m->hsync_len;
+	t->hfp = m->right_margin;
+	t->hbp = m->left_margin;
+	t->vsw = m->vsync_len;
+	t->vfp = m->lower_margin;
+	t->vbp = m->upper_margin;
+}
+
+static int omapfb_find_best_mode(struct omap_dss_device *display,
+		struct omap_video_timings *timings)
+{
+	struct fb_monspecs *specs;
+	u8 *edid;
+	int r, i, best_xres, best_idx, len;
+
+	if (!display->driver->read_edid)
+		return -ENODEV;
+
+	len = 0x80 * 2;
+	edid = kmalloc(len, GFP_KERNEL);
+
+	r = display->driver->read_edid(display, edid, len);
+	if (r < 0)
+		goto err1;
+
+	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+
+	fb_edid_to_monspecs(edid, specs);
+
+	if (edid[126] > 0)
+		fb_edid_add_monspecs(edid + 0x80, specs);
+
+	best_xres = 0;
+	best_idx = -1;
+
+	for (i = 0; i < specs->modedb_len; ++i) {
+		struct fb_videomode *m;
+		struct omap_video_timings t;
+
+		m = &specs->modedb[i];
+
+		if (m->pixclock = 0)
+			continue;
+
+		/* skip repeated pixel modes */
+		if (m->xres = 2880 || m->xres = 1440)
+			continue;
+
+		fb_videomode_to_omap_timings(m, &t);
+
+		r = display->driver->check_timings(display, &t);
+		if (r = 0 && best_xres < m->xres) {
+			best_xres = m->xres;
+			best_idx = i;
+		}
+	}
+
+	if (best_xres = 0) {
+		r = -ENOENT;
+		goto err2;
+	}
+
+	fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);
+
+	r = 0;
+
+err2:
+	fb_destroy_modedb(specs->modedb);
+	kfree(specs);
+err1:
+	kfree(edid);
+
+	return r;
+}
+
 static int omapfb_init_display(struct omapfb2_device *fbdev,
 		struct omap_dss_device *dssdev)
 {
@@ -2404,9 +2485,27 @@ static int omapfb_probe(struct platform_device *pdev)
 	for (i = 0; i < fbdev->num_managers; i++)
 		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
 
+	/* gfx overlay should be the default one. find a display
+	 * connected to that, and use it as default display */
+	ovl = omap_dss_get_overlay(0);
+	if (ovl->manager && ovl->manager->device) {
+		def_display = ovl->manager->device;
+	} else {
+		dev_warn(&pdev->dev, "cannot find default display\n");
+		def_display = NULL;
+	}
+
 	if (def_mode && strlen(def_mode) > 0) {
 		if (omapfb_parse_def_modes(fbdev))
 			dev_warn(&pdev->dev, "cannot parse default modes\n");
+	} else if (def_display && def_display->driver->set_timings &&
+			def_display->driver->check_timings) {
+		struct omap_video_timings t;
+
+		r = omapfb_find_best_mode(def_display, &t);
+
+		if (r = 0)
+			def_display->driver->set_timings(def_display, &t);
 	}
 
 	r = omapfb_create_framebuffers(fbdev);
@@ -2423,16 +2522,6 @@ static int omapfb_probe(struct platform_device *pdev)
 
 	DBG("mgr->apply'ed\n");
 
-	/* gfx overlay should be the default one. find a display
-	 * connected to that, and use it as default display */
-	ovl = omap_dss_get_overlay(0);
-	if (ovl->manager && ovl->manager->device) {
-		def_display = ovl->manager->device;
-	} else {
-		dev_warn(&pdev->dev, "cannot find default display\n");
-		def_display = NULL;
-	}
-
 	if (def_display) {
 		r = omapfb_init_display(fbdev, def_display);
 		if (r) {
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

Add i2c bus number for DVI output. The driver uses this to detect if a
panel is connected and to read EDID.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/board-omap3beagle.c |    1 +
 arch/arm/mach-omap2/board-omap4panda.c  |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 3ae16b4..13244e9 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
 	.name = "generic",
 	.platform_enable = beagle_enable_dvi,
 	.platform_disable = beagle_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 static struct omap_dss_device beagle_dvi_device = {
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 9aaa960..d5760e3 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
 	.name			= "generic",
 	.platform_enable	= omap4_panda_enable_dvi,
 	.platform_disable	= omap4_panda_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 struct omap_dss_device omap4_panda_dvi_device = {
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 10/12] OMAP: DSS2: Generic-dpi: add detect & read_edid support
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

Add i2c_bus_num field to panel_generic_dpi_data, and use it in the
panel-generic-dpi.c to detect if a panel is connected and to read EDID
from the panel.

Original by: Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/displays/panel-generic-dpi.c |   92 ++++++++++++++++++++++
 include/video/omap-panel-generic-dpi.h           |    2 +
 2 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 9c90f75..6ef36ad 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -34,6 +34,8 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <video/omapdss.h>
+#include <linux/i2c.h>
+#include <drm/drm_edid.h>
 
 #include <video/omap-panel-generic-dpi.h>
 
@@ -407,6 +409,93 @@ static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
 	return dpi_check_timings(dssdev, timings);
 }
 
+
+static int generic_dpi_ddc_read(struct i2c_adapter *adapter,
+		unsigned char *buf, u16 count, u8 offset)
+{
+	int r, retries;
+
+	for (retries = 3; retries > 0; retries--) {
+		struct i2c_msg msgs[] = {
+			{
+				.addr   = DDC_ADDR,
+				.flags  = 0,
+				.len    = 1,
+				.buf    = &offset,
+			}, {
+				.addr   = DDC_ADDR,
+				.flags  = I2C_M_RD,
+				.len    = count,
+				.buf    = buf,
+			}
+		};
+
+		r = i2c_transfer(adapter, msgs, 2);
+		if (r = 2)
+			return 0;
+
+		if (r != -EAGAIN)
+			break;
+	}
+
+	return r < 0 ? r : -EIO;
+}
+
+static int generic_dpi_panel_read_edid(struct omap_dss_device *dssdev,
+		u8 *edid, int len)
+{
+	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
+	struct i2c_adapter *adapter;
+	int r, l, bytes_read;
+
+	if (panel_data->i2c_bus_num = 0)
+		return -ENODEV;
+
+	adapter = i2c_get_adapter(panel_data->i2c_bus_num);
+	if (!adapter) {
+		dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
+				panel_data->i2c_bus_num);
+		return -EINVAL;
+	}
+
+	l = min(EDID_LENGTH, len);
+	r = generic_dpi_ddc_read(adapter, edid, l, 0);
+	if (r)
+		return r;
+
+	bytes_read = l;
+
+	/* if there are extensions, read second block */
+	if (len > EDID_LENGTH && edid[0x7e] > 0) {
+		l = min(EDID_LENGTH, len - EDID_LENGTH);
+
+		r = generic_dpi_ddc_read(adapter, edid + EDID_LENGTH,
+				l, EDID_LENGTH);
+		if (r)
+			return r;
+
+		bytes_read += l;
+	}
+
+	return bytes_read;
+}
+
+static bool generic_dpi_panel_detect(struct omap_dss_device *dssdev)
+{
+	struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
+	struct i2c_adapter *adapter;
+	unsigned char out;
+
+	if (panel_data->i2c_bus_num = 0)
+		return true;
+
+	adapter = i2c_get_adapter(panel_data->i2c_bus_num);
+	if (!adapter)
+		return true;
+
+	return generic_dpi_ddc_read(adapter, &out, 1, 0) = 0;
+}
+
 static struct omap_dss_driver dpi_driver = {
 	.probe		= generic_dpi_panel_probe,
 	.remove		= __exit_p(generic_dpi_panel_remove),
@@ -420,6 +509,9 @@ static struct omap_dss_driver dpi_driver = {
 	.get_timings	= generic_dpi_panel_get_timings,
 	.check_timings	= generic_dpi_panel_check_timings,
 
+	.read_edid	= generic_dpi_panel_read_edid,
+	.detect		= generic_dpi_panel_detect,
+
 	.driver         = {
 		.name   = "generic_dpi_panel",
 		.owner  = THIS_MODULE,
diff --git a/include/video/omap-panel-generic-dpi.h b/include/video/omap-panel-generic-dpi.h
index 127e3f2..3ab023a 100644
--- a/include/video/omap-panel-generic-dpi.h
+++ b/include/video/omap-panel-generic-dpi.h
@@ -27,11 +27,13 @@ struct omap_dss_device;
  * @name: panel name
  * @platform_enable: platform specific panel enable function
  * @platform_disable: platform specific panel disable function
+ * @i2c_bus_num: i2c bus id for the panel
  */
 struct panel_generic_dpi_data {
 	const char *name;
 	int (*platform_enable)(struct omap_dss_device *dssdev);
 	void (*platform_disable)(struct omap_dss_device *dssdev);
+	u16 i2c_bus_num;
 };
 
 #endif /* __OMAP_PANEL_GENERIC_DPI_H */
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 09/12] OMAP: DSS2: HDMI: implement detect()
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

Implement detect() by checking the hot plug detect status.

The implementation is not very good, as it always turns on the HDMI
output to get the detection working. HDMI driver needs improvements so
that we could enable only core parts of it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.h              |    1 +
 drivers/video/omap2/dss/hdmi.c             |   18 ++++++++++++++++++
 drivers/video/omap2/dss/hdmi_omap4_panel.c |   25 +++++++++++++++++++++++++
 3 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6102b80..dd7dc19 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -493,6 +493,7 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 					struct omap_video_timings *timings);
 int omapdss_hdmi_read_edid(u8 *buf, int len);
+bool omapdss_hdmi_detect(void);
 int hdmi_panel_init(void);
 void hdmi_panel_exit(void);
 
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 55edbd2..e8a977e 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1148,6 +1148,24 @@ int omapdss_hdmi_read_edid(u8 *buf, int len)
 	return r;
 }
 
+bool omapdss_hdmi_detect(void)
+{
+	int r;
+
+	mutex_lock(&hdmi.lock);
+
+	r = hdmi_runtime_get();
+	BUG_ON(r);
+
+	/* HPD */
+	r = REG_GET(HDMI_CORE_SYS_SYS_STAT, 1, 1);
+
+	hdmi_runtime_put();
+	mutex_unlock(&hdmi.lock);
+
+	return r = 1;
+}
+
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 {
 	int r = 0;
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index ffea8d3..c859421 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -25,6 +25,7 @@
 #include <linux/mutex.h>
 #include <linux/module.h>
 #include <video/omapdss.h>
+#include <linux/slab.h>
 
 #include "dss.h"
 
@@ -198,6 +199,29 @@ err:
 	return r;
 }
 
+static bool hdmi_detect(struct omap_dss_device *dssdev)
+{
+	int r;
+
+	mutex_lock(&hdmi.hdmi_lock);
+
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+		r = omapdss_hdmi_display_enable(dssdev);
+		if (r)
+			goto err;
+	}
+
+	r = omapdss_hdmi_detect();
+
+	if (dssdev->state = OMAP_DSS_DISPLAY_DISABLED ||
+			dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED)
+		omapdss_hdmi_display_disable(dssdev);
+err:
+	mutex_unlock(&hdmi.hdmi_lock);
+
+	return r;
+}
+
 static struct omap_dss_driver hdmi_driver = {
 	.probe		= hdmi_panel_probe,
 	.remove		= hdmi_panel_remove,
@@ -209,6 +233,7 @@ static struct omap_dss_driver hdmi_driver = {
 	.set_timings	= hdmi_set_timings,
 	.check_timings	= hdmi_check_timings,
 	.read_edid	= hdmi_read_edid,
+	.detect		= hdmi_detect,
 	.driver			= {
 		.name   = "hdmi_panel",
 		.owner  = THIS_MODULE,
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 08/12] OMAP: DSS2: HDMI: remove error prints in check_timings
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

check_timings() is supposed to be used to verify if timings are ok or
not. Currently the HDMI driver prints error messages if the timings are
not ok. This is not right, as it is no error to give invalid timings to
check_timings().

Remove the error prints.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c             |    1 -
 drivers/video/omap2/dss/hdmi_omap4_panel.c |    6 +-----
 2 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 34e05ee..55edbd2 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1105,7 +1105,6 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 
 	cm = hdmi_get_code(timings);
 	if (cm.code = -1) {
-		DSSERR("Invalid timing entered\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 5e314e8..ffea8d3 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -170,11 +170,7 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
 	mutex_lock(&hdmi.hdmi_lock);
 
 	r = omapdss_hdmi_display_check_timing(dssdev, timings);
-	if (r) {
-		DSSERR("Timing cannot be applied\n");
-		goto err;
-	}
-err:
+
 	mutex_unlock(&hdmi.hdmi_lock);
 	return r;
 }
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 07/12] OMAP: DSS2: HDMI: clean up edid reading & fix checksum
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

Clean up reading of EDID by passing direct address to the block being
read, instead of start address of the whole EDID memory area. Rewrite
the loop which reads the EDID.

This also fixes the checksum calculation, which used to calculate the
checksum only for the first block.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c |   67 ++++++++++++++++++++-------------------
 1 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 04ce105..34e05ee 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -414,8 +414,8 @@ static int hdmi_core_ddc_init(void)
 
 static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 {
-	u32 i, j;
-	char checksum = 0;
+	u32 i;
+	char checksum;
 	u32 offset = 0;
 
 	/* HDMI_CORE_DDC_STATUS_IN_PROG */
@@ -457,21 +457,31 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 		return -EIO;
 	}
 
-	i = ext * 128;
-	j = 0;
-	while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) = 1) ||
-			(REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) = 0)) &&
-			j < 128) {
+	for (i = 0; i < 0x80; ++i) {
+		int t;
 
-		if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) = 0) {
-			/* FIFO not empty */
-			pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
-			j++;
+		/* IN_PROG */
+		if (REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) = 0) {
+			DSSERR("operation stopped when reading edid\n");
+			return -EIO;
+		}
+
+		t = 0;
+		/* FIFO_EMPTY */
+		while (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) = 1) {
+			if (t++ > 10000) {
+				DSSERR("timeout reading edid\n");
+				return -ETIMEDOUT;
+			}
+			udelay(1);
 		}
+
+		pedid[i] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
 	}
 
-	for (j = 0; j < 128; j++)
-		checksum += pedid[j];
+	checksum = 0;
+	for (i = 0; i < 0x80; ++i)
+		checksum += pedid[i];
 
 	if (checksum != 0) {
 		DSSERR("E-EDID checksum failed!!\n");
@@ -481,40 +491,31 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 	return 0;
 }
 
-static int read_edid(u8 *pedid, u16 max_length)
+static int read_edid(u8 *edid, int len)
 {
-	int r = 0, n = 0, i = 0;
-	int max_ext_blocks = (max_length / 128) - 1;
-	int len;
+	int r, l;
+
+	if (len < 128)
+		return -EINVAL;
 
 	r = hdmi_core_ddc_init();
 	if (r)
 		return r;
 
-	r = hdmi_core_ddc_edid(pedid, 0);
+	r = hdmi_core_ddc_edid(edid, 0);
 	if (r)
 		return r;
 
-	len = 128;
-	n = pedid[0x7e];
-
-	/*
-	 * README: need to comply with max_length set by the caller.
-	 * Better implementation should be to allocate necessary
-	 * memory to store EDID according to nb_block field found
-	 * in first block
-	 */
-	if (n > max_ext_blocks)
-		n = max_ext_blocks;
+	l = 128;
 
-	for (i = 1; i <= n; i++) {
-		r = hdmi_core_ddc_edid(pedid, i);
+	if (len >= 128 * 2 && edid[0x7e] > 0) {
+		r = hdmi_core_ddc_edid(edid + 0x80, 1);
 		if (r)
 			return r;
-		len += 128;
+		l += 128;
 	}
 
-	return len;
+	return l;
 }
 
 static int get_timings_index(void)
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 06/12] OMAP: DSS2: HDMI: split hdmi_core_ddc_edid
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

Split the DDC initialization off from hdmi_core_ddc_edid() into a
separate function hdmi_core_ddc_init().

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c |   67 +++++++++++++++++++++++++++-------------
 1 files changed, 45 insertions(+), 22 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index b5aca64..04ce105 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -366,12 +366,8 @@ static void hdmi_phy_off(void)
 	hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
 }
 
-static int hdmi_core_ddc_edid(u8 *pedid, int ext)
+static int hdmi_core_ddc_init(void)
 {
-	u32 i, j;
-	char checksum = 0;
-	u32 offset = 0;
-
 	/* Turn on CLK for DDC */
 	REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0);
 
@@ -382,32 +378,55 @@ static int hdmi_core_ddc_edid(u8 *pedid, int ext)
 	 */
 	usleep_range(800, 1000);
 
-	if (!ext) {
-		/* Clk SCL Devices */
-		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
+	/* IN_PROG */
+	if (REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) = 1) {
+		/* Abort transaction */
+		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xf, 3, 0);
 
-		/* HDMI_CORE_DDC_STATUS_IN_PROG */
+		/* IN_PROG */
 		if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
-						4, 4, 0) != 0) {
-			DSSERR("Failed to program DDC\n");
+					4, 4, 0) != 0) {
+			DSSERR("Timeout aborting DDC transaction\n");
 			return -ETIMEDOUT;
 		}
+	}
 
-		/* Clear FIFO */
-		REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0);
+	/* Clk SCL Devices */
+	REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
 
-		/* HDMI_CORE_DDC_STATUS_IN_PROG */
-		if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
-						4, 4, 0) != 0) {
-			DSSERR("Failed to program DDC\n");
-			return -ETIMEDOUT;
-		}
+	/* HDMI_CORE_DDC_STATUS_IN_PROG */
+	if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
+		DSSERR("Timeout starting SCL clock\n");
+		return -ETIMEDOUT;
+	}
 
-	} else {
-		if (ext % 2 != 0)
-			offset = 0x80;
+	/* Clear FIFO */
+	REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0);
+
+	/* HDMI_CORE_DDC_STATUS_IN_PROG */
+	if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
+		DSSERR("Timeout clearing DDC fifo\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int hdmi_core_ddc_edid(u8 *pedid, int ext)
+{
+	u32 i, j;
+	char checksum = 0;
+	u32 offset = 0;
+
+	/* HDMI_CORE_DDC_STATUS_IN_PROG */
+	if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, 4, 4, 0) != 0) {
+		DSSERR("Timeout waiting DDC to be ready\n");
+		return -ETIMEDOUT;
 	}
 
+	if (ext % 2 != 0)
+		offset = 0x80;
+
 	/* Load Segment Address Register */
 	REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
 
@@ -468,6 +487,10 @@ static int read_edid(u8 *pedid, u16 max_length)
 	int max_ext_blocks = (max_length / 128) - 1;
 	int len;
 
+	r = hdmi_core_ddc_init();
+	if (r)
+		return r;
+
 	r = hdmi_core_ddc_edid(pedid, 0);
 	if (r)
 		return r;
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 05/12] OMAP: DSS2: HDMI: remove edid parsing
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

OMAPFB handles EDID parsing now, using the common helper functions in
fbdev. We can remove the EDID parsing from HDMI driver.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c             |  137 ----------------------------
 drivers/video/omap2/dss/hdmi_omap4_panel.c |    8 +--
 2 files changed, 1 insertions(+), 144 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 5e66cb8..b5aca64 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -53,9 +53,6 @@ static struct {
 	void __iomem *base_wp;	/* HDMI wrapper */
 	int code;
 	int mode;
-	u8 edid[HDMI_EDID_MAX_LENGTH];
-	u8 edid_set;
-	bool custom_set;
 	struct hdmi_config cfg;
 
 	struct clk *sys_clk;
@@ -146,8 +143,6 @@ static const int code_vesa[85] = {
 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 	-1, 27, 28, -1, 33};
 
-static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0};
-
 static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val)
 {
 	__raw_writel(val, hdmi.base_wp + idx.idx);
@@ -561,129 +556,6 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
 	return cm;
 }
 
-static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid ,
-		struct omap_video_timings *timings)
-{
-	/* X and Y resolution */
-	timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) |
-			 edid[current_descriptor_addrs + 2]);
-	timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) |
-			 edid[current_descriptor_addrs + 5]);
-
-	timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) |
-				edid[current_descriptor_addrs]);
-
-	timings->pixel_clock = 10 * timings->pixel_clock;
-
-	/* HORIZONTAL FRONT PORCH */
-	timings->hfp = edid[current_descriptor_addrs + 8] |
-			((edid[current_descriptor_addrs + 11] & 0xc0) << 2);
-	/* HORIZONTAL SYNC WIDTH */
-	timings->hsw = edid[current_descriptor_addrs + 9] |
-			((edid[current_descriptor_addrs + 11] & 0x30) << 4);
-	/* HORIZONTAL BACK PORCH */
-	timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) |
-			edid[current_descriptor_addrs + 3]) -
-			(timings->hfp + timings->hsw);
-	/* VERTICAL FRONT PORCH */
-	timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) |
-			((edid[current_descriptor_addrs + 11] & 0x0f) << 2);
-	/* VERTICAL SYNC WIDTH */
-	timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) |
-			((edid[current_descriptor_addrs + 11] & 0x03) << 4);
-	/* VERTICAL BACK PORCH */
-	timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) |
-			edid[current_descriptor_addrs + 6]) -
-			(timings->vfp + timings->vsw);
-
-}
-
-/* Description : This function gets the resolution information from EDID */
-static void get_edid_timing_data(u8 *edid)
-{
-	u8 count;
-	u16 current_descriptor_addrs;
-	struct hdmi_cm cm;
-	struct omap_video_timings edid_timings;
-
-	/* search block 0, there are 4 DTDs arranged in priority order */
-	for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) {
-		current_descriptor_addrs -			EDID_DESCRIPTOR_BLOCK0_ADDRESS +
-			count * EDID_TIMING_DESCRIPTOR_SIZE;
-		get_horz_vert_timing_info(current_descriptor_addrs,
-				edid, &edid_timings);
-		cm = hdmi_get_code(&edid_timings);
-		DSSDBG("Block0[%d] value matches code = %d , mode = %d\n",
-			count, cm.code, cm.mode);
-		if (cm.code = -1) {
-			continue;
-		} else {
-			hdmi.code = cm.code;
-			hdmi.mode = cm.mode;
-			DSSDBG("code = %d , mode = %d\n",
-				hdmi.code, hdmi.mode);
-			return;
-		}
-	}
-	if (edid[0x7e] != 0x00) {
-		for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR;
-			count++) {
-			current_descriptor_addrs -			EDID_DESCRIPTOR_BLOCK1_ADDRESS +
-			count * EDID_TIMING_DESCRIPTOR_SIZE;
-			get_horz_vert_timing_info(current_descriptor_addrs,
-						edid, &edid_timings);
-			cm = hdmi_get_code(&edid_timings);
-			DSSDBG("Block1[%d] value matches code = %d, mode = %d",
-				count, cm.code, cm.mode);
-			if (cm.code = -1) {
-				continue;
-			} else {
-				hdmi.code = cm.code;
-				hdmi.mode = cm.mode;
-				DSSDBG("code = %d , mode = %d\n",
-					hdmi.code, hdmi.mode);
-				return;
-			}
-		}
-	}
-
-	DSSINFO("no valid timing found , falling back to VGA\n");
-	hdmi.code = 4; /* setting default value of 640 480 VGA */
-	hdmi.mode = HDMI_DVI;
-}
-
-static void hdmi_read_edid(struct omap_video_timings *dp)
-{
-	int ret = 0, code;
-
-	memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH);
-
-	if (!hdmi.edid_set)
-		ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
-
-	if (ret > 0) {
-		if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
-			/* search for timings of default resolution */
-			get_edid_timing_data(hdmi.edid);
-			hdmi.edid_set = true;
-		}
-	} else {
-		DSSWARN("failed to read E-EDID\n");
-	}
-
-	if (!hdmi.edid_set) {
-		DSSINFO("fallback to VGA\n");
-		hdmi.code = 4; /* setting default value of 640 480 VGA */
-		hdmi.mode = HDMI_DVI;
-	}
-
-	code = get_timings_index();
-
-	*dp = cea_vesa_timings[code].timings;
-}
-
 static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
 			struct hdmi_core_infoframe_avi *avi_cfg,
 			struct hdmi_core_packet_enable_repeat *repeat_cfg)
@@ -1138,12 +1010,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 		dssdev->panel.timings.x_res,
 		dssdev->panel.timings.y_res);
 
-	if (!hdmi.custom_set) {
-		DSSDBG("Read EDID as no EDID is not set on poweron\n");
-		hdmi_read_edid(p);
-	}
 	code = get_timings_index();
-	dssdev->panel.timings = cea_vesa_timings[code].timings;
 	update_hdmi_timings(&hdmi.cfg, p, code);
 
 	phy = p->pixel_clock;
@@ -1205,8 +1072,6 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
 	hdmi_phy_off();
 	hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
 	hdmi_runtime_put();
-
-	hdmi.edid_set = 0;
 }
 
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -1228,8 +1093,6 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
 {
 	struct hdmi_cm cm;
 
-	hdmi.custom_set = 1;
-
 	cm = hdmi_get_code(&dssdev->panel.timings);
 	hdmi.code = cm.code;
 	hdmi.mode = cm.mode;
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 7adaf7a..5e314e8 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -40,13 +40,7 @@ static int hdmi_panel_probe(struct omap_dss_device *dssdev)
 	dssdev->panel.config = OMAP_DSS_LCD_TFT |
 			OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS;
 
-	/*
-	 * Initialize the timings to 640 * 480
-	 * This is only for framebuffer update not for TV timing setting
-	 * Setting TV timing will be done only on enable
-	 */
-	dssdev->panel.timings.x_res = 640;
-	dssdev->panel.timings.y_res = 480;
+	dssdev->panel.timings = (struct omap_video_timings){640, 480, 25175, 96, 16, 48, 2 , 11, 31};
 
 	DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
 		dssdev->panel.timings.x_res,
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 04/12] OMAP: DSS2: HDMI: implement read_edid()
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

Implement read_edid() for HDMI by implementing necessary functions to
hdmi.c and to hdmi_omap4_panel.c.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.h              |    1 +
 drivers/video/omap2/dss/hdmi.c             |   60 ++++++++++++++++++---------
 drivers/video/omap2/dss/hdmi_omap4_panel.c |   24 +++++++++++
 3 files changed, 65 insertions(+), 20 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 57b1a01..6102b80 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -492,6 +492,7 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 					struct omap_video_timings *timings);
+int omapdss_hdmi_read_edid(u8 *buf, int len);
 int hdmi_panel_init(void);
 void hdmi_panel_exit(void);
 
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 8f8ae0e..5e66cb8 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -471,29 +471,32 @@ static int read_edid(u8 *pedid, u16 max_length)
 {
 	int r = 0, n = 0, i = 0;
 	int max_ext_blocks = (max_length / 128) - 1;
+	int len;
 
 	r = hdmi_core_ddc_edid(pedid, 0);
-	if (r) {
+	if (r)
 		return r;
-	} else {
-		n = pedid[0x7e];
 
-		/*
-		 * README: need to comply with max_length set by the caller.
-		 * Better implementation should be to allocate necessary
-		 * memory to store EDID according to nb_block field found
-		 * in first block
-		 */
-		if (n > max_ext_blocks)
-			n = max_ext_blocks;
+	len = 128;
+	n = pedid[0x7e];
 
-		for (i = 1; i <= n; i++) {
-			r = hdmi_core_ddc_edid(pedid, i);
-			if (r)
-				return r;
-		}
+	/*
+	 * README: need to comply with max_length set by the caller.
+	 * Better implementation should be to allocate necessary
+	 * memory to store EDID according to nb_block field found
+	 * in first block
+	 */
+	if (n > max_ext_blocks)
+		n = max_ext_blocks;
+
+	for (i = 1; i <= n; i++) {
+		r = hdmi_core_ddc_edid(pedid, i);
+		if (r)
+			return r;
+		len += 128;
 	}
-	return 0;
+
+	return len;
 }
 
 static int get_timings_index(void)
@@ -660,7 +663,7 @@ static void hdmi_read_edid(struct omap_video_timings *dp)
 	if (!hdmi.edid_set)
 		ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
 
-	if (!ret) {
+	if (ret > 0) {
 		if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
 			/* search for timings of default resolution */
 			get_edid_timing_data(hdmi.edid);
@@ -1242,6 +1245,23 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
 	}
 }
 
+int omapdss_hdmi_read_edid(u8 *buf, int len)
+{
+	int r;
+
+	mutex_lock(&hdmi.lock);
+
+	r = hdmi_runtime_get();
+	BUG_ON(r);
+
+	r = read_edid(buf, len);
+
+	hdmi_runtime_put();
+	mutex_unlock(&hdmi.lock);
+
+	return r;
+}
+
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 {
 	int r = 0;
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 25d5fb2..7adaf7a 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -185,6 +185,29 @@ err:
 	return r;
 }
 
+static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
+{
+	int r;
+
+	mutex_lock(&hdmi.hdmi_lock);
+
+	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+		r = omapdss_hdmi_display_enable(dssdev);
+		if (r)
+			goto err;
+	}
+
+	r = omapdss_hdmi_read_edid(buf, len);
+
+	if (dssdev->state = OMAP_DSS_DISPLAY_DISABLED ||
+			dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED)
+		omapdss_hdmi_display_disable(dssdev);
+err:
+	mutex_unlock(&hdmi.hdmi_lock);
+
+	return r;
+}
+
 static struct omap_dss_driver hdmi_driver = {
 	.probe		= hdmi_panel_probe,
 	.remove		= hdmi_panel_remove,
@@ -195,6 +218,7 @@ static struct omap_dss_driver hdmi_driver = {
 	.get_timings	= hdmi_get_timings,
 	.set_timings	= hdmi_set_timings,
 	.check_timings	= hdmi_check_timings,
+	.read_edid	= hdmi_read_edid,
 	.driver			= {
 		.name   = "hdmi_panel",
 		.owner  = THIS_MODULE,
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 03/12] OMAP: DSS2: HDMI: make set_timing saner
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

Currently the set_timings code for hdmi is quite strange. The display is
disabled in hdmi_omap4_panel.c before setting timings, and enabled in
hdmi.c after setting the timings. Furthermore, the timings were not
permanent, and disabling and enabling the display would lose them.

This patch makes the set_timings handling a bit better.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c             |   13 +++++++++++--
 drivers/video/omap2/dss/hdmi_omap4_panel.c |    7 +------
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index d08096b..8f8ae0e 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1226,11 +1226,20 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
 	struct hdmi_cm cm;
 
 	hdmi.custom_set = 1;
+
 	cm = hdmi_get_code(&dssdev->panel.timings);
 	hdmi.code = cm.code;
 	hdmi.mode = cm.mode;
-	omapdss_hdmi_display_enable(dssdev);
-	hdmi.custom_set = 0;
+
+	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
+		int r;
+
+		hdmi_power_off(dssdev);
+
+		r = hdmi_power_on(dssdev);
+		if (r)
+			DSSERR("failed to power on device\n");
+	}
 }
 
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
index 7d4f2bd..25d5fb2 100644
--- a/drivers/video/omap2/dss/hdmi_omap4_panel.c
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -161,12 +161,7 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
 	mutex_lock(&hdmi.hdmi_lock);
 
 	dssdev->panel.timings = *timings;
-
-	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
-		/* turn the hdmi off and on to get new timings to use */
-		omapdss_hdmi_display_disable(dssdev);
-		omapdss_hdmi_display_set_timing(dssdev);
-	}
+	omapdss_hdmi_display_set_timing(dssdev);
 
 	mutex_unlock(&hdmi.hdmi_lock);
 }
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 02/12] OMAP: DSS2: add detect() to omap_dss_driver struct
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

detect() can be used to probe if the display is connected.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 include/video/omapdss.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 8ed5a6c..a62f49a 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -560,6 +560,7 @@ struct omap_dss_driver {
 	u32 (*get_wss)(struct omap_dss_device *dssdev);
 
 	int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
+	bool (*detect)(struct omap_dss_device *dssdev);
 };
 
 int omap_dss_register_driver(struct omap_dss_driver *);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 01/12] OMAP: DSS2: add read_edid() to omap_dss_driver struct
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

read_edid() can be used to get the EDID information from the display.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 include/video/omapdss.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index f8385ae..8ed5a6c 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -558,6 +558,8 @@ struct omap_dss_driver {
 
 	int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
 	u32 (*get_wss)(struct omap_dss_device *dssdev);
+
+	int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
 };
 
 int omap_dss_register_driver(struct omap_dss_driver *);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 00/12] OMAP: DSS2: EDID & detect support
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen

Implement EDID reading and monitor detection support for HDMI and DVI outputs.

This set is based on the previously sent "OMAP: DSS2: misc improvements" set.

 Tomi

Tomi Valkeinen (12):
  OMAP: DSS2: add read_edid() to omap_dss_driver struct
  OMAP: DSS2: add detect() to omap_dss_driver struct
  OMAP: DSS2: HDMI: make set_timing saner
  OMAP: DSS2: HDMI: implement read_edid()
  OMAP: DSS2: HDMI: remove edid parsing
  OMAP: DSS2: HDMI: split hdmi_core_ddc_edid
  OMAP: DSS2: HDMI: clean up edid reading & fix checksum
  OMAP: DSS2: HDMI: remove error prints in check_timings
  OMAP: DSS2: HDMI: implement detect()
  OMAP: DSS2: Generic-dpi: add detect & read_edid support
  OMAP: Panda & Beagle: DVI: Add i2c_bus_num
  OMAPFB: find best mode from edid

 arch/arm/mach-omap2/board-omap3beagle.c          |    1 +
 arch/arm/mach-omap2/board-omap4panda.c           |    1 +
 drivers/video/omap2/displays/panel-generic-dpi.c |   92 ++++++
 drivers/video/omap2/dss/dss.h                    |    2 +
 drivers/video/omap2/dss/hdmi.c                   |  323 +++++++++-------------
 drivers/video/omap2/dss/hdmi_omap4_panel.c       |   66 ++++-
 drivers/video/omap2/omapfb/omapfb-main.c         |  109 +++++++-
 include/video/omap-panel-generic-dpi.h           |    2 +
 include/video/omapdss.h                          |    3 +
 9 files changed, 378 insertions(+), 221 deletions(-)

-- 
1.7.4.1


^ permalink raw reply

* [PATCH 8/8] OMAP: DSS2: HDMI: fix hdmi output enable
From: Tomi Valkeinen @ 2011-08-31 13:21 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314796908-17354-1-git-send-email-tomi.valkeinen@ti.com>

Enabling HDMI output often causes sync lost errors. The problem seems to
go away if we first enable the HDMI output, and only then enable the
DISPC output.

This will also fix the dispc's dispc_mgr_enable_digit_out(), as the code
waits for two VSYNCs after enabling the output. If the HDMI output is
disabled (as it was previously), there are no VSYNCs and
dispc_mgr_enable_digit_out() will print timeout errors.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 504c507..d08096b 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1184,10 +1184,10 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 	dispc_set_digit_size(dssdev->panel.timings.x_res,
 			dssdev->panel.timings.y_res);
 
-	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1);
-
 	hdmi_wp_video_start(1);
 
+	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1);
+
 	return 0;
 err:
 	hdmi_runtime_put();
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 7/8] OMAP: DSS2: DISPC: improve dispc_mgr_enable_digit_out()
From: Tomi Valkeinen @ 2011-08-31 13:21 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314796908-17354-1-git-send-email-tomi.valkeinen@ti.com>

dispc_mgr_enable_digit_out() didn't handle HDMI case very well.

Improve the function to use FRAMEDONETV interrupt to see when HDMI has
been disabled.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |   49 +++++++++++++++++++++++----------------
 1 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 7f3d847..4af4bd4 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1924,11 +1924,16 @@ static void _enable_digit_out(bool enable)
 static void dispc_mgr_enable_digit_out(bool enable)
 {
 	struct completion frame_done_completion;
-	int r;
+	enum dss_hdmi_venc_clk_source_select src;
+	int r, i;
+	u32 irq_mask;
+	int num_irqs;
 
 	if (REG_GET(DISPC_CONTROL, 1, 1) = enable)
 		return;
 
+	src = dss_get_hdmi_venc_clk_source();
+
 	if (enable) {
 		unsigned long flags;
 		/* When we enable digit output, we'll get an extra digit
@@ -1945,36 +1950,40 @@ static void dispc_mgr_enable_digit_out(bool enable)
 	 * wait for the extra sync losts */
 	init_completion(&frame_done_completion);
 
+	if (src = DSS_HDMI_M_PCLK && enable = false) {
+		irq_mask = DISPC_IRQ_FRAMEDONETV;
+		num_irqs = 1;
+	} else {
+		irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
+		/* XXX I understand from TRM that we should only wait for the
+		 * current field to complete. But it seems we have to wait for
+		 * both fields */
+		num_irqs = 2;
+	}
+
 	r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
-			DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
+			irq_mask);
 	if (r)
-		DSSERR("failed to register EVSYNC isr\n");
+		DSSERR("failed to register %x isr\n", irq_mask);
 
 	_enable_digit_out(enable);
 
-	/* XXX I understand from TRM that we should only wait for the
-	 * current field to complete. But it seems we have to wait
-	 * for both fields */
-	if (!wait_for_completion_timeout(&frame_done_completion,
-				msecs_to_jiffies(100)))
-		DSSERR("timeout waiting for EVSYNC\n");
-
-	if (!wait_for_completion_timeout(&frame_done_completion,
-				msecs_to_jiffies(100)))
-		DSSERR("timeout waiting for EVSYNC\n");
+	for (i = 0; i < num_irqs; ++i) {
+		if (!wait_for_completion_timeout(&frame_done_completion,
+					msecs_to_jiffies(100)))
+			DSSERR("timeout waiting for digit out to %s\n",
+					enable ? "start" : "stop");
+	}
 
-	r = omap_dispc_unregister_isr(dispc_disable_isr,
-			&frame_done_completion,
-			DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
+	r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion,
+			irq_mask);
 	if (r)
-		DSSERR("failed to unregister EVSYNC isr\n");
+		DSSERR("failed to unregister %x isr\n", irq_mask);
 
 	if (enable) {
 		unsigned long flags;
 		spin_lock_irqsave(&dispc.irq_lock, flags);
-		dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
-		if (dss_has_feature(FEAT_MGR_LCD2))
-			dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
+		dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT;
 		dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
 		_omap_dispc_set_irqs();
 		spin_unlock_irqrestore(&dispc.irq_lock, flags);
-- 
1.7.4.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox