diff options
Diffstat (limited to 'drivers/video/via/hw.c')
-rw-r--r-- | drivers/video/via/hw.c | 134 |
1 files changed, 59 insertions, 75 deletions
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index d5aaca9cfa7..898590db5e1 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -1467,28 +1467,32 @@ void viafb_set_vclock(u32 clk, int set_iga) via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ } -static struct display_timing var_to_timing(const struct fb_var_screeninfo *var) +struct display_timing var_to_timing(const struct fb_var_screeninfo *var, + u16 cxres, u16 cyres) { struct display_timing timing; + u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2; - timing.hor_addr = var->xres; - timing.hor_sync_start = timing.hor_addr + var->right_margin; + timing.hor_addr = cxres; + timing.hor_sync_start = timing.hor_addr + var->right_margin + dx; 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.hor_total = timing.hor_sync_end + var->left_margin + dx; + timing.hor_blank_start = timing.hor_addr + dx; + timing.hor_blank_end = timing.hor_total - dx; + timing.ver_addr = cyres; + timing.ver_sync_start = timing.ver_addr + var->lower_margin + dy; 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; + timing.ver_total = timing.ver_sync_end + var->upper_margin + dy; + timing.ver_blank_start = timing.ver_addr + dy; + timing.ver_blank_end = timing.ver_total - dy; return timing; } -void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga) +void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, + u16 cxres, u16 cyres, int iga) { - struct display_timing crt_reg = var_to_timing(var); + struct display_timing crt_reg = var_to_timing(var, + cxres ? cxres : var->xres, cyres ? cyres : var->yres); if (iga == IGA1) via_set_primary_timing(&crt_reg); @@ -1526,13 +1530,6 @@ void viafb_update_device_setting(int hres, int vres, int bpp, int flag) if (flag == 0) { viaparinfo->tmds_setting_info->h_active = hres; viaparinfo->tmds_setting_info->v_active = vres; - - viaparinfo->lvds_setting_info->h_active = hres; - viaparinfo->lvds_setting_info->v_active = vres; - viaparinfo->lvds_setting_info->bpp = bpp; - viaparinfo->lvds_setting_info2->h_active = hres; - viaparinfo->lvds_setting_info2->v_active = vres; - viaparinfo->lvds_setting_info2->bpp = bpp; } else { if (viaparinfo->tmds_setting_info->iga_path == IGA2) { @@ -1540,16 +1537,6 @@ void viafb_update_device_setting(int hres, int vres, int bpp, int flag) viaparinfo->tmds_setting_info->v_active = vres; } - if (viaparinfo->lvds_setting_info->iga_path == IGA2) { - viaparinfo->lvds_setting_info->h_active = hres; - viaparinfo->lvds_setting_info->v_active = vres; - viaparinfo->lvds_setting_info->bpp = bpp; - } - if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) { - viaparinfo->lvds_setting_info2->h_active = hres; - viaparinfo->lvds_setting_info2->v_active = vres; - viaparinfo->lvds_setting_info2->bpp = bpp; - } } } @@ -1758,13 +1745,13 @@ static void set_display_channel(void) } } -static u8 get_sync(struct fb_info *info) +static u8 get_sync(struct fb_var_screeninfo *var) { u8 polarity = 0; - if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) + if (!(var->sync & FB_SYNC_HOR_HIGH_ACT)) polarity |= VIA_HSYNC_NEGATIVE; - if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) + if (!(var->sync & FB_SYNC_VERT_HIGH_ACT)) polarity |= VIA_VSYNC_NEGATIVE; return polarity; } @@ -1810,7 +1797,11 @@ static void hw_init(void) break; } + /* magic required on VX900 for correct modesetting on IGA1 */ + via_write_reg_mask(VIACR, 0x45, 0x00, 0x01); + /* probably this should go to the scaling code one day */ + via_write_reg_mask(VIACR, 0xFD, 0, 0x80); /* VX900 hw scale on IGA2 */ viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters)); /* Fill VPIT Parameters */ @@ -1840,9 +1831,9 @@ static void hw_init(void) load_fix_bit_crtc_reg(); } -int viafb_setmode(int video_bpp, int video_bpp1) +int viafb_setmode(void) { - int j; + int j, cxres = 0, cyres = 0; int port; u32 devices = viaparinfo->shared->iga1_devices | viaparinfo->shared->iga2_devices; @@ -1891,6 +1882,8 @@ int viafb_setmode(int video_bpp, int video_bpp1) } else if (viafb_SAMM_ON) { viafb_fill_var_timing_info(&var2, viafb_get_best_mode( viafb_second_xres, viafb_second_yres, viafb_refresh1)); + cxres = viafbinfo->var.xres; + cyres = viafbinfo->var.yres; var2.bits_per_pixel = viafbinfo->var.bits_per_pixel; } @@ -1898,9 +1891,9 @@ int viafb_setmode(int video_bpp, int video_bpp1) if (viafb_CRT_ON) { if (viaparinfo->shared->iga2_devices & VIA_CRT && viafb_SAMM_ON) - viafb_fill_crtc_timing(&var2, IGA2); + viafb_fill_crtc_timing(&var2, cxres, cyres, IGA2); else - viafb_fill_crtc_timing(&viafbinfo->var, + viafb_fill_crtc_timing(&viafbinfo->var, 0, 0, (viaparinfo->shared->iga1_devices & VIA_CRT) ? IGA1 : IGA2); @@ -1918,17 +1911,17 @@ int viafb_setmode(int video_bpp, int video_bpp1) if (viafb_DVI_ON) { if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2 && viafb_SAMM_ON) - viafb_dvi_set_mode(&var2, IGA2); + viafb_dvi_set_mode(&var2, cxres, cyres, IGA2); else - viafb_dvi_set_mode(&viafbinfo->var, + viafb_dvi_set_mode(&viafbinfo->var, 0, 0, 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(viaparinfo->lvds_setting_info, + viafb_lcd_set_mode(&var2, cxres, cyres, + viaparinfo->lvds_setting_info, &viaparinfo->chip_info->lvds_chip_info); } else { /* IGA1 doesn't have LCD scaling, so set it center. */ @@ -1936,16 +1929,16 @@ int viafb_setmode(int video_bpp, int video_bpp1) viaparinfo->lvds_setting_info->display_method = LCD_CENTERING; } - viaparinfo->lvds_setting_info->bpp = video_bpp; - viafb_lcd_set_mode(viaparinfo->lvds_setting_info, + viafb_lcd_set_mode(&viafbinfo->var, 0, 0, + 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(viaparinfo->lvds_setting_info2, + viafb_lcd_set_mode(&var2, cxres, cyres, + viaparinfo->lvds_setting_info2, &viaparinfo->chip_info->lvds_chip_info2); } else { /* IGA1 doesn't have LCD scaling, so set it center. */ @@ -1953,8 +1946,8 @@ int viafb_setmode(int video_bpp, int video_bpp1) viaparinfo->lvds_setting_info2->display_method = LCD_CENTERING; } - viaparinfo->lvds_setting_info2->bpp = video_bpp; - viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, + viafb_lcd_set_mode(&viafbinfo->var, 0, 0, + viaparinfo->lvds_setting_info2, &viaparinfo->chip_info->lvds_chip_info2); } } @@ -1967,7 +1960,7 @@ int viafb_setmode(int video_bpp, int video_bpp1) if (!viafb_hotplug) { viafb_hotplug_Xres = viafbinfo->var.xres; viafb_hotplug_Yres = viafbinfo->var.yres; - viafb_hotplug_bpp = video_bpp; + viafb_hotplug_bpp = viafbinfo->var.bits_per_pixel; viafb_hotplug_refresh = viafb_refresh; if (viafb_DVI_ON) @@ -1976,13 +1969,13 @@ int viafb_setmode(int video_bpp, int video_bpp1) viafb_DeviceStatus = CRT_Device; } device_on(); - if (!viafb_dual_fb) - via_set_sync_polarity(devices, get_sync(viafbinfo)); + if (!viafb_SAMM_ON) + via_set_sync_polarity(devices, get_sync(&viafbinfo->var)); else { via_set_sync_polarity(viaparinfo->shared->iga1_devices, - get_sync(viafbinfo)); + get_sync(&viafbinfo->var)); via_set_sync_polarity(viaparinfo->shared->iga2_devices, - get_sync(viafbinfo1)); + get_sync(&var2)); } clock.set_engine_pll_state(VIA_STATE_ON); @@ -2019,20 +2012,20 @@ int viafb_setmode(int video_bpp, int video_bpp1) int viafb_get_refresh(int hres, int vres, u32 long_refresh) { - struct crt_mode_table *best; + const struct fb_videomode *best; best = viafb_get_best_mode(hres, vres, long_refresh); if (!best) return 60; - if (abs(best->refresh_rate - long_refresh) > 3) { + if (abs(best->refresh - long_refresh) > 3) { if (hres == 1200 && vres == 900) return 49; /* OLPC DCON only supports 50 Hz */ else return 60; } - return best->refresh_rate; + return best->refresh; } static void device_off(void) @@ -2125,26 +2118,17 @@ 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, - struct crt_mode_table *mode) + const struct fb_videomode *mode) { - struct display_timing crt_reg; - - 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; - var->hsync_len = crt_reg.hor_sync_end; - var->upper_margin = - crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end); - var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr; - var->vsync_len = crt_reg.ver_sync_end; - var->sync = 0; - if (mode->h_sync_polarity == POSITIVE) - var->sync |= FB_SYNC_HOR_HIGH_ACT; - if (mode->v_sync_polarity == POSITIVE) - var->sync |= FB_SYNC_VERT_HIGH_ACT; + var->pixclock = mode->pixclock; + var->xres = mode->xres; + var->yres = mode->yres; + var->left_margin = mode->left_margin; + var->right_margin = mode->right_margin; + var->hsync_len = mode->hsync_len; + var->upper_margin = mode->upper_margin; + var->lower_margin = mode->lower_margin; + var->vsync_len = mode->vsync_len; + var->sync = mode->sync; } |