Commit 1013d266 authored by Antonino A. Daplas's avatar Antonino A. Daplas Committed by Linus Torvalds

[PATCH] atyfb: Get initial mode timings from LCD BIOS

Reported by: Jean-Philippe Guérard (Bugzilla Bug 1782)

"I've tried with video=atyfb:debug and video=atyfb:debug,mode:1280x600, \
nomtrr.

In both case, the screen stays black, but seems divided into 4 vertical bands.
 Some white lines pop up randomly on each vertical band."

The problem is a combination of an incorrect xclk plus lack of timing
information.  The adapter is attached to an LCD device that can do 1280x600
(which is not a standard resolution).  The global mode database does not have
an entry for it.  Fortunately, the Video BIOS contains the complete timing
info for this display, however, atyfb is not making use of it.

Add support to get the timing information from the BIOS, if available.
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent eba50850
...@@ -2156,11 +2156,38 @@ static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) ...@@ -2156,11 +2156,38 @@ static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
static struct fb_info *fb_list = NULL; static struct fb_info *fb_list = NULL;
#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par,
struct fb_var_screeninfo *var)
{
int ret = -EINVAL;
if (par->lcd_table != 0 && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
*var = default_var;
var->xres = var->xres_virtual = par->lcd_hdisp;
var->right_margin = par->lcd_right_margin;
var->left_margin = par->lcd_hblank_len -
(par->lcd_right_margin + par->lcd_hsync_dly +
par->lcd_hsync_len);
var->hsync_len = par->lcd_hsync_len + par->lcd_hsync_dly;
var->yres = var->yres_virtual = par->lcd_vdisp;
var->lower_margin = par->lcd_lower_margin;
var->upper_margin = par->lcd_vblank_len -
(par->lcd_lower_margin + par->lcd_vsync_len);
var->vsync_len = par->lcd_vsync_len;
var->pixclock = par->lcd_pixclock;
ret = 0;
}
return ret;
}
#endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
static int __init aty_init(struct fb_info *info, const char *name) static int __init aty_init(struct fb_info *info, const char *name)
{ {
struct atyfb_par *par = (struct atyfb_par *) info->par; struct atyfb_par *par = (struct atyfb_par *) info->par;
const char *ramname = NULL, *xtal; const char *ramname = NULL, *xtal;
int gtb_memsize; int gtb_memsize, has_var = 0;
struct fb_var_screeninfo var; struct fb_var_screeninfo var;
u8 pll_ref_div; u8 pll_ref_div;
u32 i; u32 i;
...@@ -2468,8 +2495,8 @@ static int __init aty_init(struct fb_info *info, const char *name) ...@@ -2468,8 +2495,8 @@ static int __init aty_init(struct fb_info *info, const char *name)
* applies to all Mac video cards * applies to all Mac video cards
*/ */
if (mode) { if (mode) {
if (!mac_find_mode(&var, info, mode, 8)) if (mac_find_mode(&var, info, mode, 8))
var = default_var; has_var = 1;
} else { } else {
if (default_vmode == VMODE_CHOOSE) { if (default_vmode == VMODE_CHOOSE) {
if (M64_HAS(G3_PB_1024x768)) if (M64_HAS(G3_PB_1024x768))
...@@ -2491,20 +2518,23 @@ static int __init aty_init(struct fb_info *info, const char *name) ...@@ -2491,20 +2518,23 @@ static int __init aty_init(struct fb_info *info, const char *name)
default_vmode = VMODE_640_480_60; default_vmode = VMODE_640_480_60;
if (default_cmode < CMODE_8 || default_cmode > CMODE_32) if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
default_cmode = CMODE_8; default_cmode = CMODE_8;
if (mac_vmode_to_var(default_vmode, default_cmode, &var)) if (!mac_vmode_to_var(default_vmode, default_cmode,
var = default_var; &var))
has_var = 1;
} }
} else }
#endif /* !CONFIG_PPC */ #endif /* !CONFIG_PPC */
if (
#if defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) #if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
/* On Sparc, unless the user gave a specific mode if (!atyfb_get_timings_from_lcd(par, &var))
* specification, use the PROM probed values in has_var = 1;
* default_var.
*/
!mode ||
#endif #endif
!fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
if (mode && fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
has_var = 1;
if (!has_var)
var = default_var; var = default_var;
if (noaccel) if (noaccel)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment