]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/video/via/viafbdev.c
viafb: use display information in info not in var for panning
[mv-sheeva.git] / drivers / video / via / viafbdev.c
index 4e66349e4366711a3e42c444a400e37fb2b8e1a7..aa87529d7d6ab068aeb6801371cc810f52e78bdc 100644 (file)
@@ -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,17 +38,19 @@ 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;
 
 static int viafb_accel = 1;
 
 /* Added for specifying active devices.*/
-char *viafb_active_dev;
+static char *viafb_active_dev;
 
 /*Added for specify lcd output port*/
-char *viafb_lcd_port = "";
-char *viafb_dvi_port = "";
+static char *viafb_lcd_port = "";
+static char *viafb_dvi_port = "";
 
 static void retrieve_device_setting(struct viafb_ioctl_setting
        *setting_info);
@@ -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;
@@ -334,8 +348,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) {
@@ -429,8 +444,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 +934,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 +1013,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 +1672,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 +1758,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 +1804,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 +1851,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 +1934,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,15 +2016,22 @@ 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())