video: fbmon: Check Standard Timing against DMT and maxclk
Subsystems (2)
PATCH 1/1 video: fbmon: Check Standard Timing against DMT and maxclk
fbmon may generate mode timings that are out of spec of the monitor. eg DELL U2410 has a max clock 170mhz but advertises a resolutions of 1920x1200@60 in its Standard Timings, fbmon creates a mode using the GTF timing calculation which gave it a 193mhz clock.
This patch add the VESA Display Monitor Timing (DMT) table. During parsing of Standard Timings, it compare the 2 byte STD code with DMT to see what the VESA mode should be. If there is no entry in the vesa_modes table or no match found, it fallsback to the GTF timings. A final check to see if the mode can be supported by the monitor by comparing against monspecs.dclkmax.
--- drivers/video/fbdev/core/fbmon.c | 47 ++++++++++------ drivers/video/fbdev/core/modedb.c | 111 ++++++++++++++++++++++++++++++++++++++ include/linux/fb.h | 12 ++++- 3 files changed, 153 insertions(+), 17 deletions(-)
drivers/video/fbdev/core/fbmon.c +31 -16
@@ -496,7 +496,7 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode) }static int get_std_timing (unsigned char *block,struct fb_videomode *mode, -int ver,int rev) +int ver,int rev,struct fb_monspecs *specs) {int xres, yres =0 , refresh, ratio, i;
@@ -526,26 +526,39 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode, refresh = (block[1 ] &0x3f ) +60 ;DPRINTK (" %dx%d@%dHz\n" , xres, yres, refresh); -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]; +for (i =0 ; i <DMT_SIZE ; i++) { +u32 std_2byte_code = block[0 ] <<8 | block[1 ]; + +if (std_2byte_code = dmt_modes[i].std_2byte_code) { +if (!dmt_modes[i].mode) +break ; + *mode = *dmt_modes[i].mode; mode->flag |=FB_MODE_IS_STANDARD ; -return 1 ; +DPRINTK (" DMT id=%d\n" , dmt_modes[i].dmt_id); +break ; } } -calc_mode_timings (xres, yres, refresh, mode); + +if (i =DMT_SIZE || !dmt_modes[i].mode) +calc_mode_timings (xres, yres, refresh, mode); + +/* Check the mode we got is within valid spec of the monitor */ +if (specs && specs->dclkmax + &&PICOS2KHZ (mode->pixclock) *1000 > specs->dclkmax) { +DPRINTK (" mode exceed max DCLK\n" ); +return 0 ; + } +return 1 ; } -static int get_dst_timing (unsigned char *block, -struct fb_videomode *mode,int ver,int rev) +static int get_dst_timing (unsigned char *block,struct fb_videomode *mode, +int ver,int rev,struct fb_monspecs *specs) {int j, num =0 ;for (j =0 ; j <6 ; j++, block +=STD_TIMING_DESCRIPTION_SIZE ) - num +=get_std_timing (block, &mode[num], ver, rev); + num +=get_std_timing (block, &mode[num], ver, rev, specs);return num; }
@@ -601,7 +614,8 @@ static void get_detailed_timing(unsigned char *block,* This function builds a mode database using the contents of the EDID * data */ -static struct fb_videomode *fb_create_modedb (unsigned char *edid,int *dbsize) +static struct fb_videomode *fb_create_modedb (unsigned char *edid,int *dbsize, +struct fb_monspecs *specs) {struct fb_videomode *mode, *m;unsigned char *block;
@@ -643,12 +657,13 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)DPRINTK (" Standard Timings\n" ); block = edid +STD_TIMING_DESCRIPTIONS_START ;for (i =0 ; i <STD_TIMING ; i++, block +=STD_TIMING_DESCRIPTION_SIZE ) - num +=get_std_timing (block, &mode[num], ver, rev); + num +=get_std_timing (block, &mode[num], ver, rev, specs); block = edid +DETAILED_TIMING_DESCRIPTIONS_START ;for (i =0 ; i <4 ; i++, block+=DETAILED_TIMING_DESCRIPTION_SIZE ) {if (block[0 ] =0x00 && block[1 ] =0x00 && block[3 ] =0xfa ) - num +=get_dst_timing (block +5 , &mode[num], ver, rev); + num +=get_dst_timing (block +5 , &mode[num], + ver, rev, specs); }/* Yikes, EDID data is totally useless */
@@ -707,7 +722,7 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)int num_modes, hz, hscan, pixclock;int vtotal, htotal; - modes =fb_create_modedb (edid, &num_modes); + modes =fb_create_modedb (edid, &num_modes, specs);if (!modes) {DPRINTK ("None Available\n" );return 1 ;
@@ -964,7 +979,7 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)DPRINTK (" Display Characteristics:\n" );get_monspecs (edid, specs); - specs->modedb =fb_create_modedb (edid, &specs->modedb_len); + specs->modedb =fb_create_modedb (edid, &specs->modedb_len, specs);/* * Workaround for buggy EDIDs that sets that the first
drivers/video/fbdev/core/modedb.c +111 -0
119 lines not on this page · raw message
include/linux/fb.h +11 -1
@@ -726,7 +726,9 @@ extern int fb_videomode_from_videomode(const struct videomode *vm, struct fb_videomode *fbmode);/* drivers/video/modedb.c */ -#define VESA_MODEDB_SIZE 34 +#define VESA_MODEDB_SIZE 43 +#define DMT_SIZE 0x50 +extern void fb_var_to_videomode (struct fb_videomode *mode,const struct fb_var_screeninfo *var); extern void fb_videomode_to_var(struct fb_var_screeninfo *var,
@@ -777,9 +779,17 @@ struct fb_videomode {u32 flag; }; +struct dmt_videomode { +u32 dmt_id; +u32 std_2byte_code; +u32 cvt_3byte_code; +const struct fb_videomode *mode; +}; +extern const char *fb_mode_option;extern const struct fb_videomode vesa_modes[];extern const struct fb_videomode cea_modes[64 ]; +extern const struct dmt_videomode dmt_modes[];struct fb_modelist {struct list_head list;
Signature · 1 line
1.8.1.5
Ping?
Quoted 19 lines
-----Original Message-----
From: David Ung [mailto:[email protected]]
Sent: Friday, November 21, 2014 7:22 PM
To: [email protected]; [email protected]
Cc: [email protected]; David Ung
Subject: [PATCH] video: fbmon: Check Standard Timing against DMT and maxclkfbmon may generate mode timings that are out of spec of the monitor. eg DELL U2410 has a max clock 170mhz but advertises a resolutions of 1920x1200@60 in its Standard Timings, fbmon creates a mode using the GTF timing calculation which gave it a 193mhz clock.
This patch add the VESA Display Monitor Timing (DMT) table. During parsing of Standard Timings, it compare the 2 byte STD code with DMT to see what the VESA mode should be. If there is no entry in thevesa_modestable or no match found, it fallsback to the GTF timings. A final check to see if the mode can be supported by the monitor by comparing against monspecs.dclkmax.
Quoted 2 lines
Signed-off-by David Ung <[email protected]>---
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------
Quoted 1 line · David Ung
Ping?
Sorry I haven't been able to check this yet. I had a brief glance, and I wonder if the patch should be split. You add modes to vesa_modes, I presume those modes are valid even without any DMT or maxclk changes?
Also the maxclk check sounds like an independent change.
In any case, I think it's too late to include this into the next merge window, as it's possible that this patch could break many fbdev drivers and I'd rather have this patch sit on linux-next for a while.
Tomi
Quoted 7 lines
Sorry I haven't been able to check this yet. I had a brief glance, and I wonder if the patch should be split. You add modes to
vesa_modes, I presume those modes are valid even without any DMT or maxclk changes?Also the maxclk check sounds like an independent change.
I'll split the patch up and resubmit.
David
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------