diff options
Diffstat (limited to 'drivers/video/fm2fb.c')
-rw-r--r-- | drivers/video/fm2fb.c | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c new file mode 100644 index 000000000000..a0763283d776 --- /dev/null +++ b/drivers/video/fm2fb.c | |||
@@ -0,0 +1,322 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/fm2fb.c -- BSC FrameMaster II/Rainbow II frame buffer | ||
3 | * device | ||
4 | * | ||
5 | * Copyright (C) 1998 Steffen A. Mork (linux-dev@morknet.de) | ||
6 | * Copyright (C) 1999 Geert Uytterhoeven | ||
7 | * | ||
8 | * Written for 2.0.x by Steffen A. Mork | ||
9 | * Ported to 2.1.x by Geert Uytterhoeven | ||
10 | * Ported to new api by James Simmons | ||
11 | * | ||
12 | * This file is subject to the terms and conditions of the GNU General Public | ||
13 | * License. See the file COPYING in the main directory of this archive for | ||
14 | * more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/mm.h> | ||
19 | #include <linux/fb.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/zorro.h> | ||
22 | #include <asm/io.h> | ||
23 | |||
24 | /* | ||
25 | * Some technical notes: | ||
26 | * | ||
27 | * The BSC FrameMaster II (or Rainbow II) is a simple very dumb | ||
28 | * frame buffer which allows to display 24 bit true color images. | ||
29 | * Each pixel is 32 bit width so it's very easy to maintain the | ||
30 | * frame buffer. One long word has the following layout: | ||
31 | * AARRGGBB which means: AA the alpha channel byte, RR the red | ||
32 | * channel, GG the green channel and BB the blue channel. | ||
33 | * | ||
34 | * The FrameMaster II supports the following video modes. | ||
35 | * - PAL/NTSC | ||
36 | * - interlaced/non interlaced | ||
37 | * - composite sync/sync/sync over green | ||
38 | * | ||
39 | * The resolution is to the following both ones: | ||
40 | * - 768x576 (PAL) | ||
41 | * - 768x480 (NTSC) | ||
42 | * | ||
43 | * This means that pixel access per line is fixed due to the | ||
44 | * fixed line width. In case of maximal resolution the frame | ||
45 | * buffer needs an amount of memory of 1.769.472 bytes which | ||
46 | * is near to 2 MByte (the allocated address space of Zorro2). | ||
47 | * The memory is channel interleaved. That means every channel | ||
48 | * owns four VRAMs. Unfortunatly most FrameMasters II are | ||
49 | * not assembled with memory for the alpha channel. In this | ||
50 | * case it could be possible to add the frame buffer into the | ||
51 | * normal memory pool. | ||
52 | * | ||
53 | * At relative address 0x1ffff8 of the frame buffers base address | ||
54 | * there exists a control register with the number of | ||
55 | * four control bits. They have the following meaning: | ||
56 | * bit value meaning | ||
57 | * | ||
58 | * 0 1 0=interlaced/1=non interlaced | ||
59 | * 1 2 0=video out disabled/1=video out enabled | ||
60 | * 2 4 0=normal mode as jumpered via JP8/1=complement mode | ||
61 | * 3 8 0=read onboard ROM/1 normal operation (required) | ||
62 | * | ||
63 | * As mentioned above there are several jumper. I think there | ||
64 | * is not very much information about the FrameMaster II in | ||
65 | * the world so I add these information for completeness. | ||
66 | * | ||
67 | * JP1 interlace selection (1-2 non interlaced/2-3 interlaced) | ||
68 | * JP2 wait state creation (leave as is!) | ||
69 | * JP3 wait state creation (leave as is!) | ||
70 | * JP4 modulate composite sync on green output (1-2 composite | ||
71 | * sync on green channel/2-3 normal composite sync) | ||
72 | * JP5 create test signal, shorting this jumper will create | ||
73 | * a white screen | ||
74 | * JP6 sync creation (1-2 composite sync/2-3 H-sync output) | ||
75 | * JP8 video mode (1-2 PAL/2-3 NTSC) | ||
76 | * | ||
77 | * With the following jumpering table you can connect the | ||
78 | * FrameMaster II to a normal TV via SCART connector: | ||
79 | * JP1: 2-3 | ||
80 | * JP4: 2-3 | ||
81 | * JP6: 2-3 | ||
82 | * JP8: 1-2 (means PAL for Europe) | ||
83 | * | ||
84 | * NOTE: | ||
85 | * There is no other possibility to change the video timings | ||
86 | * except the interlaced/non interlaced, sync control and the | ||
87 | * video mode PAL (50 Hz)/NTSC (60 Hz). Inside this | ||
88 | * FrameMaster II driver are assumed values to avoid anomalies | ||
89 | * to a future X server. Except the pixel clock is really | ||
90 | * constant at 30 MHz. | ||
91 | * | ||
92 | * 9 pin female video connector: | ||
93 | * | ||
94 | * 1 analog red 0.7 Vss | ||
95 | * 2 analog green 0.7 Vss | ||
96 | * 3 analog blue 0.7 Vss | ||
97 | * 4 H-sync TTL | ||
98 | * 5 V-sync TTL | ||
99 | * 6 ground | ||
100 | * 7 ground | ||
101 | * 8 ground | ||
102 | * 9 ground | ||
103 | * | ||
104 | * Some performance notes: | ||
105 | * The FrameMaster II was not designed to display a console | ||
106 | * this driver would do! It was designed to display still true | ||
107 | * color images. Imagine: When scroll up a text line there | ||
108 | * must copied ca. 1.7 MBytes to another place inside this | ||
109 | * frame buffer. This means 1.7 MByte read and 1.7 MByte write | ||
110 | * over the slow 16 bit wide Zorro2 bus! A scroll of one | ||
111 | * line needs 1 second so do not expect to much from this | ||
112 | * driver - he is at the limit! | ||
113 | * | ||
114 | */ | ||
115 | |||
116 | /* | ||
117 | * definitions | ||
118 | */ | ||
119 | |||
120 | #define FRAMEMASTER_SIZE 0x200000 | ||
121 | #define FRAMEMASTER_REG 0x1ffff8 | ||
122 | |||
123 | #define FRAMEMASTER_NOLACE 1 | ||
124 | #define FRAMEMASTER_ENABLE 2 | ||
125 | #define FRAMEMASTER_COMPL 4 | ||
126 | #define FRAMEMASTER_ROM 8 | ||
127 | |||
128 | static volatile unsigned char *fm2fb_reg; | ||
129 | |||
130 | static struct fb_fix_screeninfo fb_fix __devinitdata = { | ||
131 | .smem_len = FRAMEMASTER_REG, | ||
132 | .type = FB_TYPE_PACKED_PIXELS, | ||
133 | .visual = FB_VISUAL_TRUECOLOR, | ||
134 | .line_length = (768 << 2), | ||
135 | .mmio_len = (8), | ||
136 | .accel = FB_ACCEL_NONE, | ||
137 | }; | ||
138 | |||
139 | static int fm2fb_mode __devinitdata = -1; | ||
140 | |||
141 | #define FM2FB_MODE_PAL 0 | ||
142 | #define FM2FB_MODE_NTSC 1 | ||
143 | |||
144 | static struct fb_var_screeninfo fb_var_modes[] __devinitdata = { | ||
145 | { | ||
146 | /* 768 x 576, 32 bpp (PAL) */ | ||
147 | 768, 576, 768, 576, 0, 0, 32, 0, | ||
148 | { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 }, | ||
149 | 0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE, | ||
150 | 33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0 | ||
151 | }, { | ||
152 | /* 768 x 480, 32 bpp (NTSC - not supported yet */ | ||
153 | 768, 480, 768, 480, 0, 0, 32, 0, | ||
154 | { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 }, | ||
155 | 0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE, | ||
156 | 33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0 | ||
157 | } | ||
158 | }; | ||
159 | |||
160 | /* | ||
161 | * Interface used by the world | ||
162 | */ | ||
163 | |||
164 | static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | ||
165 | u_int transp, struct fb_info *info); | ||
166 | static int fm2fb_blank(int blank, struct fb_info *info); | ||
167 | |||
168 | static struct fb_ops fm2fb_ops = { | ||
169 | .owner = THIS_MODULE, | ||
170 | .fb_setcolreg = fm2fb_setcolreg, | ||
171 | .fb_blank = fm2fb_blank, | ||
172 | .fb_fillrect = cfb_fillrect, | ||
173 | .fb_copyarea = cfb_copyarea, | ||
174 | .fb_imageblit = cfb_imageblit, | ||
175 | .fb_cursor = soft_cursor, | ||
176 | }; | ||
177 | |||
178 | /* | ||
179 | * Blank the display. | ||
180 | */ | ||
181 | static int fm2fb_blank(int blank, struct fb_info *info) | ||
182 | { | ||
183 | unsigned char t = FRAMEMASTER_ROM; | ||
184 | |||
185 | if (!blank) | ||
186 | t |= FRAMEMASTER_ENABLE | FRAMEMASTER_NOLACE; | ||
187 | fm2fb_reg[0] = t; | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * Set a single color register. The values supplied are already | ||
193 | * rounded down to the hardware's capabilities (according to the | ||
194 | * entries in the var structure). Return != 0 for invalid regno. | ||
195 | */ | ||
196 | static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | ||
197 | u_int transp, struct fb_info *info) | ||
198 | { | ||
199 | if (regno > info->cmap.len) | ||
200 | return 1; | ||
201 | red >>= 8; | ||
202 | green >>= 8; | ||
203 | blue >>= 8; | ||
204 | |||
205 | ((u32*)(info->pseudo_palette))[regno] = (red << 16) | (green << 8) | blue; | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * Initialisation | ||
211 | */ | ||
212 | |||
213 | static int __devinit fm2fb_probe(struct zorro_dev *z, | ||
214 | const struct zorro_device_id *id); | ||
215 | |||
216 | static struct zorro_device_id fm2fb_devices[] __devinitdata = { | ||
217 | { ZORRO_PROD_BSC_FRAMEMASTER_II }, | ||
218 | { ZORRO_PROD_HELFRICH_RAINBOW_II }, | ||
219 | { 0 } | ||
220 | }; | ||
221 | |||
222 | static struct zorro_driver fm2fb_driver = { | ||
223 | .name = "fm2fb", | ||
224 | .id_table = fm2fb_devices, | ||
225 | .probe = fm2fb_probe, | ||
226 | }; | ||
227 | |||
228 | static int __devinit fm2fb_probe(struct zorro_dev *z, | ||
229 | const struct zorro_device_id *id) | ||
230 | { | ||
231 | struct fb_info *info; | ||
232 | unsigned long *ptr; | ||
233 | int is_fm; | ||
234 | int x, y; | ||
235 | |||
236 | is_fm = z->id == ZORRO_PROD_BSC_FRAMEMASTER_II; | ||
237 | |||
238 | if (!zorro_request_device(z,"fm2fb")) | ||
239 | return -ENXIO; | ||
240 | |||
241 | info = framebuffer_alloc(256 * sizeof(u32), &z->dev); | ||
242 | if (!info) { | ||
243 | zorro_release_device(z); | ||
244 | return -ENOMEM; | ||
245 | } | ||
246 | |||
247 | if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { | ||
248 | framebuffer_release(info); | ||
249 | zorro_release_device(z); | ||
250 | return -ENOMEM; | ||
251 | } | ||
252 | |||
253 | /* assigning memory to kernel space */ | ||
254 | fb_fix.smem_start = zorro_resource_start(z); | ||
255 | info->screen_base = ioremap(fb_fix.smem_start, FRAMEMASTER_SIZE); | ||
256 | fb_fix.mmio_start = fb_fix.smem_start + FRAMEMASTER_REG; | ||
257 | fm2fb_reg = (unsigned char *)(info->screen_base+FRAMEMASTER_REG); | ||
258 | |||
259 | strcpy(fb_fix.id, is_fm ? "FrameMaster II" : "Rainbow II"); | ||
260 | |||
261 | /* make EBU color bars on display */ | ||
262 | ptr = (unsigned long *)fb_fix.smem_start; | ||
263 | for (y = 0; y < 576; y++) { | ||
264 | for (x = 0; x < 96; x++) *ptr++ = 0xffffff;/* white */ | ||
265 | for (x = 0; x < 96; x++) *ptr++ = 0xffff00;/* yellow */ | ||
266 | for (x = 0; x < 96; x++) *ptr++ = 0x00ffff;/* cyan */ | ||
267 | for (x = 0; x < 96; x++) *ptr++ = 0x00ff00;/* green */ | ||
268 | for (x = 0; x < 96; x++) *ptr++ = 0xff00ff;/* magenta */ | ||
269 | for (x = 0; x < 96; x++) *ptr++ = 0xff0000;/* red */ | ||
270 | for (x = 0; x < 96; x++) *ptr++ = 0x0000ff;/* blue */ | ||
271 | for (x = 0; x < 96; x++) *ptr++ = 0x000000;/* black */ | ||
272 | } | ||
273 | fm2fb_blank(0, info); | ||
274 | |||
275 | if (fm2fb_mode == -1) | ||
276 | fm2fb_mode = FM2FB_MODE_PAL; | ||
277 | |||
278 | info->fbops = &fm2fb_ops; | ||
279 | info->var = fb_var_modes[fm2fb_mode]; | ||
280 | info->pseudo_palette = info->par; | ||
281 | info->par = NULL; | ||
282 | info->fix = fb_fix; | ||
283 | info->flags = FBINFO_DEFAULT; | ||
284 | |||
285 | if (register_framebuffer(info) < 0) { | ||
286 | fb_dealloc_cmap(&info->cmap); | ||
287 | framebuffer_release(info); | ||
288 | zorro_release_device(z); | ||
289 | return -EINVAL; | ||
290 | } | ||
291 | printk("fb%d: %s frame buffer device\n", info->node, fb_fix.id); | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | int __init fm2fb_setup(char *options) | ||
296 | { | ||
297 | char *this_opt; | ||
298 | |||
299 | if (!options || !*options) | ||
300 | return 0; | ||
301 | |||
302 | while ((this_opt = strsep(&options, ",")) != NULL) { | ||
303 | if (!strncmp(this_opt, "pal", 3)) | ||
304 | fm2fb_mode = FM2FB_MODE_PAL; | ||
305 | else if (!strncmp(this_opt, "ntsc", 4)) | ||
306 | fm2fb_mode = FM2FB_MODE_NTSC; | ||
307 | } | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | int __init fm2fb_init(void) | ||
312 | { | ||
313 | char *option = NULL; | ||
314 | |||
315 | if (fb_get_options("fm2fb", &option)) | ||
316 | return -ENODEV; | ||
317 | fm2fb_setup(option); | ||
318 | return zorro_register_driver(&fm2fb_driver); | ||
319 | } | ||
320 | |||
321 | module_init(fm2fb_init); | ||
322 | MODULE_LICENSE("GPL"); | ||