4 * Xilinx TFT LCD frame buffer driver
6 * Author: MontaVista Software, Inc.
9 * 2002-2007 (c) MontaVista Software, Inc. This file is licensed under the
10 * terms of the GNU General Public License version 2. This program is licensed
11 * "as is" without any warranty of any kind, whether express or implied.
15 * This driver was based on au1100fb.c by MontaVista rewritten for 2.6
16 * by Embedded Alley Solutions <source@embeddedalley.com>, which in turn
17 * was based on skeletonfb.c, Skeleton for a frame buffer device by
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/version.h>
24 #include <linux/errno.h>
25 #include <linux/string.h>
28 #include <linux/init.h>
29 #include <linux/dma-mapping.h>
30 #include <linux/platform_device.h>
33 #include <syslib/virtex_devices.h>
35 #define DRIVER_NAME "xilinxfb"
36 #define DRIVER_DESCRIPTION "Xilinx TFT LCD frame buffer driver"
39 * Xilinx calls it "PLB TFT LCD Controller" though it can also be used for
40 * the VGA port on the Xilinx ML40x board. This is a hardware display controller
41 * for a 640x480 resolution TFT or VGA screen.
43 * The interface to the framebuffer is nice and simple. There are two
44 * control registers. The first tells the LCD interface where in memory
45 * the frame buffer is (only the 11 most significant bits are used, so
46 * don't start thinking about scrolling). The second allows the LCD to
47 * be turned on or off as well as rotated 180 degrees.
52 #define REG_CTRL_ENABLE 0x0001
53 #define REG_CTRL_ROTATE 0x0002
56 * The hardware only handles a single mode: 640x480 24 bit true
57 * color. Each pixel gets a word (32 bits) of memory. Within each word,
58 * the 8 most significant bits are ignored, the next 8 bits are the red
59 * level, the next 8 bits are the green level and the 8 least
60 * significant bits are the blue level. Each row of the LCD uses 1024
61 * words, but only the first 640 pixels are displayed with the other 384
62 * words being ignored. There are 480 rows.
64 #define BYTES_PER_PIXEL 4
65 #define BITS_PER_PIXEL (BYTES_PER_PIXEL * 8)
68 #define XRES_VIRTUAL 1024
69 #define YRES_VIRTUAL YRES
70 #define LINE_LENGTH (XRES_VIRTUAL * BYTES_PER_PIXEL)
71 #define FB_SIZE (YRES_VIRTUAL * LINE_LENGTH)
77 #define PALETTE_ENTRIES_NO 16 /* passed to fb_alloc_cmap() */
80 * Here are the default fb_fix_screeninfo and fb_var_screeninfo structures
82 static struct fb_fix_screeninfo xilinx_fb_fix __initdata
= {
84 .type
= FB_TYPE_PACKED_PIXELS
,
85 .visual
= FB_VISUAL_TRUECOLOR
,
87 .line_length
= LINE_LENGTH
,
88 .accel
= FB_ACCEL_NONE
91 static struct fb_var_screeninfo xilinx_fb_var __initdata
= {
94 .xres_virtual
= XRES_VIRTUAL
,
95 .yres_virtual
= YRES_VIRTUAL
,
97 .bits_per_pixel
= BITS_PER_PIXEL
,
99 .red
= { RED_SHIFT
, 8, 0 },
100 .green
= { GREEN_SHIFT
, 8, 0 },
101 .blue
= { BLUE_SHIFT
, 8, 0 },
102 .transp
= { 0, 0, 0 },
104 .activate
= FB_ACTIVATE_NOW
107 struct xilinxfb_drvdata
{
109 struct fb_info info
; /* FB driver info record */
111 u32 regs_phys
; /* phys. address of the control registers */
112 u32 __iomem
*regs
; /* virt. address of the control registers */
114 unsigned char __iomem
*fb_virt
; /* virt. address of the frame buffer */
115 dma_addr_t fb_phys
; /* phys. address of the frame buffer */
117 u32 reg_ctrl_default
;
119 u32 pseudo_palette
[PALETTE_ENTRIES_NO
];
120 /* Fake palette of 16 colors */
123 #define to_xilinxfb_drvdata(_info) \
124 container_of(_info, struct xilinxfb_drvdata, info)
127 * The LCD controller has DCR interface to its registers, but all
128 * the boards and configurations the driver has been tested with
129 * use opb2dcr bridge. So the registers are seen as memory mapped.
130 * This macro is to make it simple to add the direct DCR access
133 #define xilinx_fb_out_be32(driverdata, offset, val) \
134 out_be32(driverdata->regs + offset, val)
137 xilinx_fb_setcolreg(unsigned regno
, unsigned red
, unsigned green
, unsigned blue
,
138 unsigned transp
, struct fb_info
*fbi
)
140 u32
*palette
= fbi
->pseudo_palette
;
142 if (regno
>= PALETTE_ENTRIES_NO
)
145 if (fbi
->var
.grayscale
) {
146 /* Convert color to grayscale.
147 * grayscale = 0.30*R + 0.59*G + 0.11*B */
149 (red
* 77 + green
* 151 + blue
* 28 + 127) >> 8;
152 /* fbi->fix.visual is always FB_VISUAL_TRUECOLOR */
154 /* We only handle 8 bits of each color. */
158 palette
[regno
] = (red
<< RED_SHIFT
) | (green
<< GREEN_SHIFT
) |
159 (blue
<< BLUE_SHIFT
);
165 xilinx_fb_blank(int blank_mode
, struct fb_info
*fbi
)
167 struct xilinxfb_drvdata
*drvdata
= to_xilinxfb_drvdata(fbi
);
169 switch (blank_mode
) {
170 case FB_BLANK_UNBLANK
:
172 xilinx_fb_out_be32(drvdata
, REG_CTRL
, drvdata
->reg_ctrl_default
);
175 case FB_BLANK_NORMAL
:
176 case FB_BLANK_VSYNC_SUSPEND
:
177 case FB_BLANK_HSYNC_SUSPEND
:
178 case FB_BLANK_POWERDOWN
:
180 xilinx_fb_out_be32(drvdata
, REG_CTRL
, 0);
185 return 0; /* success */
188 static struct fb_ops xilinxfb_ops
=
190 .owner
= THIS_MODULE
,
191 .fb_setcolreg
= xilinx_fb_setcolreg
,
192 .fb_blank
= xilinx_fb_blank
,
193 .fb_fillrect
= cfb_fillrect
,
194 .fb_copyarea
= cfb_copyarea
,
195 .fb_imageblit
= cfb_imageblit
,
198 /* === The device driver === */
201 xilinxfb_drv_probe(struct device
*dev
)
203 struct platform_device
*pdev
;
204 struct xilinxfb_platform_data
*pdata
;
205 struct xilinxfb_drvdata
*drvdata
;
206 struct resource
*regs_res
;
212 pdev
= to_platform_device(dev
);
213 pdata
= pdev
->dev
.platform_data
;
216 printk(KERN_ERR
"Couldn't find platform data.\n");
220 drvdata
= kzalloc(sizeof(*drvdata
), GFP_KERNEL
);
222 printk(KERN_ERR
"Couldn't allocate device private record\n");
225 dev_set_drvdata(dev
, drvdata
);
227 /* Map the control registers in */
228 regs_res
= platform_get_resource(pdev
, IORESOURCE_IO
, 0);
229 if (!regs_res
|| (regs_res
->end
- regs_res
->start
+ 1 < 8)) {
230 printk(KERN_ERR
"Couldn't get registers resource\n");
235 if (!request_mem_region(regs_res
->start
, 8, DRIVER_NAME
)) {
237 "Couldn't lock memory region at 0x%08X\n",
242 drvdata
->regs
= (u32 __iomem
*) ioremap(regs_res
->start
, 8);
243 drvdata
->regs_phys
= regs_res
->start
;
245 /* Allocate the framebuffer memory */
246 drvdata
->fb_virt
= dma_alloc_coherent(dev
, PAGE_ALIGN(FB_SIZE
),
247 &drvdata
->fb_phys
, GFP_KERNEL
);
248 if (!drvdata
->fb_virt
) {
249 printk(KERN_ERR
"Could not allocate frame buffer memory\n");
254 /* Clear (turn to black) the framebuffer */
255 memset_io((void *) drvdata
->fb_virt
, 0, FB_SIZE
);
257 /* Tell the hardware where the frame buffer is */
258 xilinx_fb_out_be32(drvdata
, REG_FB_ADDR
, drvdata
->fb_phys
);
260 /* Turn on the display */
261 if (pdata
->rotate_screen
) {
262 drvdata
->reg_ctrl_default
= REG_CTRL_ENABLE
| REG_CTRL_ROTATE
;
264 drvdata
->reg_ctrl_default
= REG_CTRL_ENABLE
;
266 xilinx_fb_out_be32(drvdata
, REG_CTRL
, drvdata
->reg_ctrl_default
);
268 /* Fill struct fb_info */
269 drvdata
->info
.device
= dev
;
270 drvdata
->info
.screen_base
= drvdata
->fb_virt
;
271 drvdata
->info
.fbops
= &xilinxfb_ops
;
272 drvdata
->info
.fix
= xilinx_fb_fix
;
273 drvdata
->info
.fix
.smem_start
= drvdata
->fb_phys
;
274 drvdata
->info
.pseudo_palette
= drvdata
->pseudo_palette
;
276 if (fb_alloc_cmap(&drvdata
->info
.cmap
, PALETTE_ENTRIES_NO
, 0) < 0) {
277 printk(KERN_ERR
"Fail to allocate colormap (%d entries)\n",
283 drvdata
->info
.flags
= FBINFO_DEFAULT
;
284 xilinx_fb_var
.height
= pdata
->screen_height_mm
;
285 xilinx_fb_var
.width
= pdata
->screen_width_mm
;
286 drvdata
->info
.var
= xilinx_fb_var
;
288 /* Register new frame buffer */
289 if (register_framebuffer(&drvdata
->info
) < 0) {
290 printk(KERN_ERR
"Could not register frame buffer\n");
295 return 0; /* success */
298 fb_dealloc_cmap(&drvdata
->info
.cmap
);
301 dma_free_coherent(dev
, PAGE_ALIGN(FB_SIZE
), drvdata
->fb_virt
,
304 /* Turn off the display */
305 xilinx_fb_out_be32(drvdata
, REG_CTRL
, 0);
306 iounmap(drvdata
->regs
);
309 release_mem_region(regs_res
->start
, 8);
313 dev_set_drvdata(dev
, NULL
);
319 xilinxfb_drv_remove(struct device
*dev
)
321 struct xilinxfb_drvdata
*drvdata
;
326 drvdata
= (struct xilinxfb_drvdata
*) dev_get_drvdata(dev
);
328 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
329 xilinx_fb_blank(VESA_POWERDOWN
, &drvdata
->info
);
332 unregister_framebuffer(&drvdata
->info
);
334 fb_dealloc_cmap(&drvdata
->info
.cmap
);
336 dma_free_coherent(dev
, PAGE_ALIGN(FB_SIZE
), drvdata
->fb_virt
,
339 /* Turn off the display */
340 xilinx_fb_out_be32(drvdata
, REG_CTRL
, 0);
341 iounmap(drvdata
->regs
);
343 release_mem_region(drvdata
->regs_phys
, 8);
346 dev_set_drvdata(dev
, NULL
);
352 static struct device_driver xilinxfb_driver
= {
354 .bus
= &platform_bus_type
,
356 .probe
= xilinxfb_drv_probe
,
357 .remove
= xilinxfb_drv_remove
364 * No kernel boot options used,
365 * so we just need to register the driver
367 return driver_register(&xilinxfb_driver
);
371 xilinxfb_cleanup(void)
373 driver_unregister(&xilinxfb_driver
);
376 module_init(xilinxfb_init
);
377 module_exit(xilinxfb_cleanup
);
379 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
380 MODULE_DESCRIPTION(DRIVER_DESCRIPTION
);
381 MODULE_LICENSE("GPL");