aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2011-03-16 12:31:32 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2011-03-16 17:42:00 -0400
commit726abbc7957a2feeaf6f5e3d72579b3fd0211134 (patch)
tree04eab2f66ab63a8aae8051ccd34aaa433a8e41a9 /drivers/video/via
parent2563afa9ec6970f3545906382cc986ee012f60ec (diff)
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>
Diffstat (limited to 'drivers/video/via')
-rw-r--r--drivers/video/via/chip.h1
-rw-r--r--drivers/video/via/hw.c17
-rw-r--r--drivers/video/via/hw.h3
-rw-r--r--drivers/video/via/viafbdev.c45
4 files changed, 36 insertions, 30 deletions
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
index 781f3aa66b42..29d70244a21f 100644
--- a/drivers/video/via/chip.h
+++ b/drivers/video/via/chip.h
@@ -139,7 +139,6 @@ struct chip_information {
139 139
140struct crt_setting_information { 140struct crt_setting_information {
141 int iga_path; 141 int iga_path;
142 int refresh_rate;
143}; 142};
144 143
145struct tmds_setting_information { 144struct tmds_setting_information {
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 5728fd76bc11..dc4c778877ce 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -2002,13 +2002,15 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
2002 int i; 2002 int i;
2003 int index = 0; 2003 int index = 0;
2004 int h_addr, v_addr; 2004 int h_addr, v_addr;
2005 u32 pll_D_N, clock; 2005 u32 pll_D_N, clock, refresh = viafb_refresh;
2006
2007 if (viafb_SAMM_ON && set_iga == IGA2)
2008 refresh = viafb_refresh1;
2006 2009
2007 for (i = 0; i < video_mode->mode_array; i++) { 2010 for (i = 0; i < video_mode->mode_array; i++) {
2008 index = i; 2011 index = i;
2009 2012
2010 if (crt_table[i].refresh_rate == viaparinfo-> 2013 if (crt_table[i].refresh_rate == refresh)
2011 crt_setting_info->refresh_rate)
2012 break; 2014 break;
2013 } 2015 }
2014 2016
@@ -2019,7 +2021,7 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
2019 if ((viafb_LCD_ON | viafb_DVI_ON) 2021 if ((viafb_LCD_ON | viafb_DVI_ON)
2020 && video_mode->crtc[0].crtc.hor_addr == 640 2022 && video_mode->crtc[0].crtc.hor_addr == 640
2021 && video_mode->crtc[0].crtc.ver_addr == 480 2023 && video_mode->crtc[0].crtc.ver_addr == 480
2022 && viaparinfo->crt_setting_info->refresh_rate == 60) { 2024 && refresh == 60) {
2023 /* The border is 8 pixels. */ 2025 /* The border is 8 pixels. */
2024 crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; 2026 crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
2025 2027
@@ -2070,7 +2072,6 @@ void __devinit viafb_init_chip_info(int chip_type)
2070 init_lvds_chip_info(); 2072 init_lvds_chip_info();
2071 2073
2072 viaparinfo->crt_setting_info->iga_path = IGA1; 2074 viaparinfo->crt_setting_info->iga_path = IGA1;
2073 viaparinfo->crt_setting_info->refresh_rate = viafb_refresh;
2074 2075
2075 /*Set IGA path for each device */ 2076 /*Set IGA path for each device */
2076 viafb_set_iga_path(); 2077 viafb_set_iga_path();
@@ -2083,13 +2084,9 @@ void __devinit viafb_init_chip_info(int chip_type)
2083 viaparinfo->lvds_setting_info->lcd_mode; 2084 viaparinfo->lvds_setting_info->lcd_mode;
2084} 2085}
2085 2086
2086void viafb_update_device_setting(int hres, int vres, 2087void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
2087 int bpp, int vmode_refresh, int flag)
2088{ 2088{
2089 if (flag == 0) { 2089 if (flag == 0) {
2090 viaparinfo->crt_setting_info->refresh_rate =
2091 vmode_refresh;
2092
2093 viaparinfo->tmds_setting_info->h_active = hres; 2090 viaparinfo->tmds_setting_info->h_active = hres;
2094 viaparinfo->tmds_setting_info->v_active = vres; 2091 viaparinfo->tmds_setting_info->v_active = vres;
2095 2092
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 7295263299f7..8858593405aa 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -949,8 +949,7 @@ void __devinit viafb_init_chip_info(int chip_type);
949void __devinit viafb_init_dac(int set_iga); 949void __devinit viafb_init_dac(int set_iga);
950int viafb_get_pixclock(int hres, int vres, int vmode_refresh); 950int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
951int viafb_get_refresh(int hres, int vres, u32 float_refresh); 951int viafb_get_refresh(int hres, int vres, u32 float_refresh);
952void viafb_update_device_setting(int hres, int vres, int bpp, 952void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
953 int vmode_refresh, int flag);
954 953
955void viafb_set_iga_path(void); 954void viafb_set_iga_path(void);
956void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); 955void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index f555b891cc72..fd6a15f0decd 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -182,13 +182,24 @@ static int viafb_release(struct fb_info *info, int user)
182 return 0; 182 return 0;
183} 183}
184 184
185static inline int get_var_refresh(struct fb_var_screeninfo *var)
186{
187 u32 htotal, vtotal;
188
189 htotal = var->left_margin + var->xres + var->right_margin
190 + var->hsync_len;
191 vtotal = var->upper_margin + var->yres + var->lower_margin
192 + var->vsync_len;
193 return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal);
194}
195
185static int viafb_check_var(struct fb_var_screeninfo *var, 196static int viafb_check_var(struct fb_var_screeninfo *var,
186 struct fb_info *info) 197 struct fb_info *info)
187{ 198{
188 int htotal, vtotal, depth; 199 int depth, refresh;
189 struct VideoModeTable *vmode_entry; 200 struct VideoModeTable *vmode_entry;
190 struct viafb_par *ppar = info->par; 201 struct viafb_par *ppar = info->par;
191 u32 long_refresh, line; 202 u32 line;
192 203
193 DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); 204 DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
194 /* Sanity check */ 205 /* Sanity check */
@@ -231,17 +242,11 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
231 /* Based on var passed in to calculate the refresh, 242 /* Based on var passed in to calculate the refresh,
232 * because our driver use some modes special. 243 * because our driver use some modes special.
233 */ 244 */
234 htotal = var->xres + var->left_margin + 245 refresh = viafb_get_refresh(var->xres, var->yres,
235 var->right_margin + var->hsync_len; 246 get_var_refresh(var));
236 vtotal = var->yres + var->upper_margin +
237 var->lower_margin + var->vsync_len;
238 long_refresh = 1000000000UL / var->pixclock * 1000;
239 long_refresh /= (htotal * vtotal);
240
241 viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
242 247
243 /* Adjust var according to our driver's own table */ 248 /* Adjust var according to our driver's own table */
244 viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); 249 viafb_fill_var_timing_info(var, refresh, vmode_entry);
245 if (var->accel_flags & FB_ACCELF_TEXT && 250 if (var->accel_flags & FB_ACCELF_TEXT &&
246 !ppar->shared->vdev->engine_mmio) 251 !ppar->shared->vdev->engine_mmio)
247 var->accel_flags = 0; 252 var->accel_flags = 0;
@@ -253,12 +258,13 @@ static int viafb_set_par(struct fb_info *info)
253{ 258{
254 struct viafb_par *viapar = info->par; 259 struct viafb_par *viapar = info->par;
255 struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; 260 struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
261 int refresh;
256 DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); 262 DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
257 263
258 viafb_update_fix(info); 264 viafb_update_fix(info);
259 viapar->depth = fb_get_color_depth(&info->var, &info->fix); 265 viapar->depth = fb_get_color_depth(&info->var, &info->fix);
260 viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, 266 viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
261 viafbinfo->var.bits_per_pixel, viafb_refresh, 0); 267 viafbinfo->var.bits_per_pixel, 0);
262 268
263 vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres); 269 vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
264 if (viafb_dual_fb) { 270 if (viafb_dual_fb) {
@@ -266,7 +272,7 @@ static int viafb_set_par(struct fb_info *info)
266 viafbinfo1->var.yres); 272 viafbinfo1->var.yres);
267 viafb_update_device_setting(viafbinfo1->var.xres, 273 viafb_update_device_setting(viafbinfo1->var.xres,
268 viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, 274 viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
269 viafb_refresh1, 1); 275 1);
270 } else if (viafb_SAMM_ON == 1) { 276 } else if (viafb_SAMM_ON == 1) {
271 DEBUG_MSG(KERN_INFO 277 DEBUG_MSG(KERN_INFO
272 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", 278 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
@@ -275,14 +281,19 @@ static int viafb_set_par(struct fb_info *info)
275 viafb_second_yres); 281 viafb_second_yres);
276 282
277 viafb_update_device_setting(viafb_second_xres, 283 viafb_update_device_setting(viafb_second_xres,
278 viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); 284 viafb_second_yres, viafb_bpp1, 1);
279 } 285 }
280 286
287 refresh = viafb_get_refresh(info->var.xres, info->var.yres,
288 get_var_refresh(&info->var));
281 if (vmode_entry) { 289 if (vmode_entry) {
282 if (viafb_dual_fb && viapar->iga_path == IGA2) 290 if (viafb_dual_fb && viapar->iga_path == IGA2) {
283 viafb_bpp1 = info->var.bits_per_pixel; 291 viafb_bpp1 = info->var.bits_per_pixel;
284 else 292 viafb_refresh1 = refresh;
293 } else {
285 viafb_bpp = info->var.bits_per_pixel; 294 viafb_bpp = info->var.bits_per_pixel;
295 viafb_refresh = refresh;
296 }
286 297
287 if (info->var.accel_flags & FB_ACCELF_TEXT) 298 if (info->var.accel_flags & FB_ACCELF_TEXT)
288 info->flags &= ~FBINFO_HWACCEL_DISABLED; 299 info->flags &= ~FBINFO_HWACCEL_DISABLED;
@@ -1843,7 +1854,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1843 default_var.bits_per_pixel = viafb_bpp1; 1854 default_var.bits_per_pixel = viafb_bpp1;
1844 default_var.pixclock = 1855 default_var.pixclock =
1845 viafb_get_pixclock(viafb_second_xres, viafb_second_yres, 1856 viafb_get_pixclock(viafb_second_xres, viafb_second_yres,
1846 viafb_refresh); 1857 viafb_refresh1);
1847 default_var.left_margin = (viafb_second_xres >> 3) & 0xf8; 1858 default_var.left_margin = (viafb_second_xres >> 3) & 0xf8;
1848 default_var.right_margin = 32; 1859 default_var.right_margin = 32;
1849 default_var.upper_margin = 16; 1860 default_var.upper_margin = 16;