Merge branch 'fbdev-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 7 Apr 2011 19:49:17 +0000 (12:49 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 7 Apr 2011 19:49:17 +0000 (12:49 -0700)
* 'fbdev-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6:
  efifb: Add override for 11" Macbook Air 3,1
  efifb: Support overriding fields FW tells us with the DMI data.
  fb: Reduce priority of resource conflict message
  savagefb: Remove obsolete else clause in savage_setup_i2c_bus
  savagefb: Set up I2C based on chip family instead of card id
  savagefb: Replace magic register address with define
  drivers/video/bfin-lq035q1-fb.c: introduce missing kfree
  video: s3c-fb: fix checkpatch errors and warning
  efifb: support AMD Radeon HD 6490
  s3fb: fix Virge/GX2
  fbcon: Remove unused 'display *p' variable from fb_flashcursor()
  fbdev: sh_mobile_lcdcfb: fix module lock acquisition
  fbdev: sh_mobile_lcdcfb: add blanking support
  viafb: initialize margins correct
  viafb: refresh rate bug collection
  sh: mach-ap325rxa: move backlight control code
  sh: mach-ecovec24: support for main lcd backlight

15 files changed:
arch/sh/boards/mach-ap325rxa/setup.c
arch/sh/boards/mach-ecovec24/setup.c
drivers/video/bfin-lq035q1-fb.c
drivers/video/console/fbcon.c
drivers/video/efifb.c
drivers/video/fbmem.c
drivers/video/s3c-fb.c
drivers/video/s3fb.c
drivers/video/savage/savagefb-i2c.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/sh_mobile_lcdcfb.h
drivers/video/via/chip.h
drivers/video/via/hw.c
drivers/video/via/hw.h
drivers/video/via/viafbdev.c

index 636d8318a72a2c76136c99b4d509247d7aa3c959..618bd566cf53bfe70b85b825072e0e7fa2b8aab5 100644 (file)
@@ -156,24 +156,34 @@ static struct platform_device nand_flash_device = {
 #define PORT_DRVCRA    0xA405018A
 #define PORT_DRVCRB    0xA405018C
 
+static int ap320_wvga_set_brightness(void *board_data, int brightness)
+{
+       if (brightness) {
+               gpio_set_value(GPIO_PTS3, 0);
+               __raw_writew(0x100, FPGA_BKLREG);
+       } else {
+               __raw_writew(0, FPGA_BKLREG);
+               gpio_set_value(GPIO_PTS3, 1);
+       }
+       
+       return 0;
+}
+
+static int ap320_wvga_get_brightness(void *board_data)
+{
+       return gpio_get_value(GPIO_PTS3);
+}
+
 static void ap320_wvga_power_on(void *board_data, struct fb_info *info)
 {
        msleep(100);
 
        /* ASD AP-320/325 LCD ON */
        __raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG);
-
-       /* backlight */
-       gpio_set_value(GPIO_PTS3, 0);
-       __raw_writew(0x100, FPGA_BKLREG);
 }
 
 static void ap320_wvga_power_off(void *board_data)
 {
-       /* backlight */
-       __raw_writew(0, FPGA_BKLREG);
-       gpio_set_value(GPIO_PTS3, 1);
-
        /* ASD AP-320/325 LCD OFF */
        __raw_writew(0, FPGA_LCDREG);
 }
@@ -209,6 +219,12 @@ static struct sh_mobile_lcdc_info lcdc_info = {
                .board_cfg = {
                        .display_on = ap320_wvga_power_on,
                        .display_off = ap320_wvga_power_off,
+                       .set_brightness = ap320_wvga_set_brightness,
+                       .get_brightness = ap320_wvga_get_brightness,
+               },
+               .bl_info = {
+                       .name = "sh_mobile_lcdc_bl",
+                       .max_brightness = 1,
                },
        }
 };
