aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/via/viafbdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/via/viafbdev.c')
-rw-r--r--drivers/video/via/viafbdev.c138
1 files changed, 78 insertions, 60 deletions
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index f555b891cc72..cf43c80d27f6 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/via-core.h>
+#include <asm/olpc.h>
#define _MASTER_FILE
#include "global.h"
@@ -37,6 +38,8 @@ 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;
@@ -182,13 +185,24 @@ static int viafb_release(struct fb_info *info, int user)
return 0;
}
+static inline int get_var_refresh(struct fb_var_screeninfo *var)
+{
+ u32 htotal, vtotal;
+
+ htotal = var->left_margin + var->xres + var->right_margin
+ + var->hsync_len;
+ vtotal = var->upper_margin + var->yres + var->lower_margin
+ + var->vsync_len;
+ return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal);
+}
+
static int viafb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- int htotal, vtotal, depth;
+ int depth, refresh;
struct VideoModeTable *vmode_entry;
struct viafb_par *ppar = info->par;
- u32 long_refresh, line;
+ u32 line;
DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
/* Sanity check */
@@ -231,17 +245,11 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
/* Based on var passed in to calculate the refresh,
* because our driver use some modes special.
*/
- htotal = var->xres + var->left_margin +
- var->right_margin + var->hsync_len;
- vtotal = var->yres + var->upper_margin +
- var->lower_margin + var->vsync_len;
- long_refresh = 1000000000UL / var->pixclock * 1000;
- long_refresh /= (htotal * vtotal);
-
- viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
+ refresh = viafb_get_refresh(var->xres, var->yres,
+ get_var_refresh(var));
/* Adjust var according to our driver's own table */
- viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry);
+ viafb_fill_var_timing_info(var, refresh, vmode_entry);
if (var->accel_flags & FB_ACCELF_TEXT &&
!ppar->shared->vdev->engine_mmio)
var->accel_flags = 0;
@@ -253,12 +261,13 @@ 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");
viafb_update_fix(info);
viapar->depth = fb_get_color_depth(&info->var, &info->fix);
viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
- viafbinfo->var.bits_per_pixel, viafb_refresh, 0);
+ viafbinfo->var.bits_per_pixel, 0);
vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
if (viafb_dual_fb) {
@@ -266,7 +275,7 @@ static int viafb_set_par(struct fb_info *info)
viafbinfo1->var.yres);
viafb_update_device_setting(viafbinfo1->var.xres,
viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
- viafb_refresh1, 1);
+ 1);
} else if (viafb_SAMM_ON == 1) {
DEBUG_MSG(KERN_INFO
"viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
@@ -275,14 +284,19 @@ static int viafb_set_par(struct fb_info *info)
viafb_second_yres);
viafb_update_device_setting(viafb_second_xres,
- viafb_second_yres, viafb_bpp1, viafb_refresh1, 1);
+ viafb_second_yres, viafb_bpp1, 1);
}
+ refresh = viafb_get_refresh(info->var.xres, info->var.yres,
+ get_var_refresh(&info->var));
if (vmode_entry) {
- if (viafb_dual_fb && viapar->iga_path == IGA2)
+ if (viafb_dual_fb && viapar->iga_path == IGA2) {
viafb_bpp1 = info->var.bits_per_pixel;
- else
+ viafb_refresh1 = refresh;
+ } else {
viafb_bpp = info->var.bits_per_pixel;
+ viafb_refresh = refresh;
+ }
if (info->var.accel_flags & FB_ACCELF_TEXT)
info->flags &= ~FBINFO_HWACCEL_DISABLED;
@@ -429,8 +443,8 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
if (viafb_SAMM_ON == 1) {
u.viamode.xres_sec = viafb_second_xres;
u.viamode.yres_sec = viafb_second_yres;
- u.viamode.virtual_xres_sec = viafb_second_virtual_xres;
- u.viamode.virtual_yres_sec = viafb_second_virtual_yres;
+ u.viamode.virtual_xres_sec = viafb_dual_fb ? viafbinfo1->var.xres_virtual : viafbinfo->var.xres_virtual;
+ u.viamode.virtual_yres_sec = viafb_dual_fb ? viafbinfo1->var.yres_virtual : viafbinfo->var.yres_virtual;
u.viamode.refresh_sec = viafb_refresh1;
u.viamode.bpp_sec = viafb_bpp1;
} else {
@@ -919,10 +933,8 @@ static int get_primary_device(void)
/* Rule: device on iga1 path are the primary device. */
if (viafb_SAMM_ON) {
if (viafb_CRT_ON) {
- if (viaparinfo->crt_setting_info->iga_path == IGA1) {
- DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n",
- viaparinfo->
- crt_setting_info->iga_path);
+ if (viaparinfo->shared->iga1_devices & VIA_CRT) {
+ DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n", IGA1);
primary_device = CRT_Device;
}
}
@@ -1000,8 +1012,13 @@ static int __init parse_active_dev(void)
/* Note: The previous of active_dev is primary device,
and the following is secondary device. */
if (!viafb_active_dev) {
- viafb_CRT_ON = STATE_ON;
- viafb_SAMM_ON = STATE_OFF;
+ if (machine_is_olpc()) { /* LCD only */
+ viafb_LCD_ON = STATE_ON;
+ viafb_SAMM_ON = STATE_OFF;
+ } else {
+ viafb_CRT_ON = STATE_ON;
+ viafb_SAMM_ON = STATE_OFF;
+ }
} else if (!strcmp(viafb_active_dev, "CRT+DVI")) {
/* CRT+DVI */
viafb_CRT_ON = STATE_ON;
@@ -1654,8 +1671,13 @@ static int parse_mode(const char *str, u32 *xres, u32 *yres)
char *ptr;
if (!str) {
- *xres = 640;
- *yres = 480;
+ if (machine_is_olpc()) {
+ *xres = 1200;
+ *yres = 900;
+ } else {
+ *xres = 640;
+ *yres = 480;
+ }
return 0;
}
@@ -1735,7 +1757,6 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info;
viaparinfo->lvds_setting_info2 =
&viaparinfo->shared->lvds_setting_info2;
- viaparinfo->crt_setting_info = &viaparinfo->shared->crt_setting_info;
viaparinfo->chip_info = &viaparinfo->shared->chip_info;
if (viafb_dual_fb)
@@ -1782,27 +1803,18 @@ 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) {
+ if (viafb_SAMM_ON == 1)
parse_mode(viafb_mode1, &viafb_second_xres,
&viafb_second_yres);
- viafb_second_virtual_xres = viafb_second_xres;
- viafb_second_virtual_yres = viafb_second_yres;
- }
-
default_var.xres = default_xres;
default_var.yres = default_yres;
default_var.xres_virtual = default_xres;
default_var.yres_virtual = default_yres;
default_var.bits_per_pixel = viafb_bpp;
- default_var.pixclock =
- viafb_get_pixclock(default_xres, default_yres, viafb_refresh);
- default_var.left_margin = (default_xres >> 3) & 0xf8;
- default_var.right_margin = 32;
- default_var.upper_margin = 16;
- default_var.lower_margin = 4;
- default_var.hsync_len = default_var.left_margin;
- default_var.vsync_len = 4;
+ 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_setup_fixinfo(&viafbinfo->fix, viaparinfo);
viafbinfo->var = default_var;
@@ -1838,18 +1850,12 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
default_var.xres = viafb_second_xres;
default_var.yres = viafb_second_yres;
- default_var.xres_virtual = viafb_second_virtual_xres;
- default_var.yres_virtual = viafb_second_virtual_yres;
+ default_var.xres_virtual = viafb_second_xres;
+ default_var.yres_virtual = viafb_second_yres;
default_var.bits_per_pixel = viafb_bpp1;
- default_var.pixclock =
- viafb_get_pixclock(viafb_second_xres, viafb_second_yres,
- viafb_refresh);
- default_var.left_margin = (viafb_second_xres >> 3) & 0xf8;
- default_var.right_margin = 32;
- default_var.upper_margin = 16;
- default_var.lower_margin = 4;
- default_var.hsync_len = default_var.left_margin;
- default_var.vsync_len = 4;
+ 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_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
viafb_check_var(&default_var, viafbinfo1);
@@ -1927,11 +1933,16 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev)
}
#ifndef MODULE
-static int __init viafb_setup(char *options)
+static int __init viafb_setup(void)
{
char *this_opt;
+ char *options;
+
DEBUG_MSG(KERN_INFO "viafb_setup!\n");
+ if (fb_get_options("viafb", &options))
+ return -ENODEV;
+
if (!options || !*options)
return 0;
@@ -2004,22 +2015,29 @@ static int __init viafb_setup(char *options)
*/
int __init viafb_init(void)
{
- u32 dummy;
+ u32 dummy_x, dummy_y;
+ int r;
+
+ if (machine_is_olpc())
+ /* Apply XO-1.5-specific configuration. */
+ viafb_lcd_panel_id = 23;
+
#ifndef MODULE
- char *option = NULL;
- if (fb_get_options("viafb", &option))
- return -ENODEV;
- viafb_setup(option);
+ r = viafb_setup();
+ if (r < 0)
+ return r;
#endif
- if (parse_mode(viafb_mode, &dummy, &dummy)
- || parse_mode(viafb_mode1, &dummy, &dummy)
+ if (parse_mode(viafb_mode, &dummy_x, &dummy_y)
+ || !viafb_get_mode(dummy_x, dummy_y)
+ || parse_mode(viafb_mode1, &dummy_x, &dummy_y)
+ || !viafb_get_mode(dummy_x, dummy_y)
|| viafb_bpp < 0 || viafb_bpp > 32
|| viafb_bpp1 < 0 || viafb_bpp1 > 32
|| parse_active_dev())
return -EINVAL;
printk(KERN_INFO
- "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n",
+ "VIA Graphics Integration Chipset framebuffer %d.%d initializing\n",
VERSION_MAJOR, VERSION_MINOR);
return 0;
}