diff options
Diffstat (limited to 'drivers/video/via')
-rw-r--r-- | drivers/video/via/dvi.c | 34 | ||||
-rw-r--r-- | drivers/video/via/dvi.h | 3 | ||||
-rw-r--r-- | drivers/video/via/global.c | 2 | ||||
-rw-r--r-- | drivers/video/via/global.h | 2 | ||||
-rw-r--r-- | drivers/video/via/hw.c | 544 | ||||
-rw-r--r-- | drivers/video/via/hw.h | 285 | ||||
-rw-r--r-- | drivers/video/via/lcd.c | 53 | ||||
-rw-r--r-- | drivers/video/via/lcd.h | 7 | ||||
-rw-r--r-- | drivers/video/via/share.h | 23 | ||||
-rw-r--r-- | drivers/video/via/via-core.c | 2 | ||||
-rw-r--r-- | drivers/video/via/via_modesetting.c | 104 | ||||
-rw-r--r-- | drivers/video/via/via_modesetting.h | 23 | ||||
-rw-r--r-- | drivers/video/via/viafbdev.c | 56 | ||||
-rw-r--r-- | drivers/video/via/viamode.c | 60 | ||||
-rw-r--r-- | drivers/video/via/viamode.h | 4 |
15 files changed, 339 insertions, 863 deletions
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index b1f3647..9138e51 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c @@ -172,30 +172,20 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) } /* DVI Set Mode */ -void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp, - int set_iga) +void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga) { - struct VideoModeTable *rb_mode; - struct crt_mode_table *pDviTiming; - unsigned long desirePixelClock, maxPixelClock; - pDviTiming = mode->crtc; - desirePixelClock = pDviTiming->refresh_rate - * pDviTiming->crtc.hor_total * pDviTiming->crtc.ver_total - / 1000000; - maxPixelClock = (unsigned long)viaparinfo-> - tmds_setting_info->max_pixel_clock; - - DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n"); - - if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) { - rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr, - mode->crtc[0].crtc.ver_addr); - if (rb_mode) { - mode = rb_mode; - pDviTiming = rb_mode->crtc; - } + struct fb_var_screeninfo dvi_var = *var; + struct crt_mode_table *rb_mode; + int maxPixelClock; + + maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock; + if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) { + rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60); + if (rb_mode) + viafb_fill_var_timing_info(&dvi_var, rb_mode); } - viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga); + + viafb_fill_crtc_timing(&dvi_var, iga); } /* Sense DVI Connector */ diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h index f473dd0..e2116aa 100644 --- a/drivers/video/via/dvi.h +++ b/drivers/video/via/dvi.h @@ -59,7 +59,6 @@ void viafb_dvi_enable(void); bool __devinit viafb_tmds_trasmitter_identify(void); void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, struct tmds_setting_information *tmds_setting); -void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp, - int set_iga); +void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga); #endif /* __DVI_H__ */ diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c index e10d824..3102171 100644 --- a/drivers/video/via/global.c +++ b/drivers/video/via/global.c @@ -35,6 +35,8 @@ int viafb_LCD_ON ; int viafb_LCD2_ON; int viafb_SAMM_ON; int viafb_dual_fb; +unsigned int viafb_second_xres = 640; +unsigned int viafb_second_yres = 480; int viafb_hotplug_Xres = 640; int viafb_hotplug_Yres = 480; int viafb_hotplug_bpp = 32; diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h index ff969dc..275dbbb 100644 --- a/drivers/video/via/global.h +++ b/drivers/video/via/global.h @@ -67,6 +67,8 @@ extern int viafb_lcd_dsp_method; extern int viafb_lcd_mode; extern int viafb_CRT_ON; +extern unsigned int viafb_second_xres; +extern unsigned int viafb_second_yres; extern int viafb_hotplug_Xres; extern int viafb_hotplug_Yres; extern int viafb_hotplug_bpp; diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 47b1353..d5aaca9 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -191,67 +191,6 @@ static struct fetch_count fetch_count_reg = { {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } } }; -static struct iga1_crtc_timing iga1_crtc_reg = { - /* IGA1 Horizontal Total */ - {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } }, - /* IGA1 Horizontal Addressable Video */ - {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } }, - /* IGA1 Horizontal Blank Start */ - {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } }, - /* IGA1 Horizontal Blank End */ - {IGA1_HOR_BLANK_END_REG_NUM, - {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } }, - /* IGA1 Horizontal Sync Start */ - {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } }, - /* IGA1 Horizontal Sync End */ - {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } }, - /* IGA1 Vertical Total */ - {IGA1_VER_TOTAL_REG_NUM, - {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } }, - /* IGA1 Vertical Addressable Video */ - {IGA1_VER_ADDR_REG_NUM, - {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } }, - /* IGA1 Vertical Blank Start */ - {IGA1_VER_BLANK_START_REG_NUM, - {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } }, - /* IGA1 Vertical Blank End */ - {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } }, - /* IGA1 Vertical Sync Start */ - {IGA1_VER_SYNC_START_REG_NUM, - {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } }, - /* IGA1 Vertical Sync End */ - {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } } -}; - -static struct iga2_crtc_timing iga2_crtc_reg = { - /* IGA2 Horizontal Total */ - {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } }, - /* IGA2 Horizontal Addressable Video */ - {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } }, - /* IGA2 Horizontal Blank Start */ - {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } }, - /* IGA2 Horizontal Blank End */ - {IGA2_HOR_BLANK_END_REG_NUM, - {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } }, - /* IGA2 Horizontal Sync Start */ - {IGA2_HOR_SYNC_START_REG_NUM, - {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } }, - /* IGA2 Horizontal Sync End */ - {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } }, - /* IGA2 Vertical Total */ - {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } }, - /* IGA2 Vertical Addressable Video */ - {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } }, - /* IGA2 Vertical Blank Start */ - {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } }, - /* IGA2 Vertical Blank End */ - {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } }, - /* IGA2 Vertical Sync Start */ - {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } }, - /* IGA2 Vertical Sync End */ - {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } } -}; - static struct rgbLUT palLUT_table[] = { /* {R,G,B} */ /* Index 0x00~0x03 */ @@ -1528,302 +1467,40 @@ void viafb_set_vclock(u32 clk, int set_iga) via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ } -void viafb_load_crtc_timing(struct display_timing device_timing, - int set_iga) +static struct display_timing var_to_timing(const struct fb_var_screeninfo *var) { - int i; - int viafb_load_reg_num = 0; - int reg_value = 0; - struct io_register *reg = NULL; - - viafb_unlock_crt(); - - for (i = 0; i < 12; i++) { - if (set_iga == IGA1) { - switch (i) { - case H_TOTAL_INDEX: - reg_value = - IGA1_HOR_TOTAL_FORMULA(device_timing. - hor_total); - viafb_load_reg_num = - iga1_crtc_reg.hor_total.reg_num; - reg = iga1_crtc_reg.hor_total.reg; - break; - case H_ADDR_INDEX: - reg_value = - IGA1_HOR_ADDR_FORMULA(device_timing. - hor_addr); - viafb_load_reg_num = - iga1_crtc_reg.hor_addr.reg_num; - reg = iga1_crtc_reg.hor_addr.reg; - break; - case H_BLANK_START_INDEX: - reg_value = - IGA1_HOR_BLANK_START_FORMULA - (device_timing.hor_blank_start); - viafb_load_reg_num = - iga1_crtc_reg.hor_blank_start.reg_num; - reg = iga1_crtc_reg.hor_blank_start.reg; - break; - case H_BLANK_END_INDEX: - reg_value = - IGA1_HOR_BLANK_END_FORMULA - (device_timing.hor_blank_start, - device_timing.hor_blank_end); - viafb_load_reg_num = - iga1_crtc_reg.hor_blank_end.reg_num; - reg = iga1_crtc_reg.hor_blank_end.reg; - break; - case H_SYNC_START_INDEX: - reg_value = - IGA1_HOR_SYNC_START_FORMULA - (device_timing.hor_sync_start); - viafb_load_reg_num = - iga1_crtc_reg.hor_sync_start.reg_num; - reg = iga1_crtc_reg.hor_sync_start.reg; - break; - case H_SYNC_END_INDEX: - reg_value = - IGA1_HOR_SYNC_END_FORMULA - (device_timing.hor_sync_start, - device_timing.hor_sync_end); - viafb_load_reg_num = - iga1_crtc_reg.hor_sync_end.reg_num; - reg = iga1_crtc_reg.hor_sync_end.reg; - break; - case V_TOTAL_INDEX: - reg_value = - IGA1_VER_TOTAL_FORMULA(device_timing. - ver_total); - viafb_load_reg_num = - iga1_crtc_reg.ver_total.reg_num; - reg = iga1_crtc_reg.ver_total.reg; - break; - case V_ADDR_INDEX: - reg_value = - IGA1_VER_ADDR_FORMULA(device_timing. - ver_addr); - viafb_load_reg_num = - iga1_crtc_reg.ver_addr.reg_num; - reg = iga1_crtc_reg.ver_addr.reg; - break; - case V_BLANK_START_INDEX: - reg_value = - IGA1_VER_BLANK_START_FORMULA - (device_timing.ver_blank_start); - viafb_load_reg_num = - iga1_crtc_reg.ver_blank_start.reg_num; - reg = iga1_crtc_reg.ver_blank_start.reg; - break; - case V_BLANK_END_INDEX: - reg_value = - IGA1_VER_BLANK_END_FORMULA - (device_timing.ver_blank_start, - device_timing.ver_blank_end); - viafb_load_reg_num = - iga1_crtc_reg.ver_blank_end.reg_num; - reg = iga1_crtc_reg.ver_blank_end.reg; - break; - case V_SYNC_START_INDEX: - reg_value = - IGA1_VER_SYNC_START_FORMULA - (device_timing.ver_sync_start); - viafb_load_reg_num = - iga1_crtc_reg.ver_sync_start.reg_num; - reg = iga1_crtc_reg.ver_sync_start.reg; - break; - case V_SYNC_END_INDEX: - reg_value = - IGA1_VER_SYNC_END_FORMULA - (device_timing.ver_sync_start, - device_timing.ver_sync_end); - viafb_load_reg_num = - iga1_crtc_reg.ver_sync_end.reg_num; - reg = iga1_crtc_reg.ver_sync_end.reg; - break; - - } - } - - if (set_iga == IGA2) { - switch (i) { - case H_TOTAL_INDEX: - reg_value = - IGA2_HOR_TOTAL_FORMULA(device_timing. - hor_total); - viafb_load_reg_num = - iga2_crtc_reg.hor_total.reg_num; - reg = iga2_crtc_reg.hor_total.reg; - break; - case H_ADDR_INDEX: - reg_value = - IGA2_HOR_ADDR_FORMULA(device_timing. - hor_addr); - viafb_load_reg_num = - iga2_crtc_reg.hor_addr.reg_num; - reg = iga2_crtc_reg.hor_addr.reg; - break; - case H_BLANK_START_INDEX: - reg_value = - IGA2_HOR_BLANK_START_FORMULA - (device_timing.hor_blank_start); - viafb_load_reg_num = - iga2_crtc_reg.hor_blank_start.reg_num; - reg = iga2_crtc_reg.hor_blank_start.reg; - break; - case H_BLANK_END_INDEX: - reg_value = - IGA2_HOR_BLANK_END_FORMULA - (device_timing.hor_blank_start, - device_timing.hor_blank_end); - viafb_load_reg_num = - iga2_crtc_reg.hor_blank_end.reg_num; - reg = iga2_crtc_reg.hor_blank_end.reg; - break; - case H_SYNC_START_INDEX: - reg_value = - IGA2_HOR_SYNC_START_FORMULA - (device_timing.hor_sync_start); - if (UNICHROME_CN700 <= - viaparinfo->chip_info->gfx_chip_name) - viafb_load_reg_num = - iga2_crtc_reg.hor_sync_start. - reg_num; - else - viafb_load_reg_num = 3; - reg = iga2_crtc_reg.hor_sync_start.reg; - break; - case H_SYNC_END_INDEX: - reg_value = - IGA2_HOR_SYNC_END_FORMULA - (device_timing.hor_sync_start, - device_timing.hor_sync_end); - viafb_load_reg_num = - iga2_crtc_reg.hor_sync_end.reg_num; - reg = iga2_crtc_reg.hor_sync_end.reg; - break; - case V_TOTAL_INDEX: - reg_value = - IGA2_VER_TOTAL_FORMULA(device_timing. - ver_total); - viafb_load_reg_num = - iga2_crtc_reg.ver_total.reg_num; - reg = iga2_crtc_reg.ver_total.reg; - break; - case V_ADDR_INDEX: - reg_value = - IGA2_VER_ADDR_FORMULA(device_timing. - ver_addr); - viafb_load_reg_num = - iga2_crtc_reg.ver_addr.reg_num; - reg = iga2_crtc_reg.ver_addr.reg; - break; - case V_BLANK_START_INDEX: - reg_value = - IGA2_VER_BLANK_START_FORMULA - (device_timing.ver_blank_start); - viafb_load_reg_num = - iga2_crtc_reg.ver_blank_start.reg_num; - reg = iga2_crtc_reg.ver_blank_start.reg; - break; - case V_BLANK_END_INDEX: - reg_value = - IGA2_VER_BLANK_END_FORMULA - (device_timing.ver_blank_start, - device_timing.ver_blank_end); - viafb_load_reg_num = - iga2_crtc_reg.ver_blank_end.reg_num; - reg = iga2_crtc_reg.ver_blank_end.reg; - break; - case V_SYNC_START_INDEX: - reg_value = - IGA2_VER_SYNC_START_FORMULA - (device_timing.ver_sync_start); - viafb_load_reg_num = - iga2_crtc_reg.ver_sync_start.reg_num; - reg = iga2_crtc_reg.ver_sync_start.reg; - break; - case V_SYNC_END_INDEX: - reg_value = - IGA2_VER_SYNC_END_FORMULA - (device_timing.ver_sync_start, - device_timing.ver_sync_end); - viafb_load_reg_num = - iga2_crtc_reg.ver_sync_end.reg_num; - reg = iga2_crtc_reg.ver_sync_end.reg; - break; - - } - } - viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); - } - - viafb_lock_crt(); + struct display_timing timing; + + timing.hor_addr = var->xres; + timing.hor_sync_start = timing.hor_addr + var->right_margin; + timing.hor_sync_end = timing.hor_sync_start + var->hsync_len; + timing.hor_total = timing.hor_sync_end + var->left_margin; + timing.hor_blank_start = timing.hor_addr; + timing.hor_blank_end = timing.hor_total; + timing.ver_addr = var->yres; + timing.ver_sync_start = timing.ver_addr + var->lower_margin; + timing.ver_sync_end = timing.ver_sync_start + var->vsync_len; + timing.ver_total = timing.ver_sync_end + var->upper_margin; + timing.ver_blank_start = timing.ver_addr; + timing.ver_blank_end = timing.ver_total; + return timing; } -void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, - struct VideoModeTable *video_mode, int bpp_byte, int set_iga) +void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga) { - struct display_timing crt_reg; - int i; - int index = 0; - int h_addr, v_addr; - u32 clock, refresh = viafb_refresh; - - if (viafb_SAMM_ON && set_iga == IGA2) - refresh = viafb_refresh1; - - for (i = 0; i < video_mode->mode_array; i++) { - index = i; - - if (crt_table[i].refresh_rate == refresh) - break; - } + struct display_timing crt_reg = var_to_timing(var); - crt_reg = crt_table[index].crtc; + if (iga == IGA1) + via_set_primary_timing(&crt_reg); + else if (iga == IGA2) + via_set_secondary_timing(&crt_reg); - /* Mode 640x480 has border, but LCD/DFP didn't have border. */ - /* So we would delete border. */ - if ((viafb_LCD_ON | viafb_DVI_ON) - && video_mode->crtc[0].crtc.hor_addr == 640 - && video_mode->crtc[0].crtc.ver_addr == 480 - && refresh == 60) { - /* The border is 8 pixels. */ - crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; - - /* Blanking time should add left and right borders. */ - crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16; - } - - h_addr = crt_reg.hor_addr; - v_addr = crt_reg.ver_addr; - if (set_iga == IGA1) { - viafb_unlock_crt(); - viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); - } - - switch (set_iga) { - case IGA1: - viafb_load_crtc_timing(crt_reg, IGA1); - break; - case IGA2: - viafb_load_crtc_timing(crt_reg, IGA2); - break; - } - - viafb_lock_crt(); - viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); - viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga); - - /* load FIFO */ - if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) - && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) - viafb_load_FIFO_reg(set_iga, h_addr, v_addr); - - clock = crt_reg.hor_total * crt_reg.ver_total - * crt_table[index].refresh_rate; - viafb_set_vclock(clock, set_iga); + viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga); + if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266 + && viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400) + viafb_load_FIFO_reg(iga, var->xres, var->yres); + viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga); } void __devinit viafb_init_chip_info(int chip_type) @@ -2092,23 +1769,9 @@ static u8 get_sync(struct fb_info *info) return polarity; } -int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, - struct VideoModeTable *vmode_tbl1, int video_bpp1) +static void hw_init(void) { - int i, j; - int port; - u32 devices = viaparinfo->shared->iga1_devices - | viaparinfo->shared->iga2_devices; - u8 value, index, mask; - struct crt_mode_table *crt_timing; - struct crt_mode_table *crt_timing1 = NULL; - - device_screen_off(); - crt_timing = vmode_tbl->crtc; - - if (viafb_SAMM_ON == 1) { - crt_timing1 = vmode_tbl1->crtc; - } + int i; inb(VIAStatus); outb(0x00, VIAAR); @@ -2147,9 +1810,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, break; } + /* probably this should go to the scaling code one day */ viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters)); - device_off(); - via_set_state(devices, VIA_STATE_OFF); /* Fill VPIT Parameters */ /* Write Misc Register */ @@ -2175,12 +1837,29 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, inb(VIAStatus); outb(0x20, VIAAR); + load_fix_bit_crtc_reg(); +} + +int viafb_setmode(int video_bpp, int video_bpp1) +{ + int j; + int port; + u32 devices = viaparinfo->shared->iga1_devices + | viaparinfo->shared->iga2_devices; + u8 value, index, mask; + struct fb_var_screeninfo var2; + + device_screen_off(); + device_off(); + via_set_state(devices, VIA_STATE_OFF); + + hw_init(); + /* Update Patch Register */ if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266 - || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400) - && vmode_tbl->crtc[0].crtc.hor_addr == 1024 - && vmode_tbl->crtc[0].crtc.ver_addr == 768) { + || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400) + && viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) { for (j = 0; j < res_patch_table[0].table_length; j++) { index = res_patch_table[0].io_reg_table[j].index; port = res_patch_table[0].io_reg_table[j].port; @@ -2190,7 +1869,6 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, } } - load_fix_bit_crtc_reg(); via_set_primary_pitch(viafbinfo->fix.line_length); via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length : viafbinfo->fix.line_length); @@ -2208,23 +1886,28 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, /* Clear On Screen */ + if (viafb_dual_fb) { + var2 = viafbinfo1->var; + } else if (viafb_SAMM_ON) { + viafb_fill_var_timing_info(&var2, viafb_get_best_mode( + viafb_second_xres, viafb_second_yres, viafb_refresh1)); + var2.bits_per_pixel = viafbinfo->var.bits_per_pixel; + } + /* CRT set mode */ if (viafb_CRT_ON) { - if (viafb_SAMM_ON && - viaparinfo->shared->iga2_devices & VIA_CRT) { - viafb_fill_crtc_timing(crt_timing1, vmode_tbl1, - video_bpp1 / 8, IGA2); - } else { - viafb_fill_crtc_timing(crt_timing, vmode_tbl, - video_bpp / 8, + if (viaparinfo->shared->iga2_devices & VIA_CRT + && viafb_SAMM_ON) + viafb_fill_crtc_timing(&var2, IGA2); + else + viafb_fill_crtc_timing(&viafbinfo->var, (viaparinfo->shared->iga1_devices & VIA_CRT) ? IGA1 : IGA2); - } /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode to 8 alignment (1368),there is several pixels (2 pixels) on right side of screen. */ - if (vmode_tbl->crtc[0].crtc.hor_addr % 8) { + if (viafbinfo->var.xres % 8) { viafb_unlock_crt(); viafb_write_reg(CR02, VIACR, viafb_read_reg(VIACR, CR02) - 1); @@ -2233,31 +1916,20 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, } if (viafb_DVI_ON) { - if (viafb_SAMM_ON && - (viaparinfo->tmds_setting_info->iga_path == IGA2)) { - viafb_dvi_set_mode(viafb_get_mode - (viaparinfo->tmds_setting_info->h_active, - viaparinfo->tmds_setting_info-> - v_active), - video_bpp1, viaparinfo-> - tmds_setting_info->iga_path); - } else { - viafb_dvi_set_mode(viafb_get_mode - (viaparinfo->tmds_setting_info->h_active, - viaparinfo-> - tmds_setting_info->v_active), - video_bpp, viaparinfo-> - tmds_setting_info->iga_path); - } + if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2 + && viafb_SAMM_ON) + viafb_dvi_set_mode(&var2, IGA2); + else + viafb_dvi_set_mode(&viafbinfo->var, + viaparinfo->tmds_setting_info->iga_path); } if (viafb_LCD_ON) { if (viafb_SAMM_ON && (viaparinfo->lvds_setting_info->iga_path == IGA2)) { viaparinfo->lvds_setting_info->bpp = video_bpp1; - viafb_lcd_set_mode(crt_timing1, viaparinfo-> - lvds_setting_info, - &viaparinfo->chip_info->lvds_chip_info); + viafb_lcd_set_mode(viaparinfo->lvds_setting_info, + &viaparinfo->chip_info->lvds_chip_info); } else { /* IGA1 doesn't have LCD scaling, so set it center. */ if (viaparinfo->lvds_setting_info->iga_path == IGA1) { @@ -2265,18 +1937,16 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, LCD_CENTERING; } viaparinfo->lvds_setting_info->bpp = video_bpp; - viafb_lcd_set_mode(crt_timing, viaparinfo-> - lvds_setting_info, - &viaparinfo->chip_info->lvds_chip_info); + viafb_lcd_set_mode(viaparinfo->lvds_setting_info, + &viaparinfo->chip_info->lvds_chip_info); } } if (viafb_LCD2_ON) { if (viafb_SAMM_ON && (viaparinfo->lvds_setting_info2->iga_path == IGA2)) { viaparinfo->lvds_setting_info2->bpp = video_bpp1; - viafb_lcd_set_mode(crt_timing1, viaparinfo-> - lvds_setting_info2, - &viaparinfo->chip_info->lvds_chip_info2); + viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, + &viaparinfo->chip_info->lvds_chip_info2); } else { /* IGA1 doesn't have LCD scaling, so set it center. */ if (viaparinfo->lvds_setting_info2->iga_path == IGA1) { @@ -2284,9 +1954,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, LCD_CENTERING; } viaparinfo->lvds_setting_info2->bpp = video_bpp; - viafb_lcd_set_mode(crt_timing, viaparinfo-> - lvds_setting_info2, - &viaparinfo->chip_info->lvds_chip_info2); + viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, + &viaparinfo->chip_info->lvds_chip_info2); } } @@ -2296,8 +1965,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, /* If set mode normally, save resolution information for hot-plug . */ if (!viafb_hotplug) { - viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr; - viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr; + viafb_hotplug_Xres = viafbinfo->var.xres; + viafb_hotplug_Yres = viafbinfo->var.yres; viafb_hotplug_bpp = video_bpp; viafb_hotplug_refresh = viafb_refresh; @@ -2348,42 +2017,14 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, return 1; } -int viafb_get_pixclock(int hres, int vres, int vmode_refresh) -{ - int i; - struct crt_mode_table *best; - struct VideoModeTable *vmode = viafb_get_mode(hres, vres); - - if (!vmode) - return RES_640X480_60HZ_PIXCLOCK; - - best = &vmode->crtc[0]; - for (i = 1; i < vmode->mode_array; i++) { - if (abs(vmode->crtc[i].refresh_rate - vmode_refresh) - < abs(best->refresh_rate - vmode_refresh)) - best = &vmode->crtc[i]; - } - - return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total) - * 1000 / best->refresh_rate; -} - int viafb_get_refresh(int hres, int vres, u32 long_refresh) { - int i; struct crt_mode_table *best; - struct VideoModeTable *vmode = viafb_get_mode(hres, vres); - if (!vmode) + best = viafb_get_best_mode(hres, vres, long_refresh); + if (!best) return 60; - best = &vmode->crtc[0]; - for (i = 1; i < vmode->mode_array; i++) { - if (abs(vmode->crtc[i].refresh_rate - long_refresh) - < abs(best->refresh_rate - long_refresh)) - best = &vmode->crtc[i]; - } - if (abs(best->refresh_rate - long_refresh) > 3) { if (hres == 1200 && vres == 900) return 49; /* OLPC DCON only supports 50 Hz */ @@ -2485,21 +2126,14 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ } /*According var's xres, yres fill var's other timing information*/ -void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, - struct VideoModeTable *vmode_tbl) +void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, + struct crt_mode_table *mode) { - struct crt_mode_table *crt_timing = NULL; struct display_timing crt_reg; - int i = 0, index = 0; - crt_timing = vmode_tbl->crtc; - for (i = 0; i < vmode_tbl->mode_array; i++) { - index = i; - if (crt_timing[i].refresh_rate == refresh) - break; - } - crt_reg = crt_timing[index].crtc; - var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh); + crt_reg = mode->crtc; + var->pixclock = 1000000000 / (crt_reg.hor_total * crt_reg.ver_total) + * 1000 / mode->refresh_rate; var->left_margin = crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; @@ -2509,8 +2143,8 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr; var->vsync_len = crt_reg.ver_sync_end; var->sync = 0; - if (crt_timing[index].h_sync_polarity == POSITIVE) + if (mode->h_sync_polarity == POSITIVE) var->sync |= FB_SYNC_HOR_HIGH_ACT; - if (crt_timing[index].v_sync_polarity == POSITIVE) + if (mode->v_sync_polarity == POSITIVE) var->sync |= FB_SYNC_VERT_HIGH_ACT; } diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index c7239eb..4db5b6e 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -51,40 +51,6 @@ #define VIA_HSYNC_NEGATIVE 0x01 #define VIA_VSYNC_NEGATIVE 0x02 -/*************************************************** -* Definition IGA1 Design Method of CRTC Registers * -****************************************************/ -#define IGA1_HOR_TOTAL_FORMULA(x) (((x)/8)-5) -#define IGA1_HOR_ADDR_FORMULA(x) (((x)/8)-1) -#define IGA1_HOR_BLANK_START_FORMULA(x) (((x)/8)-1) -#define IGA1_HOR_BLANK_END_FORMULA(x, y) (((x+y)/8)-1) -#define IGA1_HOR_SYNC_START_FORMULA(x) ((x)/8) -#define IGA1_HOR_SYNC_END_FORMULA(x, y) ((x+y)/8) - -#define IGA1_VER_TOTAL_FORMULA(x) ((x)-2) -#define IGA1_VER_ADDR_FORMULA(x) ((x)-1) -#define IGA1_VER_BLANK_START_FORMULA(x) ((x)-1) -#define IGA1_VER_BLANK_END_FORMULA(x, y) ((x+y)-1) -#define IGA1_VER_SYNC_START_FORMULA(x) ((x)-1) -#define IGA1_VER_SYNC_END_FORMULA(x, y) ((x+y)-1) - -/*************************************************** -** Definition IGA2 Design Method of CRTC Registers * -****************************************************/ -#define IGA2_HOR_TOTAL_FORMULA(x) ((x)-1) -#define IGA2_HOR_ADDR_FORMULA(x) ((x)-1) -#define IGA2_HOR_BLANK_START_FORMULA(x) ((x)-1) -#define IGA2_HOR_BLANK_END_FORMULA(x, y) ((x+y)-1) -#define IGA2_HOR_SYNC_START_FORMULA(x) ((x)-1) -#define IGA2_HOR_SYNC_END_FORMULA(x, y) ((x+y)-1) - -#define IGA2_VER_TOTAL_FORMULA(x) ((x)-1) -#define IGA2_VER_ADDR_FORMULA(x) ((x)-1) -#define IGA2_VER_BLANK_START_FORMULA(x) ((x)-1) -#define IGA2_VER_BLANK_END_FORMULA(x, y) ((x+y)-1) -#define IGA2_VER_SYNC_START_FORMULA(x) ((x)-1) -#define IGA2_VER_SYNC_END_FORMULA(x, y) ((x+y)-1) - /**********************************************************/ /* Definition IGA2 Design Method of CRTC Shadow Registers */ /**********************************************************/ @@ -97,33 +63,6 @@ #define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x) #define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y) -/* Define Register Number for IGA1 CRTC Timing */ - -/* location: {CR00,0,7},{CR36,3,3} */ -#define IGA1_HOR_TOTAL_REG_NUM 2 -/* location: {CR01,0,7} */ -#define IGA1_HOR_ADDR_REG_NUM 1 -/* location: {CR02,0,7} */ -#define IGA1_HOR_BLANK_START_REG_NUM 1 -/* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */ -#define IGA1_HOR_BLANK_END_REG_NUM 3 -/* location: {CR04,0,7},{CR33,4,4} */ -#define IGA1_HOR_SYNC_START_REG_NUM 2 -/* location: {CR05,0,4} */ -#define IGA1_HOR_SYNC_END_REG_NUM 1 -/* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */ -#define IGA1_VER_TOTAL_REG_NUM 4 -/* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */ -#define IGA1_VER_ADDR_REG_NUM 4 -/* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */ -#define IGA1_VER_BLANK_START_REG_NUM 4 -/* location: {CR16,0,7} */ -#define IGA1_VER_BLANK_END_REG_NUM 1 -/* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */ -#define IGA1_VER_SYNC_START_REG_NUM 4 -/* location: {CR11,0,3} */ -#define IGA1_VER_SYNC_END_REG_NUM 1 - /* Define Register Number for IGA2 Shadow CRTC Timing */ /* location: {CR6D,0,7},{CR71,3,3} */ @@ -143,37 +82,6 @@ /* location: {CR76,0,3} */ #define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1 -/* Define Register Number for IGA2 CRTC Timing */ - -/* location: {CR50,0,7},{CR55,0,3} */ -#define IGA2_HOR_TOTAL_REG_NUM 2 -/* location: {CR51,0,7},{CR55,4,6} */ -#define IGA2_HOR_ADDR_REG_NUM 2 -/* location: {CR52,0,7},{CR54,0,2} */ -#define IGA2_HOR_BLANK_START_REG_NUM 2 -/* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6] -is reserved, so it may have problem to set 1600x1200 on IGA2. */ -/* Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */ -#define IGA2_HOR_BLANK_END_REG_NUM 3 -/* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */ -/* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */ -#define IGA2_HOR_SYNC_START_REG_NUM 4 - -/* location: {CR57,0,7},{CR5C,6,6} */ -#define IGA2_HOR_SYNC_END_REG_NUM 2 -/* location: {CR58,0,7},{CR5D,0,2} */ -#define IGA2_VER_TOTAL_REG_NUM 2 -/* location: {CR59,0,7},{CR5D,3,5} */ -#define IGA2_VER_ADDR_REG_NUM 2 -/* location: {CR5A,0,7},{CR5C,0,2} */ -#define IGA2_VER_BLANK_START_REG_NUM 2 -/* location: {CR5E,0,7},{CR5C,3,5} */ -#define IGA2_VER_BLANK_END_REG_NUM 2 -/* location: {CR5E,0,7},{CR5F,5,7} */ -#define IGA2_VER_SYNC_START_REG_NUM 2 -/* location: {CR5F,0,4} */ -#define IGA2_VER_SYNC_END_REG_NUM 1 - /* Define Fetch Count Register*/ /* location: {SR1C,0,7},{SR1D,0,1} */ @@ -446,87 +354,12 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */ /* location: {CR78,0,7},{CR79,6,7} */ #define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2 -/************************************************ - ***** Define IGA1 Display Timing ***** - ************************************************/ struct io_register { u8 io_addr; u8 start_bit; u8 end_bit; }; -/* IGA1 Horizontal Total */ -struct iga1_hor_total { - int reg_num; - struct io_register reg[IGA1_HOR_TOTAL_REG_NUM]; -}; - -/* IGA1 Horizontal Addressable Video */ -struct iga1_hor_addr { - int reg_num; - struct io_register reg[IGA1_HOR_ADDR_REG_NUM]; -}; - -/* IGA1 Horizontal Blank Start */ -struct iga1_hor_blank_start { - int reg_num; - struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM]; -}; - -/* IGA1 Horizontal Blank End */ -struct iga1_hor_blank_end { - int reg_num; - struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM]; -}; - -/* IGA1 Horizontal Sync Start */ -struct iga1_hor_sync_start { - int reg_num; - struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM]; -}; - -/* IGA1 Horizontal Sync End */ -struct iga1_hor_sync_end { - int reg_num; - struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM]; -}; - -/* IGA1 Vertical Total */ -struct iga1_ver_total { - int reg_num; - struct io_register reg[IGA1_VER_TOTAL_REG_NUM]; -}; - -/* IGA1 Vertical Addressable Video */ -struct iga1_ver_addr { - int reg_num; - struct io_register reg[IGA1_VER_ADDR_REG_NUM]; -}; - -/* IGA1 Vertical Blank Start */ -struct iga1_ver_blank_start { - int reg_num; - struct io_register reg[IGA1_VER_BLANK_START_REG_NUM]; -}; - -/* IGA1 Vertical Blank End */ -struct iga1_ver_blank_end { - int reg_num; - struct io_register reg[IGA1_VER_BLANK_END_REG_NUM]; -}; - -/* IGA1 Vertical Sync Start */ -struct iga1_ver_sync_start { - int reg_num; - struct io_register reg[IGA1_VER_SYNC_START_REG_NUM]; -}; - -/* IGA1 Vertical Sync End */ -struct iga1_ver_sync_end { - int reg_num; - struct io_register reg[IGA1_VER_SYNC_END_REG_NUM]; -}; - /***************************************************** ** Define IGA2 Shadow Display Timing **** *****************************************************/ @@ -579,82 +412,6 @@ struct iga2_shadow_ver_sync_end { struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM]; }; -/***************************************************** -** Define IGA2 Display Timing **** -******************************************************/ - -/* IGA2 Horizontal Total */ -struct iga2_hor_total { - int reg_num; - struct io_register reg[IGA2_HOR_TOTAL_REG_NUM]; -}; - -/* IGA2 Horizontal Addressable Video */ -struct iga2_hor_addr { - int reg_num; - struct io_register reg[IGA2_HOR_ADDR_REG_NUM]; -}; - -/* IGA2 Horizontal Blank Start */ -struct iga2_hor_blank_start { - int reg_num; - struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM]; -}; - -/* IGA2 Horizontal Blank End */ -struct iga2_hor_blank_end { - int reg_num; - struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM]; -}; - -/* IGA2 Horizontal Sync Start */ -struct iga2_hor_sync_start { - int reg_num; - struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM]; -}; - -/* IGA2 Horizontal Sync End */ -struct iga2_hor_sync_end { - int reg_num; - struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM]; -}; - -/* IGA2 Vertical Total */ -struct iga2_ver_total { - int reg_num; - struct io_register reg[IGA2_VER_TOTAL_REG_NUM]; -}; - -/* IGA2 Vertical Addressable Video */ -struct iga2_ver_addr { - int reg_num; - struct io_register reg[IGA2_VER_ADDR_REG_NUM]; -}; - -/* IGA2 Vertical Blank Start */ -struct iga2_ver_blank_start { - int reg_num; - struct io_register reg[IGA2_VER_BLANK_START_REG_NUM]; -}; - -/* IGA2 Vertical Blank End */ -struct iga2_ver_blank_end { - int reg_num; - struct io_register reg[IGA2_VER_BLANK_END_REG_NUM]; -}; - -/* IGA2 Vertical Sync Start */ -struct iga2_ver_sync_start { - int reg_num; - struct io_register reg[IGA2_VER_SYNC_START_REG_NUM]; -}; - -/* IGA2 Vertical Sync End */ -struct iga2_ver_sync_end { - int reg_num; - struct io_register reg[IGA2_VER_SYNC_END_REG_NUM]; -}; - /* IGA1 Fetch Count Register */ struct iga1_fetch_count { int reg_num; @@ -817,21 +574,6 @@ struct display_queue_expire_num { iga2_display_queue_expire_num_reg; }; -struct iga1_crtc_timing { - struct iga1_hor_total hor_total; - struct iga1_hor_addr hor_addr; - struct iga1_hor_blank_start hor_blank_start; - struct iga1_hor_blank_end hor_blank_end; - struct iga1_hor_sync_start hor_sync_start; - struct iga1_hor_sync_end hor_sync_end; - struct iga1_ver_total ver_total; - struct iga1_ver_addr ver_addr; - struct iga1_ver_blank_start ver_blank_start; - struct iga1_ver_blank_end ver_blank_end; - struct iga1_ver_sync_start ver_sync_start; - struct iga1_ver_sync_end ver_sync_end; -}; - struct iga2_shadow_crtc_timing { struct iga2_shadow_hor_total hor_total_shadow; struct iga2_shadow_hor_blank_end hor_blank_end_shadow; @@ -843,21 +585,6 @@ struct iga2_shadow_crtc_timing { struct iga2_shadow_ver_sync_end ver_sync_end_shadow; }; -struct iga2_crtc_timing { - struct iga2_hor_total hor_total; - struct iga2_hor_addr hor_addr; - struct iga2_hor_blank_start hor_blank_start; - struct iga2_hor_blank_end hor_blank_end; - struct iga2_hor_sync_start hor_sync_start; - struct iga2_hor_sync_end hor_sync_end; - struct iga2_ver_total ver_total; - struct iga2_ver_addr ver_addr; - struct iga2_ver_blank_start ver_blank_start; - struct iga2_ver_blank_end ver_blank_end; - struct iga2_ver_sync_start ver_sync_start; - struct iga2_ver_sync_end ver_sync_end; -}; - /* device ID */ #define CLE266_FUNCTION3 0x3123 #define KM400_FUNCTION3 0x3205 @@ -910,9 +637,7 @@ extern int viafb_LCD_ON; extern int viafb_DVI_ON; extern int viafb_hotplug; -void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, - struct VideoModeTable *video_mode, int bpp_byte, int set_iga); - +void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga); void viafb_set_vclock(u32 CLK, int set_iga); void viafb_load_reg(int timing_value, int viafb_load_reg_num, struct io_register *reg, @@ -932,13 +657,11 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active); void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ *p_gfx_dpa_setting); -int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, - struct VideoModeTable *vmode_tbl1, int video_bpp1); -void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, - struct VideoModeTable *vmode_tbl); +int viafb_setmode(int video_bpp, int video_bpp1); +void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, + struct crt_mode_table *mode); void __devinit viafb_init_chip_info(int chip_type); void __devinit viafb_init_dac(int set_iga); -int viafb_get_pixclock(int hres, int vres, int vmode_refresh); int viafb_get_refresh(int hres, int vres, u32 float_refresh); void viafb_update_device_setting(int hres, int vres, int bpp, int flag); diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 6e06981..5f3b4e3 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c @@ -548,9 +548,8 @@ static void lcd_patch_skew(struct lvds_setting_information } /* LCD Set Mode */ -void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, - struct lvds_setting_information *plvds_setting_info, - struct lvds_chip_information *plvds_chip_info) +void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, + struct lvds_chip_information *plvds_chip_info) { int set_iga = plvds_setting_info->iga_path; int mode_bpp = plvds_setting_info->bpp; @@ -559,16 +558,15 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, int panel_hres = plvds_setting_info->lcd_panel_hres; int panel_vres = plvds_setting_info->lcd_panel_vres; u32 clock; - struct display_timing mode_crt_reg, panel_crt_reg; - struct crt_mode_table *panel_crt_table = NULL; - struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres, - panel_vres); + struct display_timing mode_crt_reg, panel_crt_reg, timing; + struct crt_mode_table *mode_crt_table, *panel_crt_table; DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); /* Get mode table */ + mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60); mode_crt_reg = mode_crt_table->crtc; /* Get panel table Pointer */ - panel_crt_table = vmode_tbl->crtc; + panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60); panel_crt_reg = panel_crt_table->crtc; DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) @@ -576,31 +574,28 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total * panel_crt_table->refresh_rate; plvds_setting_info->vclk = clock; - if (set_iga == IGA1) { - /* IGA1 doesn't have LCD scaling, so set it as centering. */ - viafb_load_crtc_timing(lcd_centering_timging - (mode_crt_reg, panel_crt_reg), IGA1); + + if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres) + && plvds_setting_info->display_method == LCD_EXPANDSION) { + timing = panel_crt_reg; + load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres); } else { - /* Expansion */ - if (plvds_setting_info->display_method == LCD_EXPANDSION - && (set_hres < panel_hres || set_vres < panel_vres)) { - /* expansion timing IGA2 loaded panel set timing*/ - viafb_load_crtc_timing(panel_crt_reg, IGA2); - DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n"); - load_lcd_scaling(set_hres, set_vres, panel_hres, - panel_vres); - DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n"); - } else { /* Centering */ - /* centering timing IGA2 always loaded panel - and mode releative timing */ - viafb_load_crtc_timing(lcd_centering_timging - (mode_crt_reg, panel_crt_reg), IGA2); - viafb_write_reg_mask(CR79, VIACR, 0x00, + timing = lcd_centering_timging(mode_crt_reg, panel_crt_reg); + if (set_iga == IGA2) + /* disable scaling */ + via_write_reg_mask(VIACR, 0x79, 0x00, BIT0 + BIT1 + BIT2); - /* LCD scaling disabled */ - } } + timing.hor_blank_end += timing.hor_blank_start; + timing.hor_sync_end += timing.hor_sync_start; + timing.ver_blank_end += timing.ver_blank_start; + timing.ver_sync_end += timing.ver_sync_start; + if (set_iga == IGA1) + via_set_primary_timing(&timing); + else if (set_iga == IGA2) + via_set_secondary_timing(&timing); + /* Fetch count for IGA2 only */ viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h index 75f60a6..77ca7b8 100644 --- a/drivers/video/via/lcd.h +++ b/drivers/video/via/lcd.h @@ -76,16 +76,13 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information *plvds_chip_info, struct lvds_setting_information *plvds_setting_info); -void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, - struct lvds_setting_information *plvds_setting_info, - struct lvds_chip_information *plvds_chip_info); +void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, + struct lvds_chip_information *plvds_chip_info); bool __devinit viafb_lvds_trasmitter_identify(void); void viafb_init_lvds_output_interface(struct lvds_chip_information *plvds_chip_info, struct lvds_setting_information *plvds_setting_info); bool viafb_lcd_get_mobile_state(bool *mobile); -void viafb_load_crtc_timing(struct display_timing device_timing, - int set_iga); #endif /* __LCD_H__ */ diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 61b0bd5..69d882c 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h @@ -22,6 +22,8 @@ #ifndef __SHARE_H__ #define __SHARE_H__ +#include "via_modesetting.h" + /* Define Bit Field */ #define BIT0 0x01 #define BIT1 0x02 @@ -634,10 +636,6 @@ #define V_SYNC_SATRT_SHADOW_INDEX 18 #define V_SYNC_END_SHADOW_INDEX 19 -/* Definition Video Mode Pixel Clock (picoseconds) -*/ -#define RES_640X480_60HZ_PIXCLOCK 39722 - /* LCD display method */ #define LCD_EXPANDSION 0x00 @@ -648,23 +646,6 @@ #define LCD_OPENLDI 0x00 #define LCD_SPWG 0x01 -/* Define display timing -*/ -struct display_timing { - u16 hor_total; - u16 hor_addr; - u16 hor_blank_start; - u16 hor_blank_end; - u16 hor_sync_start; - u16 hor_sync_end; - u16 ver_total; - u16 ver_addr; - u16 ver_blank_start; - u16 ver_blank_end; - u16 ver_sync_start; - u16 ver_sync_end; -}; - struct crt_mode_table { int refresh_rate; int h_sync_polarity; diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index eb112b6..dd58b53 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c @@ -35,7 +35,7 @@ static struct via_port_cfg adap_configs[] = { * The OLPC XO-1.5 puts the camera power and reset lines onto * GPIO 2C. */ -static const struct via_port_cfg olpc_adap_configs[] = { +static struct via_port_cfg olpc_adap_configs[] = { [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 }, [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c index 3cddcff..0e431ae 100644 --- a/drivers/video/via/via_modesetting.c +++ b/drivers/video/via/via_modesetting.c @@ -29,6 +29,110 @@ #include "share.h" #include "debug.h" + +void via_set_primary_timing(const struct display_timing *timing) +{ + struct display_timing raw; + + raw.hor_total = timing->hor_total / 8 - 5; + raw.hor_addr = timing->hor_addr / 8 - 1; + raw.hor_blank_start = timing->hor_blank_start / 8 - 1; + raw.hor_blank_end = timing->hor_blank_end / 8 - 1; + raw.hor_sync_start = timing->hor_sync_start / 8; + raw.hor_sync_end = timing->hor_sync_end / 8; + raw.ver_total = timing->ver_total - 2; + raw.ver_addr = timing->ver_addr - 1; + raw.ver_blank_start = timing->ver_blank_start - 1; + raw.ver_blank_end = timing->ver_blank_end - 1; + raw.ver_sync_start = timing->ver_sync_start - 1; + raw.ver_sync_end = timing->ver_sync_end - 1; + + /* unlock timing registers */ + via_write_reg_mask(VIACR, 0x11, 0x00, 0x80); + + via_write_reg(VIACR, 0x00, raw.hor_total & 0xFF); + via_write_reg(VIACR, 0x01, raw.hor_addr & 0xFF); + via_write_reg(VIACR, 0x02, raw.hor_blank_start & 0xFF); + via_write_reg_mask(VIACR, 0x03, raw.hor_blank_end & 0x1F, 0x1F); + via_write_reg(VIACR, 0x04, raw.hor_sync_start & 0xFF); + via_write_reg_mask(VIACR, 0x05, (raw.hor_sync_end & 0x1F) + | (raw.hor_blank_end << (7 - 5) & 0x80), 0x9F); + via_write_reg(VIACR, 0x06, raw.ver_total & 0xFF); + via_write_reg_mask(VIACR, 0x07, (raw.ver_total >> 8 & 0x01) + | (raw.ver_addr >> (8 - 1) & 0x02) + | (raw.ver_sync_start >> (8 - 2) & 0x04) + | (raw.ver_blank_start >> (8 - 3) & 0x08) + | (raw.ver_total >> (9 - 5) & 0x20) + | (raw.ver_addr >> (9 - 6) & 0x40) + | (raw.ver_sync_start >> (9 - 7) & 0x80), 0xEF); + via_write_reg_mask(VIACR, 0x09, raw.ver_blank_start >> (9 - 5) & 0x20, + 0x20); + via_write_reg(VIACR, 0x10, raw.ver_sync_start & 0xFF); + via_write_reg_mask(VIACR, 0x11, raw.ver_sync_end & 0x0F, 0x0F); + via_write_reg(VIACR, 0x12, raw.ver_addr & 0xFF); + via_write_reg(VIACR, 0x15, raw.ver_blank_start & 0xFF); + via_write_reg(VIACR, 0x16, raw.ver_blank_end & 0xFF); + via_write_reg_mask(VIACR, 0x33, (raw.hor_sync_start >> (8 - 4) & 0x10) + | (raw.hor_blank_end >> (6 - 5) & 0x20), 0x30); + via_write_reg_mask(VIACR, 0x35, (raw.ver_total >> 10 & 0x01) + | (raw.ver_sync_start >> (10 - 1) & 0x02) + | (raw.ver_addr >> (10 - 2) & 0x04) + | (raw.ver_blank_start >> (10 - 3) & 0x08), 0x0F); + via_write_reg_mask(VIACR, 0x36, raw.hor_total >> (8 - 3) & 0x08, 0x08); + + /* lock timing registers */ + via_write_reg_mask(VIACR, 0x11, 0x80, 0x80); + + /* reset timing control */ + via_write_reg_mask(VIACR, 0x17, 0x00, 0x80); + via_write_reg_mask(VIACR, 0x17, 0x80, 0x80); +} + +void via_set_secondary_timing(const struct display_timing *timing) +{ + struct display_timing raw; + + raw.hor_total = timing->hor_total - 1; + raw.hor_addr = timing->hor_addr - 1; + raw.hor_blank_start = timing->hor_blank_start - 1; + raw.hor_blank_end = timing->hor_blank_end - 1; + raw.hor_sync_start = timing->hor_sync_start - 1; + raw.hor_sync_end = timing->hor_sync_end - 1; + raw.ver_total = timing->ver_total - 1; + raw.ver_addr = timing->ver_addr - 1; + raw.ver_blank_start = timing->ver_blank_start - 1; + raw.ver_blank_end = timing->ver_blank_end - 1; + raw.ver_sync_start = timing->ver_sync_start - 1; + raw.ver_sync_end = timing->ver_sync_end - 1; + + via_write_reg(VIACR, 0x50, raw.hor_total & 0xFF); + via_write_reg(VIACR, 0x51, raw.hor_addr & 0xFF); + via_write_reg(VIACR, 0x52, raw.hor_blank_start & 0xFF); + via_write_reg(VIACR, 0x53, raw.hor_blank_end & 0xFF); + via_write_reg(VIACR, 0x54, (raw.hor_blank_start >> 8 & 0x07) + | (raw.hor_blank_end >> (8 - 3) & 0x38) + | (raw.hor_sync_start >> (8 - 6) & 0xC0)); + via_write_reg_mask(VIACR, 0x55, (raw.hor_total >> 8 & 0x0F) + | (raw.hor_addr >> (8 - 4) & 0x70), 0x7F); + via_write_reg(VIACR, 0x56, raw.hor_sync_start & 0xFF); + via_write_reg(VIACR, 0x57, raw.hor_sync_end & 0xFF); + via_write_reg(VIACR, 0x58, raw.ver_total & 0xFF); + via_write_reg(VIACR, 0x59, raw.ver_addr & 0xFF); + via_write_reg(VIACR, 0x5A, raw.ver_blank_start & 0xFF); + via_write_reg(VIACR, 0x5B, raw.ver_blank_end & 0xFF); + via_write_reg(VIACR, 0x5C, (raw.ver_blank_start >> 8 & 0x07) + | (raw.ver_blank_end >> (8 - 3) & 0x38) + | (raw.hor_sync_end >> (8 - 6) & 0x40) + | (raw.hor_sync_start >> (10 - 7) & 0x80)); + via_write_reg(VIACR, 0x5D, (raw.ver_total >> 8 & 0x07) + | (raw.ver_addr >> (8 - 3) & 0x38) + | (raw.hor_blank_end >> (11 - 6) & 0x40) + | (raw.hor_sync_start >> (11 - 7) & 0x80)); + via_write_reg(VIACR, 0x5E, raw.ver_sync_start & 0xFF); + via_write_reg(VIACR, 0x5F, (raw.ver_sync_end & 0x1F) + | (raw.ver_sync_start >> (8 - 5) & 0xE0)); +} + void via_set_primary_address(u32 addr) { DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr); diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h index ae35cfd..06e09fe 100644 --- a/drivers/video/via/via_modesetting.h +++ b/drivers/video/via/via_modesetting.h @@ -28,6 +28,29 @@ #include <linux/types.h> + +#define VIA_PITCH_SIZE (1<<3) +#define VIA_PITCH_MAX 0x3FF8 + + +struct display_timing { + u16 hor_total; + u16 hor_addr; + u16 hor_blank_start; + u16 hor_blank_end; + u16 hor_sync_start; + u16 hor_sync_end; + u16 ver_total; + u16 ver_addr; + u16 ver_blank_start; + u16 ver_blank_end; + u16 ver_sync_start; + u16 ver_sync_end; +}; + + +void via_set_primary_timing(const struct display_timing *timing); +void via_set_secondary_timing(const struct display_timing *timing); void via_set_primary_address(u32 addr); void via_set_secondary_address(u32 addr); void via_set_primary_pitch(u32 pitch); diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 53aa443..a1c4a39 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -38,8 +38,6 @@ static char *viafb_mode1; static int viafb_bpp = 32; static int viafb_bpp1 = 32; -static unsigned int viafb_second_xres = 640; -static unsigned int viafb_second_yres = 480; static unsigned int viafb_second_offset; static int viafb_second_size; @@ -151,7 +149,8 @@ static void viafb_update_fix(struct fb_info *info) info->fix.visual = bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7; + info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8, + VIA_PITCH_SIZE); } static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, @@ -200,7 +199,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { int depth, refresh; - struct VideoModeTable *vmode_entry; struct viafb_par *ppar = info->par; u32 line; @@ -210,8 +208,10 @@ static int viafb_check_var(struct fb_var_screeninfo *var, if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) return -EINVAL; - vmode_entry = viafb_get_mode(var->xres, var->yres); - if (!vmode_entry) { + /* the refresh rate is not important here, as we only want to know + * whether the resolution exists + */ + if (!viafb_get_best_mode(var->xres, var->yres, 60)) { DEBUG_MSG(KERN_INFO "viafb: Mode %dx%dx%d not supported!!\n", var->xres, var->yres, var->bits_per_pixel); @@ -238,8 +238,12 @@ static int viafb_check_var(struct fb_var_screeninfo *var, depth = 24; viafb_fill_var_color_info(var, depth); - line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7; - if (line * var->yres_virtual > ppar->memsize) + if (var->xres_virtual < var->xres) + var->xres_virtual = var->xres; + + line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8, + VIA_PITCH_SIZE); + if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize) return -EINVAL; /* Based on var passed in to calculate the refresh, @@ -249,7 +253,8 @@ static int viafb_check_var(struct fb_var_screeninfo *var, get_var_refresh(var)); /* Adjust var according to our driver's own table */ - viafb_fill_var_timing_info(var, refresh, vmode_entry); + viafb_fill_var_timing_info(var, + viafb_get_best_mode(var->xres, var->yres, refresh)); if (var->accel_flags & FB_ACCELF_TEXT && !ppar->shared->vdev->engine_mmio) var->accel_flags = 0; @@ -260,7 +265,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var, static int viafb_set_par(struct fb_info *info) { struct viafb_par *viapar = info->par; - struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; int refresh; DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); @@ -269,10 +273,7 @@ static int viafb_set_par(struct fb_info *info) viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, viafbinfo->var.bits_per_pixel, 0); - vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres); if (viafb_dual_fb) { - vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres, - viafbinfo1->var.yres); viafb_update_device_setting(viafbinfo1->var.xres, viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, 1); @@ -280,8 +281,6 @@ static int viafb_set_par(struct fb_info *info) DEBUG_MSG(KERN_INFO "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", viafb_second_xres, viafb_second_yres, viafb_bpp1); - vmode_entry1 = viafb_get_mode(viafb_second_xres, - viafb_second_yres); viafb_update_device_setting(viafb_second_xres, viafb_second_yres, viafb_bpp1, 1); @@ -289,7 +288,8 @@ static int viafb_set_par(struct fb_info *info) refresh = viafb_get_refresh(info->var.xres, info->var.yres, get_var_refresh(&info->var)); - if (vmode_entry) { + if (viafb_get_best_mode(viafbinfo->var.xres, viafbinfo->var.yres, + refresh)) { if (viafb_dual_fb && viapar->iga_path == IGA2) { viafb_bpp1 = info->var.bits_per_pixel; viafb_refresh1 = refresh; @@ -302,8 +302,7 @@ static int viafb_set_par(struct fb_info *info) info->flags &= ~FBINFO_HWACCEL_DISABLED; else info->flags |= FBINFO_HWACCEL_DISABLED; - viafb_setmode(vmode_entry, info->var.bits_per_pixel, - vmode_entry1, viafb_bpp1); + viafb_setmode(info->var.bits_per_pixel, viafb_bpp1); viafb_pan_display(&info->var, info); } @@ -348,8 +347,9 @@ static int viafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { struct viafb_par *viapar = info->par; - u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset) - * (var->bits_per_pixel / 8) + viapar->vram_addr; + u32 vram_addr = viapar->vram_addr + + var->yoffset * info->fix.line_length + + var->xoffset * info->var.bits_per_pixel / 8; DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); if (!viafb_dual_fb) { @@ -1729,7 +1729,6 @@ static struct viafb_pm_hooks viafb_fb_pm_hooks = { int __devinit via_fb_pci_probe(struct viafb_dev *vdev) { u32 default_xres, default_yres; - struct VideoModeTable *vmode_entry; struct fb_var_screeninfo default_var; int rc; u32 viafb_par_length; @@ -1802,7 +1801,6 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) } parse_mode(viafb_mode, &default_xres, &default_yres); - vmode_entry = viafb_get_mode(default_xres, default_yres); if (viafb_SAMM_ON == 1) parse_mode(viafb_mode1, &viafb_second_xres, &viafb_second_yres); @@ -1812,9 +1810,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) default_var.xres_virtual = default_xres; default_var.yres_virtual = default_yres; default_var.bits_per_pixel = viafb_bpp; - viafb_fill_var_timing_info(&default_var, viafb_get_refresh( - default_var.xres, default_var.yres, viafb_refresh), - viafb_get_mode(default_var.xres, default_var.yres)); + viafb_fill_var_timing_info(&default_var, viafb_get_best_mode( + default_var.xres, default_var.yres, viafb_refresh)); viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); viafbinfo->var = default_var; @@ -1853,9 +1850,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) default_var.xres_virtual = viafb_second_xres; default_var.yres_virtual = viafb_second_yres; default_var.bits_per_pixel = viafb_bpp1; - viafb_fill_var_timing_info(&default_var, viafb_get_refresh( - default_var.xres, default_var.yres, viafb_refresh1), - viafb_get_mode(default_var.xres, default_var.yres)); + viafb_fill_var_timing_info(&default_var, viafb_get_best_mode( + default_var.xres, default_var.yres, viafb_refresh1)); viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); viafb_check_var(&default_var, viafbinfo1); @@ -2028,9 +2024,9 @@ int __init viafb_init(void) return r; #endif if (parse_mode(viafb_mode, &dummy_x, &dummy_y) - || !viafb_get_mode(dummy_x, dummy_y) + || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh) || parse_mode(viafb_mode1, &dummy_x, &dummy_y) - || !viafb_get_mode(dummy_x, dummy_y) + || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1) || viafb_bpp < 0 || viafb_bpp > 32 || viafb_bpp1 < 0 || viafb_bpp1 > 32 || parse_active_dev()) diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index 58df74e..0911cac 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c @@ -281,7 +281,7 @@ static struct crt_mode_table CRTM640x480[] = { /*r_rate,hsp,vsp */ /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ {REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP, - {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} }, + {800, 640, 640, 160, 656, 96, 525, 480, 480, 45, 490, 2} }, {REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP, {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} }, {REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP, @@ -863,26 +863,56 @@ int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs); int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); -struct VideoModeTable *viafb_get_mode(int hres, int vres) +static struct VideoModeTable *get_modes(struct VideoModeTable *vmt, int n, + int hres, int vres) { - u32 i; - for (i = 0; i < ARRAY_SIZE(viafb_modes); i++) - if (viafb_modes[i].mode_array && - viafb_modes[i].crtc[0].crtc.hor_addr == hres && - viafb_modes[i].crtc[0].crtc.ver_addr == vres) + int i; + + for (i = 0; i < n; i++) + if (vmt[i].mode_array && + vmt[i].crtc[0].crtc.hor_addr == hres && + vmt[i].crtc[0].crtc.ver_addr == vres) return &viafb_modes[i]; return NULL; } -struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) +static struct crt_mode_table *get_best_mode(struct VideoModeTable *vmt, + int refresh) { - u32 i; - for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++) - if (viafb_rb_modes[i].mode_array && - viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres && - viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres) - return &viafb_rb_modes[i]; + struct crt_mode_table *best; + int i; - return NULL; + if (!vmt) + return NULL; + + best = &vmt->crtc[0]; + for (i = 1; i < vmt->mode_array; i++) { + if (abs(vmt->crtc[i].refresh_rate - refresh) + < abs(best->refresh_rate - refresh)) + best = &vmt->crtc[i]; + } + + return best; +} + +static struct VideoModeTable *viafb_get_mode(int hres, int vres) +{ + return get_modes(viafb_modes, ARRAY_SIZE(viafb_modes), hres, vres); +} + +struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh) +{ + return get_best_mode(viafb_get_mode(hres, vres), refresh); +} + +static struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) +{ + return get_modes(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes), hres, + vres); +} + +struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh) +{ + return get_best_mode(viafb_get_rb_mode(hres, vres), refresh); } diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h index 3751289..5917a2b 100644 --- a/drivers/video/via/viamode.h +++ b/drivers/video/via/viamode.h @@ -60,7 +60,7 @@ extern struct io_reg PM1024x768[]; extern struct patch_table res_patch_table[]; extern struct VPITTable VPIT; -struct VideoModeTable *viafb_get_mode(int hres, int vres); -struct VideoModeTable *viafb_get_rb_mode(int hres, int vres); +struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh); +struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh); #endif /* __VIAMODE_H__ */ |