4 * Xilinx TFT LCD frame buffer driver
6 * Author: MontaVista Software, Inc.
9 * 2002 (c) MontaVista, Software, Inc. This file is licensed under the terms
10 * of the GNU General Public License version 2.1. This program is licensed
11 * "as is" without any warranty of any kind, whether express or implied.
15 * This driver was based off of au1100fb.c by MontaVista, which in turn
16 * was based off of skeletonfb.c, Skeleton for a frame buffer device by
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <linux/string.h>
25 #include <linux/wrapper.h> /* mem_map_(un)reserve */
26 #include <linux/tty.h>
27 #include <linux/slab.h>
28 #include <linux/delay.h>
30 #include <linux/init.h>
33 #include <video/fbcon.h>
34 #include <video/fbcon-cfb32.h>
36 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
37 MODULE_DESCRIPTION("Xilinx TFT LCD frame buffer driver");
38 MODULE_LICENSE("GPL");
41 * The interface to the framebuffer is nice and simple. There are two
42 * control registers. The first tells the LCD interface where in memory
43 * the frame buffer is (only the 11 most significant bits are used, so
44 * don't start thinking about scrolling). The second allows the LCD to
45 * be turned on or off as well as rotated 180 degrees.
50 #define REG_CTRL_ENABLE 0x0001
51 #define REG_CTRL_ROTATE 0x0002
52 #if defined(CONFIG_FB_XILINX_ROTATE)
53 #define REG_CTRL_DEFAULT (REG_CTRL_ENABLE | REG_CTRL_ROTATE)
55 #define REG_CTRL_DEFAULT (REG_CTRL_ENABLE)
56 #endif /* CONFIG_FB_XILINX_ROTATE */
59 * The hardware only handles a single mode: 640x480 24 bit true
60 * color. Each pixel gets a word (32 bits) of memory. Within each word,
61 * the 8 most significant bits are ignored, the next 8 bits are the red
62 * level, the next 8 bits are the green level and the 8 least
63 * significant bits are the blue level. Each row of the LCD uses 1024
64 * words, but only the first 640 pixels are displayed with the other 384
65 * words being ignored. There are 480 rows.
67 #define BYTES_PER_PIXEL 4
68 #define BITS_PER_PIXEL (BYTES_PER_PIXEL * 8)
71 #define XRES_VIRTUAL 1024
72 #define YRES_VIRTUAL YRES
73 #define LINE_LENGTH (XRES_VIRTUAL * BYTES_PER_PIXEL)
74 #define FB_SIZE (YRES_VIRTUAL * LINE_LENGTH)
77 * Here's the definition of the information needed per frame buffer. We
78 * start off with the generic structure and then follow that with our private
81 struct xilinxfb_info {
82 struct fb_info_gen gen;
83 struct xilinxfb_info *next; /* The next node in info_list */
84 u32 *regs; /* Virtual address of our control registers */
85 unsigned long fb_virt_start; /* Virtual address of our frame buffer */
86 dma_addr_t fb_phys; /* Physical address of our frame buffer */
87 u32 fbcon_cmap32[16]; /* Colormap */
92 struct fb_var_screeninfo var;
96 * So we can handle multiple frame buffers with this one driver, we need
97 * a list of xilinxfb_info's.
99 static struct xilinxfb_info *info_list = NULL;
100 static spinlock_t info_lock = SPIN_LOCK_UNLOCKED;
102 /* Our parameters are unchangeable, so we only need one parameters struct. */
103 static struct xilinxfb_par current_par;
106 * Free the head of our info_list and remove it from the list. Note
107 * that this function does *not* unregister_framebuffer(). That is up
108 * to the caller to do if it is appropriate.
111 remove_head_info(void)
113 struct xilinxfb_info *i;
115 /* Pull the head off of info_list. */
116 spin_lock(&info_lock);
119 spin_unlock(&info_lock);
122 /* Turn off the display; the frame buffer is going away. */
123 out_be32(i->regs + REG_CTRL, 0);
127 if (i->fb_virt_start)
128 consistent_free((void *)i->fb_virt_start);
134 xilinxfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
135 u_long arg, int con, struct fb_info *info)
137 /* nothing to do yet */
141 static struct fb_ops xilinxfb_ops = {
143 fb_get_fix:fbgen_get_fix,
144 fb_get_var:fbgen_get_var,
145 fb_set_var:fbgen_set_var,
146 fb_get_cmap:fbgen_get_cmap,
147 fb_set_cmap:fbgen_set_cmap,
148 fb_pan_display:fbgen_pan_display,
149 fb_ioctl:xilinxfb_ioctl,
156 * This function should detect the current video mode settings
157 * and store it as the default video mode
161 * Yeh, well, we're not going to change any settings so we're
162 * always stuck with the default ...
168 xilinx_encode_fix(struct fb_fix_screeninfo *fix, const void *par,
169 struct fb_info_gen *info)
171 struct xilinxfb_info *i = (struct xilinxfb_info *) info;
173 memset(fix, 0, sizeof (struct fb_fix_screeninfo));
175 strcpy(fix->id, "Xilinx");
176 fix->smem_start = i->fb_phys;
177 fix->smem_len = FB_SIZE;
178 fix->type = FB_TYPE_PACKED_PIXELS;
179 fix->visual = FB_VISUAL_TRUECOLOR;
180 fix->line_length = LINE_LENGTH;
185 xilinx_decode_var(const struct fb_var_screeninfo *var, void *par,
186 struct fb_info_gen *info)
188 struct xilinxfb_par *p = (struct xilinxfb_par *) par;
190 if (var->xres != XRES
192 || var->xres_virtual != XRES_VIRTUAL
193 || var->yres_virtual != YRES_VIRTUAL
194 || var->bits_per_pixel != BITS_PER_PIXEL
197 || var->grayscale != 0
199 || var->pixclock != 0
200 || var->left_margin != 0
201 || var->right_margin != 0
202 || var->hsync_len != 0
203 || var->vsync_len != 0
204 || var->sync != 0 || var->vmode != FB_VMODE_NONINTERLACED) {
208 memset(p, 0, sizeof (struct xilinxfb_par));
210 p->var.red.offset = 16;
211 p->var.red.length = 8;
212 p->var.green.offset = 8;
213 p->var.green.length = 8;
214 p->var.blue.offset = 0;
215 p->var.blue.length = 8;
216 p->var.transp.offset = 0;
217 p->var.transp.length = 0;
218 p->var.red.msb_right = 0;
219 p->var.green.msb_right = 0;
220 p->var.blue.msb_right = 0;
221 p->var.transp.msb_right = 0;
222 p->var.height = 99; /* in mm of NEC NL6448BC20-08 on ML300 */
223 p->var.width = 132; /* in mm of NEC NL6448BC20-08 on ML300 */
229 xilinx_encode_var(struct fb_var_screeninfo *var, const void *par,
230 struct fb_info_gen *info)
232 struct xilinxfb_par *p = (struct xilinxfb_par *) par;
239 xilinx_get_par(void *par, struct fb_info_gen *info)
241 struct xilinxfb_par *p = (struct xilinxfb_par *) par;
247 xilinx_set_par(const void *par, struct fb_info_gen *info)
249 /* nothing to do: we don't change any settings */
253 xilinx_getcolreg(unsigned regno, unsigned *red, unsigned *green,
254 unsigned *blue, unsigned *transp, struct fb_info *info)
256 struct xilinxfb_info *i = (struct xilinxfb_info *) info;
262 r = (i->fbcon_cmap32[regno] & 0xFF0000) >> 16;
263 g = (i->fbcon_cmap32[regno] & 0x00FF00) >> 8;
264 b = (i->fbcon_cmap32[regno] & 0x0000FF);
275 xilinx_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
276 unsigned transp, struct fb_info *info)
278 struct xilinxfb_info *i = (struct xilinxfb_info *) info;
283 /* We only handle 8 bits of each color. */
287 i->fbcon_cmap32[regno] = ((unsigned long) red << 16
288 | (unsigned long) green << 8
289 | (unsigned long) blue);
294 xilinx_pan_display(const struct fb_var_screeninfo *var,
295 struct fb_info_gen *info)
297 if (var->xoffset != 0 || var->yoffset != 0)
304 xilinx_blank(int blank_mode, struct fb_info_gen *info)
306 struct xilinxfb_info *i = (struct xilinxfb_info *) info;
308 switch (blank_mode) {
309 case VESA_NO_BLANKING:
311 out_be32(i->regs + REG_CTRL, REG_CTRL_DEFAULT);
314 case VESA_VSYNC_SUSPEND:
315 case VESA_HSYNC_SUSPEND:
318 out_be32(i->regs + REG_CTRL, 0);
327 xilinx_set_disp(const void *unused, struct display *disp,
328 struct fb_info_gen *info)
330 struct xilinxfb_info *i = (struct xilinxfb_info *) info;
332 disp->screen_base = (char *) i->fb_virt_start;
334 disp->dispsw = &fbcon_cfb32;
335 disp->dispsw_data = i->fbcon_cmap32;
338 static struct fbgen_hwswitch xilinx_switch = {
356 struct xilinxfb_info *i;
357 struct page *page, *end_page;
360 #if defined(XPAR_TFT_0_BASEADDR)
362 phys_reg_addr = (u32 *) XPAR_TFT_0_BASEADDR;
364 #if defined(XPAR_TFT_1_BASEADDR)
366 phys_reg_addr = (u32 *) XPAR_TFT_1_BASEADDR;
368 #if defined(XPAR_TFT_2_BASEADDR)
370 phys_reg_addr = (u32 *) XPAR_TFT_2_BASEADDR;
372 #if defined(XPAR_TFT_3_BASEADDR)
373 #error Edit this file to add more devices.
382 /* Allocate the info and zero it out. */
383 i = (struct xilinxfb_info *) kmalloc(sizeof (struct xilinxfb_info),
386 printk(KERN_ERR "Could not allocate Xilinx "
387 "frame buffer #%d information.\n", index);
390 memset(i, 0, sizeof (struct xilinxfb_info));
392 /* Make it the head of info_list. */
393 spin_lock(&info_lock);
396 spin_unlock(&info_lock);
399 * At this point, things are ok for us to call remove_head_info() to
400 * clean up if we run into any problems; i is on info_list and
401 * all the pointers are zeroed because of the memset above.
404 i->fb_virt_start = (unsigned long) consistent_alloc(GFP_KERNEL|GFP_DMA,
407 if (!i->fb_virt_start) {
408 printk(KERN_ERR "Could not allocate frame buffer memory "
409 "for Xilinx device #%d.\n", index);
415 * The 2.4 PPC version of consistent_alloc does not set the
416 * pages reserved. The pages need to be reserved so that mmap
417 * will work. This means that we need the following code. When
418 * consistent_alloc gets fixed, this will no longer be needed.
419 * Note that in 2.4, consistent_alloc doesn't free up the extra
420 * pages either. This is already fixed in 2.5.
422 page = virt_to_page(__va(i->fb_phys));
423 end_page = page + ((FB_SIZE+PAGE_SIZE-1)/PAGE_SIZE);
424 while (page < end_page)
425 mem_map_reserve(page++);
427 /* Clear the frame buffer. */
428 memset((void *) i->fb_virt_start, 0, FB_SIZE);
430 /* Map the control registers in. */
431 i->regs = (u32 *) ioremap((unsigned long) phys_reg_addr, NUM_REGS);
433 /* Tell the hardware where the frame buffer is. */
434 out_be32(i->regs + REG_FB_ADDR, i->fb_phys);
436 /* Turn on the display. */
437 out_be32(i->regs + REG_CTRL, REG_CTRL_DEFAULT);
439 current_par.var.xres = XRES;
440 current_par.var.xres_virtual = XRES_VIRTUAL;
441 current_par.var.yres = YRES;
442 current_par.var.yres_virtual = YRES_VIRTUAL;
443 current_par.var.bits_per_pixel = BITS_PER_PIXEL;
445 i->gen.parsize = sizeof (struct xilinxfb_par);
446 i->gen.fbhw = &xilinx_switch;
448 strcpy(i->gen.info.modename, "Xilinx LCD");
449 i->gen.info.changevar = NULL;
450 i->gen.info.node = -1;
452 i->gen.info.fbops = &xilinxfb_ops;
453 i->gen.info.disp = &i->disp;
454 i->gen.info.switch_con = &fbgen_switch;
455 i->gen.info.updatevar = &fbgen_update_var;
456 i->gen.info.blank = &fbgen_blank;
457 i->gen.info.flags = FBINFO_FLAG_DEFAULT;
459 /* This should give a reasonable default video mode */
460 fbgen_get_var(&i->disp.var, -1, &i->gen.info);
461 fbgen_do_set_var(&i->disp.var, 1, &i->gen);
462 fbgen_set_disp(-1, &i->gen);
463 fbgen_install_cmap(0, &i->gen);
464 if (register_framebuffer(&i->gen.info) < 0) {
465 printk(KERN_ERR "Could not register frame buffer "
466 "for Xilinx device #%d.\n", index);
470 printk(KERN_INFO "fb%d: %s frame buffer at 0x%08X mapped to 0x%08lX\n",
471 GET_FB_IDX(i->gen.info.node), i->gen.info.modename,
472 i->fb_phys, i->fb_virt_start);
482 while (probe(index++) == 0) ;
484 /* If we found at least one, report success. */
485 return (index > 1) ? 0 : -ENODEV;
489 xilinxfb_cleanup(void)
492 unregister_framebuffer((struct fb_info *) info_list);
499 module_init(xilinxfb_init);
500 module_exit(xilinxfb_cleanup);