index 30ae2e4283f0a85f6d583c299e5209f8353ef125..86a0d565adededfd69fcb491963fe30db5572f69 100644 (file)
@@ -263,6 +263,18 @@ const static struct fb_videomode ecovec_dvi_modes[] = {
        },
 };
 
+static int ecovec24_set_brightness(void *board_data, int brightness)
+{
+       gpio_set_value(GPIO_PTR1, brightness);
+
+       return 0;
+}
+
+static int ecovec24_get_brightness(void *board_data)
+{
+       return gpio_get_value(GPIO_PTR1);
+}
+
 static struct sh_mobile_lcdc_info lcdc_info = {
        .ch[0] = {
                .interface_type = RGB18,
@@ -273,6 +285,12 @@ static struct sh_mobile_lcdc_info lcdc_info = {
                        .height = 91,
                },
                .board_cfg = {
+                       .set_brightness = ecovec24_set_brightness,
+                       .get_brightness = ecovec24_get_brightness,
+               },
+               .bl_info = {
+                       .name = "sh_mobile_lcdc_bl",
+                       .max_brightness = 1,
                },
        }
 };
index c8e1f04941bd5333e467fa358f06691067ad0e3a..23b6c4b62c78cdd642083b7b36245dca2d13d5e6 100644 (file)
@@ -154,8 +154,10 @@ static int __devinit lq035q1_spidev_probe(struct spi_device *spi)
 
        ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
        ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
-       if (ret)
+       if (ret) {
+               kfree(ctl);
                return ret;
+       }
 
        spi_set_drvdata(spi, ctl);
 
index c58393402da2ef466bd8de0edce08dae0ea53aac..8745637e4b7e3811d27935b07dd1a24e6f3700c0 100644 (file)
@@ -370,7 +370,6 @@ static void fb_flashcursor(struct work_struct *work)
 {
        struct fb_info *info = container_of(work, struct fb_info, queue);
        struct fbcon_ops *ops = info->fbcon_par;
-       struct display *p;
        struct vc_data *vc = NULL;
        int c;
        int mode;
@@ -386,7 +385,6 @@ static void fb_flashcursor(struct work_struct *work)
                return;
        }
 
-       p = &fb_display[vc->vc_num];
        c = scr_readw((u16 *) vc->vc_pos);
        mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
                CM_ERASE : CM_DRAW;
