diff options
author | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2011-03-16 12:31:32 -0400 |
---|---|---|
committer | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2011-03-16 17:42:00 -0400 |
commit | 726abbc7957a2feeaf6f5e3d72579b3fd0211134 (patch) | |
tree | 04eab2f66ab63a8aae8051ccd34aaa433a8e41a9 /drivers/video | |
parent | 2563afa9ec6970f3545906382cc986ee012f60ec (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')
-rw-r--r-- | drivers/video/via/chip.h | 1 | ||||
-rw-r--r-- | drivers/video/via/hw.c | 17 | ||||
-rw-r--r-- | drivers/video/via/hw.h | 3 | ||||
-rw-r--r-- | drivers/video/via/viafbdev.c | 45 |
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 | ||
140 | struct crt_setting_information { | 140 | struct crt_setting_information { |
141 | int iga_path; | 141 | int iga_path; |
142 | int refresh_rate; | ||
143 | }; | 142 | }; |
144 | 143 | ||
145 | struct tmds_setting_information { | 144 | struct 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 | ||
2086 | void viafb_update_device_setting(int hres, int vres, | 2087 | void 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); | |||
949 | void __devinit viafb_init_dac(int set_iga); | 949 | void __devinit viafb_init_dac(int set_iga); |
950 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh); | 950 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh); |
951 | int viafb_get_refresh(int hres, int vres, u32 float_refresh); | 951 | int viafb_get_refresh(int hres, int vres, u32 float_refresh); |
952 | void viafb_update_device_setting(int hres, int vres, int bpp, | 952 | void viafb_update_device_setting(int hres, int vres, int bpp, int flag); |
953 | int vmode_refresh, int flag); | ||
954 | 953 | ||
955 | void viafb_set_iga_path(void); | 954 | void viafb_set_iga_path(void); |
956 | void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); | 955 | void 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 | ||
185 | static 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 | |||
185 | static int viafb_check_var(struct fb_var_screeninfo *var, | 196 | static 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; |