1 | /* |
2 | * linux/drivers/video/q40fb.c -- Q40 frame buffer device |
3 | * |
4 | * Copyright (C) 2001 |
5 | * |
6 | * Richard Zidlicky <rz@linux-m68k.org> |
7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public |
9 | * License. See the file COPYING in the main directory of this archive for |
10 | * more details. |
11 | */ |
12 | |
13 | #include <linux/kernel.h> |
14 | #include <linux/errno.h> |
15 | #include <linux/string.h> |
16 | #include <linux/mm.h> |
17 | #include <linux/delay.h> |
18 | #include <linux/interrupt.h> |
19 | #include <linux/platform_device.h> |
20 | |
21 | #include <linux/uaccess.h> |
22 | #include <asm/setup.h> |
23 | #include <asm/q40_master.h> |
24 | #include <linux/fb.h> |
25 | #include <linux/module.h> |
26 | |
27 | #define Q40_PHYS_SCREEN_ADDR 0xFE800000 |
28 | |
29 | static struct fb_fix_screeninfo q40fb_fix = { |
30 | .id = "Q40" , |
31 | .smem_len = 1024*1024, |
32 | .type = FB_TYPE_PACKED_PIXELS, |
33 | .visual = FB_VISUAL_TRUECOLOR, |
34 | .line_length = 1024*2, |
35 | .accel = FB_ACCEL_NONE, |
36 | }; |
37 | |
38 | static const struct fb_var_screeninfo q40fb_var = { |
39 | .xres = 1024, |
40 | .yres = 512, |
41 | .xres_virtual = 1024, |
42 | .yres_virtual = 512, |
43 | .bits_per_pixel = 16, |
44 | .red = {6, 5, 0}, |
45 | .green = {11, 5, 0}, |
46 | .blue = {0, 6, 0}, |
47 | .activate = FB_ACTIVATE_NOW, |
48 | .height = 230, |
49 | .width = 300, |
50 | .vmode = FB_VMODE_NONINTERLACED, |
51 | }; |
52 | |
53 | static int q40fb_setcolreg(unsigned regno, unsigned red, unsigned green, |
54 | unsigned blue, unsigned transp, |
55 | struct fb_info *info) |
56 | { |
57 | /* |
58 | * Set a single color register. The values supplied have a 16 bit |
59 | * magnitude. |
60 | * Return != 0 for invalid regno. |
61 | */ |
62 | |
63 | if (regno > 255) |
64 | return 1; |
65 | red>>=11; |
66 | green>>=11; |
67 | blue>>=10; |
68 | |
69 | if (regno < 16) { |
70 | ((u32 *)info->pseudo_palette)[regno] = ((red & 31) <<6) | |
71 | ((green & 31) << 11) | |
72 | (blue & 63); |
73 | } |
74 | return 0; |
75 | } |
76 | |
77 | static const struct fb_ops q40fb_ops = { |
78 | .owner = THIS_MODULE, |
79 | FB_DEFAULT_IOMEM_OPS, |
80 | .fb_setcolreg = q40fb_setcolreg, |
81 | }; |
82 | |
83 | static int q40fb_probe(struct platform_device *dev) |
84 | { |
85 | struct fb_info *info; |
86 | |
87 | if (!MACH_IS_Q40) |
88 | return -ENXIO; |
89 | |
90 | /* mapped in q40/config.c */ |
91 | q40fb_fix.smem_start = Q40_PHYS_SCREEN_ADDR; |
92 | |
93 | info = framebuffer_alloc(size: sizeof(u32) * 16, dev: &dev->dev); |
94 | if (!info) |
95 | return -ENOMEM; |
96 | |
97 | info->var = q40fb_var; |
98 | info->fix = q40fb_fix; |
99 | info->fbops = &q40fb_ops; |
100 | info->pseudo_palette = info->par; |
101 | info->par = NULL; |
102 | info->screen_base = (char *) q40fb_fix.smem_start; |
103 | |
104 | if (fb_alloc_cmap(cmap: &info->cmap, len: 256, transp: 0) < 0) { |
105 | framebuffer_release(info); |
106 | return -ENOMEM; |
107 | } |
108 | |
109 | master_outb(3, DISPLAY_CONTROL_REG); |
110 | |
111 | if (register_framebuffer(fb_info: info) < 0) { |
112 | printk(KERN_ERR "Unable to register Q40 frame buffer\n" ); |
113 | fb_dealloc_cmap(cmap: &info->cmap); |
114 | framebuffer_release(info); |
115 | return -EINVAL; |
116 | } |
117 | |
118 | fb_info(info, "Q40 frame buffer alive and kicking !\n" ); |
119 | return 0; |
120 | } |
121 | |
122 | static struct platform_driver q40fb_driver = { |
123 | .probe = q40fb_probe, |
124 | .driver = { |
125 | .name = "q40fb" , |
126 | }, |
127 | }; |
128 | |
129 | static struct platform_device q40fb_device = { |
130 | .name = "q40fb" , |
131 | }; |
132 | |
133 | static int __init q40fb_init(void) |
134 | { |
135 | int ret = 0; |
136 | |
137 | if (fb_get_options(name: "q40fb" , NULL)) |
138 | return -ENODEV; |
139 | |
140 | ret = platform_driver_register(&q40fb_driver); |
141 | |
142 | if (!ret) { |
143 | ret = platform_device_register(&q40fb_device); |
144 | if (ret) |
145 | platform_driver_unregister(&q40fb_driver); |
146 | } |
147 | return ret; |
148 | } |
149 | |
150 | module_init(q40fb_init); |
151 | MODULE_LICENSE("GPL" ); |
152 | |