Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] fbdev: geode updates

Geode framebuffer driver updates:

- Local mode list (taken from modedb.c) containing only relevant modes.
This also makes the driver work as a module.

- Make it a PCI driver (from James Simmons <jsimmons@infradead.org>).

- A few other minor cosmetic bits and pieces.

Signed-off-by: David Vrabel <dvrabel@arcom.com>
Signed-off-by: James Simmons <jsimmons@infradead.org>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

David Vrabel and committed by
Linus Torvalds
53eed4ec 4c7ffe0b

+145 -56
+3 -7
drivers/video/geode/Kconfig
··· 3 3 # 4 4 config FB_GEODE 5 5 bool "AMD Geode family framebuffer support (EXPERIMENTAL)" 6 - default n 7 - depends on FB && EXPERIMENTAL && X86 6 + depends on FB && PCI && EXPERIMENTAL && X86 8 7 ---help--- 9 8 Say 'Y' here to allow you to select framebuffer drivers for 10 9 the AMD Geode family of processors. 11 10 12 11 config FB_GEODE_GX1 13 12 tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)" 14 - default n 15 13 depends on FB_GEODE && EXPERIMENTAL 16 14 select FB_CFB_FILLRECT 17 15 select FB_CFB_COPYAREA ··· 19 21 Framebuffer driver for the display controller integrated into the 20 22 AMD Geode GX1 processor. 21 23 22 - This driver is also available as a module ( = code which can be 23 - inserted and removed from the running kernel whenever you want). The 24 - module will be called gx1fb. If you want to compile it as a module, 25 - say M here and read <file:Documentation/modules.txt>. 24 + To compile this driver as a module, choose M here: the module will be 25 + called gx1fb. 26 26 27 27 If unsure, say N.
-1
drivers/video/geode/geodefb.h
··· 29 29 int enable_crt; 30 30 int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */ 31 31 int panel_y; 32 - struct pci_dev *vid_dev; 33 32 void __iomem *dc_regs; 34 33 void __iomem *vid_regs; 35 34 struct geode_dc_ops *dc_ops;
+141 -45
drivers/video/geode/gx1fb_core.c
··· 30 30 static int crt_option = 1; 31 31 static char panel_option[32] = ""; 32 32 33 + /* Modes relevant to the GX1 (taken from modedb.c) */ 34 + static const struct fb_videomode __initdata gx1_modedb[] = { 35 + /* 640x480-60 VESA */ 36 + { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 37 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 38 + /* 640x480-75 VESA */ 39 + { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3, 40 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 41 + /* 640x480-85 VESA */ 42 + { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3, 43 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 44 + /* 800x600-60 VESA */ 45 + { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4, 46 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 47 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 48 + /* 800x600-75 VESA */ 49 + { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3, 50 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 51 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 52 + /* 800x600-85 VESA */ 53 + { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3, 54 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 55 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 56 + /* 1024x768-60 VESA */ 57 + { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6, 58 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 59 + /* 1024x768-75 VESA */ 60 + { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3, 61 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 62 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 63 + /* 1024x768-85 VESA */ 64 + { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3, 65 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 66 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 67 + /* 1280x960-60 VESA */ 68 + { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3, 69 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 70 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 71 + /* 1280x960-85 VESA */ 72 + { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3, 73 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 74 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 75 + /* 1280x1024-60 VESA */ 76 + { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, 77 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 78 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 79 + /* 1280x1024-75 VESA */ 80 + { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3, 81 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 82 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 83 + /* 1280x1024-85 VESA */ 84 + { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3, 85 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 86 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 87 + }; 88 + 33 89 static int gx1_line_delta(int xres, int bpp) 34 90 { 35 91 int line_delta = xres * (bpp >> 3); ··· 102 46 static int gx1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 103 47 { 104 48 struct geodefb_par *par = info->par; 105 - 106 - printk(KERN_DEBUG "%s()\n", __FUNCTION__); 107 49 108 50 /* Maximum resolution is 1280x1024. */ 109 51 if (var->xres > 1280 || var->yres > 1024) ··· 200 146 return par->vid_ops->blank_display(info, blank_mode); 201 147 } 202 148 203 - static int __init gx1fb_map_video_memory(struct fb_info *info) 149 + static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev) 204 150 { 205 151 struct geodefb_par *par = info->par; 206 152 unsigned gx_base; 207 153 int fb_len; 154 + int ret; 208 155 209 156 gx_base = gx1_gx_base(); 210 157 if (!gx_base) 211 158 return -ENODEV; 212 159 213 - par->vid_dev = pci_get_device(PCI_VENDOR_ID_CYRIX, 214 - PCI_DEVICE_ID_CYRIX_5530_VIDEO, NULL); 215 - if (!par->vid_dev) 216 - return -ENODEV; 160 + ret = pci_enable_device(dev); 161 + if (ret < 0) 162 + return ret; 217 163 218 - par->vid_regs = ioremap(pci_resource_start(par->vid_dev, 1), 219 - pci_resource_len(par->vid_dev, 1)); 164 + ret = pci_request_region(dev, 1, "gx1fb (video)"); 165 + if (ret < 0) 166 + return ret; 167 + par->vid_regs = ioremap(pci_resource_start(dev, 1), 168 + pci_resource_len(dev, 1)); 220 169 if (!par->vid_regs) 221 170 return -ENOMEM; 222 171 172 + if (!request_mem_region(gx_base + 0x8300, 0x100, "gx1fb (display controller)")) 173 + return -EBUSY; 223 174 par->dc_regs = ioremap(gx_base + 0x8300, 0x100); 224 175 if (!par->dc_regs) 225 176 return -ENOMEM; 226 177 227 - info->fix.smem_start = gx_base + 0x800000; 178 + ret = pci_request_region(dev, 0, "gx1fb (frame buffer)"); 179 + if (ret < 0 ) 180 + return -EBUSY; 228 181 if ((fb_len = gx1_frame_buffer_size()) < 0) 229 182 return -ENOMEM; 183 + info->fix.smem_start = pci_resource_start(dev, 0); 230 184 info->fix.smem_len = fb_len; 231 185 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); 232 186 if (!info->screen_base) 233 187 return -ENOMEM; 234 188 235 - printk(KERN_INFO "%s: %d Kibyte of video memory at 0x%lx\n", 236 - info->fix.id, info->fix.smem_len / 1024, info->fix.smem_start); 189 + dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n", 190 + info->fix.smem_len / 1024, info->fix.smem_start); 237 191 238 192 return 0; 239 193 } ··· 278 216 .fb_cursor = soft_cursor, 279 217 }; 280 218 281 - static struct fb_info * __init gx1fb_init_fbinfo(void) 219 + static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev) 282 220 { 283 - struct fb_info *info; 284 221 struct geodefb_par *par; 222 + struct fb_info *info; 285 223 286 224 /* Alloc enough space for the pseudo palette. */ 287 - info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, NULL); 225 + info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev); 288 226 if (!info) 289 227 return NULL; 290 228 ··· 317 255 /* CRT and panel options */ 318 256 par->enable_crt = crt_option; 319 257 if (parse_panel_option(info) < 0) 320 - printk(KERN_WARNING "%s: invalid 'panel' option -- disabling flat panel\n", 321 - info->fix.id); 258 + printk(KERN_WARNING "gx1fb: invalid 'panel' option -- disabling flat panel\n"); 322 259 if (!par->panel_x) 323 260 par->enable_crt = 1; /* fall back to CRT if no panel is specified */ 324 261 325 262 return info; 326 263 } 327 264 328 - 329 - static struct fb_info *gx1fb_info; 330 - 331 - static int __init gx1fb_init(void) 265 + static int __init gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) 332 266 { 267 + struct geodefb_par *par; 333 268 struct fb_info *info; 334 - struct geodefb_par *par; 335 269 int ret; 336 270 337 - #ifndef MODULE 338 - if (fb_get_options("gx1fb", NULL)) 339 - return -ENODEV; 340 - #endif 341 - 342 - info = gx1fb_init_fbinfo(); 271 + info = gx1fb_init_fbinfo(&pdev->dev); 343 272 if (!info) 344 273 return -ENOMEM; 345 - gx1fb_info = info; 346 - 347 274 par = info->par; 348 275 349 276 /* GX1 display controller and CS5530 video device */ 350 277 par->dc_ops = &gx1_dc_ops; 351 278 par->vid_ops = &cs5530_vid_ops; 352 279 353 - if ((ret = gx1fb_map_video_memory(info)) < 0) { 354 - printk(KERN_ERR "%s: gx1fb_map_video_memory() failed\n", info->fix.id); 280 + if ((ret = gx1fb_map_video_memory(info, pdev)) < 0) { 281 + dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n"); 355 282 goto err; 356 283 } 357 284 358 - ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16); 285 + ret = fb_find_mode(&info->var, info, mode_option, 286 + gx1_modedb, ARRAY_SIZE(gx1_modedb), NULL, 16); 359 287 if (ret == 0 || ret == 4) { 360 - printk(KERN_ERR "%s: could not find valid video mode\n", info->fix.id); 288 + dev_err(&pdev->dev, "could not find valid video mode\n"); 361 289 ret = -EINVAL; 362 290 goto err; 363 291 } ··· 362 310 ret = -EINVAL; 363 311 goto err; 364 312 } 313 + pci_set_drvdata(pdev, info); 365 314 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); 366 315 return 0; 367 316 368 317 err: 369 - if (info->screen_base) 318 + if (info->screen_base) { 370 319 iounmap(info->screen_base); 371 - if (par->vid_regs) 320 + pci_release_region(pdev, 0); 321 + } 322 + if (par->vid_regs) { 372 323 iounmap(par->vid_regs); 373 - if (par->dc_regs) 324 + pci_release_region(pdev, 1); 325 + } 326 + if (par->dc_regs) { 374 327 iounmap(par->dc_regs); 375 - if (par->vid_dev) 376 - pci_dev_put(par->vid_dev); 328 + release_mem_region(gx1_gx_base() + 0x8300, 0x100); 329 + } 330 + 331 + pci_disable_device(pdev); 332 + 377 333 if (info) 378 334 framebuffer_release(info); 379 335 return ret; 380 336 } 381 337 382 - static void __exit gx1fb_cleanup(void) 338 + static void gx1fb_remove(struct pci_dev *pdev) 383 339 { 384 - struct fb_info *info = gx1fb_info; 385 - struct geodefb_par *par = gx1fb_info->par; 340 + struct fb_info *info = pci_get_drvdata(pdev); 341 + struct geodefb_par *par = info->par; 386 342 387 343 unregister_framebuffer(info); 388 344 389 345 iounmap((void __iomem *)info->screen_base); 390 - iounmap(par->vid_regs); 391 - iounmap(par->dc_regs); 346 + pci_release_region(pdev, 0); 392 347 393 - pci_dev_put(par->vid_dev); 348 + iounmap(par->vid_regs); 349 + pci_release_region(pdev, 1); 350 + 351 + iounmap(par->dc_regs); 352 + release_mem_region(gx1_gx_base() + 0x8300, 0x100); 353 + 354 + pci_disable_device(pdev); 355 + pci_set_drvdata(pdev, NULL); 394 356 395 357 framebuffer_release(info); 358 + } 359 + 360 + static struct pci_device_id gx1fb_id_table[] = { 361 + { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_VIDEO, 362 + PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, 363 + 0xff0000, 0 }, 364 + { 0, } 365 + }; 366 + 367 + MODULE_DEVICE_TABLE(pci, gx1fb_id_table); 368 + 369 + static struct pci_driver gx1fb_driver = { 370 + .name = "gx1fb", 371 + .id_table = gx1fb_id_table, 372 + .probe = gx1fb_probe, 373 + .remove = gx1fb_remove, 374 + }; 375 + 376 + static int __init gx1fb_init(void) 377 + { 378 + #ifndef MODULE 379 + if (fb_get_options("gx1fb", NULL)) 380 + return -ENODEV; 381 + #endif 382 + return pci_register_driver(&gx1fb_driver); 383 + } 384 + 385 + static void __exit gx1fb_cleanup(void) 386 + { 387 + pci_unregister_driver(&gx1fb_driver); 396 388 } 397 389 398 390 module_init(gx1fb_init);
+1 -3
drivers/video/geode/video_cs5530.c
··· 69 69 { 4310, 0x2FB1B802, }, /* 232.0000 */ 70 70 }; 71 71 72 - #define NUM_CS5530_FREQUENCIES sizeof(cs5530_pll_table)/sizeof(struct cs5530_pll_entry) 73 - 74 72 static void cs5530_set_dclk_frequency(struct fb_info *info) 75 73 { 76 74 struct geodefb_par *par = info->par; ··· 80 82 value = cs5530_pll_table[0].pll_value; 81 83 min = cs5530_pll_table[0].pixclock - info->var.pixclock; 82 84 if (min < 0) min = -min; 83 - for (i = 1; i < NUM_CS5530_FREQUENCIES; i++) { 85 + for (i = 1; i < ARRAY_SIZE(cs5530_pll_table); i++) { 84 86 diff = cs5530_pll_table[i].pixclock - info->var.pixclock; 85 87 if (diff < 0L) diff = -diff; 86 88 if (diff < min) {