aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2011-08-06 19:04:43 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2011-08-06 19:22:49 -0400
commit94715ba97508dd42919a7525e362efb00dde1271 (patch)
tree9ad5e92149e59eed1b0385a950608608d7df0494 /drivers/video/via
parent363699722a2a6801d098693fa15bc3b68d6b4f31 (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.c45
-rw-r--r--drivers/video/via/hw.h4
-rw-r--r--drivers/video/via/viafbdev.c24
-rw-r--r--drivers/video/via/viamode.c56
-rw-r--r--drivers/video/via/viamode.h2
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
2036int viafb_get_pixclock(int hres, int vres, int vmode_refresh) 2036int 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
2056int viafb_get_refresh(int hres, int vres, u32 long_refresh) 2048int 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*/
2173void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, 2157void 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
662int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, 662int 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);
664void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, 664void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
665 struct VideoModeTable *vmode_tbl); 665 struct crt_mode_table *mode);
666void __devinit viafb_init_chip_info(int chip_type); 666void __devinit viafb_init_chip_info(int chip_type);
667void __devinit viafb_init_dac(int set_iga); 667void __devinit viafb_init_dac(int set_iga);
668int viafb_get_pixclock(int hres, int vres, int vmode_refresh); 668int 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);
863int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); 863int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
864 864
865 865
866struct VideoModeTable *viafb_get_mode(int hres, int vres) 866static 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
880static 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
899struct VideoModeTable *viafb_get_mode(int hres, int vres)
900{
901 return get_modes(viafb_modes, ARRAY_SIZE(viafb_modes), hres, vres);
902}
903
904struct 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
878struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) 909struct 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; 915struct 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[];
61extern struct VPITTable VPIT; 61extern struct VPITTable VPIT;
62 62
63struct VideoModeTable *viafb_get_mode(int hres, int vres); 63struct VideoModeTable *viafb_get_mode(int hres, int vres);
64struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh);
64struct VideoModeTable *viafb_get_rb_mode(int hres, int vres); 65struct VideoModeTable *viafb_get_rb_mode(int hres, int vres);
66struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh);
65 67
66#endif /* __VIAMODE_H__ */ 68#endif /* __VIAMODE_H__ */