aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via/hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/via/hw.c')
-rw-r--r--drivers/video/via/hw.c134
1 files changed, 59 insertions, 75 deletions
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index d5aaca9cfa7e..898590db5e14 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;
}