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");