Thread (8 messages) 8 messages, 5 authors, 2010-10-21

Re: [PATCH] fbdev: add a function to parse further EDID Detailed

From: Guennadi Liakhovetski <hidden>
Date: 2010-10-20 15:12:05
Subsystem: framebuffer layer, the rest · Maintainers: Helge Deller, Linus Torvalds

Hi Erik

On Fri, 20 Aug 2010, Erik Gilling wrote:
Guennadi,
    Not sure how you're using the edid but you can get all 4 DTDs by
calling fb_edid_to_monspecs() then calling fb_videomode_to_var() on
each of the entries in monspecs.modedb.  This is still lacking as
modern monitors/tvs can have multiple EDID blocks.  My recent patch
[1] is a proposal for addressing that.
Thanks for your reply, yes, I did switch to using fb_edid_to_monspecs(), 
which does just what I need. However, I would indeed need the extra modes 
from extended EDID blocks, so, your patch would come in handy. What's its 
status? There have been no comments and it's not in next. I would imagine, 
that at least an EXPORT_SYNBOL() and a dummy version for when 
CONFIG_FB_MODE_HELPERS is not set are missing in your patch, but otherwise 
- are there any big objections? I.e., you just need to apply something 
like the diff below. With it applied:

Tested-by: Guennadi Liakhovetski <redacted>

Andrew, would you be taking it after the above issues are corrected?

As a TODO: are you planning to add parsing of SVDs to your E-EDID code?

Thanks
Guennadi
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 7a77170..5ba2234 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -1345,6 +1345,9 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
 {
 }
+void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+}
 void fb_destroy_modedb(struct fb_videomode *modedb)
 {
 }
@@ -1452,6 +1455,7 @@ EXPORT_SYMBOL(fb_firmware_edid);
 
 EXPORT_SYMBOL(fb_parse_edid);
 EXPORT_SYMBOL(fb_edid_to_monspecs);
+EXPORT_SYMBOL(fb_edid_add_monspecs);
 EXPORT_SYMBOL(fb_get_mode);
 EXPORT_SYMBOL(fb_validate_mode);
 EXPORT_SYMBOL(fb_destroy_modedb);
Cheers,
    Erik

[1] http://marc.info/?l=linux-fbdev&m8208740412602&w=2

On Thu, Aug 19, 2010 at 11:48 PM, Guennadi Liakhovetski
[off-list ref] wrote:
quoted
Currently a function is available to parse the first EDID Detailed Timing
Descriptor (DTD) block. However, EDID can contain up to four DTDs. Add a
function to parse further DTDs.

Signed-off-by: Guennadi Liakhovetski <redacted>
---
 drivers/video/fbmon.c |   74 ++++++++++++++++++++++++++++++++++++------------
 include/linux/fb.h    |    2 +
 2 files changed, 57 insertions(+), 19 deletions(-)
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 563a98b..03de586 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -866,6 +866,29 @@ static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs)
       }
 }

+static void fb_edid_to_var(unsigned char *block, struct fb_var_screeninfo *var)
+{
+       var->xres = var->xres_virtual = H_ACTIVE;
+       var->yres = var->yres_virtual = V_ACTIVE;
+       var->height = var->width = 0;
+       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;
+}
+
 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 {
       int i;
@@ -884,31 +907,38 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
       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 = 0;
-                       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;
+                       fb_edid_to_var(block, var);
                       return 0;
               }
       }
       return 1;
 }

+int fb_parse_edid_index(unsigned char *edid, struct fb_var_screeninfo *var,
+                       unsigned int idx)
+{
+       unsigned char *block;
+
+       if (edid = NULL || var = NULL || idx > 3)
+               return 1;
+
+       if (!(edid_checksum(edid)))
+               return 1;
+
+       if (!(edid_check_header(edid)))
+               return 1;
+
+       block = edid + DETAILED_TIMING_DESCRIPTIONS_START +
+               idx * DETAILED_TIMING_DESCRIPTION_SIZE;
+
+       if (edid_is_timing_block(block)) {
+               fb_edid_to_var(block, var);
+               return 0;
+       }
+
+       return 1;
+}
+
 void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
 {
       unsigned char *block;
@@ -1285,6 +1315,11 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 {
       return 1;
 }
+int fb_parse_edid_index(unsigned char *edid, struct fb_var_screeninfo *var,
+                       unsigned int idx)
+{
+       return 1;
+}
 void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
 {
       specs = NULL;
@@ -1395,6 +1430,7 @@ const unsigned char *fb_firmware_edid(struct device *device)
 EXPORT_SYMBOL(fb_firmware_edid);

 EXPORT_SYMBOL(fb_parse_edid);
+EXPORT_SYMBOL(fb_parse_edid_index);
 EXPORT_SYMBOL(fb_edid_to_monspecs);
 EXPORT_SYMBOL(fb_get_mode);
 EXPORT_SYMBOL(fb_validate_mode);
diff --git a/include/linux/fb.h b/include/linux/fb.h
index f0268de..3649c47 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -1083,6 +1083,8 @@ extern int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
 extern int fb_validate_mode(const struct fb_var_screeninfo *var,
                           struct fb_info *info);
 extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
+extern int fb_parse_edid_index(unsigned char *edid, struct fb_var_screeninfo *var,
+                              unsigned int idx);
 extern const unsigned char *fb_firmware_edid(struct device *device);
 extern void fb_edid_to_monspecs(unsigned char *edid,
                               struct fb_monspecs *specs);
--
1.7.2

--
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
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help