diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/vga16fb.c | 169 |
1 files changed, 110 insertions, 59 deletions
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 690bb6fe8281..226ae8a88482 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/fb.h> | 21 | #include <linux/fb.h> |
22 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/platform_device.h> | ||
24 | 25 | ||
25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
26 | #include <video/vga.h> | 27 | #include <video/vga.h> |
@@ -51,35 +52,33 @@ | |||
51 | * card parameters | 52 | * card parameters |
52 | */ | 53 | */ |
53 | 54 | ||
54 | static struct fb_info vga16fb; | 55 | struct vga16fb_par { |
55 | |||
56 | static struct vga16fb_par { | ||
57 | /* structure holding original VGA register settings when the | 56 | /* structure holding original VGA register settings when the |
58 | screen is blanked */ | 57 | screen is blanked */ |
59 | struct { | 58 | struct { |
60 | unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ | 59 | unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ |
61 | unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ | 60 | unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ |
62 | unsigned char CrtMiscIO; /* Miscellaneous register */ | 61 | unsigned char CrtMiscIO; /* Miscellaneous register */ |
63 | unsigned char HorizontalTotal; /* CRT-Controller:00h */ | 62 | unsigned char HorizontalTotal; /* CRT-Controller:00h */ |
64 | unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ | 63 | unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ |
65 | unsigned char StartHorizRetrace; /* CRT-Controller:04h */ | 64 | unsigned char StartHorizRetrace;/* CRT-Controller:04h */ |
66 | unsigned char EndHorizRetrace; /* CRT-Controller:05h */ | 65 | unsigned char EndHorizRetrace; /* CRT-Controller:05h */ |
67 | unsigned char Overflow; /* CRT-Controller:07h */ | 66 | unsigned char Overflow; /* CRT-Controller:07h */ |
68 | unsigned char StartVertRetrace; /* CRT-Controller:10h */ | 67 | unsigned char StartVertRetrace; /* CRT-Controller:10h */ |
69 | unsigned char EndVertRetrace; /* CRT-Controller:11h */ | 68 | unsigned char EndVertRetrace; /* CRT-Controller:11h */ |
70 | unsigned char ModeControl; /* CRT-Controller:17h */ | 69 | unsigned char ModeControl; /* CRT-Controller:17h */ |
71 | unsigned char ClockingMode; /* Seq-Controller:01h */ | 70 | unsigned char ClockingMode; /* Seq-Controller:01h */ |
72 | } vga_state; | 71 | } vga_state; |
73 | struct vgastate state; | 72 | struct vgastate state; |
74 | atomic_t ref_count; | 73 | atomic_t ref_count; |
75 | int palette_blanked, vesa_blanked, mode, isVGA; | 74 | int palette_blanked, vesa_blanked, mode, isVGA; |
76 | u8 misc, pel_msk, vss, clkdiv; | 75 | u8 misc, pel_msk, vss, clkdiv; |
77 | u8 crtc[VGA_CRT_C]; | 76 | u8 crtc[VGA_CRT_C]; |
78 | } vga16_par; | 77 | }; |
79 | 78 | ||
80 | /* --------------------------------------------------------------------- */ | 79 | /* --------------------------------------------------------------------- */ |
81 | 80 | ||
82 | static struct fb_var_screeninfo vga16fb_defined = { | 81 | static struct fb_var_screeninfo vga16fb_defined __initdata = { |
83 | .xres = 640, | 82 | .xres = 640, |
84 | .yres = 480, | 83 | .yres = 480, |
85 | .xres_virtual = 640, | 84 | .xres_virtual = 640, |
@@ -205,7 +204,7 @@ static inline void setindex(int index) | |||
205 | static void vga16fb_pan_var(struct fb_info *info, | 204 | static void vga16fb_pan_var(struct fb_info *info, |
206 | struct fb_var_screeninfo *var) | 205 | struct fb_var_screeninfo *var) |
207 | { | 206 | { |
208 | struct vga16fb_par *par = (struct vga16fb_par *) info->par; | 207 | struct vga16fb_par *par = info->par; |
209 | u32 xoffset, pos; | 208 | u32 xoffset, pos; |
210 | 209 | ||
211 | xoffset = var->xoffset; | 210 | xoffset = var->xoffset; |
@@ -300,7 +299,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par, | |||
300 | 299 | ||
301 | static int vga16fb_open(struct fb_info *info, int user) | 300 | static int vga16fb_open(struct fb_info *info, int user) |
302 | { | 301 | { |
303 | struct vga16fb_par *par = (struct vga16fb_par *) info->par; | 302 | struct vga16fb_par *par = info->par; |
304 | int cnt = atomic_read(&par->ref_count); | 303 | int cnt = atomic_read(&par->ref_count); |
305 | 304 | ||
306 | if (!cnt) { | 305 | if (!cnt) { |
@@ -315,7 +314,7 @@ static int vga16fb_open(struct fb_info *info, int user) | |||
315 | 314 | ||
316 | static int vga16fb_release(struct fb_info *info, int user) | 315 | static int vga16fb_release(struct fb_info *info, int user) |
317 | { | 316 | { |
318 | struct vga16fb_par *par = (struct vga16fb_par *) info->par; | 317 | struct vga16fb_par *par = info->par; |
319 | int cnt = atomic_read(&par->ref_count); | 318 | int cnt = atomic_read(&par->ref_count); |
320 | 319 | ||
321 | if (!cnt) | 320 | if (!cnt) |
@@ -330,7 +329,7 @@ static int vga16fb_release(struct fb_info *info, int user) | |||
330 | static int vga16fb_check_var(struct fb_var_screeninfo *var, | 329 | static int vga16fb_check_var(struct fb_var_screeninfo *var, |
331 | struct fb_info *info) | 330 | struct fb_info *info) |
332 | { | 331 | { |
333 | struct vga16fb_par *par = (struct vga16fb_par *) info->par; | 332 | struct vga16fb_par *par = info->par; |
334 | u32 xres, right, hslen, left, xtotal; | 333 | u32 xres, right, hslen, left, xtotal; |
335 | u32 yres, lower, vslen, upper, ytotal; | 334 | u32 yres, lower, vslen, upper, ytotal; |
336 | u32 vxres, xoffset, vyres, yoffset; | 335 | u32 vxres, xoffset, vyres, yoffset; |
@@ -535,7 +534,7 @@ static int vga16fb_check_var(struct fb_var_screeninfo *var, | |||
535 | 534 | ||
536 | static int vga16fb_set_par(struct fb_info *info) | 535 | static int vga16fb_set_par(struct fb_info *info) |
537 | { | 536 | { |
538 | struct vga16fb_par *par = (struct vga16fb_par *) info->par; | 537 | struct vga16fb_par *par = info->par; |
539 | u8 gdc[VGA_GFX_C]; | 538 | u8 gdc[VGA_GFX_C]; |
540 | u8 seq[VGA_SEQ_C]; | 539 | u8 seq[VGA_SEQ_C]; |
541 | u8 atc[VGA_ATT_C]; | 540 | u8 atc[VGA_ATT_C]; |
@@ -677,7 +676,7 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
677 | unsigned blue, unsigned transp, | 676 | unsigned blue, unsigned transp, |
678 | struct fb_info *info) | 677 | struct fb_info *info) |
679 | { | 678 | { |
680 | struct vga16fb_par *par = (struct vga16fb_par *) info->par; | 679 | struct vga16fb_par *par = info->par; |
681 | int gray; | 680 | int gray; |
682 | 681 | ||
683 | /* | 682 | /* |
@@ -850,7 +849,7 @@ static void vga_pal_blank(void) | |||
850 | /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ | 849 | /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ |
851 | static int vga16fb_blank(int blank, struct fb_info *info) | 850 | static int vga16fb_blank(int blank, struct fb_info *info) |
852 | { | 851 | { |
853 | struct vga16fb_par *par = (struct vga16fb_par *) info->par; | 852 | struct vga16fb_par *par = info->par; |
854 | 853 | ||
855 | switch (blank) { | 854 | switch (blank) { |
856 | case FB_BLANK_UNBLANK: /* Unblank */ | 855 | case FB_BLANK_UNBLANK: /* Unblank */ |
@@ -1201,7 +1200,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im | |||
1201 | { | 1200 | { |
1202 | char __iomem *where = info->screen_base + (image->dx/8) + | 1201 | char __iomem *where = info->screen_base + (image->dx/8) + |
1203 | image->dy * info->fix.line_length; | 1202 | image->dy * info->fix.line_length; |
1204 | struct vga16fb_par *par = (struct vga16fb_par *) info->par; | 1203 | struct vga16fb_par *par = info->par; |
1205 | char *cdat = (char *) image->data; | 1204 | char *cdat = (char *) image->data; |
1206 | char __iomem *dst; | 1205 | char __iomem *dst; |
1207 | int x, y; | 1206 | int x, y; |
@@ -1266,7 +1265,7 @@ static void vga_imageblit_color(struct fb_info *info, const struct fb_image *ima | |||
1266 | /* | 1265 | /* |
1267 | * Draw logo | 1266 | * Draw logo |
1268 | */ | 1267 | */ |
1269 | struct vga16fb_par *par = (struct vga16fb_par *) info->par; | 1268 | struct vga16fb_par *par = info->par; |
1270 | char __iomem *where = | 1269 | char __iomem *where = |
1271 | info->screen_base + image->dy * info->fix.line_length + | 1270 | info->screen_base + image->dy * info->fix.line_length + |
1272 | image->dx/8; | 1271 | image->dx/8; |
@@ -1343,89 +1342,141 @@ static int vga16fb_setup(char *options) | |||
1343 | } | 1342 | } |
1344 | #endif | 1343 | #endif |
1345 | 1344 | ||
1346 | static int __init vga16fb_init(void) | 1345 | static int __init vga16fb_probe(struct device *device) |
1347 | { | 1346 | { |
1347 | struct platform_device *dev = to_platform_device(device); | ||
1348 | struct fb_info *info; | ||
1349 | struct vga16fb_par *par; | ||
1348 | int i; | 1350 | int i; |
1349 | int ret; | 1351 | int ret = 0; |
1350 | #ifndef MODULE | ||
1351 | char *option = NULL; | ||
1352 | 1352 | ||
1353 | if (fb_get_options("vga16fb", &option)) | ||
1354 | return -ENODEV; | ||
1355 | |||
1356 | vga16fb_setup(option); | ||
1357 | #endif | ||
1358 | printk(KERN_DEBUG "vga16fb: initializing\n"); | 1353 | printk(KERN_DEBUG "vga16fb: initializing\n"); |
1354 | info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev); | ||
1355 | |||
1356 | if (!info) { | ||
1357 | ret = -ENOMEM; | ||
1358 | goto err_fb_alloc; | ||
1359 | } | ||
1359 | 1360 | ||
1360 | /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ | 1361 | /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ |
1362 | info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS); | ||
1361 | 1363 | ||
1362 | vga16fb.screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS); | 1364 | if (!info->screen_base) { |
1363 | if (!vga16fb.screen_base) { | ||
1364 | printk(KERN_ERR "vga16fb: unable to map device\n"); | 1365 | printk(KERN_ERR "vga16fb: unable to map device\n"); |
1365 | ret = -ENOMEM; | 1366 | ret = -ENOMEM; |
1366 | goto err_ioremap; | 1367 | goto err_ioremap; |
1367 | } | 1368 | } |
1368 | printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.screen_base); | ||
1369 | 1369 | ||
1370 | vga16_par.isVGA = ORIG_VIDEO_ISVGA; | 1370 | printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base); |
1371 | vga16_par.palette_blanked = 0; | 1371 | par = info->par; |
1372 | vga16_par.vesa_blanked = 0; | ||
1373 | 1372 | ||
1374 | i = vga16_par.isVGA? 6 : 2; | 1373 | par->isVGA = ORIG_VIDEO_ISVGA; |
1374 | par->palette_blanked = 0; | ||
1375 | par->vesa_blanked = 0; | ||
1376 | |||
1377 | i = par->isVGA? 6 : 2; | ||
1375 | 1378 | ||
1376 | vga16fb_defined.red.length = i; | 1379 | vga16fb_defined.red.length = i; |
1377 | vga16fb_defined.green.length = i; | 1380 | vga16fb_defined.green.length = i; |
1378 | vga16fb_defined.blue.length = i; | 1381 | vga16fb_defined.blue.length = i; |
1379 | 1382 | ||
1380 | /* name should not depend on EGA/VGA */ | 1383 | /* name should not depend on EGA/VGA */ |
1381 | vga16fb.fbops = &vga16fb_ops; | 1384 | info->fbops = &vga16fb_ops; |
1382 | vga16fb.var = vga16fb_defined; | 1385 | info->var = vga16fb_defined; |
1383 | vga16fb.fix = vga16fb_fix; | 1386 | info->fix = vga16fb_fix; |
1384 | vga16fb.par = &vga16_par; | 1387 | info->flags = FBINFO_FLAG_DEFAULT | |
1385 | vga16fb.flags = FBINFO_FLAG_DEFAULT | | ||
1386 | FBINFO_HWACCEL_YPAN; | 1388 | FBINFO_HWACCEL_YPAN; |
1387 | 1389 | ||
1388 | i = (vga16fb_defined.bits_per_pixel == 8) ? 256 : 16; | 1390 | i = (info->var.bits_per_pixel == 8) ? 256 : 16; |
1389 | ret = fb_alloc_cmap(&vga16fb.cmap, i, 0); | 1391 | ret = fb_alloc_cmap(&info->cmap, i, 0); |
1390 | if (ret) { | 1392 | if (ret) { |
1391 | printk(KERN_ERR "vga16fb: unable to allocate colormap\n"); | 1393 | printk(KERN_ERR "vga16fb: unable to allocate colormap\n"); |
1392 | ret = -ENOMEM; | 1394 | ret = -ENOMEM; |
1393 | goto err_alloc_cmap; | 1395 | goto err_alloc_cmap; |
1394 | } | 1396 | } |
1395 | 1397 | ||
1396 | if (vga16fb_check_var(&vga16fb.var, &vga16fb)) { | 1398 | if (vga16fb_check_var(&info->var, info)) { |
1397 | printk(KERN_ERR "vga16fb: unable to validate variable\n"); | 1399 | printk(KERN_ERR "vga16fb: unable to validate variable\n"); |
1398 | ret = -EINVAL; | 1400 | ret = -EINVAL; |
1399 | goto err_check_var; | 1401 | goto err_check_var; |
1400 | } | 1402 | } |
1401 | 1403 | ||
1402 | vga16fb_update_fix(&vga16fb); | 1404 | vga16fb_update_fix(info); |
1403 | 1405 | ||
1404 | if (register_framebuffer(&vga16fb) < 0) { | 1406 | if (register_framebuffer(info) < 0) { |
1405 | printk(KERN_ERR "vga16fb: unable to register framebuffer\n"); | 1407 | printk(KERN_ERR "vga16fb: unable to register framebuffer\n"); |
1406 | ret = -EINVAL; | 1408 | ret = -EINVAL; |
1407 | goto err_check_var; | 1409 | goto err_check_var; |
1408 | } | 1410 | } |
1409 | 1411 | ||
1410 | printk(KERN_INFO "fb%d: %s frame buffer device\n", | 1412 | printk(KERN_INFO "fb%d: %s frame buffer device\n", |
1411 | vga16fb.node, vga16fb.fix.id); | 1413 | info->node, info->fix.id); |
1414 | dev_set_drvdata(device, info); | ||
1412 | 1415 | ||
1413 | return 0; | 1416 | return 0; |
1414 | 1417 | ||
1415 | err_check_var: | 1418 | err_check_var: |
1416 | fb_dealloc_cmap(&vga16fb.cmap); | 1419 | fb_dealloc_cmap(&info->cmap); |
1417 | err_alloc_cmap: | 1420 | err_alloc_cmap: |
1418 | iounmap(vga16fb.screen_base); | 1421 | iounmap(info->screen_base); |
1419 | err_ioremap: | 1422 | err_ioremap: |
1423 | framebuffer_release(info); | ||
1424 | err_fb_alloc: | ||
1425 | return ret; | ||
1426 | } | ||
1427 | |||
1428 | static int vga16fb_remove(struct device *device) | ||
1429 | { | ||
1430 | struct fb_info *info = dev_get_drvdata(device); | ||
1431 | |||
1432 | if (info) { | ||
1433 | unregister_framebuffer(info); | ||
1434 | iounmap(info->screen_base); | ||
1435 | fb_dealloc_cmap(&info->cmap); | ||
1436 | /* XXX unshare VGA regions */ | ||
1437 | framebuffer_release(info); | ||
1438 | } | ||
1439 | |||
1440 | return 0; | ||
1441 | } | ||
1442 | |||
1443 | static struct device_driver vga16fb_driver = { | ||
1444 | .name = "vga16fb", | ||
1445 | .bus = &platform_bus_type, | ||
1446 | .probe = vga16fb_probe, | ||
1447 | .remove = vga16fb_remove, | ||
1448 | }; | ||
1449 | |||
1450 | static struct platform_device vga16fb_device = { | ||
1451 | .name = "vga16fb", | ||
1452 | }; | ||
1453 | |||
1454 | static int __init vga16fb_init(void) | ||
1455 | { | ||
1456 | int ret; | ||
1457 | #ifndef MODULE | ||
1458 | char *option = NULL; | ||
1459 | |||
1460 | if (fb_get_options("vga16fb", &option)) | ||
1461 | return -ENODEV; | ||
1462 | |||
1463 | vga16fb_setup(option); | ||
1464 | #endif | ||
1465 | ret = driver_register(&vga16fb_driver); | ||
1466 | |||
1467 | if (!ret) { | ||
1468 | ret = platform_device_register(&vga16fb_device); | ||
1469 | if (ret) | ||
1470 | driver_unregister(&vga16fb_driver); | ||
1471 | } | ||
1472 | |||
1420 | return ret; | 1473 | return ret; |
1421 | } | 1474 | } |
1422 | 1475 | ||
1423 | static void __exit vga16fb_exit(void) | 1476 | static void __exit vga16fb_exit(void) |
1424 | { | 1477 | { |
1425 | unregister_framebuffer(&vga16fb); | 1478 | platform_device_unregister(&vga16fb_device); |
1426 | iounmap(vga16fb.screen_base); | 1479 | driver_unregister(&vga16fb_driver); |
1427 | fb_dealloc_cmap(&vga16fb.cmap); | ||
1428 | /* XXX unshare VGA regions */ | ||
1429 | } | 1480 | } |
1430 | 1481 | ||
1431 | MODULE_LICENSE("GPL"); | 1482 | MODULE_LICENSE("GPL"); |