2 * drivers/video/tx3912fb.c
4 * Copyright (C) 1999 Harald Koerfgen
5 * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com)
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive for
11 * Framebuffer for LCD controller in TMPR3912/05 and PR31700 processors
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/string.h>
17 #include <linux/tty.h>
18 #include <linux/delay.h>
19 #include <linux/interrupt.h>
20 #include <linux/init.h>
24 #include <asm/bootinfo.h>
25 #include <asm/uaccess.h>
26 #include <asm/tx3912.h>
27 #include <video/tx3912.h>
30 * Frame buffer, palette and console structures
32 static struct fb_info fb_info;
35 static struct fb_fix_screeninfo tx3912fb_fix __initdata = {
37 .smem_len = ((240 * 320)/2),
38 .type = FB_TYPE_PACKED_PIXELS,
39 .visual = FB_VISUAL_TRUECOLOR,
43 .accel = FB_ACCEL_NONE,
46 static struct fb_var_screeninfo tx3912fb_var = {
52 .red = { 0, 4, 0 }, /* ??? */
55 .activate = FB_ACTIVATE_NOW,
65 .vmode = FB_VMODE_NONINTERLACED,
69 * Interface used by the world
71 int tx3912fb_init(void);
73 static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green,
74 u_int blue, u_int transp,
75 struct fb_info *info);
80 #define get_line_length(xres_virtual, bpp) \
81 (u_long) (((int) xres_virtual * (int) bpp + 7) >> 3)
84 * Frame buffer operations structure used by console driver
86 static struct fb_ops tx3912fb_ops = {
88 .fb_setcolreg = tx3912fb_setcolreg,
89 .fb_fillrect = cfb_fillrect,
90 .fb_copyarea = cfb_copyarea,
91 .fb_imageblit = cfb_imageblit,
94 static int tx3912fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
100 get_line_length(var->xres_virtual, var->bits_per_pixel);
101 if ((line_length * var->yres_virtual) > info->fix.smem_len)
107 static int tx3912fb_set_par(struct fb_info *info)
109 u_long tx3912fb_paddr = 0;
111 /* Disable the video logic */
112 outl(inl(TX3912_VIDEO_CTRL1) &
113 ~(TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
117 /* Set start address for DMA transfer */
118 outl(tx3912fb_paddr, TX3912_VIDEO_CTRL3);
120 /* Set end address for DMA transfer */
121 outl((tx3912fb_paddr + tx3912fb_fix.smem_len + 1), TX3912_VIDEO_CTRL4);
123 /* Set the pixel depth */
124 switch (info->var.bits_per_pixel) {
127 outl(inl(TX3912_VIDEO_CTRL1) &
128 ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
129 info->fix.visual = FB_VISUAL_MONO10;
133 outl(inl(TX3912_VIDEO_CTRL1) &
134 ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
135 outl(inl(TX3912_VIDEO_CTRL1) |
136 TX3912_VIDEO_CTRL1_BITSEL_4BIT_GRAY,
138 info->fix.visual = FB_VISUAL_TRUECOLOR;
142 outl(inl(TX3912_VIDEO_CTRL1) &
143 ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
144 outl(inl(TX3912_VIDEO_CTRL1) |
145 TX3912_VIDEO_CTRL1_BITSEL_8BIT_COLOR,
147 info->fix.visual = FB_VISUAL_TRUECOLOR;
152 outl(inl(TX3912_VIDEO_CTRL1) &
153 ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
154 outl(inl(TX3912_VIDEO_CTRL1) |
155 TX3912_VIDEO_CTRL1_BITSEL_2BIT_GRAY,
157 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
161 /* Enable the video clock */
162 outl(inl(TX3912_CLK_CTRL) | TX3912_CLK_CTRL_ENVIDCLK,
165 /* Unfreeze video logic and enable DF toggle */
166 outl(inl(TX3912_VIDEO_CTRL1) &
167 ~(TX3912_VIDEO_CTRL1_ENFREEZEFRAME |
168 TX3912_VIDEO_CTRL1_DFMODE)
169 , TX3912_VIDEO_CTRL1);
172 /* Enable the video logic */
173 outl(inl(TX3912_VIDEO_CTRL1) |
174 (TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
177 info->fix.line_length = get_line_length(var->xres_virtual,
178 var->bits_per_pixel);
182 * Set a single color register
184 static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green,
185 u_int blue, u_int transp,
186 struct fb_info *info)
192 ((u32 *)(info->pseudo_palette))[regno] = ((red & 0xe000) >> 8)
193 | ((green & 0xe000) >> 11)
194 | ((blue & 0xc000) >> 14);
198 int __init tx3912fb_setup(char *options);
201 * Initialization of the framebuffer
203 int __init tx3912fb_init(void)
205 u_long tx3912fb_paddr = 0;
206 int size = (info->var.bits_per_pixel == 8) ? 256 : 16;
209 if (fb_get_options("tx3912fb", &option))
211 tx3912fb_setup(option);
213 /* Disable the video logic */
214 outl(inl(TX3912_VIDEO_CTRL1) &
215 ~(TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
219 /* Set start address for DMA transfer */
220 outl(tx3912fb_paddr, TX3912_VIDEO_CTRL3);
222 /* Set end address for DMA transfer */
223 outl((tx3912fb_paddr + tx3912fb_fix.smem_len + 1), TX3912_VIDEO_CTRL4);
225 /* Set the pixel depth */
226 switch (tx3912fb_var.bits_per_pixel) {
229 outl(inl(TX3912_VIDEO_CTRL1) &
230 ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
231 tx3912fb_fix.visual = FB_VISUAL_MONO10;
235 outl(inl(TX3912_VIDEO_CTRL1) &
236 ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
237 outl(inl(TX3912_VIDEO_CTRL1) |
238 TX3912_VIDEO_CTRL1_BITSEL_4BIT_GRAY,
240 tx3912fb_fix.visual = FB_VISUAL_TRUECOLOR;
241 tx3912fb_fix.grayscale = 1;
245 outl(inl(TX3912_VIDEO_CTRL1) &
246 ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
247 outl(inl(TX3912_VIDEO_CTRL1) |
248 TX3912_VIDEO_CTRL1_BITSEL_8BIT_COLOR,
250 tx3912fb_fix.visual = FB_VISUAL_TRUECOLOR;
255 outl(inl(TX3912_VIDEO_CTRL1) &
256 ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
257 outl(inl(TX3912_VIDEO_CTRL1) |
258 TX3912_VIDEO_CTRL1_BITSEL_2BIT_GRAY,
260 tx3912fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
261 tx3912fb_fix.grayscale = 1;
265 /* Enable the video clock */
266 outl(inl(TX3912_CLK_CTRL) | TX3912_CLK_CTRL_ENVIDCLK,
269 /* Unfreeze video logic and enable DF toggle */
270 outl(inl(TX3912_VIDEO_CTRL1) &
271 ~(TX3912_VIDEO_CTRL1_ENFREEZEFRAME | TX3912_VIDEO_CTRL1_DFMODE),
275 /* Clear the framebuffer */
276 memset((void *) tx3912fb_fix.smem_start, 0xff, tx3912fb_fix.smem_len);
279 /* Enable the video logic */
280 outl(inl(TX3912_VIDEO_CTRL1) |
281 (TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
287 tx3912fb_fix.line_length =
288 get_line_length(tx3912fb_var.xres_virtual, tx3912fb_var.bits_per_pixel);
289 if ((tx3912fb_fix.line_length * tx3912fb_var.yres_virtual) > tx3912fb_fix.smem_len)
292 fb_info.fbops = &tx3912fb_ops;
293 fb_info.var = tx3912fb_var;
294 fb_info.fix = tx3912fb_fix;
295 fb_info.pseudo_palette = pseudo_palette;
296 fb_info.flags = FBINFO_DEFAULT;
298 /* Clear the framebuffer */
299 memset((void *) fb_info.fix.smem_start, 0xff, fb_info.fix.smem_len);
302 fb_alloc_cmap(&info->cmap, size, 0);
304 if (register_framebuffer(&fb_info) < 0)
307 printk(KERN_INFO "fb%d: TX3912 frame buffer using %uKB.\n",
308 fb_info.node, (u_int) (fb_info.fix.smem_len >> 10));
312 int __init tx3912fb_setup(char *options)
316 if (!options || !*options)
319 while ((this_opt = strsep(&options, ","))) {
320 if (!strncmp(options, "bpp:", 4))
321 tx3912fb_var.bits_per_pixel = simple_strtoul(options+4, NULL, 0);
326 module_init(tx3912fb_init);
327 MODULE_LICENSE("GPL");