]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/video/cirrusfb.c
cirrusfb: use modedb and add mode_option parameter
[linux-2.6-omap-h63xx.git] / drivers / video / cirrusfb.c
index e729fb279645dd34f634be1fb0ddaea60396a7bb..4c16b68a9c5acd6cc0321cfbab6dbe5ec88cd262 100644 (file)
@@ -367,110 +367,13 @@ struct cirrusfb_info {
 
        struct cirrusfb_regs currentmode;
        int blank_mode;
+       u32 pseudo_palette[16];
 
-       u32     pseudo_palette[16];
-
-#ifdef CONFIG_ZORRO
-       struct zorro_dev *zdev;
-#endif
-#ifdef CONFIG_PCI
-       struct pci_dev *pdev;
-#endif
        void (*unmap)(struct fb_info *info);
 };
 
-static unsigned cirrusfb_def_mode = 1;
 static int noaccel;
-
-/*
- *    Predefined Video Modes
- */
-
-static const struct {
-       const char *name;
-       struct fb_var_screeninfo var;
-} cirrusfb_predefined[] = {
-       {
-               /* autodetect mode */
-               .name   = "Autodetect",
-       }, {
-               /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
-               .name   = "640x480",
-               .var    = {
-                       .xres           = 640,
-                       .yres           = 480,
-                       .xres_virtual   = 640,
-                       .yres_virtual   = 480,
-                       .bits_per_pixel = 8,
-                       .red            = { .length = 8 },
-                       .green          = { .length = 8 },
-                       .blue           = { .length = 8 },
-                       .width          = -1,
-                       .height         = -1,
-                       .pixclock       = 40000,
-                       .left_margin    = 48,
-                       .right_margin   = 16,
-                       .upper_margin   = 32,
-                       .lower_margin   = 8,
-                       .hsync_len      = 96,
-                       .vsync_len      = 4,
-                       .sync   = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-                       .vmode          = FB_VMODE_NONINTERLACED
-                }
-       }, {
-               /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
-               .name   = "800x600",
-               .var    = {
-                       .xres           = 800,
-                       .yres           = 600,
-                       .xres_virtual   = 800,
-                       .yres_virtual   = 600,
-                       .bits_per_pixel = 8,
-                       .red            = { .length = 8 },
-                       .green          = { .length = 8 },
-                       .blue           = { .length = 8 },
-                       .width          = -1,
-                       .height         = -1,
-                       .pixclock       = 20000,
-                       .left_margin    = 128,
-                       .right_margin   = 16,
-                       .upper_margin   = 24,
-                       .lower_margin   = 2,
-                       .hsync_len      = 96,
-                       .vsync_len      = 6,
-                       .vmode          = FB_VMODE_NONINTERLACED
-                }
-       }, {
-               /*
-                * Modeline from XF86Config:
-                * Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
-                */
-               /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
-               .name   = "1024x768",
-               .var    = {
-                       .xres           = 1024,
-                       .yres           = 768,
-                       .xres_virtual   = 1024,
-                       .yres_virtual   = 768,
-                       .bits_per_pixel = 8,
-                       .red            = { .length = 8 },
-                       .green          = { .length = 8 },
-                       .blue           = { .length = 8 },
-                       .width          = -1,
-                       .height         = -1,
-                       .pixclock       = 12500,
-                       .left_margin    = 144,
-                       .right_margin   = 32,
-                       .upper_margin   = 30,
-                       .lower_margin   = 2,
-                       .hsync_len      = 192,
-                       .vsync_len      = 6,
-                       .vmode          = FB_VMODE_NONINTERLACED
-               }
-       }
-};
-
-#define NUM_TOTAL_MODES    ARRAY_SIZE(cirrusfb_predefined)
+static char *mode_option __devinitdata = "640x480@60";
 
 /****************************************************************************/
 /**** BEGIN PROTOTYPES ******************************************************/
@@ -638,7 +541,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
                break;          /* 8 pixel per byte, only 1/4th of mem usable */
        case 8:
        case 16:
-       case 24:
        case 32:
                break;          /* 1 pixel == 1 byte */
        default:
@@ -713,7 +615,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
                var->blue.length = 5;
                break;
 