index 70477c2e4b619cd6a2ca5562771e15243cd647a3..4eb38db36e4b4a3c9d50e6a169cd71fd088ba8cb 100644 (file)
@@ -53,6 +53,7 @@ enum {
        M_MB_7_1,       /* MacBook, 7th rev. */
        M_MB_SR,        /* MacBook, 2nd gen, (Santa Rosa) */
        M_MBA,          /* MacBook Air */
+       M_MBA_3,        /* Macbook Air, 3rd rev */
        M_MBP,          /* MacBook Pro */
        M_MBP_2,        /* MacBook Pro 2nd gen */
        M_MBP_2_2,      /* MacBook Pro 2,2nd gen */
@@ -64,43 +65,54 @@ enum {
        M_MBP_6_1,      /* MacBook Pro, 6,1th gen */
        M_MBP_6_2,      /* MacBook Pro, 6,2th gen */
        M_MBP_7_1,      /* MacBook Pro, 7,1th gen */
+       M_MBP_8_2,      /* MacBook Pro, 8,2nd gen */
        M_UNKNOWN       /* placeholder */
 };
 
+#define OVERRIDE_NONE  0x0
+#define OVERRIDE_BASE  0x1
+#define OVERRIDE_STRIDE        0x2
+#define OVERRIDE_HEIGHT        0x4
+#define OVERRIDE_WIDTH 0x8
+
 static struct efifb_dmi_info {
        char *optname;
        unsigned long base;
        int stride;
        int width;
        int height;
+       int flags;
 } dmi_list[] __initdata = {
-       [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 },
-       [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */
-       [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 },
-       [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */
-       [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 },
-       [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 },
-       [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 },
-       [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 },
-       [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 },
-       [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 },
-       [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 },
-       [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 },
-       [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 },
-       [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 },
-       [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 },
-       [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 },
-       [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
-       [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 },
-       [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
-       [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
-       [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 },
-       [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 },
-       [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 },
-       [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 },
-       [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 },
-       [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 },
-       [M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
+       [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
+       [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */
+       [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE },
+       [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */
+       [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
+       [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE },
+       [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE },
+       [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE },
+       [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE },
+       [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
+       [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
+       [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
+       [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
+       [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
+       [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
+       /* 11" Macbook Air 3,1 passes the wrong stride */
+       [M_MBA_3] = { "mba3", 0, 2048 * 4, 0, 0, OVERRIDE_STRIDE },
+       [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
+       [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */
+       [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
+       [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
+       [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
+       [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
+       [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
+       [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
+       [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
+       [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE },
+       [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
+       [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
+       [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE }
 };
 
 static int set_system(const struct dmi_system_id *id);
@@ -138,6 +150,7 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir3,1", M_MBA_3),
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
        EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
@@ -151,19 +164,26 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
        EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro8,2", M_MBP_8_2),
        {},
 };
 
+#define choose_value(dmivalue, fwvalue, field, flags) ({       \
+               typeof(fwvalue) _ret_ = fwvalue;                \
+               if ((flags) & (field))                          \
+                       _ret_ = dmivalue;                       \
+               else if ((fwvalue) == 0)                        \
+                       _ret_ = dmivalue;                       \
+               _ret_;                                          \
+       })
+
 static int set_system(const struct dmi_system_id *id)
 {
        struct efifb_dmi_info *info = id->driver_data;
-       if (info->base == 0)
-               return 0;
 
-       printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
-                        "(%dx%d, stride %d)\n", id->ident,
-                        (void *)info->base, info->width, info->height,
-                        info->stride);
+       if (info->base == 0 && info->height == 0 && info->width == 0
+                       && info->stride == 0)
+               return 0;
 
        /* Trust the bootloader over the DMI tables */
        if (screen_info.lfb_base == 0) {
@@ -171,40 +191,47 @@ static int set_system(const struct dmi_system_id *id)
                struct pci_dev *dev = NULL;
                int found_bar = 0;
 #endif
-               screen_info.lfb_base = info->base;
+               if (info->base) {
+                       screen_info.lfb_base = choose_value(info->base,
+                               screen_info.lfb_base, OVERRIDE_BASE,
+                               info->flags);
 
 #if defined(CONFIG_PCI)
-               /* make sure that the address in the table is actually on a
-                * VGA device's PCI BAR */
-
-               for_each_pci_dev(dev) {
-                       int i;
-                       if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
-                               continue;
-                       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-                               resource_size_t start, end;
-
-                               start = pci_resource_start(dev, i);
-                               if (start == 0)
-                                       break;
-                               end = pci_resource_end(dev, i);
-                               if (screen_info.lfb_base >= start &&
-                                               screen_info.lfb_base < end) {
-                                       found_bar = 1;
+                       /* make sure that the address in the table is actually
+                        * on a VGA device's PCI BAR */
+
+                       for_each_pci_dev(dev) {
+                               int i;
+                               if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+                                       continue;
+                               for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+                                       resource_size_t start, end;
+
+                                       start = pci_resource_start(dev, i);
+                                       if (start == 0)
+                                               break;
+                                       end = pci_resource_end(dev, i);
+                                       if (screen_info.lfb_base >= start &&
+                                           screen_info.lfb_base < end) {
+                                               found_bar = 1;
+                                       }
                                }
                        }
-               }
-               if (!found_bar)
-                       screen_info.lfb_base = 0;
+                       if (!found_bar)
+                               screen_info.lfb_base = 0;
 #endif
+               }
        }
        if (screen_info.lfb_base) {
-               if (screen_info.lfb_linelength == 0)
-                       screen_info.lfb_linelength = info->stride;
-               if (screen_info.lfb_width == 0)
-                       screen_info.lfb_width = info->width;
-               if (screen_info.lfb_height == 0)
-                       screen_info.lfb_height = info->height;
+               screen_info.lfb_linelength = choose_value(info->stride,
+                       screen_info.lfb_linelength, OVERRIDE_STRIDE,
+                       info->flags);
+               screen_info.lfb_width = choose_value(info->width,
+                       screen_info.lfb_width, OVERRIDE_WIDTH,
+                       info->flags);
+               screen_info.lfb_height = choose_value(info->height,
+                       screen_info.lfb_height, OVERRIDE_HEIGHT,
+                       info->flags);
                if (screen_info.orig_video_isVGA == 0)
                        screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
        } else {
@@ -214,6 +241,13 @@ static int set_system(const struct dmi_system_id *id)
                screen_info.orig_video_isVGA = 0;
                return 0;
        }
+
+       printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
+                        "(%dx%d, stride %d)\n", id->ident,
+                        (void *)screen_info.lfb_base, screen_info.lfb_width,
+                        screen_info.lfb_height, screen_info.lfb_linelength);
+
+
        return 1;
 }
 
index e2bf95370e40bd63a5743b2ee26f5b6cd302095b..e0c2284924b63b4a390aa8a4eb862fcfddac2609 100644 (file)
@@ -1507,7 +1507,7 @@ void remove_conflicting_framebuffers(struct apertures_struct *a,
                        (primary && gen_aper && gen_aper->count &&
                         gen_aper->ranges[0].base == VGA_FB_PHYS)) {
 
-                       printk(KERN_ERR "fb: conflicting fb hw usage "
+                       printk(KERN_INFO "fb: conflicting fb hw usage "
                               "%s vs %s - removing generic driver\n",
                               name, registered_fb[i]->fix.id);
                        unregister_framebuffer(registered_fb[i]);
index 6817d187d46eac726b7cd44349b51ae480188155..3b6cdcac8f1a6a930dd49399dd4af97a9a835a8b 100644 (file)
@@ -48,7 +48,7 @@
 #undef writel
 #define writel(v, r) do { \
        printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \
-       __raw_writel(v, r); } while(0)
+       __raw_writel(v, r); } while (0)
 #endif /* FB_S3C_DEBUG_REGWRITE */
 
 /* irq_flags bits */
@@ -518,7 +518,7 @@ static int s3c_fb_set_par(struct fb_info *info)
 
                data = VIDTCON2_LINEVAL(var->yres - 1) |
                       VIDTCON2_HOZVAL(var->xres - 1);
-               writel(data, regs +sfb->variant.vidtcon + 8 );
+               writel(data, regs + sfb->variant.vidtcon + 8);
        }
 
        /* write the buffer address */
@@ -1304,6 +1304,7 @@ static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
 
 static int __devinit s3c_fb_probe(struct platform_device *pdev)
 {
+       const struct platform_device_id *platid;
        struct s3c_fb_driverdata *fbdrv;
        struct device *dev = &pdev->dev;
        struct s3c_fb_platdata *pd;
@@ -1312,7 +1313,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
        int win;
        int ret = 0;
 
-       fbdrv = (struct s3c_fb_driverdata *)platform_get_device_id(pdev)->driver_data;
+       platid = platform_get_device_id(pdev);
+       fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
 
        if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
                dev_err(dev, "too many windows, cannot attach\n");
index ddedad9cd06971aa94a598f4a8930185e43982c7..c4482f2e5799130f946cb8daf80c63a295a83ee1 100644 (file)
@@ -71,9 +71,9 @@ static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512};
 
 static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+",
                        "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
-                       "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge",
+                       "S3 Plato/PX", "S3 Aurora64V+", "S3 Virge",
                        "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
-                       "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P",
+                       "S3 Virge/GX2", "S3 Virge/GX2+", "",
                        "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X",
                        "S3 Trio3D"};
 
@@ -90,9 +90,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64",
 #define CHIP_988_VIRGE_VX      0x0A
 #define CHIP_375_VIRGE_DX      0x0B
 #define CHIP_385_VIRGE_GX      0x0C
-#define CHIP_356_VIRGE_GX2     0x0D
-#define CHIP_357_VIRGE_GX2P    0x0E
-#define CHIP_359_VIRGE_GX2P    0x0F
+#define CHIP_357_VIRGE_GX2     0x0D
+#define CHIP_359_VIRGE_GX2P    0x0E
 #define CHIP_360_TRIO3D_1X     0x10
 #define CHIP_362_TRIO3D_2X     0x11
 #define CHIP_368_TRIO3D_2X     0x12
@@ -359,7 +358,9 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
        vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
 
        /* Set S3 clock registers */
-       if (par->chip == CHIP_360_TRIO3D_1X ||
+       if (par->chip == CHIP_357_VIRGE_GX2 ||
+           par->chip == CHIP_359_VIRGE_GX2P ||
+           par->chip == CHIP_360_TRIO3D_1X ||
            par->chip == CHIP_362_TRIO3D_2X ||
            par->chip == CHIP_368_TRIO3D_2X) {
                vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6));   /* n and two bits of r */
@@ -560,7 +561,9 @@ static int s3fb_set_par(struct fb_info *info)
        pr_debug("fb%d: offset register       : %d\n", info->node, offset_value);
        svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value);
 
-       if (par->chip != CHIP_360_TRIO3D_1X &&
+       if (par->chip != CHIP_357_VIRGE_GX2 &&
+           par->chip != CHIP_359_VIRGE_GX2P &&
+           par->chip != CHIP_360_TRIO3D_1X &&
            par->chip != CHIP_362_TRIO3D_2X &&
            par->chip != CHIP_368_TRIO3D_2X) {
                vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */
@@ -604,7 +607,9 @@ static int s3fb_set_par(struct fb_info *info)
                vga_wcrt(par->state.vgabase, 0x66, 0x90);
        }
 
-       if (par->chip == CHIP_360_TRIO3D_1X ||
+       if (par->chip == CHIP_357_VIRGE_GX2 ||
+           par->chip == CHIP_359_VIRGE_GX2P ||
+           par->chip == CHIP_360_TRIO3D_1X ||
            par->chip == CHIP_362_TRIO3D_2X ||
            par->chip == CHIP_368_TRIO3D_2X ||
            par->chip == CHIP_365_TRIO3D    ||
@@ -617,8 +622,7 @@ static int s3fb_set_par(struct fb_info *info)
                vga_wcrt(par->state.vgabase, 0x66, 0x81);
        }
 
-       if (par->chip == CHIP_356_VIRGE_GX2  ||
-           par->chip == CHIP_357_VIRGE_GX2P ||
+       if (par->chip == CHIP_357_VIRGE_GX2  ||
            par->chip == CHIP_359_VIRGE_GX2P ||
            par->chip == CHIP_360_TRIO3D_1X ||
            par->chip == CHIP_362_TRIO3D_2X ||
@@ -674,6 +678,8 @@ static int s3fb_set_par(struct fb_info *info)
                pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
                svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
                if (info->var.pixclock > 20000 ||
+                   par->chip == CHIP_357_VIRGE_GX2 ||
+                   par->chip == CHIP_359_VIRGE_GX2P ||
                    par->chip == CHIP_360_TRIO3D_1X ||
                    par->chip == CHIP_362_TRIO3D_2X ||
                    par->chip == CHIP_368_TRIO3D_2X)
@@ -702,7 +708,9 @@ static int s3fb_set_par(struct fb_info *info)
                } else {
                        svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
                        svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
-                       if (par->chip != CHIP_360_TRIO3D_1X &&
+                       if (par->chip != CHIP_357_VIRGE_GX2 &&
+                           par->chip != CHIP_359_VIRGE_GX2P &&
+                           par->chip != CHIP_360_TRIO3D_1X &&
                            par->chip != CHIP_362_TRIO3D_2X &&
                            par->chip != CHIP_368_TRIO3D_2X)
                                hmul = 2;
@@ -727,7 +735,9 @@ static int s3fb_set_par(struct fb_info *info)
                } else {
                        svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
                        svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
-                       if (par->chip != CHIP_360_TRIO3D_1X &&
+                       if (par->chip != CHIP_357_VIRGE_GX2 &&
+                           par->chip != CHIP_359_VIRGE_GX2P &&
+                           par->chip != CHIP_360_TRIO3D_1X &&
                            par->chip != CHIP_362_TRIO3D_2X &&
                            par->chip != CHIP_368_TRIO3D_2X)
                                hmul = 2;
@@ -1069,6 +1079,16 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
                        info->screen_size = 2 << 20;
                        break;
                }
+       } else if (par->chip == CHIP_357_VIRGE_GX2 ||
+                  par->chip == CHIP_359_VIRGE_GX2P) {
+               switch ((regval & 0xC0) >> 6) {
+               case 1: /* 4MB */
+                       info->screen_size = 4 << 20;
+                       break;
+               case 3: /* 2MB */
+                       info->screen_size = 2 << 20;
+                       break;
+               }
        } else
                info->screen_size = s3_memsizes[regval >> 5] << 10;
        info->fix.smem_len = info->screen_size;
@@ -1268,8 +1288,8 @@ static struct pci_device_id s3_devices[] __devinitdata = {
        {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE},
        {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX},
        {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX},
-       {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2},
-       {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P},
+       {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_357_VIRGE_GX2},
+       {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_359_VIRGE_GX2P},
        {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
        {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X},
        {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D},
index b16e6138fdd46a971ee20c542a65a32a634bf0c4..bb71fea07284e547cbf2632141748b8155691a74 100644 (file)
@@ -159,8 +159,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
                else
                        dev_warn(&chan->par->pcidev->dev,
                                 "Failed to register I2C bus %s.\n", name);
-       } else
-               chan->par = NULL;
+       }
 
        return rc;
 }
@@ -170,9 +169,8 @@ void savagefb_create_i2c_busses(struct fb_info *info)
        struct savagefb_par *par = info->par;
        par->chan.par   = par;
 
-       switch(info->fix.accel) {
-       case FB_ACCEL_PROSAVAGE_DDRK:
-       case FB_ACCEL_PROSAVAGE_PM:
+       switch (par->chip) {
+       case S3_PROSAVAGE:
                par->chan.reg         = CR_SERIAL2;
                par->chan.ioaddr      = par->mmio.vbase;
                par->chan.algo.setsda = prosavage_gpio_setsda;
@@ -180,7 +178,7 @@ void savagefb_create_i2c_busses(struct fb_info *info)
                par->chan.algo.getsda = prosavage_gpio_getsda;
                par->chan.algo.getscl = prosavage_gpio_getscl;
                break;
-       case FB_ACCEL_SAVAGE4:
+       case S3_SAVAGE4:
                par->chan.reg = CR_SERIAL1;
                if (par->pcidev->revision > 1 && !(VGArCR(0xa6, par) & 0x40))
                        par->chan.reg = CR_SERIAL2;
@@ -190,8 +188,8 @@ void savagefb_create_i2c_busses(struct fb_info *info)
                par->chan.algo.getsda = prosavage_gpio_getsda;
                par->chan.algo.getscl = prosavage_gpio_getscl;
                break;
-       case FB_ACCEL_SAVAGE2000:
-               par->chan.reg         = 0xff20;
+       case S3_SAVAGE2000:
+               par->chan.reg         = MM_SERIAL1;
                par->chan.ioaddr      = par->mmio.vbase;
                par->chan.algo.setsda = savage4_gpio_setsda;
                par->chan.algo.setscl = savage4_gpio_setscl;
index 757665bc500f1c009540673ed497f556f1a26024..9bcc61b4ef149a258e6159a9728ffebac2bd5daf 100644 (file)
@@ -643,7 +643,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
                        continue;
 
                board_cfg = &ch->cfg.board_cfg;
-               if (try_module_get(board_cfg->owner) && board_cfg->display_on) {
+               if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
                        board_cfg->display_on(board_cfg->board_data, ch->info);
                        module_put(board_cfg->owner);
                }
@@ -688,7 +688,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
                }
 
                board_cfg = &ch->cfg.board_cfg;
-               if (try_module_get(board_cfg->owner) && board_cfg->display_off) {
+               if (board_cfg->display_off && try_module_get(board_cfg->owner)) {
                        board_cfg->display_off(board_cfg->board_data);
                        module_put(board_cfg->owner);
                }
@@ -1032,6 +1032,49 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
        return 0;
 }
 
+/*
+ * Screen blanking. Behavior is as follows:
+ * FB_BLANK_UNBLANK: screen unblanked, clocks enabled
+ * FB_BLANK_NORMAL: screen blanked, clocks enabled
+ * FB_BLANK_VSYNC,
+ * FB_BLANK_HSYNC,
+ * FB_BLANK_POWEROFF: screen blanked, clocks disabled
+ */
+static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
+{
+       struct sh_mobile_lcdc_chan *ch = info->par;
+       struct sh_mobile_lcdc_priv *p = ch->lcdc;
+
+       /* blank the screen? */
+       if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
+               struct fb_fillrect rect = {
+                       .width = info->var.xres,
+                       .height = info->var.yres,
+               };
+               sh_mobile_lcdc_fillrect(info, &rect);
+       }
+       /* turn clocks on? */
+       if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) {
+               sh_mobile_lcdc_clk_on(p);
+       }
+       /* turn clocks off? */
+       if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) {
+               /* make sure the screen is updated with the black fill before
+                * switching the clocks off. one vsync is not enough since
+                * blanking may occur in the middle of a refresh. deferred io
+                * mode will reenable the clocks and update the screen in time,
+                * so it does not need this. */
+               if (!info->fbdefio) {
+                       sh_mobile_wait_for_vsync(info);
+                       sh_mobile_wait_for_vsync(info);
+               }
+               sh_mobile_lcdc_clk_off(p);
+       }
+
+       ch->blank_status = blank;
+       return 0;
+}
+
 static struct fb_ops sh_mobile_lcdc_ops = {
        .owner          = THIS_MODULE,
        .fb_setcolreg   = sh_mobile_lcdc_setcolreg,
@@ -1040,6 +1083,7 @@ static struct fb_ops sh_mobile_lcdc_ops = {
        .fb_fillrect    = sh_mobile_lcdc_fillrect,
        .fb_copyarea    = sh_mobile_lcdc_copyarea,
        .fb_imageblit   = sh_mobile_lcdc_imageblit,
+       .fb_blank       = sh_mobile_lcdc_blank,
        .fb_pan_display = sh_mobile_fb_pan_display,
        .fb_ioctl       = sh_mobile_ioctl,
        .fb_open        = sh_mobile_open,
@@ -1254,7 +1298,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
 
        switch(action) {
        case FB_EVENT_SUSPEND:
-               if (try_module_get(board_cfg->owner) && board_cfg->display_off) {
+               if (board_cfg->display_off && try_module_get(board_cfg->owner)) {
                        board_cfg->display_off(board_cfg->board_data);
                        module_put(board_cfg->owner);
                }
@@ -1267,7 +1311,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
                mutex_unlock(&ch->open_lock);
 
                /* HDMI must be enabled before LCDC configuration */
-               if (try_module_get(board_cfg->owner) && board_cfg->display_on) {
+               if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
                        board_cfg->display_on(board_cfg->board_data, info);
                        module_put(board_cfg->owner);
                }
index 4635eed63eee0f90e60f505935d8803c4a4c436e..f16cb5645a13fd12b8c95881dd51a5daab6352ad 100644 (file)
@@ -37,6 +37,7 @@ struct sh_mobile_lcdc_chan {
        struct completion vsync_completion;
        struct fb_var_screeninfo display_var;
        int use_count;
+       int blank_status;
        struct mutex open_lock;         /* protects the use counter */
 };
 
index 781f3aa66b42712d989c015617000c020291b82a..29d70244a21fe53c75d314b61221e1b9dba29c0a 100644 (file)
@@ -139,7 +139,6 @@ struct chip_information {
 
 struct crt_setting_information {
        int iga_path;
-       int refresh_rate;
 };
 
 struct tmds_setting_information {
index 5728fd76bc11f691e144e004592dc0e3da6debb8..dc4c778877ceee51fdf128abe304f0fb3ce9a350 100644 (file)
@@ -2002,13 +2002,15 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
        int i;
        int index = 0;
        int h_addr, v_addr;
-       u32 pll_D_N, clock;
+       u32 pll_D_N, 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;
 
-               if (crt_table[i].refresh_rate == viaparinfo->
-                       crt_setting_info->refresh_rate)
+               if (crt_table[i].refresh_rate == refresh)
                        break;
        }
 
@@ -2019,7 +2021,7 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
        if ((viafb_LCD_ON | viafb_DVI_ON)
            && video_mode->crtc[0].crtc.hor_addr == 640
            && video_mode->crtc[0].crtc.ver_addr == 480
-           && viaparinfo->crt_setting_info->refresh_rate == 60) {
+           && refresh == 60) {
                /* The border is 8 pixels. */
                crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
 
@@ -2070,7 +2072,6 @@ void __devinit viafb_init_chip_info(int chip_type)
        init_lvds_chip_info();
 
        viaparinfo->crt_setting_info->iga_path = IGA1;
-       viaparinfo->crt_setting_info->refresh_rate = viafb_refresh;
 
        /*Set IGA path for each device */
        viafb_set_iga_path();
@@ -2083,13 +2084,9 @@ void __devinit viafb_init_chip_info(int chip_type)
                viaparinfo->lvds_setting_info->lcd_mode;
 }
 
-void viafb_update_device_setting(int hres, int vres,
-       int bpp, int vmode_refresh, int flag)
+void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
 {
        if (flag == 0) {
-               viaparinfo->crt_setting_info->refresh_rate =
-                       vmode_refresh;
-
                viaparinfo->tmds_setting_info->h_active = hres;
                viaparinfo->tmds_setting_info->v_active = vres;
 
index 7295263299f793c3d89c8194098bed7dd6a2f74a..8858593405aab122049c5d4a1365741287e7b98b 100644 (file)
@@ -949,8 +949,7 @@ void __devinit viafb_init_chip_info(int chip_type);
 void __devinit viafb_init_dac(int set_iga);
 int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
 int viafb_get_refresh(int hres, int vres, u32 float_refresh);
-void viafb_update_device_setting(int hres, int vres, int bpp,
-                          int vmode_refresh, int flag);
+void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
 
 void viafb_set_iga_path(void);
 void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
index b64818953aa7017f82ac559d1290eaabf74cb72f..a542bed086e24900af1ee2f85ab670a2015ef4ff 100644 (file)
@@ -182,13 +182,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 +242,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 +258,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 +272,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 +281,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;
@@ -1795,14 +1806,9 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
        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;
 
@@ -1841,15 +1847,9 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
                default_var.xres_virtual = viafb_second_virtual_xres;
                default_var.yres_virtual = viafb_second_virtual_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);
@@ -2004,15 +2004,17 @@ static int __init viafb_setup(char *options)
  */
 int __init viafb_init(void)
 {
-       u32 dummy;
+       u32 dummy_x, dummy_y;
 #ifndef MODULE
        char *option = NULL;
        if (fb_get_options("viafb", &option))
                return -ENODEV;
        viafb_setup(option);
 #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())