diff options
author | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2011-08-06 19:04:43 -0400 |
---|---|---|
committer | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2011-08-06 19:22:49 -0400 |
commit | 94715ba97508dd42919a7525e362efb00dde1271 (patch) | |
tree | 9ad5e92149e59eed1b0385a950608608d7df0494 /drivers/video/via | |
parent | 363699722a2a6801d098693fa15bc3b68d6b4f31 (diff) |
viafb: add new funcions to select a single mode
This patch introduces 2 new functions for selecting a single mode
based on hres, vres and refresh rate and changes some uses to use
those. The advantage is that it is less error prone than doing the
selection based on refresh rate everywhere and allows replacing the
modetable structure. This includes a little change that users may
notice: If a refresh rate was given as module parameters but does
not exist in the modetable prior to this patch a refresh rate of 60
was assumed and after this patch the closest supported refresh rate
to the one provided by the user is used.
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Diffstat (limited to 'drivers/video/via')
-rw-r--r-- | drivers/video/via/hw.c | 45 | ||||
-rw-r--r-- | drivers/video/via/hw.h | 4 | ||||
-rw-r--r-- | drivers/video/via/viafbdev.c | 24 | ||||
-rw-r--r-- | drivers/video/via/viamode.c | 56 | ||||
-rw-r--r-- | drivers/video/via/viamode.h | 2 |
5 files changed, 70 insertions, 61 deletions
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index c5e7833a5ae5..5e69c203163c 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c | |||
@@ -2035,40 +2035,24 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2035 | 2035 | ||
2036 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh) | 2036 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh) |
2037 | { | 2037 | { |
2038 | int i; | ||
2039 | struct crt_mode_table *best; | 2038 | struct crt_mode_table *best; |
2040 | struct VideoModeTable *vmode = viafb_get_mode(hres, vres); | ||
2041 | 2039 | ||
2042 | if (!vmode) | 2040 | best = viafb_get_best_mode(hres, vres, vmode_refresh); |
2041 | if (!best) | ||
2043 | return RES_640X480_60HZ_PIXCLOCK; | 2042 | return RES_640X480_60HZ_PIXCLOCK; |
2044 | 2043 | ||
2045 | best = &vmode->crtc[0]; | ||
2046 | for (i = 1; i < vmode->mode_array; i++) { | ||
2047 | if (abs(vmode->crtc[i].refresh_rate - vmode_refresh) | ||
2048 | < abs(best->refresh_rate - vmode_refresh)) | ||
2049 | best = &vmode->crtc[i]; | ||
2050 | } | ||
2051 | |||
2052 | return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total) | 2044 | return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total) |
2053 | * 1000 / best->refresh_rate; | 2045 | * 1000 / best->refresh_rate; |
2054 | } | 2046 | } |
2055 | 2047 | ||
2056 | int viafb_get_refresh(int hres, int vres, u32 long_refresh) | 2048 | int viafb_get_refresh(int hres, int vres, u32 long_refresh) |
2057 | { | 2049 | { |
2058 | int i; | ||
2059 | struct crt_mode_table *best; | 2050 | struct crt_mode_table *best; |
2060 | struct VideoModeTable *vmode = viafb_get_mode(hres, vres); | ||
2061 | 2051 | ||
2062 | if (!vmode) | 2052 | best = viafb_get_best_mode(hres, vres, long_refresh); |
2053 | if (!best) | ||
2063 | return 60; | 2054 | return 60; |
2064 | 2055 | ||
2065 | best = &vmode->crtc[0]; | ||
2066 | for (i = 1; i < vmode->mode_array; i++) { | ||
2067 | if (abs(vmode->crtc[i].refresh_rate - long_refresh) | ||
2068 | < abs(best->refresh_rate - long_refresh)) | ||
2069 | best = &vmode->crtc[i]; | ||
2070 | } | ||
2071 | |||
2072 | if (abs(best->refresh_rate - long_refresh) > 3) { | 2056 | if (abs(best->refresh_rate - long_refresh) > 3) { |
2073 | if (hres == 1200 && vres == 900) | 2057 | if (hres == 1200 && vres == 900) |
2074 | return 49; /* OLPC DCON only supports 50 Hz */ | 2058 | return 49; /* OLPC DCON only supports 50 Hz */ |
@@ -2170,21 +2154,14 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | |||
2170 | } | 2154 | } |
2171 | 2155 | ||
2172 | /*According var's xres, yres fill var's other timing information*/ | 2156 | /*According var's xres, yres fill var's other timing information*/ |
2173 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | 2157 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, |
2174 | struct VideoModeTable *vmode_tbl) | 2158 | struct crt_mode_table *mode) |
2175 | { | 2159 | { |
2176 | struct crt_mode_table *crt_timing = NULL; | ||
2177 | struct display_timing crt_reg; | 2160 | struct display_timing crt_reg; |
2178 | int i = 0, index = 0; | ||
2179 | crt_timing = vmode_tbl->crtc; | ||
2180 | for (i = 0; i < vmode_tbl->mode_array; i++) { | ||
2181 | index = i; | ||
2182 | if (crt_timing[i].refresh_rate == refresh) | ||
2183 | break; | ||
2184 | } | ||
2185 | 2161 | ||
2186 | crt_reg = crt_timing[index].crtc; | 2162 | crt_reg = mode->crtc; |
2187 | var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh); | 2163 | var->pixclock = viafb_get_pixclock(var->xres, var->yres, |
2164 | mode->refresh_rate); | ||
2188 | var->left_margin = | 2165 | var->left_margin = |
2189 | crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); | 2166 | crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); |
2190 | var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; | 2167 | var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; |
@@ -2194,8 +2171,8 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | |||
2194 | var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr; | 2171 | var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr; |
2195 | var->vsync_len = crt_reg.ver_sync_end; | 2172 | var->vsync_len = crt_reg.ver_sync_end; |
2196 | var->sync = 0; | 2173 | var->sync = 0; |
2197 | if (crt_timing[index].h_sync_polarity == POSITIVE) | 2174 | if (mode->h_sync_polarity == POSITIVE) |
2198 | var->sync |= FB_SYNC_HOR_HIGH_ACT; | 2175 | var->sync |= FB_SYNC_HOR_HIGH_ACT; |
2199 | if (crt_timing[index].v_sync_polarity == POSITIVE) | 2176 | if (mode->v_sync_polarity == POSITIVE) |
2200 | var->sync |= FB_SYNC_VERT_HIGH_ACT; | 2177 | var->sync |= FB_SYNC_VERT_HIGH_ACT; |
2201 | } | 2178 | } |
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index 1fd8d98f7395..3b7e1496657b 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h | |||
@@ -661,8 +661,8 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | |||
661 | 661 | ||
662 | int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | 662 | int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, |
663 | struct VideoModeTable *vmode_tbl1, int video_bpp1); | 663 | struct VideoModeTable *vmode_tbl1, int video_bpp1); |
664 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | 664 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, |
665 | struct VideoModeTable *vmode_tbl); | 665 | struct crt_mode_table *mode); |
666 | void __devinit viafb_init_chip_info(int chip_type); | 666 | void __devinit viafb_init_chip_info(int chip_type); |
667 | void __devinit viafb_init_dac(int set_iga); | 667 | void __devinit viafb_init_dac(int set_iga); |
668 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh); | 668 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh); |
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 3eaf607bdf48..0c0ef9568cf3 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
@@ -201,7 +201,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
201 | struct fb_info *info) | 201 | struct fb_info *info) |
202 | { | 202 | { |
203 | int depth, refresh; | 203 | int depth, refresh; |
204 | struct VideoModeTable *vmode_entry; | ||
205 | struct viafb_par *ppar = info->par; | 204 | struct viafb_par *ppar = info->par; |
206 | u32 line; | 205 | u32 line; |
207 | 206 | ||
@@ -211,8 +210,10 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
211 | if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) | 210 | if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) |
212 | return -EINVAL; | 211 | return -EINVAL; |
213 | 212 | ||
214 | vmode_entry = viafb_get_mode(var->xres, var->yres); | 213 | /* the refresh rate is not important here, as we only want to know |
215 | if (!vmode_entry) { | 214 | * whether the resolution exists |
215 | */ | ||
216 | if (!viafb_get_best_mode(var->xres, var->yres, 60)) { | ||
216 | DEBUG_MSG(KERN_INFO | 217 | DEBUG_MSG(KERN_INFO |
217 | "viafb: Mode %dx%dx%d not supported!!\n", | 218 | "viafb: Mode %dx%dx%d not supported!!\n", |
218 | var->xres, var->yres, var->bits_per_pixel); | 219 | var->xres, var->yres, var->bits_per_pixel); |
@@ -254,7 +255,8 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
254 | get_var_refresh(var)); | 255 | get_var_refresh(var)); |
255 | 256 | ||
256 | /* Adjust var according to our driver's own table */ | 257 | /* Adjust var according to our driver's own table */ |
257 | viafb_fill_var_timing_info(var, refresh, vmode_entry); | 258 | viafb_fill_var_timing_info(var, |
259 | viafb_get_best_mode(var->xres, var->yres, refresh)); | ||
258 | if (var->accel_flags & FB_ACCELF_TEXT && | 260 | if (var->accel_flags & FB_ACCELF_TEXT && |
259 | !ppar->shared->vdev->engine_mmio) | 261 | !ppar->shared->vdev->engine_mmio) |
260 | var->accel_flags = 0; | 262 | var->accel_flags = 0; |
@@ -1816,9 +1818,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | |||
1816 | default_var.xres_virtual = default_xres; | 1818 | default_var.xres_virtual = default_xres; |
1817 | default_var.yres_virtual = default_yres; | 1819 | default_var.yres_virtual = default_yres; |
1818 | default_var.bits_per_pixel = viafb_bpp; | 1820 | default_var.bits_per_pixel = viafb_bpp; |
1819 | viafb_fill_var_timing_info(&default_var, viafb_get_refresh( | 1821 | viafb_fill_var_timing_info(&default_var, viafb_get_best_mode( |
1820 | default_var.xres, default_var.yres, viafb_refresh), | 1822 | default_var.xres, default_var.yres, viafb_refresh)); |
1821 | viafb_get_mode(default_var.xres, default_var.yres)); | ||
1822 | viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); | 1823 | viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); |
1823 | viafbinfo->var = default_var; | 1824 | viafbinfo->var = default_var; |
1824 | 1825 | ||
@@ -1857,9 +1858,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | |||
1857 | default_var.xres_virtual = viafb_second_xres; | 1858 | default_var.xres_virtual = viafb_second_xres; |
1858 | default_var.yres_virtual = viafb_second_yres; | 1859 | default_var.yres_virtual = viafb_second_yres; |
1859 | default_var.bits_per_pixel = viafb_bpp1; | 1860 | default_var.bits_per_pixel = viafb_bpp1; |
1860 | viafb_fill_var_timing_info(&default_var, viafb_get_refresh( | 1861 | viafb_fill_var_timing_info(&default_var, viafb_get_best_mode( |
1861 | default_var.xres, default_var.yres, viafb_refresh1), | 1862 | default_var.xres, default_var.yres, viafb_refresh1)); |
1862 | viafb_get_mode(default_var.xres, default_var.yres)); | ||
1863 | 1863 | ||
1864 | viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); | 1864 | viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); |
1865 | viafb_check_var(&default_var, viafbinfo1); | 1865 | viafb_check_var(&default_var, viafbinfo1); |
@@ -2032,9 +2032,9 @@ int __init viafb_init(void) | |||
2032 | return r; | 2032 | return r; |
2033 | #endif | 2033 | #endif |
2034 | if (parse_mode(viafb_mode, &dummy_x, &dummy_y) | 2034 | if (parse_mode(viafb_mode, &dummy_x, &dummy_y) |
2035 | || !viafb_get_mode(dummy_x, dummy_y) | 2035 | || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh) |
2036 | || parse_mode(viafb_mode1, &dummy_x, &dummy_y) | 2036 | || parse_mode(viafb_mode1, &dummy_x, &dummy_y) |
2037 | || !viafb_get_mode(dummy_x, dummy_y) | 2037 | || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1) |
2038 | || viafb_bpp < 0 || viafb_bpp > 32 | 2038 | || viafb_bpp < 0 || viafb_bpp > 32 |
2039 | || viafb_bpp1 < 0 || viafb_bpp1 > 32 | 2039 | || viafb_bpp1 < 0 || viafb_bpp1 > 32 |
2040 | || parse_active_dev()) | 2040 | || parse_active_dev()) |
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index 8a9f4fcb50e9..88096e5fa077 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c | |||
@@ -863,26 +863,56 @@ int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs); | |||
863 | int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); | 863 | int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); |
864 | 864 | ||
865 | 865 | ||
866 | struct VideoModeTable *viafb_get_mode(int hres, int vres) | 866 | static struct VideoModeTable *get_modes(struct VideoModeTable *vmt, int n, |
867 | int hres, int vres) | ||
867 | { | 868 | { |
868 | u32 i; | 869 | int i; |
869 | for (i = 0; i < ARRAY_SIZE(viafb_modes); i++) | 870 | |
870 | if (viafb_modes[i].mode_array && | 871 | for (i = 0; i < n; i++) |
871 | viafb_modes[i].crtc[0].crtc.hor_addr == hres && | 872 | if (vmt[i].mode_array && |
872 | viafb_modes[i].crtc[0].crtc.ver_addr == vres) | 873 | vmt[i].crtc[0].crtc.hor_addr == hres && |
874 | vmt[i].crtc[0].crtc.ver_addr == vres) | ||
873 | return &viafb_modes[i]; | 875 | return &viafb_modes[i]; |
874 | 876 | ||
875 | return NULL; | 877 | return NULL; |
876 | } | 878 | } |
877 | 879 | ||
880 | static struct crt_mode_table *get_best_mode(struct VideoModeTable *vmt, | ||
881 | int refresh) | ||
882 | { | ||
883 | struct crt_mode_table *best; | ||
884 | int i; | ||
885 | |||
886 | if (!vmt) | ||
887 | return NULL; | ||
888 | |||
889 | best = &vmt->crtc[0]; | ||
890 | for (i = 1; i < vmt->mode_array; i++) { | ||
891 | if (abs(vmt->crtc[i].refresh_rate - refresh) | ||
892 | < abs(best->refresh_rate - refresh)) | ||
893 | best = &vmt->crtc[i]; | ||
894 | } | ||
895 | |||
896 | return best; | ||
897 | } | ||
898 | |||
899 | struct VideoModeTable *viafb_get_mode(int hres, int vres) | ||
900 | { | ||
901 | return get_modes(viafb_modes, ARRAY_SIZE(viafb_modes), hres, vres); | ||
902 | } | ||
903 | |||
904 | struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh) | ||
905 | { | ||
906 | return get_best_mode(viafb_get_mode(hres, vres), refresh); | ||
907 | } | ||
908 | |||
878 | struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) | 909 | struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) |
879 | { | 910 | { |
880 | u32 i; | 911 | return get_modes(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes), hres, |
881 | for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++) | 912 | vres); |
882 | if (viafb_rb_modes[i].mode_array && | 913 | } |
883 | viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres && | ||
884 | viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres) | ||
885 | return &viafb_rb_modes[i]; | ||
886 | 914 | ||
887 | return NULL; | 915 | struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh) |
916 | { | ||
917 | return get_best_mode(viafb_get_rb_mode(hres, vres), refresh); | ||
888 | } | 918 | } |
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h index 3751289eb450..0396581b9775 100644 --- a/drivers/video/via/viamode.h +++ b/drivers/video/via/viamode.h | |||
@@ -61,6 +61,8 @@ extern struct patch_table res_patch_table[]; | |||
61 | extern struct VPITTable VPIT; | 61 | extern struct VPITTable VPIT; |
62 | 62 | ||
63 | struct VideoModeTable *viafb_get_mode(int hres, int vres); | 63 | struct VideoModeTable *viafb_get_mode(int hres, int vres); |
64 | struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh); | ||
64 | struct VideoModeTable *viafb_get_rb_mode(int hres, int vres); | 65 | struct VideoModeTable *viafb_get_rb_mode(int hres, int vres); |
66 | struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh); | ||
65 | 67 | ||
66 | #endif /* __VIAMODE_H__ */ | 68 | #endif /* __VIAMODE_H__ */ |