From d60defb7b2c05b5c4b187171c09b714b0a00efe9 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 21 May 2011 22:46:31 +0000 Subject: viafb: use more compact modesetting functions This patch replaces the old timing setup code with a redesigned one. The new code might be slightly faster as it has no conditinals and does not write the same register multiple times. Also it makes the comparison to the documentation easier. Regressions are unlikely but could happen as a lot of hardware is undocumented. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 296 ++----------------------------------------------- 1 file changed, 8 insertions(+), 288 deletions(-) (limited to 'drivers/video/via/hw.c') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 47b13535ed2..372ce4f071c 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 */ @@ -1531,234 +1470,15 @@ void viafb_set_vclock(u32 clk, int set_iga) void viafb_load_crtc_timing(struct display_timing device_timing, int set_iga) { - 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; + device_timing.hor_blank_end += device_timing.hor_blank_start; + device_timing.hor_sync_end += device_timing.hor_sync_start; + device_timing.ver_blank_end += device_timing.ver_blank_start; + device_timing.ver_sync_end += device_timing.ver_sync_start; - } - } - viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); - } - - viafb_lock_crt(); + if (set_iga == IGA1) + via_set_primary_timing(&device_timing); + else if (set_iga == IGA2) + via_set_secondary_timing(&device_timing); } void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, -- cgit v1.2.3-18-g5258 From f18e3e0ce0dacca497e3f1547095b3f9b111b0f7 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sun, 22 May 2011 23:30:48 +0000 Subject: viafb: kill viafb_load_crtc_timing This patch replaces calls to viafb_load_crtc_timing with the code. This should make it easier to fix the oddity that in the modetable the blank and sync end entries contain the length and we need to add the start values to get those to be written to the hardware. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) (limited to 'drivers/video/via/hw.c') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 372ce4f071c..52d41f011d8 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -1467,20 +1467,6 @@ 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) -{ - device_timing.hor_blank_end += device_timing.hor_blank_start; - device_timing.hor_sync_end += device_timing.hor_sync_start; - device_timing.ver_blank_end += device_timing.ver_blank_start; - device_timing.ver_sync_end += device_timing.ver_sync_start; - - if (set_iga == IGA1) - via_set_primary_timing(&device_timing); - else if (set_iga == IGA2) - via_set_secondary_timing(&device_timing); -} - void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, struct VideoModeTable *video_mode, int bpp_byte, int set_iga) { @@ -1515,6 +1501,10 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16; } + crt_reg.hor_blank_end += crt_reg.hor_blank_start; + crt_reg.hor_sync_end += crt_reg.hor_sync_start; + crt_reg.ver_blank_end += crt_reg.ver_blank_start; + crt_reg.ver_sync_end += crt_reg.ver_sync_start; h_addr = crt_reg.hor_addr; v_addr = crt_reg.ver_addr; if (set_iga == IGA1) { @@ -1522,14 +1512,10 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, 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; - } + if (set_iga == IGA1) + via_set_primary_timing(&crt_reg); + else if (set_iga == IGA2) + via_set_secondary_timing(&crt_reg); viafb_lock_crt(); viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); -- cgit v1.2.3-18-g5258 From c174e3a3cd0594958c9afc6cdb8fbe20780d9c76 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sun, 22 May 2011 23:40:46 +0000 Subject: viafb: remove superfluous register unlocking/locking The locking is done within the viafb_set_*_timing functions so there is no need to do it here. Move a missing hardware reset into the modesetting function. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/video/via/hw.c') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 52d41f011d8..8b4bdf53b95 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -1507,18 +1507,11 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, crt_reg.ver_sync_end += crt_reg.ver_sync_start; 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); - } - if (set_iga == IGA1) via_set_primary_timing(&crt_reg); else if (set_iga == IGA2) via_set_secondary_timing(&crt_reg); - viafb_lock_crt(); - viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga); /* load FIFO */ -- cgit v1.2.3-18-g5258 From 92746c3c82135b13d7fb1bbdebbabb0faedd8433 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Thu, 2 Jun 2011 14:03:53 +0000 Subject: viafb: simplify viafb_fill_crtc_timing As the first argument is just part of the structure passed as the second argument there is no need for it at all. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/video/via/hw.c') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 8b4bdf53b95..2050fb81ef6 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -1467,9 +1467,10 @@ void viafb_set_vclock(u32 clk, int set_iga) via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ } -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(struct VideoModeTable *video_mode, int bpp_byte, + int set_iga) { + struct crt_mode_table *crt_table = video_mode->crtc; struct display_timing crt_reg; int i; int index = 0; @@ -1911,11 +1912,10 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, 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); + viafb_fill_crtc_timing(vmode_tbl1, video_bpp1 / 8, + IGA2); } else { - viafb_fill_crtc_timing(crt_timing, vmode_tbl, - video_bpp / 8, + viafb_fill_crtc_timing(vmode_tbl, video_bpp / 8, (viaparinfo->shared->iga1_devices & VIA_CRT) ? IGA1 : IGA2); } -- cgit v1.2.3-18-g5258 From 0492262281b82e71c6063e35ef73a33fad93cc6d Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Mon, 6 Jun 2011 15:39:20 +0000 Subject: viafb: remove 640x480-60 CRT special case The timing for 640x480-60 was handled different than all others. This patch changes this by changing the blanking start and end. The reason for this is that I can't find any reason for the old behaviour and it was not consistent anyway as the special case for LCD did not always trigger as the LCD code does not use this function and it did trigger regardless of whether the display set is CRT or LCD but only based whether any DVI/LCD device exists. There are no negative effects observed for CRT or DVI devices. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/video/via/hw.c') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 2050fb81ef6..c5e7833a5ae 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -1488,20 +1488,6 @@ void viafb_fill_crtc_timing(struct VideoModeTable *video_mode, int bpp_byte, } crt_reg = crt_table[index].crtc; - - /* 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; - } - crt_reg.hor_blank_end += crt_reg.hor_blank_start; crt_reg.hor_sync_end += crt_reg.hor_sync_start; crt_reg.ver_blank_end += crt_reg.ver_blank_start; -- cgit v1.2.3-18-g5258 From 94715ba97508dd42919a7525e362efb00dde1271 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 6 Aug 2011 23:04:43 +0000 Subject: 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 --- drivers/video/via/hw.c | 45 +++++++++++---------------------------------- 1 file changed, 11 insertions(+), 34 deletions(-) (limited to 'drivers/video/via/hw.c') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index c5e7833a5ae..5e69c203163 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, 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) + best = viafb_get_best_mode(hres, vres, vmode_refresh); + if (!best) 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 */ @@ -2170,21 +2154,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 = viafb_get_pixclock(var->xres, var->yres, + 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; @@ -2194,8 +2171,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; } -- cgit v1.2.3-18-g5258 From 42edcb162d67e8a88c7b873941c19eab689db272 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 6 Aug 2011 23:35:25 +0000 Subject: viafb: eliminate viafb_get_pixclock As there is only one user we can just insert the formula where needed. Avoids one lookup in the modetable and viafb_fill_var_timing_info does no longer depend on the modetable. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers/video/via/hw.c') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 5e69c203163..d7b9a9f32de 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -2033,18 +2033,6 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, return 1; } -int viafb_get_pixclock(int hres, int vres, int vmode_refresh) -{ - struct crt_mode_table *best; - - best = viafb_get_best_mode(hres, vres, vmode_refresh); - if (!best) - return RES_640X480_60HZ_PIXCLOCK; - - 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) { struct crt_mode_table *best; @@ -2160,8 +2148,8 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, struct display_timing crt_reg; crt_reg = mode->crtc; - var->pixclock = viafb_get_pixclock(var->xres, var->yres, - mode->refresh_rate); + 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; -- cgit v1.2.3-18-g5258 From ebb29fb47e198787b8b47a74cb10334cd9647a9d Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sun, 7 Aug 2011 01:51:41 +0000 Subject: 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 --- drivers/video/via/hw.c | 107 ++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 59 deletions(-) (limited to 'drivers/video/via/hw.c') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index d7b9a9f32de..6845c82db3c 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) via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ } -void viafb_fill_crtc_timing(struct VideoModeTable *video_mode, int bpp_byte, - int set_iga) +static struct display_timing var_to_timing(const struct fb_var_screeninfo *var) { - struct crt_mode_table *crt_table = video_mode->crtc; - 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; + 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; +} - if (crt_table[i].refresh_rate == refresh) - break; - } +void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga) +{ + struct display_timing crt_reg = var_to_timing(var); - crt_reg = crt_table[index].crtc; - crt_reg.hor_blank_end += crt_reg.hor_blank_start; - crt_reg.hor_sync_end += crt_reg.hor_sync_start; - crt_reg.ver_blank_end += crt_reg.ver_blank_start; - crt_reg.ver_sync_end += crt_reg.ver_sync_start; - h_addr = crt_reg.hor_addr; - v_addr = crt_reg.ver_addr; - if (set_iga == IGA1) + if (iga == IGA1) via_set_primary_timing(&crt_reg); - else if (set_iga == IGA2) + else if (iga == IGA2) via_set_secondary_timing(&crt_reg); - 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) @@ -1788,6 +1779,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, u8 value, index, mask; struct crt_mode_table *crt_timing; struct crt_mode_table *crt_timing1 = NULL; + struct fb_var_screeninfo var2; device_screen_off(); crt_timing = vmode_tbl->crtc; @@ -1894,17 +1886,24 @@ 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( + vmode_tbl1->crtc->crtc.hor_addr, + vmode_tbl1->crtc->crtc.ver_addr, 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(vmode_tbl1, video_bpp1 / 8, - IGA2); - } else { - viafb_fill_crtc_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) @@ -1918,22 +1917,12 @@ 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) { -- cgit v1.2.3-18-g5258 From 4fbf4bfe6fb5460bfd4a18ca7c7f21ffec941b07 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sun, 7 Aug 2011 11:13:39 +0000 Subject: viafb: seperate hardware initialization This patch splits the hardware initialization out of the modesetting function which will make it easier to make it conditional and not require starting from scratch for every mode change, which is especially annoying in dual framebuffer mode. This required some minor reordering but it should not influence its functionality. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'drivers/video/via/hw.c') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 6845c82db3c..76fad92600f 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -1769,24 +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; - struct fb_var_screeninfo var2; - - 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); @@ -1825,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 */ @@ -1853,6 +1837,31 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, inb(VIAStatus); outb(0x20, VIAAR); + load_fix_bit_crtc_reg(); +} + +int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, + struct VideoModeTable *vmode_tbl1, int video_bpp1) +{ + int 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; + struct fb_var_screeninfo var2; + + device_screen_off(); + crt_timing = vmode_tbl->crtc; + if (viafb_SAMM_ON == 1) + crt_timing1 = vmode_tbl1->crtc; + + device_off(); + via_set_state(devices, VIA_STATE_OFF); + + hw_init(); + /* Update Patch Register */ if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266 @@ -1868,7 +1877,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); -- cgit v1.2.3-18-g5258 From bfe7d5f9396d5f2607454fd9ff89397fa3ba9a32 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sun, 7 Aug 2011 13:08:45 +0000 Subject: viafb: eliminate modetable dependancy of LCD modesetting This patch removes the need for knowing the modetable structure within the LCD modesetting function. The magic 60Hz refresh rate was already there as always the first entry for a resolution was choosen based on the ascending refresh rate ordering in the modetable. For all but one this is at least 60Hz, if only higher frequencies available we choose those like the code before did. The exception is OLPC but that resolution has only one frequency so we get the same behaviour there as well. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers/video/via/hw.c') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 76fad92600f..30668bd1787 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -1937,9 +1937,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, 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) { @@ -1947,18 +1946,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) { @@ -1966,9 +1963,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); } } -- cgit v1.2.3-18-g5258 From 5dd72f12df00cbabc16de770b79b17ced63138be Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sun, 7 Aug 2011 13:34:35 +0000 Subject: viafb: get rid of the remaining modetable structure assumptions This patch removes the remaining places where assumptions about the structure of the modetable were made. Aside from some places where assumptions are made that certain modes are in the modetable the only code dealing with the modetable and not just a single mode is in viamode. This will allow chaniging the modetable and use other sources for videomodes like the subsystem or EDID. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'drivers/video/via/hw.c') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 30668bd1787..d5aaca9cfa7 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -1840,23 +1840,16 @@ static void hw_init(void) load_fix_bit_crtc_reg(); } -int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, - struct VideoModeTable *vmode_tbl1, int video_bpp1) +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 crt_mode_table *crt_timing; - struct crt_mode_table *crt_timing1 = NULL; struct fb_var_screeninfo var2; device_screen_off(); - crt_timing = vmode_tbl->crtc; - if (viafb_SAMM_ON == 1) - crt_timing1 = vmode_tbl1->crtc; - device_off(); via_set_state(devices, VIA_STATE_OFF); @@ -1865,9 +1858,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, /* 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; @@ -1898,8 +1890,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, var2 = viafbinfo1->var; } else if (viafb_SAMM_ON) { viafb_fill_var_timing_info(&var2, viafb_get_best_mode( - vmode_tbl1->crtc->crtc.hor_addr, - vmode_tbl1->crtc->crtc.ver_addr, viafb_refresh1)); + viafb_second_xres, viafb_second_yres, viafb_refresh1)); var2.bits_per_pixel = viafbinfo->var.bits_per_pixel; } @@ -1916,7 +1907,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, /* 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); @@ -1974,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; -- cgit v1.2.3-18-g5258