-       case 24:
        case 32:
                if (isPReP) {
                        var->red.offset = 8;
@@ -782,7 +683,6 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
                break;
 
        case 16:
-       case 24:
        case 32:
                info->fix.line_length = var->xres_virtual * maxclockidx;
                info->fix.visual = FB_VISUAL_DIRECTCOLOR;
@@ -1360,7 +1260,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
         */
 
        else if (var->bits_per_pixel == 32) {
-               DPRINTK("cirrusfb: preparing for 24/32 bit deep display\n");
+               DPRINTK("cirrusfb: preparing for 32 bit deep display\n");
                switch (cinfo->btype) {
                case BT_SD64:
                        /* Extended Sequencer Mode: 256c col. mode */
@@ -1949,8 +1849,6 @@ static void init_vgachip(struct fb_info *info)
        /* misc... */
        WHDR(cinfo, 0); /* Hidden DAC register: - */
 
-       printk(KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n",
-               info->screen_size);
        DPRINTK("EXIT\n");
        return;
 }
@@ -2188,8 +2086,7 @@ static void get_pci_addrs(const struct pci_dev *pdev,
 
 static void cirrusfb_pci_unmap(struct fb_info *info)
 {
-       struct cirrusfb_info *cinfo = info->par;
-       struct pci_dev *pdev = cinfo->pdev;
+       struct pci_dev *pdev = to_pci_dev(info->device);
 
        iounmap(info->screen_base);
 #if 0 /* if system didn't claim this region, we would... */
@@ -2205,14 +2102,16 @@ static void cirrusfb_pci_unmap(struct fb_info *info)
 static void __devexit cirrusfb_zorro_unmap(struct fb_info *info)
 {
        struct cirrusfb_info *cinfo = info->par;
-       zorro_release_device(cinfo->zdev);
+       struct zorro_dev *zdev = to_zorro_dev(info->device);
+
+       zorro_release_device(zdev);
 
        if (cinfo->btype == BT_PICASSO4) {
                cinfo->regbase -= 0x600000;
                iounmap((void *)cinfo->regbase);
                iounmap(info->screen_base);
        } else {
-               if (zorro_resource_start(cinfo->zdev) > 0x01000000)
+               if (zorro_resource_start(zdev) > 0x01000000)
                        iounmap(info->screen_base);
        }
 }
@@ -2235,7 +2134,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info)
        if (cinfo->btype == BT_GD5480) {
                if (var->bits_per_pixel == 16)
                        info->screen_base += 1 * MB_;
-               if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
+               if (var->bits_per_pixel == 32)
                        info->screen_base += 2 * MB_;
        }
 
@@ -2278,23 +2177,27 @@ static int cirrusfb_register(struct fb_info *info)
        /* sanity checks */
        assert(btype != BT_NONE);
 
+       /* set all the vital stuff */
+       cirrusfb_set_fbinfo(info);
+
        DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
 
-       /* Make pretend we've set the var so our structures are in a "good" */
-       /* state, even though we haven't written the mode to the hw yet...  */
-       info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
+       err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
+       if (!err) {
+               DPRINTK("wrong initial video mode\n");
+               err = -EINVAL;
+               goto err_dealloc_cmap;
+       }
+
        info->var.activate = FB_ACTIVATE_NOW;
 
        err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
        if (err < 0) {
                /* should never happen */
                DPRINTK("choking on default var... umm, no good.\n");
-               goto err_unmap_cirrusfb;
+               goto err_dealloc_cmap;
        }
 
-       /* set all the vital stuff */
-       cirrusfb_set_fbinfo(info);
-
        err = register_framebuffer(info);
        if (err < 0) {
                printk(KERN_ERR "cirrusfb: could not register "
@@ -2307,7 +2210,6 @@ static int cirrusfb_register(struct fb_info *info)
 
 err_dealloc_cmap:
        fb_dealloc_cmap(&info->cmap);
-err_unmap_cirrusfb:
        cinfo->unmap(info);
        framebuffer_release(info);
        return err;
@@ -2353,7 +2255,6 @@ static int cirrusfb_pci_register(struct pci_dev *pdev,
        }
 
        cinfo = info->par;
-       cinfo->pdev = pdev;
        cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
 
        DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
@@ -2489,7 +2390,6 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
        assert(z);
        assert(btype != BT_NONE);
 
-       cinfo->zdev = z;
        board_addr = zorro_resource_start(z);
        board_size = zorro_resource_len(z);
        info->screen_size = size;
@@ -2621,17 +2521,17 @@ static int __init cirrusfb_setup(char *options) {
                return 0;
 
        while ((this_opt = strsep(&options, ",")) != NULL) {
-               if (!*this_opt) continue;
+               if (!*this_opt)
+                       continue;
 
                DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
 
-               for (i = 0; i < NUM_TOTAL_MODES; i++) {
-                       sprintf(s, "mode:%s", cirrusfb_predefined[i].name);
-                       if (strcmp(this_opt, s) == 0)
-                               cirrusfb_def_mode = i;
-               }
                if (!strcmp(this_opt, "noaccel"))
                        noaccel = 1;
+               else if (!strncmp(this_opt, "mode:", 5))
+                       mode_option = this_opt + 5;
+               else
+                       mode_option = this_opt;
        }
        return 0;
 }
@@ -2657,6 +2557,9 @@ static void __exit cirrusfb_exit(void)
 
 module_init(cirrusfb_init);
 
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
+
 #ifdef MODULE
 module_exit(cirrusfb_exit);
 #endif
@@ -3077,38 +2980,36 @@ static void bestclock(long freq, long *best, long *nom,
        f = freq * 10;
 
        for (n = 32; n < 128; n++) {
+               int s = 0;
+
                d = (143181 * n) / f;
                if ((d >= 7) && (d <= 63)) {
-                       if (d > 31)
-                               d = (d / 2) * 2;
-                       h = (14318 * n) / d;
+                       int temp = d;
+
+                       if (temp > 31) {
+                               s = 1;
+                               temp >>= 1;
+                       }
+                       h = ((14318 * n) / temp) >> s;
                        if (abs(h - freq) < abs(*best - freq)) {
                                *best = h;
                                *nom = n;
-                               if (d < 32) {
-                                       *den = d;
-                                       *div = 0;
-                               } else {
-                                       *den = d / 2;
-                                       *div = 1;
-                               }
+                               *den = temp;
+                               *div = s;
                        }
                }
-               d = DIV_ROUND_UP(143181 * n, f);
+               d++;
                if ((d >= 7) && (d <= 63)) {
-                       if (d > 31)
-                               d = (d / 2) * 2;
-                       h = (14318 * n) / d;
+                       if (d > 31) {
+                               s = 1;
+                               d >>= 1;
+                       }
+                       h = ((14318 * n) / d) >> s;
                        if (abs(h - freq) < abs(*best - freq)) {
                                *best = h;
                                *nom = n;
-                               if (d < 32) {
-                                       *den = d;
-                                       *div = 0;
-                               } else {
-                                       *den = d / 2;
-                                       *div = 1;
-                               }
+                               *den = d;
+                               *div = s;
                        }
                }
        }