viafb: refresh rate bug collection

This patch fixes multiple issues with the handling of refresh rates
especially for multi-display setups. If you experienced problems
with wrong refresh rates this patch might fix them.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
This commit is contained in:
Florian Tobias Schandinat 2011-03-16 16:31:32 +00:00
parent 2563afa9ec
commit 726abbc795
4 changed files with 36 additions and 30 deletions

View file

@ -139,7 +139,6 @@ struct chip_information {
struct crt_setting_information { struct crt_setting_information {
int iga_path; int iga_path;
int refresh_rate;
}; };
struct tmds_setting_information { struct tmds_setting_information {

View file

@ -2002,13 +2002,15 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
int i; int i;
int index = 0; int index = 0;
int h_addr, v_addr; int h_addr, v_addr;
u32 pll_D_N, clock; u32 pll_D_N, clock, refresh = viafb_refresh;
if (viafb_SAMM_ON && set_iga == IGA2)
refresh = viafb_refresh1;
for (i = 0; i < video_mode->mode_array; i++) { for (i = 0; i < video_mode->mode_array; i++) {
index = i; index = i;
if (crt_table[i].refresh_rate == viaparinfo-> if (crt_table[i].refresh_rate == refresh)
crt_setting_info->refresh_rate)
break; break;
} }
@ -2019,7 +2021,7 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
if ((viafb_LCD_ON | viafb_DVI_ON) if ((viafb_LCD_ON | viafb_DVI_ON)
&& video_mode->crtc[0].crtc.hor_addr == 640 && video_mode->crtc[0].crtc.hor_addr == 640
&& video_mode->crtc[0].crtc.ver_addr == 480 && video_mode->crtc[0].crtc.ver_addr == 480
&& viaparinfo->crt_setting_info->refresh_rate == 60) { && refresh == 60) {
/* The border is 8 pixels. */ /* The border is 8 pixels. */
crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
@ -2070,7 +2072,6 @@ void __devinit viafb_init_chip_info(int chip_type)
init_lvds_chip_info(); init_lvds_chip_info();
viaparinfo->crt_setting_info->iga_path = IGA1; viaparinfo->crt_setting_info->iga_path = IGA1;
viaparinfo->crt_setting_info->refresh_rate = viafb_refresh;
/*Set IGA path for each device */ /*Set IGA path for each device */
viafb_set_iga_path(); viafb_set_iga_path();
@ -2083,13 +2084,9 @@ void __devinit viafb_init_chip_info(int chip_type)
viaparinfo->lvds_setting_info->lcd_mode; viaparinfo->lvds_setting_info->lcd_mode;
} }
void viafb_update_device_setting(int hres, int vres, void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
int bpp, int vmode_refresh, int flag)
{ {
if (flag == 0) { if (flag == 0) {
viaparinfo->crt_setting_info->refresh_rate =
vmode_refresh;
viaparinfo->tmds_setting_info->h_active = hres; viaparinfo->tmds_setting_info->h_active = hres;
viaparinfo->tmds_setting_info->v_active = vres; viaparinfo->tmds_setting_info->v_active = vres;

View file

@ -949,8 +949,7 @@ void __devinit viafb_init_chip_info(int chip_type);
void __devinit viafb_init_dac(int set_iga); void __devinit viafb_init_dac(int set_iga);
int viafb_get_pixclock(int hres, int vres, int vmode_refresh); int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
int viafb_get_refresh(int hres, int vres, u32 float_refresh); int viafb_get_refresh(int hres, int vres, u32 float_refresh);
void viafb_update_device_setting(int hres, int vres, int bpp, void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
int vmode_refresh, int flag);
void viafb_set_iga_path(void); void viafb_set_iga_path(void);
void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);

View file

@ -182,13 +182,24 @@ static int viafb_release(struct fb_info *info, int user)
return 0; return 0;
} }
static inline int get_var_refresh(struct fb_var_screeninfo *var)
{
u32 htotal, vtotal;
htotal = var->left_margin + var->xres + var->right_margin
+ var->hsync_len;
vtotal = var->upper_margin + var->yres + var->lower_margin
+ var->vsync_len;
return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal);
}
static int viafb_check_var(struct fb_var_screeninfo *var, static int viafb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info) struct fb_info *info)
{ {
int htotal, vtotal, depth; int depth, refresh;
struct VideoModeTable *vmode_entry; struct VideoModeTable *vmode_entry;
struct viafb_par *ppar = info->par; struct viafb_par *ppar = info->par;
u32 long_refresh, line; u32 line;
DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
/* Sanity check */ /* Sanity check */
@ -231,17 +242,11 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
/* Based on var passed in to calculate the refresh, /* Based on var passed in to calculate the refresh,
* because our driver use some modes special. * because our driver use some modes special.
*/ */
htotal = var->xres + var->left_margin + refresh = viafb_get_refresh(var->xres, var->yres,
var->right_margin + var->hsync_len; get_var_refresh(var));
vtotal = var->yres + var->upper_margin +
var->lower_margin + var->vsync_len;
long_refresh = 1000000000UL / var->pixclock * 1000;
long_refresh /= (htotal * vtotal);
viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
/* Adjust var according to our driver's own table */ /* Adjust var according to our driver's own table */
viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); viafb_fill_var_timing_info(var, refresh, vmode_entry);
if (var->accel_flags & FB_ACCELF_TEXT && if (var->accel_flags & FB_ACCELF_TEXT &&
!ppar->shared->vdev->engine_mmio) !ppar->shared->vdev->engine_mmio)
var->accel_flags = 0; var->accel_flags = 0;
@ -253,12 +258,13 @@ static int viafb_set_par(struct fb_info *info)
{ {
struct viafb_par *viapar = info->par; struct viafb_par *viapar = info->par;
struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
int refresh;
DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
viafb_update_fix(info); viafb_update_fix(info);
viapar->depth = fb_get_color_depth(&info->var, &info->fix); viapar->depth = fb_get_color_depth(&info->var, &info->fix);
viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
viafbinfo->var.bits_per_pixel, viafb_refresh, 0); viafbinfo->var.bits_per_pixel, 0);
vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres); vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
if (viafb_dual_fb) { if (viafb_dual_fb) {
@ -266,7 +272,7 @@ static int viafb_set_par(struct fb_info *info)
viafbinfo1->var.yres); viafbinfo1->var.yres);
viafb_update_device_setting(viafbinfo1->var.xres, viafb_update_device_setting(viafbinfo1->var.xres,
viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
viafb_refresh1, 1); 1);
} else if (viafb_SAMM_ON == 1) { } else if (viafb_SAMM_ON == 1) {
DEBUG_MSG(KERN_INFO DEBUG_MSG(KERN_INFO
"viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
@ -275,14 +281,19 @@ static int viafb_set_par(struct fb_info *info)
viafb_second_yres); viafb_second_yres);
viafb_update_device_setting(viafb_second_xres, viafb_update_device_setting(viafb_second_xres,
viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); viafb_second_yres, viafb_bpp1, 1);
} }
refresh = viafb_get_refresh(info->var.xres, info->var.yres,
get_var_refresh(&info->var));
if (vmode_entry) { if (vmode_entry) {
if (viafb_dual_fb && viapar->iga_path == IGA2) if (viafb_dual_fb && viapar->iga_path == IGA2) {
viafb_bpp1 = info->var.bits_per_pixel; viafb_bpp1 = info->var.bits_per_pixel;
else viafb_refresh1 = refresh;
} else {
viafb_bpp = info->var.bits_per_pixel; viafb_bpp = info->var.bits_per_pixel;
viafb_refresh = refresh;
}
if (info->var.accel_flags & FB_ACCELF_TEXT) if (info->var.accel_flags & FB_ACCELF_TEXT)
info->flags &= ~FBINFO_HWACCEL_DISABLED; info->flags &= ~FBINFO_HWACCEL_DISABLED;
@ -1843,7 +1854,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
default_var.bits_per_pixel = viafb_bpp1; default_var.bits_per_pixel = viafb_bpp1;
default_var.pixclock = default_var.pixclock =
viafb_get_pixclock(viafb_second_xres, viafb_second_yres, viafb_get_pixclock(viafb_second_xres, viafb_second_yres,
viafb_refresh); viafb_refresh1);
default_var.left_margin = (viafb_second_xres >> 3) & 0xf8; default_var.left_margin = (viafb_second_xres >> 3) & 0xf8;
default_var.right_margin = 32; default_var.right_margin = 32;
default_var.upper_margin = 16; default_var.upper_margin = 16;