aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbmon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbmon.c')
-rw-r--r--drivers/video/fbmon.c126
1 files changed, 68 insertions, 58 deletions
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index fc7965b66775..0ef75a9f84af 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -317,26 +317,29 @@ static int edid_is_monitor_block(unsigned char *block)
317static void calc_mode_timings(int xres, int yres, int refresh, 317static void calc_mode_timings(int xres, int yres, int refresh,
318 struct fb_videomode *mode) 318 struct fb_videomode *mode)
319{ 319{
320 struct fb_var_screeninfo var; 320 struct fb_var_screeninfo *var;
321 struct fb_info info;
322 321
323 memset(&var, 0, sizeof(struct fb_var_screeninfo)); 322 var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
324 var.xres = xres; 323
325 var.yres = yres; 324 if (var) {
326 fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 325 var->xres = xres;
327 refresh, &var, &info); 326 var->yres = yres;
328 mode->xres = xres; 327 fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
329 mode->yres = yres; 328 refresh, var, NULL);
330 mode->pixclock = var.pixclock; 329 mode->xres = xres;
331 mode->refresh = refresh; 330 mode->yres = yres;
332 mode->left_margin = var.left_margin; 331 mode->pixclock = var->pixclock;
333 mode->right_margin = var.right_margin; 332 mode->refresh = refresh;
334 mode->upper_margin = var.upper_margin; 333 mode->left_margin = var->left_margin;
335 mode->lower_margin = var.lower_margin; 334 mode->right_margin = var->right_margin;
336 mode->hsync_len = var.hsync_len; 335 mode->upper_margin = var->upper_margin;
337 mode->vsync_len = var.vsync_len; 336 mode->lower_margin = var->lower_margin;
338 mode->vmode = 0; 337 mode->hsync_len = var->hsync_len;
339 mode->sync = 0; 338 mode->vsync_len = var->vsync_len;
339 mode->vmode = 0;
340 mode->sync = 0;
341 kfree(var);
342 }
340} 343}
341 344
342static int get_est_timing(unsigned char *block, struct fb_videomode *mode) 345static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
@@ -1105,15 +1108,21 @@ static void fb_timings_dclk(struct __fb_timings *timings)
1105 */ 1108 */
1106int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info) 1109int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
1107{ 1110{
1108 struct __fb_timings timings; 1111 struct __fb_timings *timings;
1109 u32 interlace = 1, dscan = 1; 1112 u32 interlace = 1, dscan = 1;
1110 u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax; 1113 u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
1114
1115
1116 timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
1117
1118 if (!timings)
1119 return -ENOMEM;
1111 1120
1112 /* 1121 /*
1113 * If monspecs are invalid, use values that are enough 1122 * If monspecs are invalid, use values that are enough
1114 * for 640x480@60 1123 * for 640x480@60
1115 */ 1124 */
1116 if (!info->monspecs.hfmax || !info->monspecs.vfmax || 1125 if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
1117 !info->monspecs.dclkmax || 1126 !info->monspecs.dclkmax ||
1118 info->monspecs.hfmax < info->monspecs.hfmin || 1127 info->monspecs.hfmax < info->monspecs.hfmin ||
1119 info->monspecs.vfmax < info->monspecs.vfmin || 1128 info->monspecs.vfmax < info->monspecs.vfmin ||
@@ -1130,65 +1139,66 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
1130 dclkmax = info->monspecs.dclkmax; 1139 dclkmax = info->monspecs.dclkmax;
1131 } 1140 }
1132 1141
1133 memset(&timings, 0, sizeof(struct __fb_timings)); 1142 timings->hactive = var->xres;
1134 timings.hactive = var->xres; 1143 timings->vactive = var->yres;
1135 timings.vactive = var->yres;
1136 if (var->vmode & FB_VMODE_INTERLACED) { 1144 if (var->vmode & FB_VMODE_INTERLACED) {
1137 timings.vactive /= 2; 1145 timings->vactive /= 2;
1138 interlace = 2; 1146 interlace = 2;
1139 } 1147 }
1140 if (var->vmode & FB_VMODE_DOUBLE) { 1148 if (var->vmode & FB_VMODE_DOUBLE) {
1141 timings.vactive *= 2; 1149 timings->vactive *= 2;
1142 dscan = 2; 1150 dscan = 2;
1143 } 1151 }
1144 1152
1145 switch (flags & ~FB_IGNOREMON) { 1153 switch (flags & ~FB_IGNOREMON) {
1146 case FB_MAXTIMINGS: /* maximize refresh rate */ 1154 case FB_MAXTIMINGS: /* maximize refresh rate */
1147 timings.hfreq = hfmax; 1155 timings->hfreq = hfmax;
1148 fb_timings_hfreq(&timings); 1156 fb_timings_hfreq(timings);
1149 if (timings.vfreq > vfmax) { 1157 if (timings->vfreq > vfmax) {
1150 timings.vfreq = vfmax; 1158 timings->vfreq = vfmax;
1151 fb_timings_vfreq(&timings); 1159 fb_timings_vfreq(timings);
1152 } 1160 }
1153 if (timings.dclk > dclkmax) { 1161 if (timings->dclk > dclkmax) {
1154 timings.dclk = dclkmax; 1162 timings->dclk = dclkmax;
1155 fb_timings_dclk(&timings); 1163 fb_timings_dclk(timings);
1156 } 1164 }
1157 break; 1165 break;
1158 case FB_VSYNCTIMINGS: /* vrefresh driven */ 1166 case FB_VSYNCTIMINGS: /* vrefresh driven */
1159 timings.vfreq = val; 1167 timings->vfreq = val;
1160 fb_timings_vfreq(&timings); 1168 fb_timings_vfreq(timings);
1161 break; 1169 break;
1162 case FB_HSYNCTIMINGS: /* hsync driven */ 1170 case FB_HSYNCTIMINGS: /* hsync driven */
1163 timings.hfreq = val; 1171 timings->hfreq = val;
1164 fb_timings_hfreq(&timings); 1172 fb_timings_hfreq(timings);
1165 break; 1173 break;
1166 case FB_DCLKTIMINGS: /* pixelclock driven */ 1174 case FB_DCLKTIMINGS: /* pixelclock driven */
1167 timings.dclk = PICOS2KHZ(val) * 1000; 1175 timings->dclk = PICOS2KHZ(val) * 1000;
1168 fb_timings_dclk(&timings); 1176 fb_timings_dclk(timings);
1169 break; 1177 break;
1170 default: 1178 default:
1171 return -EINVAL; 1179 err = -EINVAL;
1172 1180
1173 } 1181 }
1174 1182
1175 if (!(flags & FB_IGNOREMON) && 1183 if (err || (!(flags & FB_IGNOREMON) &&
1176 (timings.vfreq < vfmin || timings.vfreq > vfmax || 1184 (timings->vfreq < vfmin || timings->vfreq > vfmax ||
1177 timings.hfreq < hfmin || timings.hfreq > hfmax || 1185 timings->hfreq < hfmin || timings->hfreq > hfmax ||
1178 timings.dclk < dclkmin || timings.dclk > dclkmax)) 1186 timings->dclk < dclkmin || timings->dclk > dclkmax))) {
1179 return -EINVAL; 1187 err = -EINVAL;
1180 1188 } else {
1181 var->pixclock = KHZ2PICOS(timings.dclk/1000); 1189 var->pixclock = KHZ2PICOS(timings->dclk/1000);
1182 var->hsync_len = (timings.htotal * 8)/100; 1190 var->hsync_len = (timings->htotal * 8)/100;
1183 var->right_margin = (timings.hblank/2) - var->hsync_len; 1191 var->right_margin = (timings->hblank/2) - var->hsync_len;
1184 var->left_margin = timings.hblank - var->right_margin - var->hsync_len; 1192 var->left_margin = timings->hblank - var->right_margin -
1185 1193 var->hsync_len;
1186 var->vsync_len = (3 * interlace)/dscan; 1194 var->vsync_len = (3 * interlace)/dscan;
1187 var->lower_margin = (1 * interlace)/dscan; 1195 var->lower_margin = (1 * interlace)/dscan;
1188 var->upper_margin = (timings.vblank * interlace)/dscan - 1196 var->upper_margin = (timings->vblank * interlace)/dscan -
1189 (var->vsync_len + var->lower_margin); 1197 (var->vsync_len + var->lower_margin);
1198 }
1190 1199
1191 return 0; 1200 kfree(timings);
1201 return err;
1192} 1202}
1193#else 1203#else
1194int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) 1204int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)