diff options
author | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2011-08-06 21:51:41 -0400 |
---|---|---|
committer | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2011-08-06 21:51:41 -0400 |
commit | ebb29fb47e198787b8b47a74cb10334cd9647a9d (patch) | |
tree | 25ab6ed861e7ada2f2c063d4e18b4e9bb2edcd9d /drivers/video | |
parent | 42edcb162d67e8a88c7b873941c19eab689db272 (diff) |
viafb: use information in var for modesetting
This patch starts to use the information in var for modesetting for
CRT and DVI devices. This is the right thing as it allows us to use
more generic modes than the ones predefined by VIA. We do not yet
allow more generic modes as check_var still limits them to the
predefined ones but with this patch applied it would be really easy
to do so. A problem was VIAs SAMM mode as it has 2 different modes
but just one frame buffer device. This is solved by creating a
pseudo var which contains enough information to use it for
modesetting. Hopefully one day we can use information in var for all
modes that do not involve hardware scaling.
Well I'd like to say that the chance of regressions is low but it is
quite likely that the behaviour in some cases changed especially
when SAMM is involved. I hope we made it better than before in
particular the DVI frequency check was probably broken before and
hopefully works better now.
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/via/dvi.c | 30 | ||||
-rw-r--r-- | drivers/video/via/dvi.h | 3 | ||||
-rw-r--r-- | drivers/video/via/hw.c | 107 | ||||
-rw-r--r-- | drivers/video/via/hw.h | 4 |
4 files changed, 61 insertions, 83 deletions
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index c7ff5c0e9c7e..9138e517267c 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c | |||
@@ -172,28 +172,20 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) | |||
172 | } | 172 | } |
173 | 173 | ||
174 | /* DVI Set Mode */ | 174 | /* DVI Set Mode */ |
175 | void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp, | 175 | void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga) |
176 | int set_iga) | ||
177 | { | 176 | { |
178 | struct VideoModeTable *rb_mode; | 177 | struct fb_var_screeninfo dvi_var = *var; |
179 | struct crt_mode_table *pDviTiming; | 178 | struct crt_mode_table *rb_mode; |
180 | unsigned long desirePixelClock, maxPixelClock; | 179 | int maxPixelClock; |
181 | pDviTiming = mode->crtc; | 180 | |
182 | desirePixelClock = pDviTiming->refresh_rate | 181 | maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock; |
183 | * pDviTiming->crtc.hor_total * pDviTiming->crtc.ver_total | 182 | if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) { |
184 | / 1000000; | 183 | rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60); |
185 | maxPixelClock = (unsigned long)viaparinfo-> | ||
186 | tmds_setting_info->max_pixel_clock; | ||
187 | |||
188 | DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n"); | ||
189 | |||
190 | if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) { | ||
191 | rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr, | ||
192 | mode->crtc[0].crtc.ver_addr); | ||
193 | if (rb_mode) | 184 | if (rb_mode) |
194 | mode = rb_mode; | 185 | viafb_fill_var_timing_info(&dvi_var, rb_mode); |
195 | } | 186 | } |
196 | viafb_fill_crtc_timing(mode, mode_bpp / 8, set_iga); | 187 | |
188 | viafb_fill_crtc_timing(&dvi_var, iga); | ||
197 | } | 189 | } |
198 | 190 | ||
199 | /* Sense DVI Connector */ | 191 | /* Sense DVI Connector */ |
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h index f473dd010977..e2116aaf797a 100644 --- a/drivers/video/via/dvi.h +++ b/drivers/video/via/dvi.h | |||
@@ -59,7 +59,6 @@ void viafb_dvi_enable(void); | |||
59 | bool __devinit viafb_tmds_trasmitter_identify(void); | 59 | bool __devinit viafb_tmds_trasmitter_identify(void); |
60 | void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, | 60 | void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, |
61 | struct tmds_setting_information *tmds_setting); | 61 | struct tmds_setting_information *tmds_setting); |
62 | void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp, | 62 | void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga); |
63 | int set_iga); | ||
64 | 63 | ||
65 | #endif /* __DVI_H__ */ | 64 | #endif /* __DVI_H__ */ |
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index d7b9a9f32dee..6845c82db3cb 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c | |||
@@ -1467,49 +1467,40 @@ void viafb_set_vclock(u32 clk, int set_iga) | |||
1467 | via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ | 1467 | via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ |
1468 | } | 1468 | } |
1469 | 1469 | ||
1470 | void viafb_fill_crtc_timing(struct VideoModeTable *video_mode, int bpp_byte, | 1470 | static struct display_timing var_to_timing(const struct fb_var_screeninfo *var) |
1471 | int set_iga) | ||
1472 | { | 1471 | { |
1473 | struct crt_mode_table *crt_table = video_mode->crtc; | 1472 | struct display_timing timing; |
1474 | struct display_timing crt_reg; | 1473 | |
1475 | int i; | 1474 | timing.hor_addr = var->xres; |
1476 | int index = 0; | 1475 | timing.hor_sync_start = timing.hor_addr + var->right_margin; |
1477 | int h_addr, v_addr; | 1476 | timing.hor_sync_end = timing.hor_sync_start + var->hsync_len; |
1478 | u32 clock, refresh = viafb_refresh; | 1477 | timing.hor_total = timing.hor_sync_end + var->left_margin; |
1479 | 1478 | timing.hor_blank_start = timing.hor_addr; | |
1480 | if (viafb_SAMM_ON && set_iga == IGA2) | 1479 | timing.hor_blank_end = timing.hor_total; |
1481 | refresh = viafb_refresh1; | 1480 | timing.ver_addr = var->yres; |
1482 | 1481 | timing.ver_sync_start = timing.ver_addr + var->lower_margin; | |
1483 | for (i = 0; i < video_mode->mode_array; i++) { | 1482 | timing.ver_sync_end = timing.ver_sync_start + var->vsync_len; |
1484 | index = i; | 1483 | timing.ver_total = timing.ver_sync_end + var->upper_margin; |
1484 | timing.ver_blank_start = timing.ver_addr; | ||
1485 | timing.ver_blank_end = timing.ver_total; | ||
1486 | return timing; | ||
1487 | } | ||
1485 | 1488 | ||
1486 | if (crt_table[i].refresh_rate == refresh) | 1489 | void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga) |
1487 | break; | 1490 | { |
1488 | } | 1491 | struct display_timing crt_reg = var_to_timing(var); |
1489 | 1492 | ||
1490 | crt_reg = crt_table[index].crtc; | 1493 | if (iga == IGA1) |
1491 | crt_reg.hor_blank_end += crt_reg.hor_blank_start; | ||
1492 | crt_reg.hor_sync_end += crt_reg.hor_sync_start; | ||
1493 | crt_reg.ver_blank_end += crt_reg.ver_blank_start; | ||
1494 | crt_reg.ver_sync_end += crt_reg.ver_sync_start; | ||
1495 | h_addr = crt_reg.hor_addr; | ||
1496 | v_addr = crt_reg.ver_addr; | ||
1497 | if (set_iga == IGA1) | ||
1498 | via_set_primary_timing(&crt_reg); | 1494 | via_set_primary_timing(&crt_reg); |
1499 | else if (set_iga == IGA2) | 1495 | else if (iga == IGA2) |
1500 | via_set_secondary_timing(&crt_reg); | 1496 | via_set_secondary_timing(&crt_reg); |
1501 | 1497 | ||
1502 | viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga); | 1498 | viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga); |
1503 | 1499 | if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266 | |
1504 | /* load FIFO */ | 1500 | && viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400) |
1505 | if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) | 1501 | viafb_load_FIFO_reg(iga, var->xres, var->yres); |
1506 | && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) | ||
1507 | viafb_load_FIFO_reg(set_iga, h_addr, v_addr); | ||
1508 | |||
1509 | clock = crt_reg.hor_total * crt_reg.ver_total | ||
1510 | * crt_table[index].refresh_rate; | ||
1511 | viafb_set_vclock(clock, set_iga); | ||
1512 | 1502 | ||
1503 | viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga); | ||
1513 | } | 1504 | } |
1514 | 1505 | ||
1515 | void __devinit viafb_init_chip_info(int chip_type) | 1506 | void __devinit viafb_init_chip_info(int chip_type) |
@@ -1788,6 +1779,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
1788 | u8 value, index, mask; | 1779 | u8 value, index, mask; |
1789 | struct crt_mode_table *crt_timing; | 1780 | struct crt_mode_table *crt_timing; |
1790 | struct crt_mode_table *crt_timing1 = NULL; | 1781 | struct crt_mode_table *crt_timing1 = NULL; |
1782 | struct fb_var_screeninfo var2; | ||
1791 | 1783 | ||
1792 | device_screen_off(); | 1784 | device_screen_off(); |
1793 | crt_timing = vmode_tbl->crtc; | 1785 | crt_timing = vmode_tbl->crtc; |
@@ -1894,17 +1886,24 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
1894 | 1886 | ||
1895 | /* Clear On Screen */ | 1887 | /* Clear On Screen */ |
1896 | 1888 | ||
1889 | if (viafb_dual_fb) { | ||
1890 | var2 = viafbinfo1->var; | ||
1891 | } else if (viafb_SAMM_ON) { | ||
1892 | viafb_fill_var_timing_info(&var2, viafb_get_best_mode( | ||
1893 | vmode_tbl1->crtc->crtc.hor_addr, | ||
1894 | vmode_tbl1->crtc->crtc.ver_addr, viafb_refresh1)); | ||
1895 | var2.bits_per_pixel = viafbinfo->var.bits_per_pixel; | ||
1896 | } | ||
1897 | |||
1897 | /* CRT set mode */ | 1898 | /* CRT set mode */ |
1898 | if (viafb_CRT_ON) { | 1899 | if (viafb_CRT_ON) { |
1899 | if (viafb_SAMM_ON && | 1900 | if (viaparinfo->shared->iga2_devices & VIA_CRT |
1900 | viaparinfo->shared->iga2_devices & VIA_CRT) { | 1901 | && viafb_SAMM_ON) |
1901 | viafb_fill_crtc_timing(vmode_tbl1, video_bpp1 / 8, | 1902 | viafb_fill_crtc_timing(&var2, IGA2); |
1902 | IGA2); | 1903 | else |
1903 | } else { | 1904 | viafb_fill_crtc_timing(&viafbinfo->var, |
1904 | viafb_fill_crtc_timing(vmode_tbl, video_bpp / 8, | ||
1905 | (viaparinfo->shared->iga1_devices & VIA_CRT) | 1905 | (viaparinfo->shared->iga1_devices & VIA_CRT) |
1906 | ? IGA1 : IGA2); | 1906 | ? IGA1 : IGA2); |
1907 | } | ||
1908 | 1907 | ||
1909 | /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode | 1908 | /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode |
1910 | to 8 alignment (1368),there is several pixels (2 pixels) | 1909 | to 8 alignment (1368),there is several pixels (2 pixels) |
@@ -1918,22 +1917,12 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
1918 | } | 1917 | } |
1919 | 1918 | ||
1920 | if (viafb_DVI_ON) { | 1919 | if (viafb_DVI_ON) { |
1921 | if (viafb_SAMM_ON && | 1920 | if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2 |
1922 | (viaparinfo->tmds_setting_info->iga_path == IGA2)) { | 1921 | && viafb_SAMM_ON) |
1923 | viafb_dvi_set_mode(viafb_get_mode | 1922 | viafb_dvi_set_mode(&var2, IGA2); |
1924 | (viaparinfo->tmds_setting_info->h_active, | 1923 | else |
1925 | viaparinfo->tmds_setting_info-> | 1924 | viafb_dvi_set_mode(&viafbinfo->var, |
1926 | v_active), | 1925 | viaparinfo->tmds_setting_info->iga_path); |
1927 | video_bpp1, viaparinfo-> | ||
1928 | tmds_setting_info->iga_path); | ||
1929 | } else { | ||
1930 | viafb_dvi_set_mode(viafb_get_mode | ||
1931 | (viaparinfo->tmds_setting_info->h_active, | ||
1932 | viaparinfo-> | ||
1933 | tmds_setting_info->v_active), | ||
1934 | video_bpp, viaparinfo-> | ||
1935 | tmds_setting_info->iga_path); | ||
1936 | } | ||
1937 | } | 1926 | } |
1938 | 1927 | ||
1939 | if (viafb_LCD_ON) { | 1928 | if (viafb_LCD_ON) { |
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index 5516b025926b..46f65da11e77 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h | |||
@@ -637,9 +637,7 @@ extern int viafb_LCD_ON; | |||
637 | extern int viafb_DVI_ON; | 637 | extern int viafb_DVI_ON; |
638 | extern int viafb_hotplug; | 638 | extern int viafb_hotplug; |
639 | 639 | ||
640 | void viafb_fill_crtc_timing(struct VideoModeTable *video_mode, int bpp_byte, | 640 | void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga); |
641 | int set_iga); | ||
642 | |||
643 | void viafb_set_vclock(u32 CLK, int set_iga); | 641 | void viafb_set_vclock(u32 CLK, int set_iga); |
644 | void viafb_load_reg(int timing_value, int viafb_load_reg_num, | 642 | void viafb_load_reg(int timing_value, int viafb_load_reg_num, |
645 | struct io_register *reg, | 643 | struct io_register *reg, |