* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
@ 2003-04-03 2:07 Petr Vandrovec
2003-04-03 7:40 ` Sven Luther
0 siblings, 1 reply; 20+ messages in thread
From: Petr Vandrovec @ 2003-04-03 2:07 UTC (permalink / raw)
To: James Simmons
Cc: Linux Fbdev development list, Linux Kernel Mailing List, adaplas
On 2 Apr 03 at 22:55, James Simmons wrote:
> It doesn't need a struct pci_dev in this case. It is possible to get this
> info from the i2c bus but I never seen any drivers do this. What data would
> we have to pass in get the EDID inforamtion? So the question is how
> generic will get_EDID end up being or will we have to have driver specfic
> hooks since I don't pitcure i2c approaches being the same for each video
> card. Petr didn't you attempt this with the matrox driver at one time?
Yes, matroxfb provides one i2c (DDC) bus for each output videocard has.
I ended with only this support (and userspace EDID parser) as i2c was
initialized loong after framebuffer at that time... Now when i2c is usable
when fbdev initializes, it looks much better.
Only get_EDID interface I need is one which gets i2c bus as argument. But
I have no idea how I should handle situation where you have connected
two different monitors to both crtc1 outputs... Like 50Hz PAL TV &
60+Hz VGA monitor. Currently it is user responsibility to resolve such
situation...
Petr
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 2:07 [Linux-fbdev-devel] [PATCH]: EDID parser Petr Vandrovec
@ 2003-04-03 7:40 ` Sven Luther
0 siblings, 0 replies; 20+ messages in thread
From: Sven Luther @ 2003-04-03 7:40 UTC (permalink / raw)
To: Petr Vandrovec
Cc: James Simmons, Linux Fbdev development list,
Linux Kernel Mailing List, adaplas
On Thu, Apr 03, 2003 at 03:07:33AM +0100, Petr Vandrovec wrote:
> On 2 Apr 03 at 22:55, James Simmons wrote:
>
> > It doesn't need a struct pci_dev in this case. It is possible to get this
> > info from the i2c bus but I never seen any drivers do this. What data would
> > we have to pass in get the EDID inforamtion? So the question is how
> > generic will get_EDID end up being or will we have to have driver specfic
> > hooks since I don't pitcure i2c approaches being the same for each video
> > card. Petr didn't you attempt this with the matrox driver at one time?
>
> Yes, matroxfb provides one i2c (DDC) bus for each output videocard has.
> I ended with only this support (and userspace EDID parser) as i2c was
> initialized loong after framebuffer at that time... Now when i2c is usable
> when fbdev initializes, it looks much better.
>
> Only get_EDID interface I need is one which gets i2c bus as argument. But
> I have no idea how I should handle situation where you have connected
> two different monitors to both crtc1 outputs... Like 50Hz PAL TV &
> 60+Hz VGA monitor. Currently it is user responsibility to resolve such
> situation...
Is the EDID reading stuff not done per head ?
Friendly,
Sven Luther
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
@ 2003-04-03 14:38 Petr Vandrovec
2003-04-03 13:48 ` Sven Luther
0 siblings, 1 reply; 20+ messages in thread
From: Petr Vandrovec @ 2003-04-03 14:38 UTC (permalink / raw)
To: Sven Luther; +Cc: James Simmons, Linux Fbdev development list, linux-kernel
On 3 Apr 03 at 15:11, Sven Luther wrote:
> On Thu, Apr 03, 2003 at 03:05:54PM +0100, Petr Vandrovec wrote:
> > On 3 Apr 03 at 14:38, Sven Luther wrote:
> > > On Thu, Apr 03, 2003 at 12:05:13PM +0100, Petr Vandrovec wrote:
> > > > No. With matroxfb, you have two framebuffer devices, /dev/fb0 &
> > > > /dev/fb1, which can be connected to any of three outputs: analog
> > > > primary, analog secondary and DVI. Analog primary & DVI share same
> > > > pair of DDC cables, and analog secondary has its own... And user can
> > > > interconnect fb* with outputs in almost any way he wants, as long as
> > > > hardware supports it.
> > >
> > > Mmm, i have not been into fbdev much lately, but for my X devel work, i
> > > believe thta it is a good thing to separate the framebuffer issues from
> > > the output issues, and thus, for the card i have at least, have one
> > > function where the per chip things are done (memory detection, bypass
> > > unit handling, framebuffer and memory management) and another set of
> > > functions which would be head, that is output, specific. This way, you
> > > would configure the /dev/fbx and when the user which to use this or that
> > > output, the DDC will be connected to the output, not the framebuffer.
> > > This seems a reasonable way of doing this and should solve your problem,
> > > no ?
> >
> > Of course. But because of James decided that fbdev layer will
> > automatically choose appropriate resolution only from xres/yres, I need to
> > have monitor capabilities at the time upper layer asks to set videomode on
> > /dev/fbx... And it just sets it on /dev/fbx, leaving out both VTs (so I
> > cannot remember what mode was probed on each VT anymore) and outputs.
>
> Mmm, and at what time is the fbdev->output mapping done ?
At random time, when user asks to change fbdev->output mapping... And it
still means that I have to create new EDID based on all EDIDs I read from
each output - this is biggest problem, and that currently used videomode
can become invalid - and this is even worse problem.
In the past life was sweet, user apps showed windows that currently used
setting is unavailable, and offered some changes. Now when we are moving
more and more policy to the kernel...
Petr Vandrovec
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 14:38 Petr Vandrovec
@ 2003-04-03 13:48 ` Sven Luther
0 siblings, 0 replies; 20+ messages in thread
From: Sven Luther @ 2003-04-03 13:48 UTC (permalink / raw)
To: Petr Vandrovec
Cc: Sven Luther, James Simmons, Linux Fbdev development list,
linux-kernel
On Thu, Apr 03, 2003 at 03:38:43PM +0100, Petr Vandrovec wrote:
> On 3 Apr 03 at 15:11, Sven Luther wrote:
> > On Thu, Apr 03, 2003 at 03:05:54PM +0100, Petr Vandrovec wrote:
> > > On 3 Apr 03 at 14:38, Sven Luther wrote:
> > > > On Thu, Apr 03, 2003 at 12:05:13PM +0100, Petr Vandrovec wrote:
> > > > > No. With matroxfb, you have two framebuffer devices, /dev/fb0 &
> > > > > /dev/fb1, which can be connected to any of three outputs: analog
> > > > > primary, analog secondary and DVI. Analog primary & DVI share same
> > > > > pair of DDC cables, and analog secondary has its own... And user can
> > > > > interconnect fb* with outputs in almost any way he wants, as long as
> > > > > hardware supports it.
> > > >
> > > > Mmm, i have not been into fbdev much lately, but for my X devel work, i
> > > > believe thta it is a good thing to separate the framebuffer issues from
> > > > the output issues, and thus, for the card i have at least, have one
> > > > function where the per chip things are done (memory detection, bypass
> > > > unit handling, framebuffer and memory management) and another set of
> > > > functions which would be head, that is output, specific. This way, you
> > > > would configure the /dev/fbx and when the user which to use this or that
> > > > output, the DDC will be connected to the output, not the framebuffer.
> > > > This seems a reasonable way of doing this and should solve your problem,
> > > > no ?
> > >
> > > Of course. But because of James decided that fbdev layer will
> > > automatically choose appropriate resolution only from xres/yres, I need to
> > > have monitor capabilities at the time upper layer asks to set videomode on
> > > /dev/fbx... And it just sets it on /dev/fbx, leaving out both VTs (so I
> > > cannot remember what mode was probed on each VT anymore) and outputs.
> >
> > Mmm, and at what time is the fbdev->output mapping done ?
>
> At random time, when user asks to change fbdev->output mapping... And it
> still means that I have to create new EDID based on all EDIDs I read from
> each output - this is biggest problem, and that currently used videomode
> can become invalid - and this is even worse problem.
Ideally, the EDID reading would be done just after the user request an
output mapping change for the first time, and then stored privately to
each output. mode changes and such would be done after the output has
been assigned only, and you would have the EDID by then. You could even
reread it regularly, in case the monitor is hot swapped or something
such.
I have not read James response to you, but had the impression he did
propose something such, did he not ?
Friendly,
Sven Luther
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
@ 2003-04-03 14:05 Petr Vandrovec
2003-04-03 13:11 ` Sven Luther
0 siblings, 1 reply; 20+ messages in thread
From: Petr Vandrovec @ 2003-04-03 14:05 UTC (permalink / raw)
To: Sven Luther; +Cc: James Simmons, Linux Fbdev development list, linux-kernel
On 3 Apr 03 at 14:38, Sven Luther wrote:
> On Thu, Apr 03, 2003 at 12:05:13PM +0100, Petr Vandrovec wrote:
> > No. With matroxfb, you have two framebuffer devices, /dev/fb0 & /dev/fb1,
> > which can be connected to any of three outputs: analog primary, analog
> > secondary and DVI. Analog primary & DVI share same pair of DDC cables,
> > and analog secondary has its own... And user can interconnect fb* with
> > outputs in almost any way he wants, as long as hardware supports it.
>
> Mmm, i have not been into fbdev much lately, but for my X devel work, i
> believe thta it is a good thing to separate the framebuffer issues from
> the output issues, and thus, for the card i have at least, have one
> function where the per chip things are done (memory detection, bypass
> unit handling, framebuffer and memory management) and another set of
> functions which would be head, that is output, specific. This way, you
> would configure the /dev/fbx and when the user which to use this or that
> output, the DDC will be connected to the output, not the framebuffer.
> This seems a reasonable way of doing this and should solve your problem,
> no ?
Of course. But because of James decided that fbdev layer will automatically
choose appropriate resolution only from xres/yres, I need to have monitor
capabilities at the time upper layer asks to set videomode on /dev/fbx...
And it just sets it on /dev/fbx, leaving out both VTs (so I cannot remember
what mode was probed on each VT anymore) and outputs.
Petr
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 14:05 Petr Vandrovec
@ 2003-04-03 13:11 ` Sven Luther
0 siblings, 0 replies; 20+ messages in thread
From: Sven Luther @ 2003-04-03 13:11 UTC (permalink / raw)
To: Petr Vandrovec
Cc: Sven Luther, James Simmons, Linux Fbdev development list,
linux-kernel
On Thu, Apr 03, 2003 at 03:05:54PM +0100, Petr Vandrovec wrote:
> On 3 Apr 03 at 14:38, Sven Luther wrote:
> > On Thu, Apr 03, 2003 at 12:05:13PM +0100, Petr Vandrovec wrote:
> > > No. With matroxfb, you have two framebuffer devices, /dev/fb0 & /dev/fb1,
> > > which can be connected to any of three outputs: analog primary, analog
> > > secondary and DVI. Analog primary & DVI share same pair of DDC cables,
> > > and analog secondary has its own... And user can interconnect fb* with
> > > outputs in almost any way he wants, as long as hardware supports it.
> >
> > Mmm, i have not been into fbdev much lately, but for my X devel work, i
> > believe thta it is a good thing to separate the framebuffer issues from
> > the output issues, and thus, for the card i have at least, have one
> > function where the per chip things are done (memory detection, bypass
> > unit handling, framebuffer and memory management) and another set of
> > functions which would be head, that is output, specific. This way, you
> > would configure the /dev/fbx and when the user which to use this or that
> > output, the DDC will be connected to the output, not the framebuffer.
> > This seems a reasonable way of doing this and should solve your problem,
> > no ?
>
> Of course. But because of James decided that fbdev layer will automatically
> choose appropriate resolution only from xres/yres, I need to have monitor
> capabilities at the time upper layer asks to set videomode on /dev/fbx...
> And it just sets it on /dev/fbx, leaving out both VTs (so I cannot remember
> what mode was probed on each VT anymore) and outputs.
Mmm, and at what time is the fbdev->output mapping done ?
Friendly,
Sven Luther
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
@ 2003-04-03 13:55 Petr Vandrovec
2003-04-03 14:15 ` Sven Luther
0 siblings, 1 reply; 20+ messages in thread
From: Petr Vandrovec @ 2003-04-03 13:55 UTC (permalink / raw)
To: Sven Luther; +Cc: James Simmons, Linux Fbdev development list, linux-kernel
On 3 Apr 03 at 15:48, Sven Luther wrote:
>
> Ideally, the EDID reading would be done just after the user request an
> output mapping change for the first time, and then stored privately to
> each output. mode changes and such would be done after the output has
> been assigned only, and you would have the EDID by then. You could even
> reread it regularly, in case the monitor is hot swapped or something such.
Read is not enough. If you have connected one /dev/fbx to two monitors,
you must find highest common denominator for them, and use this one.
Petr
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 13:55 Petr Vandrovec
@ 2003-04-03 14:15 ` Sven Luther
2003-04-03 15:21 ` Alan Cox
0 siblings, 1 reply; 20+ messages in thread
From: Sven Luther @ 2003-04-03 14:15 UTC (permalink / raw)
To: Petr Vandrovec
Cc: Sven Luther, James Simmons, Linux Fbdev development list,
linux-kernel
On Thu, Apr 03, 2003 at 03:55:48PM +0200, Petr Vandrovec wrote:
> On 3 Apr 03 at 15:48, Sven Luther wrote:
> >
> > Ideally, the EDID reading would be done just after the user request an
> > output mapping change for the first time, and then stored privately to
> > each output. mode changes and such would be done after the output has
> > been assigned only, and you would have the EDID by then. You could even
> > reread it regularly, in case the monitor is hot swapped or something such.
>
> Read is not enough. If you have connected one /dev/fbx to two monitors,
> you must find highest common denominator for them, and use this one.
Err, i don't understand this ? Do you mean you are outputing to two
monitors at the same time ?
If that is so maybe you mean, speaking in graphic card terminology, and
not in fbdev one, that you are sharing one common framebuffer between
two outputs, right, possibly doing mirroring tricks or something such ?
If that is so, then it is ok still, since you would do the EDID read and
the mode setting at the moment you activate the video output. At this
time, you know what monitor is attached (since you can probe it) and can
check the mode with respect of what you know is possible. The main point
here is to do the mode setting based on what the ouptu can support, not
on what the fbdev thinks is right.
Friendly,
Sven Luther
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 14:15 ` Sven Luther
@ 2003-04-03 15:21 ` Alan Cox
2003-04-03 16:21 ` Sven Luther
2003-04-03 16:33 ` Geert Uytterhoeven
0 siblings, 2 replies; 20+ messages in thread
From: Alan Cox @ 2003-04-03 15:21 UTC (permalink / raw)
To: Sven Luther
Cc: Petr Vandrovec, James Simmons, Linux Fbdev development list,
Linux Kernel Mailing List
On Iau, 2003-04-03 at 15:15, Sven Luther wrote:
> > Read is not enough. If you have connected one /dev/fbx to two monitors,
> > you must find highest common denominator for them, and use this one.
>
> Err, i don't understand this ? Do you mean you are outputing to two
> monitors at the same time ?
I think you mean lowest common denominator.
> If that is so maybe you mean, speaking in graphic card terminology, and
> not in fbdev one, that you are sharing one common framebuffer between
> two outputs, right, possibly doing mirroring tricks or something such ?
Classic example is a SiS 6326 driving monitor and TV. You need to keep
the display to TV acceptable ranges.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 15:21 ` Alan Cox
@ 2003-04-03 16:21 ` Sven Luther
2003-04-03 16:18 ` Alan Cox
2003-04-03 16:33 ` Geert Uytterhoeven
1 sibling, 1 reply; 20+ messages in thread
From: Sven Luther @ 2003-04-03 16:21 UTC (permalink / raw)
To: Alan Cox
Cc: Sven Luther, Petr Vandrovec, James Simmons,
Linux Fbdev development list, Linux Kernel Mailing List
On Thu, Apr 03, 2003 at 04:21:14PM +0100, Alan Cox wrote:
> On Iau, 2003-04-03 at 15:15, Sven Luther wrote:
> > > Read is not enough. If you have connected one /dev/fbx to two monitors,
> > > you must find highest common denominator for them, and use this one.
> >
> > Err, i don't understand this ? Do you mean you are outputing to two
> > monitors at the same time ?
>
> I think you mean lowest common denominator.
>
> > If that is so maybe you mean, speaking in graphic card terminology, and
> > not in fbdev one, that you are sharing one common framebuffer between
> > two outputs, right, possibly doing mirroring tricks or something such ?
>
> Classic example is a SiS 6326 driving monitor and TV. You need to keep
> the display to TV acceptable ranges.
You mean, driving both display with the same ramdac ?
Friendly,
Sven Luther
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH]: EDID parser
2003-04-03 15:21 ` Alan Cox
2003-04-03 16:21 ` Sven Luther
@ 2003-04-03 16:33 ` Geert Uytterhoeven
2003-04-03 17:10 ` [Linux-fbdev-devel] " Sven Luther
1 sibling, 1 reply; 20+ messages in thread
From: Geert Uytterhoeven @ 2003-04-03 16:33 UTC (permalink / raw)
To: Alan Cox
Cc: Sven Luther, Petr Vandrovec, James Simmons,
Linux Fbdev development list, Linux Kernel Mailing List
On 3 Apr 2003, Alan Cox wrote:
> On Iau, 2003-04-03 at 15:15, Sven Luther wrote:
> > > Read is not enough. If you have connected one /dev/fbx to two monitors,
> > > you must find highest common denominator for them, and use this one.
> >
> > Err, i don't understand this ? Do you mean you are outputing to two
> > monitors at the same time ?
>
> I think you mean lowest common denominator.
>
> > If that is so maybe you mean, speaking in graphic card terminology, and
> > not in fbdev one, that you are sharing one common framebuffer between
> > two outputs, right, possibly doing mirroring tricks or something such ?
>
> Classic example is a SiS 6326 driving monitor and TV. You need to keep
> the display to TV acceptable ranges.
I don't know whether that's a good example...
I assume the signal for the TV is different from the signal for the monitor
(these days you don't find many monitors that do 15.6 kHz / 50 Hz)? In that
case it's just the resolution that has to be more or less compatible.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
-------------------------------------------------------
This SF.net email is sponsored by: ValueWeb:
Dedicated Hosting for just $79/mo with 500 GB of bandwidth!
No other company gives more support or power for your dedicated server
http://click.atdmt.com/AFF/go/sdnxxaff00300020aff/direct/01/
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 16:33 ` Geert Uytterhoeven
@ 2003-04-03 17:10 ` Sven Luther
2003-04-03 16:15 ` Alan Cox
0 siblings, 1 reply; 20+ messages in thread
From: Sven Luther @ 2003-04-03 17:10 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Alan Cox, Sven Luther, Petr Vandrovec, James Simmons,
Linux Fbdev development list, Linux Kernel Mailing List
On Thu, Apr 03, 2003 at 06:33:17PM +0200, Geert Uytterhoeven wrote:
> On 3 Apr 2003, Alan Cox wrote:
> > On Iau, 2003-04-03 at 15:15, Sven Luther wrote:
> > > > Read is not enough. If you have connected one /dev/fbx to two monitors,
> > > > you must find highest common denominator for them, and use this one.
> > >
> > > Err, i don't understand this ? Do you mean you are outputing to two
> > > monitors at the same time ?
> >
> > I think you mean lowest common denominator.
> >
> > > If that is so maybe you mean, speaking in graphic card terminology, and
> > > not in fbdev one, that you are sharing one common framebuffer between
> > > two outputs, right, possibly doing mirroring tricks or something such ?
> >
> > Classic example is a SiS 6326 driving monitor and TV. You need to keep
> > the display to TV acceptable ranges.
>
> I don't know whether that's a good example...
Ok, i will take the card i am currently working on for XFree86 as an
example, and you (Alan and Petr mostly) will tell me if this is a common
case, or if i miss something.
It has two outputs, where i can hook either a DVI or a VGA monitor. Each
of these video outputs correspond to a viewport, and there is hardware
which will let you set the output timings and the dot clock. You also
have to configure which part of the framebuffer you are reading, and
eventually setup a scaller to scale the pixels you read to the correct
output buffer. You also have for each head a DDC/I2C bus you can use to
speak with the monitor.
On the other side, you have the framebuffer area, which you can split in
two or not, and is fully independent from the above head issues.
So you could either have one fbdev and two viewports inside it, or have
two separate viewports each with only one viewport.
What i am trying to implement for the XFree86 driver is to have a common
framebuffer, so the graphic engine can be shared between them without
further changes, enabling dual head DRI suppport for example. Sure i
have a 8K coordinates range which makes this easy, but maybe other cards
have more strenous limits there.
Now, the plan is to separate the setup stuff that is common to the
_chip_ from the setup stuff that is specific to each _head_ or output.
In this case, it becomes easy to have the DDC port being specific to
each head, and this would sole all problems, since you would read all
the monitors attached to all the DDC buses, store them somewhere (and
ask again at the user demand, like Benjamin suggested), and when the
user changes the head mapping, or at head mapping initialization, have
the mode being validated against the monitors we _know_ are attached to
each DDC bus.
Now, i know that some boards have more DDC buses than heads or maybe
ramdacs, and things can be a bit more complicated. What do you say Petr ?
Could you yell us more about the matrox internal design with regard to
this ?
Friendly,
Sven Luther
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH]: EDID parser
2003-04-03 17:10 ` [Linux-fbdev-devel] " Sven Luther
@ 2003-04-03 16:15 ` Alan Cox
2003-04-03 17:18 ` Sven Luther
0 siblings, 1 reply; 20+ messages in thread
From: Alan Cox @ 2003-04-03 16:15 UTC (permalink / raw)
To: Sven Luther
Cc: Geert Uytterhoeven, Petr Vandrovec, James Simmons,
Linux Fbdev development list, Linux Kernel Mailing List
On Iau, 2003-04-03 at 18:10, Sven Luther wrote:
> It has two outputs, where i can hook either a DVI or a VGA monitor. Each
> of these video outputs correspond to a viewport, and there is hardware
> which will let you set the output timings and the dot clock. You also
> have to configure which part of the framebuffer you are reading, and
> eventually setup a scaller to scale the pixels you read to the correct
> output buffer. You also have for each head a DDC/I2C bus you can use to
> speak with the monitor.
Very common except lower end stuff generally has a single frame buffer
that both show and cannot be split or scanned by multiple outputs at
different rates.
-------------------------------------------------------
This SF.net email is sponsored by: ValueWeb:
Dedicated Hosting for just $79/mo with 500 GB of bandwidth!
No other company gives more support or power for your dedicated server
http://click.atdmt.com/AFF/go/sdnxxaff00300020aff/direct/01/
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH]: EDID parser
2003-04-03 16:15 ` Alan Cox
@ 2003-04-03 17:18 ` Sven Luther
2003-04-03 16:29 ` [Linux-fbdev-devel] " Alan Cox
0 siblings, 1 reply; 20+ messages in thread
From: Sven Luther @ 2003-04-03 17:18 UTC (permalink / raw)
To: Alan Cox
Cc: Sven Luther, Geert Uytterhoeven, Petr Vandrovec, James Simmons,
Linux Fbdev development list, Linux Kernel Mailing List
On Thu, Apr 03, 2003 at 05:15:32PM +0100, Alan Cox wrote:
> On Iau, 2003-04-03 at 18:10, Sven Luther wrote:
> > It has two outputs, where i can hook either a DVI or a VGA monitor. Each
> > of these video outputs correspond to a viewport, and there is hardware
> > which will let you set the output timings and the dot clock. You also
> > have to configure which part of the framebuffer you are reading, and
> > eventually setup a scaller to scale the pixels you read to the correct
> > output buffer. You also have for each head a DDC/I2C bus you can use to
> > speak with the monitor.
>
> Very common except lower end stuff generally has a single frame buffer
> that both show and cannot be split or scanned by multiple outputs at
> different rates.
So, using the terminology of Petr's graph, you have only one CRTC, with
two possible outputs, or maybe you have two CRTC but which needs to be
synchronized between them ?
Friendly,
Sven Luther
-------------------------------------------------------
This SF.net email is sponsored by: ValueWeb:
Dedicated Hosting for just $79/mo with 500 GB of bandwidth!
No other company gives more support or power for your dedicated server
http://click.atdmt.com/AFF/go/sdnxxaff00300020aff/direct/01/
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 17:18 ` Sven Luther
@ 2003-04-03 16:29 ` Alan Cox
0 siblings, 0 replies; 20+ messages in thread
From: Alan Cox @ 2003-04-03 16:29 UTC (permalink / raw)
To: Sven Luther
Cc: Geert Uytterhoeven, Petr Vandrovec, James Simmons,
Linux Fbdev development list, Linux Kernel Mailing List
On Iau, 2003-04-03 at 18:18, Sven Luther wrote:
> So, using the terminology of Petr's graph, you have only one CRTC, with
> two possible outputs, or maybe you have two CRTC but which needs to be
> synchronized between them ?
The EPIA seems to support both outputs at once so I would assume it has
two CRTC's while the old SIS can do only one at a time so it may be a
switch.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
@ 2003-04-03 11:05 Petr Vandrovec
2003-04-03 12:20 ` Benjamin Herrenschmidt
2003-04-03 12:38 ` Sven Luther
0 siblings, 2 replies; 20+ messages in thread
From: Petr Vandrovec @ 2003-04-03 11:05 UTC (permalink / raw)
To: Sven Luther
Cc: James Simmons, Linux Fbdev development list, linux-kernel,
adaplas
On 3 Apr 03 at 9:40, Sven Luther wrote:
> On Thu, Apr 03, 2003 at 03:07:33AM +0100, Petr Vandrovec wrote:
> > On 2 Apr 03 at 22:55, James Simmons wrote:
> >
> > > It doesn't need a struct pci_dev in this case. It is possible to get this
> > > info from the i2c bus but I never seen any drivers do this. What data would
> > > we have to pass in get the EDID inforamtion? So the question is how
> > > generic will get_EDID end up being or will we have to have driver specfic
> > > hooks since I don't pitcure i2c approaches being the same for each video
> > > card. Petr didn't you attempt this with the matrox driver at one time?
> >
> > Yes, matroxfb provides one i2c (DDC) bus for each output videocard has.
> > I ended with only this support (and userspace EDID parser) as i2c was
> > initialized loong after framebuffer at that time... Now when i2c is usable
> > when fbdev initializes, it looks much better.
> >
> > Only get_EDID interface I need is one which gets i2c bus as argument. But
> > I have no idea how I should handle situation where you have connected
> > two different monitors to both crtc1 outputs... Like 50Hz PAL TV &
> > 60+Hz VGA monitor. Currently it is user responsibility to resolve such
> > situation...
>
> Is the EDID reading stuff not done per head ?
No. With matroxfb, you have two framebuffer devices, /dev/fb0 & /dev/fb1,
which can be connected to any of three outputs: analog primary, analog
secondary and DVI. Analog primary & DVI share same pair of DDC cables,
and analog secondary has its own... And user can interconnect fb* with
outputs in almost any way he wants, as long as hardware supports it.
Petr Vandrovec
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 11:05 Petr Vandrovec
@ 2003-04-03 12:20 ` Benjamin Herrenschmidt
2003-04-03 12:38 ` Sven Luther
1 sibling, 0 replies; 20+ messages in thread
From: Benjamin Herrenschmidt @ 2003-04-03 12:20 UTC (permalink / raw)
To: Petr Vandrovec
Cc: Sven Luther, James Simmons, Linux Fbdev development list,
linux-kernel, adaplas
> No. With matroxfb, you have two framebuffer devices, /dev/fb0 & /dev/fb1,
> which can be connected to any of three outputs: analog primary, analog
> secondary and DVI. Analog primary & DVI share same pair of DDC cables,
> and analog secondary has its own... And user can interconnect fb* with
> outputs in almost any way he wants, as long as hardware supports it.
> Petr Vandrovec
It's +/- similar on radeon's and r128's...
I think at this point, we really need to add a structure defining
an "output" along with a few calls so the driver can tell us about
the "default" output/head mapping and can be changed from userland.
That way, the "struct fb_connection" would then be the parameter
passed to those EDID routines...
The driver would setup a default policy at boot based on what
have been probed. But userland would be able to
- Request connection info from all outputs. Note that these contains
more than just EDID. Some drivers can "probe" for the presence of
something in the VGA or S-Video connectors by sensing the load on
the signals, even if that "thing" cannot provide an EDID. So we need
a bit more than just the EDID, something like
struct fb_connection_info {
int index; /* Absolute index of output on this card */
int type; /* FB_VGA, FB_DVI, FB_ADC, FB_LVDS, ... */
int flags; /* FB_CONN_PRESENCE, FB_VALID_EDID, ... */
u8 edid[128];
}
- Ask/Set output<->head mapping. Possibly by an ioctl to the head
that sets the connection index. Of course, the driver may fail if
the combo isn't supported. Also, the policy isn't defined on what
happens to the head's current mode. I beleive the head should try to
keep it's current mode unless it's not suitable to whatever have been
detected on that connection.
What do you think ?
Ben.
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 11:05 Petr Vandrovec
2003-04-03 12:20 ` Benjamin Herrenschmidt
@ 2003-04-03 12:38 ` Sven Luther
1 sibling, 0 replies; 20+ messages in thread
From: Sven Luther @ 2003-04-03 12:38 UTC (permalink / raw)
To: Petr Vandrovec
Cc: Sven Luther, James Simmons, Linux Fbdev development list,
linux-kernel, adaplas
On Thu, Apr 03, 2003 at 12:05:13PM +0100, Petr Vandrovec wrote:
> On 3 Apr 03 at 9:40, Sven Luther wrote:
> > On Thu, Apr 03, 2003 at 03:07:33AM +0100, Petr Vandrovec wrote:
> > > On 2 Apr 03 at 22:55, James Simmons wrote:
> > >
> > > > It doesn't need a struct pci_dev in this case. It is possible to get this
> > > > info from the i2c bus but I never seen any drivers do this. What data would
> > > > we have to pass in get the EDID inforamtion? So the question is how
> > > > generic will get_EDID end up being or will we have to have driver specfic
> > > > hooks since I don't pitcure i2c approaches being the same for each video
> > > > card. Petr didn't you attempt this with the matrox driver at one time?
> > >
> > > Yes, matroxfb provides one i2c (DDC) bus for each output videocard has.
> > > I ended with only this support (and userspace EDID parser) as i2c was
> > > initialized loong after framebuffer at that time... Now when i2c is usable
> > > when fbdev initializes, it looks much better.
> > >
> > > Only get_EDID interface I need is one which gets i2c bus as argument. But
> > > I have no idea how I should handle situation where you have connected
> > > two different monitors to both crtc1 outputs... Like 50Hz PAL TV &
> > > 60+Hz VGA monitor. Currently it is user responsibility to resolve such
> > > situation...
> >
> > Is the EDID reading stuff not done per head ?
>
> No. With matroxfb, you have two framebuffer devices, /dev/fb0 & /dev/fb1,
> which can be connected to any of three outputs: analog primary, analog
> secondary and DVI. Analog primary & DVI share same pair of DDC cables,
> and analog secondary has its own... And user can interconnect fb* with
> outputs in almost any way he wants, as long as hardware supports it.
Mmm, i have not been into fbdev much lately, but for my X devel work, i
believe thta it is a good thing to separate the framebuffer issues from
the output issues, and thus, for the card i have at least, have one
function where the per chip things are done (memory detection, bypass
unit handling, framebuffer and memory management) and another set of
functions which would be head, that is output, specific. This way, you
would configure the /dev/fbx and when the user which to use this or that
output, the DDC will be connected to the output, not the framebuffer.
This seems a reasonable way of doing this and should solve your problem,
no ?
Friendly,
Sven Luther
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH]: EDID parser
@ 2003-04-02 15:41 Antonino Daplas
2003-04-02 21:55 ` [Linux-fbdev-devel] " James Simmons
0 siblings, 1 reply; 20+ messages in thread
From: Antonino Daplas @ 2003-04-02 15:41 UTC (permalink / raw)
To: Antonino Daplas; +Cc: James Simmons, Linux Fbdev development list
On Tue, 2003-04-01 at 23:32, Antonino Daplas wrote:
> Hi James,
>
> Attached is a diff against 2.5.66. It includes a reasonably complete
> EDID parser and also includes some new functions that can be used by
> fbdev drivers (for mode selection purposes)
>
> 1. fb_create_modedb()
>
> creates a mode database which can be fed to fb_find_mode(). This means
> that fb_find_mode() should not be __init anymore.
>
> 2. fb_destroy_modedb()
>
> destroy mode database created by fb_create_modedb()
>
> 3. fb_get_monitor_limits()
>
> gets monitor operating limits (max and min hscan, max and min refresh,
> max pixclock, DPMS and GTF capability)
>
> useful for validating video modes and calculating mode timings (if GTF
> capable)
>
> 4. show_edid()
>
> just prints EDID data into human-readable format.
>
> All of of the above depends on valid EDID data.
>
James,
Here's a revised patch. I was able to receive source code from SciTech
(c/o Kendall Bennett) which allowed me to fix bugs and complete the
parser. It's probably around 90-95% complete in terms of basic parsing.
It also fixes memory leaks which was present in the old patch.
Tony
diff -Naur linux-2.5.66-orig/drivers/video/edid.h linux-2.5.66-fbdev/drivers/video/edid.h
--- linux-2.5.66-orig/drivers/video/edid.h 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.5.66-fbdev/drivers/video/edid.h 2003-04-02 03:54:32.000000000 +0000
@@ -0,0 +1,138 @@
+/*
+ * drivers/video/edid.h - EDID/DDC Header
+ *
+ * Based on:
+ * 1. XFree86 4.3.0, edid.h
+ * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ *
+ * 2. John Fremlin <vii@users.sourceforge.net> and
+ * Ani Joshi <ajoshi@unixbox.com>
+ *
+ * DDC is a Trademark of VESA (Video Electronics Standard Association).
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+*/
+
+#ifndef __EDID_H__
+#define __EDID_H__
+
+#define EDID_LENGTH 0x80
+#define EDID_HEADER 0x00
+#define EDID_HEADER_END 0x07
+
+#define ID_MANUFACTURER_NAME 0x08
+#define ID_MANUFACTURER_NAME_END 0x09
+#define ID_MODEL 0x0a
+
+#define ID_SERIAL_NUMBER 0x0c
+
+#define MANUFACTURE_WEEK 0x10
+#define MANUFACTURE_YEAR 0x11
+
+#define EDID_STRUCT_VERSION 0x12
+#define EDID_STRUCT_REVISION 0x13
+
+#define EDID_STRUCT_DISPLAY 0x14
+
+#define DPMS_FLAGS 0x18
+#define ESTABLISHED_TIMING_1 0x23
+#define ESTABLISHED_TIMING_2 0x24
+#define MANUFACTURERS_TIMINGS 0x25
+
+/* standard timings supported */
+#define STD_TIMING 8
+#define STD_TIMING_DESCRIPTION_SIZE 2
+#define STD_TIMING_DESCRIPTIONS_START 0x26
+
+#define DETAILED_TIMING_DESCRIPTIONS_START 0x36
+#define DETAILED_TIMING_DESCRIPTION_SIZE 18
+#define NO_DETAILED_TIMING_DESCRIPTIONS 4
+
+#define DETAILED_TIMING_DESCRIPTION_1 0x36
+#define DETAILED_TIMING_DESCRIPTION_2 0x48
+#define DETAILED_TIMING_DESCRIPTION_3 0x5a
+#define DETAILED_TIMING_DESCRIPTION_4 0x6c
+
+#define DESCRIPTOR_DATA 5
+
+#define UPPER_NIBBLE( x ) \
+ (((128|64|32|16) & (x)) >> 4)
+
+#define LOWER_NIBBLE( x ) \
+ ((1|2|4|8) & (x))
+
+#define COMBINE_HI_8LO( hi, lo ) \
+ ( (((unsigned)hi) << 8) | (unsigned)lo )
+
+#define COMBINE_HI_4LO( hi, lo ) \
+ ( (((unsigned)hi) << 4) | (unsigned)lo )
+
+#define PIXEL_CLOCK_LO (unsigned)block[ 0 ]
+#define PIXEL_CLOCK_HI (unsigned)block[ 1 ]
+#define PIXEL_CLOCK (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*10000)
+#define H_ACTIVE_LO (unsigned)block[ 2 ]
+#define H_BLANKING_LO (unsigned)block[ 3 ]
+#define H_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_ACTIVE COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
+#define H_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_BLANKING COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
+
+#define V_ACTIVE_LO (unsigned)block[ 5 ]
+#define V_BLANKING_LO (unsigned)block[ 6 ]
+#define V_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_ACTIVE COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
+#define V_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_BLANKING COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
+
+#define H_SYNC_OFFSET_LO (unsigned)block[ 8 ]
+#define H_SYNC_WIDTH_LO (unsigned)block[ 9 ]
+
+#define V_SYNC_OFFSET_LO UPPER_NIBBLE( (unsigned)block[ 10 ] )
+#define V_SYNC_WIDTH_LO LOWER_NIBBLE( (unsigned)block[ 10 ] )
+
+#define V_SYNC_WIDTH_HI ((unsigned)block[ 11 ] & (1|2))
+#define V_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (4|8)) >> 2)
+
+#define H_SYNC_WIDTH_HI (((unsigned)block[ 11 ] & (16|32)) >> 4)
+#define H_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (64|128)) >> 6)
+
+#define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
+#define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
+
+#define H_SYNC_WIDTH COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
+#define H_SYNC_OFFSET COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
+
+#define H_SIZE_LO (unsigned)block[ 12 ]
+#define V_SIZE_LO (unsigned)block[ 13 ]
+
+#define H_SIZE_HI UPPER_NIBBLE( (unsigned)block[ 14 ] )
+#define V_SIZE_HI LOWER_NIBBLE( (unsigned)block[ 14 ] )
+
+#define H_SIZE COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
+#define V_SIZE COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
+
+#define H_BORDER (unsigned)block[ 15 ]
+#define V_BORDER (unsigned)block[ 16 ]
+
+#define FLAGS (unsigned)block[ 17 ]
+
+#define INTERLACED (FLAGS&128)
+#define SYNC_TYPE (FLAGS&3<<3) /* bits 4,3 */
+#define SYNC_SEPARATE (3<<3)
+#define HSYNC_POSITIVE (FLAGS & 4)
+#define VSYNC_POSITIVE (FLAGS & 2)
+
+#define V_MIN_RATE block[ 5 ]
+#define V_MAX_RATE block[ 6 ]
+#define H_MIN_RATE block[ 7 ]
+#define H_MAX_RATE block[ 8 ]
+#define MAX_PIXEL_CLOCK (((int)block[ 9 ]) * 10)
+#define GTF_SUPPORT block[10]
+
+#define DPMS_ACTIVE_OFF (1 << 5)
+#define DPMS_SUSPEND (1 << 6)
+#define DPMS_STANDBY (1 << 7)
+
+#endif /* __EDID_H__ */
diff -Naur linux-2.5.66-orig/drivers/video/fbmon.c linux-2.5.66-fbdev/drivers/video/fbmon.c
--- linux-2.5.66-orig/drivers/video/fbmon.c 2003-03-29 12:37:03.000000000 +0000
+++ linux-2.5.66-fbdev/drivers/video/fbmon.c 2003-04-02 03:54:27.000000000 +0000
@@ -1,7 +1,25 @@
/*
- * linux/drivers/video/fbmon.c
+ * linux/drivers/video/fbmon.c
*
- * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
+ * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
+ *
+ * Credits:
+ *
+ * The EDID Parser is a conglomeration from the following sources:
+ *
+ * 1. SciTech SNAP Graphics Architecture
+ * Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved.
+ *
+ * 2. XFree86 4.3.0, interpret_edid.c
+ * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ *
+ * 3. John Fremlin <vii@users.sourceforge.net> and
+ * Ani Joshi <ajoshi@unixbox.com>
+ *
+ * Generalized Timing Formula is derived from:
+ *
+ * GTF Spreadsheet by Andy Morrish (1/5/97)
+ * available at http://www.vesa.org
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
@@ -11,124 +29,30 @@
#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/module.h>
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-#endif
#ifdef CONFIG_ALL_PPC
#include <asm/prom.h>
#endif
+#include "edid.h"
/*
* EDID parser
- *
- * portions of this file were based on the EDID parser by
- * John Fremlin <vii@users.sourceforge.net> and Ani Joshi <ajoshi@unixbox.com>
*/
-#define EDID_LENGTH 0x80
-#define EDID_HEADER 0x00
-#define EDID_HEADER_END 0x07
-
-#define ID_MANUFACTURER_NAME 0x08
-#define ID_MANUFACTURER_NAME_END 0x09
-#define ID_MODEL 0x0a
-
-#define ID_SERIAL_NUMBER 0x0c
-
-#define MANUFACTURE_WEEK 0x10
-#define MANUFACTURE_YEAR 0x11
-
-#define EDID_STRUCT_VERSION 0x12
-#define EDID_STRUCT_REVISION 0x13
-
-#define DPMS_FLAGS 0x18
-#define ESTABLISHED_TIMING_1 0x23
-#define ESTABLISHED_TIMING_2 0x24
-#define MANUFACTURERS_TIMINGS 0x25
-
-#define DETAILED_TIMING_DESCRIPTIONS_START 0x36
-#define DETAILED_TIMING_DESCRIPTION_SIZE 18
-#define NO_DETAILED_TIMING_DESCRIPTIONS 4
-
-#define DETAILED_TIMING_DESCRIPTION_1 0x36
-#define DETAILED_TIMING_DESCRIPTION_2 0x48
-#define DETAILED_TIMING_DESCRIPTION_3 0x5a
-#define DETAILED_TIMING_DESCRIPTION_4 0x6c
-
-#define DESCRIPTOR_DATA 5
-
-#define UPPER_NIBBLE( x ) \
- (((128|64|32|16) & (x)) >> 4)
-
-#define LOWER_NIBBLE( x ) \
- ((1|2|4|8) & (x))
-
-#define COMBINE_HI_8LO( hi, lo ) \
- ( (((unsigned)hi) << 8) | (unsigned)lo )
-
-#define COMBINE_HI_4LO( hi, lo ) \
- ( (((unsigned)hi) << 4) | (unsigned)lo )
-
-#define PIXEL_CLOCK_LO (unsigned)block[ 0 ]
-#define PIXEL_CLOCK_HI (unsigned)block[ 1 ]
-#define PIXEL_CLOCK (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*1000)
-#define H_ACTIVE_LO (unsigned)block[ 2 ]
-#define H_BLANKING_LO (unsigned)block[ 3 ]
-#define H_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 4 ] )
-#define H_ACTIVE COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
-#define H_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 4 ] )
-#define H_BLANKING COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
-
-#define V_ACTIVE_LO (unsigned)block[ 5 ]
-#define V_BLANKING_LO (unsigned)block[ 6 ]
-#define V_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 7 ] )
-#define V_ACTIVE COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
-#define V_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 7 ] )
-#define V_BLANKING COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
-
-#define H_SYNC_OFFSET_LO (unsigned)block[ 8 ]
-#define H_SYNC_WIDTH_LO (unsigned)block[ 9 ]
-
-#define V_SYNC_OFFSET_LO UPPER_NIBBLE( (unsigned)block[ 10 ] )
-#define V_SYNC_WIDTH_LO LOWER_NIBBLE( (unsigned)block[ 10 ] )
-
-#define V_SYNC_WIDTH_HI ((unsigned)block[ 11 ] & (1|2))
-#define V_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (4|8)) >> 2)
-
-#define H_SYNC_WIDTH_HI (((unsigned)block[ 11 ] & (16|32)) >> 4)
-#define H_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (64|128)) >> 6)
-
-#define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
-#define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
-
-#define H_SYNC_WIDTH COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
-#define H_SYNC_OFFSET COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
-
-#define H_SIZE_LO (unsigned)block[ 12 ]
-#define V_SIZE_LO (unsigned)block[ 13 ]
-
-#define H_SIZE_HI UPPER_NIBBLE( (unsigned)block[ 14 ] )
-#define V_SIZE_HI LOWER_NIBBLE( (unsigned)block[ 14 ] )
-
-#define H_SIZE COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
-#define V_SIZE COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
-
-#define H_BORDER (unsigned)block[ 15 ]
-#define V_BORDER (unsigned)block[ 16 ]
-
-#define FLAGS (unsigned)block[ 17 ]
-
-#define INTERLACED (FLAGS&128)
-#define SYNC_TYPE (FLAGS&3<<3) /* bits 4,3 */
-#define SYNC_SEPARATE (3<<3)
-#define HSYNC_POSITIVE (FLAGS & 4)
-#define VSYNC_POSITIVE (FLAGS & 2)
-
const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00
};
const unsigned char edid_v1_descriptor_flag[] = { 0x00, 0x00 };
+static void copy_string(unsigned char *c, unsigned char *s)
+{
+ int i;
+ c = c + 5;
+ for (i = 0; (i < 13 && *c != 0x0A); i++)
+ *(s++) = *(c++);
+ *s = 0;
+ while (i-- && (*--s == 0x20)) *s = 0;
+}
+
static int edid_checksum(unsigned char *edid)
{
unsigned char i, csum = 0;
@@ -157,122 +81,763 @@
return 1;
}
-
-static char *edid_get_vendor(unsigned char *block)
+static void parse_vendor_block(unsigned char *block)
{
- static char sign[4];
- unsigned short h;
+ unsigned char c[4];
+
+ c[0] = ((block[0] & 0x7c) >> 2) + '@';
+ c[1] = ((block[0] & 0x03) << 3) + ((block[1] & 0xe0) >> 5) + '@';
+ c[2] = (block[1] & 0x1f) + '@';
+ c[3] = 0;
+ printk(" Manufacturer: %s ", c);
+ printk("Model: %x ", block[2] + (block[3] << 8));
+ printk("Serial#: %u\n", block[4] + (block[5] << 8) +
+ (block[6] << 16) + (block[7] << 24));
+ printk(" Year: %u Week %u\n", block[9] + 1990, block[8]);
+}
- h = COMBINE_HI_8LO(block[0], block[1]);
- sign[0] = ((h >> 10) & 0x1f) + 'A' - 1;
- sign[1] = ((h >> 5) & 0x1f) + 'A' - 1;
- sign[2] = (h & 0x1f) + 'A' - 1;
- sign[3] = 0;
+static void parse_dpms_capabilities(unsigned char flags)
+{
+ printk(" DPMS: Active %s, Suspend %s, Standby %s\n",
+ (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
+ (flags & DPMS_SUSPEND) ? "yes" : "no",
+ (flags & DPMS_STANDBY) ? "yes" : "no");
+}
+
+static void print_chroma(unsigned char *block)
+{
+ int tmp;
- return sign;
+ /* Chromaticity data */
+ printk(" Chromaticity: ");
+ tmp = ((block[5] & (3 << 6)) >> 6) | (block[0x7] << 2);
+ tmp *= 1000;
+ tmp += 512;
+ printk("RedX: 0.%03d ", tmp/1024);
+
+ tmp = ((block[5] & (3 << 4)) >> 4) | (block[0x8] << 2);
+ tmp *= 1000;
+ tmp += 512;
+ printk("RedY: 0.%03d\n", tmp/1024);
+
+ tmp = ((block[5] & (3 << 2)) >> 2) | (block[0x9] << 2);
+ tmp *= 1000;
+ tmp += 512;
+ printk(" GreenX: 0.%03d ", tmp/1024);
+
+ tmp = (block[5] & 3) | (block[0xa] << 2);
+ tmp *= 1000;
+ tmp += 512;
+ printk("GreenY: 0.%03d\n", tmp/1024);
+
+ tmp = ((block[6] & (3 << 6)) >> 6) | (block[0xb] << 2);
+ tmp *= 1000;
+ tmp += 512;
+ printk(" BlueX: 0.%03d ", tmp/1024);
+
+ tmp = ((block[6] & (3 << 4)) >> 4) | (block[0xc] << 2);
+ tmp *= 1000;
+ tmp += 512;
+ printk("BlueY: 0.%03d\n", tmp/1024);
+
+ tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2);
+ tmp *= 1000;
+ tmp += 512;
+ printk(" WhiteX: 0.%03d ", tmp/1024);
+
+ tmp = (block[6] & 3) | (block[0xe] << 2);
+ tmp *= 1000;
+ tmp += 512;
+ printk("WhiteY: 0.%03d\n", tmp/1024);
}
-static char *edid_get_monitor(unsigned char *block)
+static void parse_display_block(unsigned char *block)
{
- static char name[13];
- unsigned i;
- const unsigned char *ptr = block + DESCRIPTOR_DATA;
+ unsigned char c;
- for (i = 0; i < 13; i++, ptr++) {
- if (*ptr == 0xa) {
- name[i] = 0x00;
- return name;
+ c = (block[0] & 0x80) >> 7;
+ if (c)
+ printk(" Digital Display Input");
+ else {
+ printk(" Analog Display Input: Input Voltage - ");
+ switch ((block[0] & 0x60) >> 5) {
+ case 0:
+ printk("0.700V/0.300V");
+ break;
+ case 1:
+ printk("0.714V/0.286V");
+ break;
+ case 2:
+ printk("1.000V/0.400V");
+ break;
+ case 3:
+ printk("0.700V/0.000V");
+ break;
+ default:
+ printk("unknown");
}
- name[i] = *ptr;
+ printk("\n");
}
- return name;
+ c = (block[0] & 0x10) >> 4;
+ if (c)
+ printk(" Configurable signal level\n");
+ printk(" Sync: ");
+ c = block[0] & 0x0f;
+ if (c & 0x10)
+ printk("Blank to Blank ");
+ if (c & 0x08)
+ printk("Separate ");
+ if (c & 0x04)
+ printk("Composite ");
+ if (c & 0x02)
+ printk("Sync on Green ");
+ if (c & 0x01)
+ printk("Serration on ");
+ printk("\n");
+
+ printk(" Max H-size in cm: ");
+ c = block[1];
+ if (c)
+ printk("%d\n", c);
+ else
+ printk("variable\n");
+
+ printk(" Max V-size in cm: ");
+ c = block[2];
+ if (c)
+ printk("%d\n", c);
+ else
+ printk("variable\n");
+
+ c = block[3];
+ printk(" Gamma: ");
+ printk("%d.%d\n", (c + 100)/100, (c+100) % 100);
+
+ parse_dpms_capabilities(block[4]);
+
+ switch ((block[4] & 0x18) >> 3) {
+ case 0:
+ printk(" Monochrome/Grayscale\n");
+ break;
+ case 1:
+ printk(" RGB Color Display\n");
+ break;
+ case 2:
+ printk(" Non-RGB Multicolor Display\n");
+ break;
+ default:
+ printk(" Unknown\n");
+ break;
+ }
+
+ print_chroma(block);
+
+ c = block[4] & 0x7;
+ if (c & 0x04)
+ printk(" Default color format is primary\n");
+ if (c & 0x02)
+ printk(" First DETAILED Timing is preferred\n");
+ if (c & 0x01)
+ printk(" Display is GTF capable\n");
}
+static void parse_std_md_block(unsigned char *block)
+{
+ unsigned char c;
+
+ c = block[0];
+ if (c&0x80) printk(" 720x400@70Hz\n");
+ if (c&0x40) printk(" 720x400@88Hz\n");
+ if (c&0x20) printk(" 640x480@60Hz\n");
+ if (c&0x10) printk(" 640x480@67Hz\n");
+ if (c&0x08) printk(" 640x480@72Hz\n");
+ if (c&0x04) printk(" 640x480@75Hz\n");
+ if (c&0x02) printk(" 800x600@56Hz\n");
+ if (c&0x01) printk(" 800x600@60Hz\n");
+
+ c = block[1];
+ if (c&0x80) printk(" 800x600@72Hz\n");
+ if (c&0x40) printk(" 800x600@75Hz\n");
+ if (c&0x20) printk(" 832x624@75Hz\n");
+ if (c&0x10) printk(" 1024x768@87Hz (interlaced)\n");
+ if (c&0x08) printk(" 1024x768@60Hz\n");
+ if (c&0x04) printk(" 1024x768@70Hz\n");
+ if (c&0x02) printk(" 1024x768@75Hz\n");
+ if (c&0x01) printk(" 1280x1024@75Hz\n");
+
+ c = block[2];
+ if (c&0x80) printk(" 1152x870@75Hz\n");
+ printk(" Manufacturer's mask: %x\n",c&0x7F);
+}
+
+
static int edid_is_timing_block(unsigned char *block)
{
- if ((block[0] == 0x00) && (block[1] == 0x00))
+ if ((block[0] != 0x00) || (block[1] != 0x00) ||
+ (block[2] != 0x00) || (block[4] != 0x00))
+ return 1;
+ else
return 0;
+}
+
+static int edid_is_serial_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) &&
+ (block[2] == 0x00) && (block[3] == 0xff) &&
+ (block[4] == 0x00))
+ return 1;
+ else
+ return 0;
+}
+
+static int edid_is_ascii_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) &&
+ (block[2] == 0x00) && (block[3] == 0xfe) &&
+ (block[4] == 0x00))
+ return 1;
else
+ return 0;
+}
+
+static int edid_is_limits_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) &&
+ (block[2] == 0x00) && (block[3] == 0xfd) &&
+ (block[4] == 0x00))
return 1;
+ else
+ return 0;
}
static int edid_is_monitor_block(unsigned char *block)
{
- if ((block[0] == 0x00) && (block[1] == 0x00) && (block[3] == 0xfc))
+ if ((block[0] == 0x00) && (block[1] == 0x00) &&
+ (block[2] == 0x00) && (block[3] == 0xfc) &&
+ (block[4] == 0x00))
return 1;
else
return 0;
}
-static void parse_timing_block(unsigned char *block,
- struct fb_var_screeninfo *var)
+static int edid_is_color_block(unsigned char *block)
{
- var->xres = var->xres_virtual = H_ACTIVE;
- var->yres = var->yres_virtual = V_ACTIVE;
- var->height = var->width = -1;
- var->right_margin = H_SYNC_OFFSET;
- var->left_margin = (H_ACTIVE + H_BLANKING) -
- (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
- var->upper_margin = V_BLANKING - V_SYNC_OFFSET - V_SYNC_WIDTH;
- var->lower_margin = V_SYNC_OFFSET;
- var->hsync_len = H_SYNC_WIDTH;
- var->vsync_len = V_SYNC_WIDTH;
- var->pixclock = PIXEL_CLOCK;
- var->pixclock /= 1000;
- var->pixclock = KHZ2PICOS(var->pixclock);
+ if ((block[0] == 0x00) && (block[1] == 0x00) &&
+ (block[2] == 0x00) && (block[3] == 0xfb) &&
+ (block[4] == 0x00))
+ return 1;
+ else
+ return 0;
+}
- if (HSYNC_POSITIVE)
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (VSYNC_POSITIVE)
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
+static int edid_is_std_timings_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) &&
+ (block[2] == 0x00) && (block[3] == 0xfa) &&
+ (block[4] == 0x00))
+ return 1;
+ else
+ return 0;
+}
+
+static void parse_serial_block(unsigned char *block)
+{
+ unsigned char c[13];
+
+ copy_string(block, c);
+ printk(" Serial No : %s\n", c);
+}
+
+static void parse_ascii_block(unsigned char *block)
+{
+ unsigned char c[13];
+
+ copy_string(block, c);
+ printk(" %s\n", c);
+}
+
+static void parse_limits_block(unsigned char *block)
+{
+ printk(" HorizSync : %d-%d KHz\n", H_MIN_RATE, H_MAX_RATE);
+ printk(" VertRefresh : %d-%d Hz\n", V_MIN_RATE, V_MAX_RATE);
+ if (MAX_PIXEL_CLOCK != 10*0xff)
+ printk(" Max Pixelclock: %d MHz\n", (int) MAX_PIXEL_CLOCK);
+}
+
+static void parse_monitor_block(unsigned char *block)
+{
+ unsigned char c[13];
+
+ copy_string(block, c);
+ printk(" Monitor Name : %s\n", c);
+}
+
+static void parse_color_block(unsigned char *block)
+{
+ printk(" Color Point : unimplemented\n");
+}
+
+static void parse_std_timing_block(unsigned char *block)
+{
+ int xres, yres = 0, refresh, ratio, err = 1;
+
+ xres = (block[0] + 31) * 8;
+ if (xres <= 256)
+ return;
+
+ ratio = (block[1] & 0xc0) >> 6;
+ switch (ratio) {
+ case 0:
+ yres = xres;
+ break;
+ case 1:
+ yres = (xres * 3)/4;
+ break;
+ case 2:
+ yres = (xres * 4)/5;
+ break;
+ case 3:
+ yres = (xres * 9)/16;
+ break;
+ }
+ refresh = (block[1] & 0x3f) + 60;
+ printk(" %dx%d@%dHz\n", xres, yres, refresh);
+ err = 0;
+}
+
+static void parse_dst_timing_block(unsigned char *block)
+{
+ int i;
+
+ block += 5;
+ for (i = 0; i < 5; i++, block += STD_TIMING_DESCRIPTION_SIZE)
+ parse_std_timing_block(block);
+}
+
+static void parse_detailed_timing_block(unsigned char *block)
+{
+ printk(" %d MHz ", PIXEL_CLOCK/1000000);
+ printk("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
+ H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
+ printk("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
+ V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
+ printk("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
+ (VSYNC_POSITIVE) ? "+" : "-");
}
int parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
{
- unsigned char *block, *vendor, *monitor = NULL;
int i;
+ unsigned char *block;
+
+ if (edid == NULL || var == NULL)
+ return 1;
if (!(edid_checksum(edid)))
- return 0;
+ return 1;
if (!(edid_check_header(edid)))
+ return 1;
+
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+
+ for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+ if (edid_is_timing_block(block)) {
+ var->xres = var->xres_virtual = H_ACTIVE;
+ var->yres = var->yres_virtual = V_ACTIVE;
+ var->height = var->width = -1;
+ var->right_margin = H_SYNC_OFFSET;
+ var->left_margin = (H_ACTIVE + H_BLANKING) -
+ (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+ var->upper_margin = V_BLANKING - V_SYNC_OFFSET -
+ V_SYNC_WIDTH;
+ var->lower_margin = V_SYNC_OFFSET;
+ var->hsync_len = H_SYNC_WIDTH;
+ var->vsync_len = V_SYNC_WIDTH;
+ var->pixclock = PIXEL_CLOCK;
+ var->pixclock /= 1000;
+ var->pixclock = KHZ2PICOS(var->pixclock);
+
+ if (HSYNC_POSITIVE)
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (VSYNC_POSITIVE)
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void calc_mode_timings(int xres, int yres, int refresh, struct fb_videomode *mode)
+{
+ struct fb_var_screeninfo var;
+ struct fb_info info;
+
+ var.xres = xres;
+ var.yres = yres;
+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
+ refresh, &var, &info);
+ mode->xres = xres;
+ mode->yres = yres;
+ mode->pixclock = var.pixclock;
+ mode->refresh = refresh;
+ mode->left_margin = var.left_margin;
+ mode->right_margin = var.right_margin;
+ mode->upper_margin = var.upper_margin;
+ mode->lower_margin = var.lower_margin;
+ mode->hsync_len = var.hsync_len;
+ mode->vsync_len = var.vsync_len;
+ mode->vmode = 0;
+ mode->sync = 0;
+}
+
+static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
+{
+ int num = 0;
+ unsigned char c;
+
+ c = block[0];
+ if (c&0x80)
+ calc_mode_timings(720, 400, 70, &mode[num++]);
+ if (c&0x40)
+ calc_mode_timings(720, 400, 88, &mode[num++]);
+ if (c&0x20)
+ mode[num++] = vesa_modes[3];
+ if (c&0x10)
+ calc_mode_timings(640, 480, 67, &mode[num++]);
+ if (c&0x08)
+ mode[num++] = vesa_modes[4];
+ if (c&0x04)
+ mode[num++] = vesa_modes[5];
+ if (c&0x02)
+ mode[num++] = vesa_modes[7];
+ if (c&0x01)
+ mode[num++] = vesa_modes[8];
+
+ c = block[1];
+ if (c&0x80)
+ mode[num++] = vesa_modes[9];
+ if (c&0x40)
+ mode[num++] = vesa_modes[10];
+ if (c&0x20)
+ calc_mode_timings(832, 624, 75, &mode[num++]);
+ if (c&0x10)
+ mode[num++] = vesa_modes[12];
+ if (c&0x08)
+ mode[num++] = vesa_modes[13];
+ if (c&0x04)
+ mode[num++] = vesa_modes[14];
+ if (c&0x02)
+ mode[num++] = vesa_modes[15];
+ if (c&0x01)
+ mode[num++] = vesa_modes[21];
+
+ c = block[2];
+ if (c&0x80)
+ mode[num++] = vesa_modes[17];
+
+ return num;
+}
+
+static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
+{
+ int xres, yres = 0, refresh, ratio, i;
+
+ xres = (block[0] + 31) * 8;
+ if (xres <= 256)
return 0;
- printk("EDID ver %d rev %d\n", (int) edid[EDID_STRUCT_VERSION],
- (int) edid[EDID_STRUCT_REVISION]);
+ ratio = (block[1] & 0xc0) >> 6;
+ switch (ratio) {
+ case 0:
+ yres = xres;
+ break;
+ case 1:
+ yres = (xres * 3)/4;
+ break;
+ case 2:
+ yres = (xres * 4)/5;
+ break;
+ case 3:
+ yres = (xres * 9)/16;
+ break;
+ }
+ refresh = (block[1] & 0x3f) + 60;
+
+ for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+ if (vesa_modes[i].xres == xres &&
+ vesa_modes[i].yres == yres &&
+ vesa_modes[i].refresh == refresh) {
+ *mode = vesa_modes[i];
+ break;
+ } else {
+ calc_mode_timings(xres, yres, refresh, mode);
+ break;
+ }
+ }
+ return 1;
+}
+
+static int get_dst_timing(unsigned char *block,
+ struct fb_videomode *mode)
+{
+ int j, num = 0;
+
+ for (j = 0; j < 6; j++, block+= STD_TIMING_DESCRIPTION_SIZE)
+ num += get_std_timing(block, &mode[num]);
+
+ return num;
+}
+
+static void get_detailed_timing(unsigned char *block,
+ struct fb_videomode *mode)
+{
+ mode->xres = H_ACTIVE;
+ mode->yres = V_ACTIVE;
+ mode->pixclock = PIXEL_CLOCK;
+ mode->pixclock /= 1000;
+ mode->pixclock = KHZ2PICOS(mode->pixclock);
+ mode->right_margin = H_SYNC_OFFSET;
+ mode->left_margin = (H_ACTIVE + H_BLANKING) -
+ (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+ mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
+ V_SYNC_WIDTH;
+ mode->lower_margin = V_SYNC_OFFSET;
+ mode->hsync_len = H_SYNC_WIDTH;
+ mode->vsync_len = V_SYNC_WIDTH;
+ if (HSYNC_POSITIVE)
+ mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (VSYNC_POSITIVE)
+ mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+ mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
+ (V_ACTIVE + V_BLANKING));
+ mode->vmode = 0;
+}
+
+/**
+ * fb_create_modedb - create video mode database
+ * @edid: EDID data
+ * @dbsize: database size
+ *
+ * RETURNS: struct fb_videomode, @dbsize contains length of database
+ *
+ * DESCRIPTION:
+ * This function builds a mode database using the contents of the EDID
+ * data
+ */
+struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
+{
+ struct fb_videomode *mode, *m;
+ unsigned char *block;
+ int num = 0, i;
+
+ mode = kmalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
+ if (mode == NULL)
+ return NULL;
+ memset(mode, 0, 50 * sizeof(struct fb_videomode));
+
+ if (edid == NULL || !edid_checksum(edid) ||
+ !edid_check_header(edid)) {
+ kfree(mode);
+ return NULL;
+ }
+
+ *dbsize = 0;
+
+ block = edid + ESTABLISHED_TIMING_1;
+ num += get_est_timing(block, &mode[num]);
+
+ 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]);
+
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+ for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
+ if (block[0] == 0x00 && block[1] == 0x00) {
+ if (block[3] == 0xfa) {
+ num += get_dst_timing(block + 5, &mode[num]);
+ }
+ } else {
+ get_detailed_timing(block, &mode[num]);
+ num++;
+ }
+ }
+
+ /* Yikes, EDID data is totally useless */
+ if (!num) {
+ kfree(mode);
+ return NULL;
+ }
+
+ *dbsize = num;
+ m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL);
+ if (!m)
+ return mode;
+ memmove(m, mode, num * sizeof(struct fb_videomode));
+ kfree(mode);
+ return m;
+}
+
+/**
+ * fb_destroy_modedb - destroys mode database
+ * @modedb: mode database to destroy
+ *
+ * DESCRIPTION:
+ * Destroy mode database created by fb_create_modedb
+ */
+void fb_destroy_modedb(struct fb_videomode *modedb)
+{
+ if (modedb)
+ kfree(modedb);
+}
+
+/**
+ * fb_get_monitor_limits - get monitor operating limits
+ * @edid: EDID data
+ * @specs: fb_monspecs structure pointer
+ *
+ * DESCRIPTION:
+ * Gets monitor operating limits from EDID data and places them in
+ * @specs
+ */
+int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
+{
+ int i, retval = 1;
+ unsigned char *block;
+
+ if (edid == NULL || specs == NULL)
+ return 1;
- vendor = edid_get_vendor(edid + ID_MANUFACTURER_NAME);
+ if (!(edid_checksum(edid)))
+ return 1;
+
+ if (!(edid_check_header(edid)))
+ return 1;
+ memset(specs, 0, sizeof(struct fb_monspecs));
block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+ printk("Monitor Operating Limits: ");
for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
- if (edid_is_monitor_block(block)) {
- monitor = edid_get_monitor(block);
+ if (edid_is_limits_block(block)) {
+ specs->hfmin = H_MIN_RATE * 1000;
+ specs->hfmax = H_MAX_RATE * 1000;
+ specs->vfmin = V_MIN_RATE;
+ specs->vfmax = V_MAX_RATE;
+ specs->dclkmax = (MAX_PIXEL_CLOCK != 10*0xff) ?
+ MAX_PIXEL_CLOCK * 1000000 : 0;
+ specs->gtf = (GTF_SUPPORT) ? 1 : 0;
+ specs->dpms = edid[DPMS_FLAGS];
+ retval = 0;
+ printk("From EDID\n");
+ break;
}
}
+
+ /* estimate monitor limits based on modes supported */
+ if (retval) {
+ struct fb_videomode *modes;
+ int num_modes, i, hz, hscan, pixclock;
+
+ modes = fb_create_modedb(edid, &num_modes);
+ if (!modes) {
+ printk("None Available\n");
+ return 1;
+ }
- printk("EDID: detected %s %s\n", vendor, monitor);
+ retval = 0;
+ for (i = 0; i < num_modes; i++) {
+ hz = modes[i].refresh;
+ pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
+ hscan = (modes[i].yres * 105 * hz + 5000)/100;
+
+ if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
+ specs->dclkmax = pixclock;
+ if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
+ specs->dclkmin = pixclock;
+ if (specs->hfmax == 0 || specs->hfmax < hscan)
+ specs->hfmax = hscan;
+ if (specs->hfmin == 0 || specs->hfmin > hscan)
+ specs->hfmin = hscan;
+ if (specs->vfmax == 0 || specs->vfmax < hz)
+ specs->vfmax = hz;
+ if (specs->vfmin == 0 || specs->vfmin > hz)
+ specs->vfmin = hz;
+ }
+ printk("Extrapolated\n");
+ fb_destroy_modedb(modes);
+ }
+ printk(" H: %d-%dKHz V: %d-%dHz DCLK: %dMHz\n", specs->hfmin/1000, specs->hfmax/1000,
+ specs->vfmin, specs->vfmax, specs->dclkmax/1000000);
+ return retval;
+}
- block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+void show_edid(unsigned char *edid)
+{
+ unsigned char *block;
+ int i;
+
+ if (edid == NULL)
+ return;
+
+ if (!(edid_checksum(edid)))
+ return;
+
+ if (!(edid_check_header(edid)))
+ return;
+ printk("========================================\n");
+ printk("Display Information (EDID)\n");
+ printk("========================================\n");
+ printk(" EDID Version %d.%d\n", (int) edid[EDID_STRUCT_VERSION],
+ (int) edid[EDID_STRUCT_REVISION]);
+
+ parse_vendor_block(edid + ID_MANUFACTURER_NAME);
+
+ printk(" Display Characteristics:\n");
+ parse_display_block(edid + EDID_STRUCT_DISPLAY);
+
+ printk(" Standard Timings\n");
+ block = edid + STD_TIMING_DESCRIPTIONS_START;
+ for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
+ parse_std_timing_block(block);
+
+ printk(" Supported VESA Modes\n");
+ parse_std_md_block(edid + ESTABLISHED_TIMING_1);
+ printk(" Detailed Monitor Information\n");
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
- if (edid_is_timing_block(block)) {
- parse_timing_block(block, var);
+ if (edid_is_serial_block(block)) {
+ parse_serial_block(block);
+ } else if (edid_is_ascii_block(block)) {
+ parse_ascii_block(block);
+ } else if (edid_is_limits_block(block)) {
+ parse_limits_block(block);
+ } else if (edid_is_monitor_block(block)) {
+ parse_monitor_block(block);
+ } else if (edid_is_color_block(block)) {
+ parse_color_block(block);
+ } else if (edid_is_std_timings_block(block)) {
+ parse_dst_timing_block(block);
+ } else if (edid_is_timing_block(block)) {
+ parse_detailed_timing_block(block);
}
}
- return 1;
+ printk("========================================\n");
}
#ifdef CONFIG_PCI
char *get_EDID(struct pci_dev *pdev)
{
+ unsigned char *pedid = NULL;
#ifdef CONFIG_ALL_PPC
static char *propnames[] =
{ "DFP,EDID", "LCD,EDID", "EDID", "EDID1", NULL };
- unsigned char *pedid = NULL;
struct device_node *dp;
int i;
+ if (pdev == NULL)
+ return NULL;
dp = pci_device_to_OF_node(pdev);
while (dp != NULL) {
for (i = 0; propnames[i] != NULL; ++i) {
@@ -285,10 +850,9 @@
}
dp = dp->child;
}
- return pedid;
-#else
- return NULL;
#endif
+ show_edid(pedid);
+ return pedid;
}
#endif
@@ -679,8 +1243,12 @@
}
EXPORT_SYMBOL(parse_edid);
+EXPORT_SYMBOL(show_edid);
#ifdef CONFIG_PCI
EXPORT_SYMBOL(get_EDID);
#endif
+EXPORT_SYMBOL(fb_get_monitor_limits);
EXPORT_SYMBOL(fb_get_mode);
EXPORT_SYMBOL(fb_validate_mode);
+EXPORT_SYMBOL(fb_create_modedb);
+EXPORT_SYMBOL(fb_destroy_modedb);
diff -Naur linux-2.5.66-orig/drivers/video/modedb.c linux-2.5.66-fbdev/drivers/video/modedb.c
--- linux-2.5.66-orig/drivers/video/modedb.c 2003-03-29 12:37:03.000000000 +0000
+++ linux-2.5.66-fbdev/drivers/video/modedb.c 2003-04-02 03:56:00.000000000 +0000
@@ -251,6 +251,110 @@
},
};
+const struct fb_videomode vesa_modes[] = {
+ /* 0 640x350-85 VESA */
+ { NULL, 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3,
+ FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 1 640x400-85 VESA */
+ { NULL, 85, 640, 400, 31746, 96, 32, 41, 01, 64, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 2 720x400-85 VESA */
+ { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 3 640x480-60 VESA */
+ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
+ 0, FB_VMODE_NONINTERLACED },
+ /* 4 640x480-72 VESA */
+ { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2,
+ 0, FB_VMODE_NONINTERLACED },
+ /* 5 640x480-75 VESA */
+ { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+ 0, FB_VMODE_NONINTERLACED },
+ /* 6 640x480-85 VESA */
+ { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+ 0, FB_VMODE_NONINTERLACED },
+ /* 7 800x600-56 VESA */
+ { NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 8 800x600-60 VESA */
+ { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 9 800x600-72 VESA */
+ { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 10 800x600-75 VESA */
+ { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 11 800x600-85 VESA */
+ { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 12 1024x768i-43 VESA */
+ { NULL, 53, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED },
+ /* 13 1024x768-60 VESA */
+ { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+ 0, FB_VMODE_NONINTERLACED },
+ /* 14 1024x768-70 VESA */
+ { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
+ 0, FB_VMODE_NONINTERLACED },
+ /* 15 1024x768-75 VESA */
+ { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 16 1024x768-85 VESA */
+ { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 17 1152x864-75 VESA */
+ { NULL, 75, 1153, 864, 9259, 256, 64, 32, 1, 128, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 18 1280x960-60 VESA */
+ { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 19 1280x960-85 VESA */
+ { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 20 1280x1024-60 VESA */
+ { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 21 1280x1024-75 VESA */
+ { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 22 1280x1024-85 VESA */
+ { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 23 1600x1200-60 VESA */
+ { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 24 1600x1200-65 VESA */
+ { NULL, 65, 1600, 1200, 5698, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 25 1600x1200-70 VESA */
+ { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 26 1600x1200-75 VESA */
+ { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 27 1600x1200-85 VESA */
+ { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 28 1792x1344-60 VESA */
+ { NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 29 1792x1344-75 VESA */
+ { NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 30 1856x1392-60 VESA */
+ { NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 31 1856x1392-75 VESA */
+ { NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 32 1920x1440-60 VESA */
+ { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ /* 33 1920x1440-75 VESA */
+ { NULL, 60, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+};
static int __init my_atoi(const char *name)
{
@@ -432,3 +536,4 @@
}
EXPORT_SYMBOL(__fb_try_mode);
+EXPORT_SYMBOL(vesa_modes);
diff -Naur linux-2.5.66-orig/include/linux/fb.h linux-2.5.66-fbdev/include/linux/fb.h
--- linux-2.5.66-orig/include/linux/fb.h 2003-03-29 21:09:54.000000000 +0000
+++ linux-2.5.66-fbdev/include/linux/fb.h 2003-04-02 14:36:16.000000000 +0000
@@ -492,6 +492,10 @@
extern int num_registered_fb;
/* drivers/video/fbmon.c */
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
+
#define FB_MAXTIMINGS 0
#define FB_VSYNCTIMINGS 1
#define FB_HSYNCTIMINGS 2
@@ -505,6 +509,16 @@
struct fb_info *info);
extern int fb_validate_mode(struct fb_var_screeninfo *var,
struct fb_info *info);
+extern int parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
+extern char *get_EDID(struct pci_dev *pdev);
+extern void show_edid(unsigned char *edid);
+extern int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs);
+extern struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize);
+extern void fb_destroy_modedb(struct fb_videomode *modedb);
+
+/* drivers/video/modedb.c */
+#define VESA_MODEDB_SIZE 34
+extern const struct fb_videomode vesa_modes[];
/* drivers/video/fbcmap.c */
extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
-------------------------------------------------------
This SF.net email is sponsored by: ValueWeb:
Dedicated Hosting for just $79/mo with 500 GB of bandwidth!
No other company gives more support or power for your dedicated server
http://click.atdmt.com/AFF/go/sdnxxaff00300020aff/direct/01/
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-02 15:41 Antonino Daplas
@ 2003-04-02 21:55 ` James Simmons
2003-04-02 22:20 ` Benjamin Herrenschmidt
2003-04-03 0:45 ` Antonino Daplas
0 siblings, 2 replies; 20+ messages in thread
From: James Simmons @ 2003-04-02 21:55 UTC (permalink / raw)
To: Antonino Daplas
Cc: Linux Fbdev development list, Linux Kernel Mailing List, Petr
> James,
>
> Here's a revised patch. I was able to receive source code from SciTech
> (c/o Kendall Bennett) which allowed me to fix bugs and complete the
> parser. It's probably around 90-95% complete in terms of basic parsing.
>
> It also fixes memory leaks which was present in the old patch.
Let really good. I applied it to my local tree but haven't passed it to BK
fbdev yet. The only thing I like to see changed is get_EDID. At present it
accepts a struct pci_dev. Now for generic support for the intel platform
we can get this from the BIOS. You already have a patch that does this.
It doesn't need a struct pci_dev in this case. It is possible to get this
info from the i2c bus but I never seen any drivers do this. What data would
we have to pass in get the EDID inforamtion? So the question is how
generic will get_EDID end up being or will we have to have driver specfic
hooks since I don't pitcure i2c approaches being the same for each video
card. Petr didn't you attempt this with the matrox driver at one time?
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-02 21:55 ` [Linux-fbdev-devel] " James Simmons
@ 2003-04-02 22:20 ` Benjamin Herrenschmidt
2003-04-03 0:45 ` Antonino Daplas
1 sibling, 0 replies; 20+ messages in thread
From: Benjamin Herrenschmidt @ 2003-04-02 22:20 UTC (permalink / raw)
To: James Simmons
Cc: Antonino Daplas, Linux Fbdev development list,
Linux Kernel Mailing List, Petr
> Let really good. I applied it to my local tree but haven't passed it to BK
> fbdev yet. The only thing I like to see changed is get_EDID. At present it
> accepts a struct pci_dev. Now for generic support for the intel platform
> we can get this from the BIOS. You already have a patch that does this.
> It doesn't need a struct pci_dev in this case. It is possible to get this
> info from the i2c bus but I never seen any drivers do this. What data would
> we have to pass in get the EDID inforamtion? So the question is how
> generic will get_EDID end up being or will we have to have driver specfic
> hooks since I don't pitcure i2c approaches being the same for each video
> card. Petr didn't you attempt this with the matrox driver at one time?
get_EDID() has to be a driver specific hook
EDID via BIOS is a way to get it, BIOS emulation in userland is another,
on PPC, I can retreive it from the firmware device-tree in a different
way with some cards, and finally, I plan to implement i2c sooner or
later with some drivers...
Ben.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH]: EDID parser
2003-04-02 21:55 ` [Linux-fbdev-devel] " James Simmons
2003-04-02 22:20 ` Benjamin Herrenschmidt
@ 2003-04-03 0:45 ` Antonino Daplas
2003-04-03 6:44 ` [Linux-fbdev-devel] " Benjamin Herrenschmidt
1 sibling, 1 reply; 20+ messages in thread
From: Antonino Daplas @ 2003-04-03 0:45 UTC (permalink / raw)
To: James Simmons
Cc: Linux Fbdev development list, Linux Kernel Mailing List,
Petr Vandrovec
On Thu, 2003-04-03 at 05:55, James Simmons wrote:
>
> > James,
> >
> > Here's a revised patch. I was able to receive source code from SciTech
> > (c/o Kendall Bennett) which allowed me to fix bugs and complete the
> > parser. It's probably around 90-95% complete in terms of basic parsing.
> >
> > It also fixes memory leaks which was present in the old patch.
>
> Let really good. I applied it to my local tree but haven't passed it to BK
> fbdev yet. The only thing I like to see changed is get_EDID. At present it
> accepts a struct pci_dev. Now for generic support for the intel platform
> we can get this from the BIOS. You already have a patch that does this.
> It doesn't need a struct pci_dev in this case. It is possible to get this
> info from the i2c bus but I never seen any drivers do this. What data would
> we have to pass in get the EDID inforamtion? So the question is how
> generic will get_EDID end up being or will we have to have driver specfic
> hooks since I don't pitcure i2c approaches being the same for each video
> card. Petr didn't you attempt this with the matrox driver at one time?
>
I think we just need an additional method in struct fb_ops. Something like
this:
unsigned char *fb_get_edid(struct fb_info *info)
{
if (info->fbops->fb_get_edid)
return info->fbops->fb_get_edid(info);
else
return fallback_get_edid_method();
}
We can get the EDID by different methods:
1. User uploads EDID to kernel via an ioctl. This is always preferred,
as it gives the user the power to override machine settings, or if there
is no other method to get the EDID. We can also have a userland utility
that encodes user-specified monitor information and modelines into EDID
info (a reverse EDID parser). For instance, selected entries in
/etc/fb.modes can be easily converted to EDID which the user can upload
to fbdev.
2. Gets it through device-specific hooks (i2c, whatever), if available.
This is second choice, as it can get the EDID anytime. This is useful
when a user decides to change monitors without rebooting, or if the
device is a non-primary display.
3. Some architecture specific methods, such as doing it via the BIOS.
This is the last choice, our fallback method. as this EDID may be static
and represents only the display detected at boot time.
For supplementary functions, we also need some kind of control that
allows the user to tell fbdev "I've switched monitors, please reread the
EDID". We want to avoid doing DDC each time fbdev does an fb_set_var(),
especially for DDC1 which can be very slow.
Also, a way to download the EDID from kernel to userland.
Tony
-------------------------------------------------------
This SF.net email is sponsored by: ValueWeb:
Dedicated Hosting for just $79/mo with 500 GB of bandwidth!
No other company gives more support or power for your dedicated server
http://click.atdmt.com/AFF/go/sdnxxaff00300020aff/direct/01/
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 0:45 ` Antonino Daplas
@ 2003-04-03 6:44 ` Benjamin Herrenschmidt
2003-04-03 7:05 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 20+ messages in thread
From: Benjamin Herrenschmidt @ 2003-04-03 6:44 UTC (permalink / raw)
To: Antonino Daplas
Cc: James Simmons, Linux Fbdev development list,
Linux Kernel Mailing List, Petr Vandrovec
> 3. Some architecture specific methods, such as doing it via the BIOS.
> This is the last choice, our fallback method. as this EDID may be static
> and represents only the display detected at boot time.
>
> For supplementary functions, we also need some kind of control that
> allows the user to tell fbdev "I've switched monitors, please reread the
> EDID". We want to avoid doing DDC each time fbdev does an fb_set_var(),
> especially for DDC1 which can be very slow.
That's also what Apple does indeed. It's too complicated/long to
dynamically detect hotplug, but they do have a button you can
click to force a re-detect of the displays in the GUI and this
goes via some kind of ioctl to the video driver to ask for new
connection informations (basically EDID).
> Also, a way to download the EDID from kernel to userland.
Just define an ioctl for that and let each driver that support EDID
return something seem to be the simplest way.
If we really want to make EDID a generic thing, then we can eventually
have the EDID block attached to each fb_info and then a generic
fbmem.c ioctl to read it, but then make sure that EDID block isn"t
mandatory (it has no sense to some specific HW like some embedded
stuffs) and I always prefer when drivers are the real target of
the calls like this ioctl, eventually using fbdev "tools" as helpers
instead of having fbdev do something directly as a "mid-mayer".
Ben.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [Linux-fbdev-devel] [PATCH]: EDID parser
2003-04-03 6:44 ` [Linux-fbdev-devel] " Benjamin Herrenschmidt
@ 2003-04-03 7:05 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 20+ messages in thread
From: Benjamin Herrenschmidt @ 2003-04-03 7:05 UTC (permalink / raw)
To: Antonino Daplas
Cc: James Simmons, Linux Fbdev development list,
Linux Kernel Mailing List, Petr Vandrovec
> Just define an ioctl for that and let each driver that support EDID
> return something seem to be the simplest way.
Replying to myself... and definitely not the best way for 2.5
(would be ok for 2.4 but do we care at this point ?)
Instead, we'd rather add the EDID as an attribute of the fb
to sysfs.
Actually, I suggest that each fbdev driver defines ones or more
nodes in sysfs below the actual driver node, representing the
various heads. Each head would then have attributes representing
the various display properties, one beeing the EDID block.
> If we really want to make EDID a generic thing, then we can eventually
> have the EDID block attached to each fb_info and then a generic
> fbmem.c ioctl to read it, but then make sure that EDID block isn"t
> mandatory (it has no sense to some specific HW like some embedded
> stuffs) and I always prefer when drivers are the real target of
> the calls like this ioctl, eventually using fbdev "tools" as helpers
> instead of having fbdev do something directly as a "mid-mayer".
>
> Ben.
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
Benjamin Herrenschmidt <benh@kernel.crashing.org>
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2003-04-03 17:10 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-04-03 2:07 [Linux-fbdev-devel] [PATCH]: EDID parser Petr Vandrovec
2003-04-03 7:40 ` Sven Luther
-- strict thread matches above, loose matches on Subject: below --
2003-04-03 14:38 Petr Vandrovec
2003-04-03 13:48 ` Sven Luther
2003-04-03 14:05 Petr Vandrovec
2003-04-03 13:11 ` Sven Luther
2003-04-03 13:55 Petr Vandrovec
2003-04-03 14:15 ` Sven Luther
2003-04-03 15:21 ` Alan Cox
2003-04-03 16:21 ` Sven Luther
2003-04-03 16:18 ` Alan Cox
2003-04-03 16:33 ` Geert Uytterhoeven
2003-04-03 17:10 ` [Linux-fbdev-devel] " Sven Luther
2003-04-03 16:15 ` Alan Cox
2003-04-03 17:18 ` Sven Luther
2003-04-03 16:29 ` [Linux-fbdev-devel] " Alan Cox
2003-04-03 11:05 Petr Vandrovec
2003-04-03 12:20 ` Benjamin Herrenschmidt
2003-04-03 12:38 ` Sven Luther
2003-04-02 15:41 Antonino Daplas
2003-04-02 21:55 ` [Linux-fbdev-devel] " James Simmons
2003-04-02 22:20 ` Benjamin Herrenschmidt
2003-04-03 0:45 ` Antonino Daplas
2003-04-03 6:44 ` [Linux-fbdev-devel] " Benjamin Herrenschmidt
2003-04-03 7:05 ` Benjamin Herrenschmidt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).