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 | |
| 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>
| -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; |
