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. Cheers, Erik [1] http://marc.info/?l=linux-fbdev&m=128208740412602&w=2 On Thu, Aug 19, 2010 at 11:48 PM, Guennadi Liakhovetski <g.liakhovetski@xxxxxx> wrote: > 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 <g.liakhovetski@xxxxxx> > --- > 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@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html