2 * linux/drivers/video/hitfb.c -- Hitachi LCD frame buffer device
4 * (C) 1999 Mihai Spatar
5 * (C) 2000 YAEGASHI Takeshi
6 * (C) 2003, 2004 Paul Mundt
7 * (C) 2003, 2004 Andriy Skulysh
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file COPYING in the main directory of this archive for
14 #include <linux/config.h>
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/sched.h>
18 #include <linux/errno.h>
19 #include <linux/string.h>
21 #include <linux/tty.h>
22 #include <linux/slab.h>
23 #include <linux/delay.h>
24 #include <linux/init.h>
27 #include <asm/machvec.h>
28 #include <asm/uaccess.h>
29 #include <asm/pgtable.h>
31 #include <asm/hd64461/hd64461.h>
34 #include <asm/cpu/dac.h>
35 #include <asm/hp6xx/hp6xx.h>
40 static struct fb_var_screeninfo hitfb_var __initdata
= {
41 .activate
= FB_ACTIVATE_NOW
,
44 .vmode
= FB_VMODE_NONINTERLACED
,
47 static struct fb_fix_screeninfo hitfb_fix __initdata
= {
48 .id
= "Hitachi HD64461",
49 .type
= FB_TYPE_PACKED_PIXELS
,
51 .accel
= FB_ACCEL_NONE
,
54 static u32 pseudo_palette
[16];
55 static struct fb_info fb_info
;
57 static inline void hitfb_accel_wait(void)
59 while (fb_readw(HD64461_GRCFGR
) & HD64461_GRCFGR_ACCSTATUS
) ;
62 static inline void hitfb_accel_start(int truecolor
)
65 fb_writew(6, HD64461_GRCFGR
);
67 fb_writew(7, HD64461_GRCFGR
);
71 static inline void hitfb_accel_set_dest(int truecolor
, u16 dx
, u16 dy
,
72 u16 width
, u16 height
)
74 u32 saddr
= WIDTH
* dy
+ dx
;
78 fb_writew(width
, HD64461_BBTDWR
);
79 fb_writew(height
, HD64461_BBTDHR
);
81 fb_writew(saddr
& 0xffff, HD64461_BBTDSARL
);
82 fb_writew(saddr
>> 16, HD64461_BBTDSARH
);
86 static inline void hitfb_accel_solidfill(int truecolor
, u16 dx
, u16 dy
,
87 u16 width
, u16 height
, u16 color
)
89 hitfb_accel_set_dest(truecolor
, dx
, dy
, width
, height
);
91 fb_writew(0x00f0, HD64461_BBTROPR
);
92 fb_writew(16, HD64461_BBTMDR
);
93 fb_writew(color
, HD64461_GRSCR
);
95 hitfb_accel_start(truecolor
);
98 static inline void hitfb_accel_bitblt(int truecolor
, u16 sx
, u16 sy
, u16 dx
,
99 u16 dy
, u16 width
, u16 height
, u16 rop
,
105 fb_writew(rop
, HD64461_BBTROPR
);
106 if ((sy
< dy
) || ((sy
== dy
) && (sx
<= dx
))) {
107 saddr
= WIDTH
* (sy
+ height
) + sx
+ width
;
108 daddr
= WIDTH
* (dy
+ height
) + dx
+ width
;
111 maddr
= ((width
>> 3) + 1) * (height
+ 1) - 1;
114 (((width
>> 4) + 1) * (height
+ 1) - 1) * 2;
116 fb_writew((1 << 5) | 1, HD64461_BBTMDR
);
118 fb_writew(1, HD64461_BBTMDR
);
120 saddr
= WIDTH
* sy
+ sx
;
121 daddr
= WIDTH
* dy
+ dx
;
123 fb_writew((1 << 5), HD64461_BBTMDR
);
125 fb_writew(0, HD64461_BBTMDR
);
132 fb_writew(width
, HD64461_BBTDWR
);
133 fb_writew(height
, HD64461_BBTDHR
);
134 fb_writew(saddr
& 0xffff, HD64461_BBTSSARL
);
135 fb_writew(saddr
>> 16, HD64461_BBTSSARH
);
136 fb_writew(daddr
& 0xffff, HD64461_BBTDSARL
);
137 fb_writew(daddr
>> 16, HD64461_BBTDSARH
);
140 fb_writew(maddr
& 0xffff, HD64461_BBTMARL
);
141 fb_writew(maddr
>> 16, HD64461_BBTMARH
);
143 hitfb_accel_start(truecolor
);
146 static void hitfb_fillrect(struct fb_info
*p
, const struct fb_fillrect
*rect
)
148 if (rect
->rop
!= ROP_COPY
)
149 cfb_fillrect(p
, rect
);
151 fb_writew(0x00f0, HD64461_BBTROPR
);
152 fb_writew(16, HD64461_BBTMDR
);
154 if (p
->var
.bits_per_pixel
== 16) {
155 fb_writew(((u32
*) (p
->pseudo_palette
))[rect
->color
],
157 hitfb_accel_set_dest(1, rect
->dx
, rect
->dy
, rect
->width
,
159 hitfb_accel_start(1);
161 fb_writew(rect
->color
, HD64461_GRSCR
);
162 hitfb_accel_set_dest(0, rect
->dx
, rect
->dy
, rect
->width
,
164 hitfb_accel_start(0);
170 static void hitfb_copyarea(struct fb_info
*p
, const struct fb_copyarea
*area
)
172 hitfb_accel_bitblt(p
->var
.bits_per_pixel
== 16, area
->sx
, area
->sy
,
173 area
->dx
, area
->dy
, area
->width
, area
->height
,
178 static int hitfb_pan_display(struct fb_var_screeninfo
*var
,
179 struct fb_info
*info
)
181 int xoffset
= var
->xoffset
;
182 int yoffset
= var
->yoffset
;
187 fb_writew(yoffset
, HD64461_LCDCBAR
);
192 int hitfb_blank(int blank_mode
, struct fb_info
*info
)
198 sh_dac_disable(DAC_LCD_BRIGHTNESS
);
199 v
= fb_readw(HD64461_GPBDR
);
200 v
|= HD64461_GPBDR_LCDOFF
;
201 fb_writew(v
, HD64461_GPBDR
);
203 v
= fb_readw(HD64461_LDR1
);
204 v
&= ~HD64461_LDR1_DON
;
205 fb_writew(v
, HD64461_LDR1
);
207 v
= fb_readw(HD64461_LCDCCR
);
208 v
|= HD64461_LCDCCR_MOFF
;
209 fb_writew(v
, HD64461_LCDCCR
);
211 v
= fb_readw(HD64461_STBCR
);
212 v
|= HD64461_STBCR_SLCDST
;
213 fb_writew(v
, HD64461_STBCR
);
215 v
= fb_readw(HD64461_STBCR
);
216 v
&= ~HD64461_STBCR_SLCDST
;
217 fb_writew(v
, HD64461_STBCR
);
219 sh_dac_enable(DAC_LCD_BRIGHTNESS
);
220 v
= fb_readw(HD64461_GPBDR
);
221 v
&= ~HD64461_GPBDR_LCDOFF
;
222 fb_writew(v
, HD64461_GPBDR
);
224 v
= fb_readw(HD64461_LDR1
);
225 v
|= HD64461_LDR1_DON
;
226 fb_writew(v
, HD64461_LDR1
);
228 v
= fb_readw(HD64461_LCDCCR
);
229 v
&= ~HD64461_LCDCCR_MOFF
;
230 fb_writew(v
, HD64461_LCDCCR
);
235 static int hitfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
236 unsigned blue
, unsigned transp
, struct fb_info
*info
)
238 if (regno
>= info
->cmap
.len
)
241 switch (info
->var
.bits_per_pixel
) {
243 fb_writew(regno
<< 8, HD64461_CPTWAR
);
244 fb_writew(red
>> 10, HD64461_CPTWDR
);
245 fb_writew(green
>> 10, HD64461_CPTWDR
);
246 fb_writew(blue
>> 10, HD64461_CPTWDR
);
249 ((u32
*) (info
->pseudo_palette
))[regno
] =
251 ((green
& 0xfc00) >> 5) | ((blue
& 0xf800) >> 11);
257 static struct fb_ops hitfb_ops
= {
258 .owner
= THIS_MODULE
,
259 .fb_setcolreg
= hitfb_setcolreg
,
260 .fb_blank
= hitfb_blank
,
261 .fb_pan_display
= hitfb_pan_display
,
262 .fb_fillrect
= hitfb_fillrect
,
263 .fb_copyarea
= hitfb_copyarea
,
264 .fb_imageblit
= cfb_imageblit
,
265 .fb_cursor
= soft_cursor
,
268 int __init
hitfb_init(void)
270 unsigned short lcdclor
, ldr3
, ldvndr
;
273 if (fb_get_options("hitfb", NULL
))
276 hitfb_fix
.smem_start
= CONFIG_HD64461_IOBASE
+ 0x02000000;
277 hitfb_fix
.smem_len
= (MACH_HP690
) ? 1024 * 1024 : 512 * 1024;
279 lcdclor
= fb_readw(HD64461_LCDCLOR
);
280 ldvndr
= fb_readw(HD64461_LDVNDR
);
281 ldr3
= fb_readw(HD64461_LDR3
);
286 hitfb_var
.bits_per_pixel
= 8;
287 hitfb_var
.xres
= lcdclor
;
290 hitfb_var
.bits_per_pixel
= 16;
291 hitfb_var
.xres
= lcdclor
/ 2;
294 hitfb_fix
.line_length
= lcdclor
;
295 hitfb_fix
.visual
= (hitfb_var
.bits_per_pixel
== 8) ?
296 FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR
;
297 hitfb_var
.yres
= ldvndr
+ 1;
298 hitfb_var
.xres_virtual
= hitfb_var
.xres
;
299 hitfb_var
.yres_virtual
= hitfb_fix
.smem_len
/ lcdclor
;
300 switch (hitfb_var
.bits_per_pixel
) {
302 hitfb_var
.red
.offset
= 0;
303 hitfb_var
.red
.length
= 8;
304 hitfb_var
.green
.offset
= 0;
305 hitfb_var
.green
.length
= 8;
306 hitfb_var
.blue
.offset
= 0;
307 hitfb_var
.blue
.length
= 8;
308 hitfb_var
.transp
.offset
= 0;
309 hitfb_var
.transp
.length
= 0;
311 case 16: /* RGB 565 */
312 hitfb_var
.red
.offset
= 11;
313 hitfb_var
.red
.length
= 5;
314 hitfb_var
.green
.offset
= 5;
315 hitfb_var
.green
.length
= 6;
316 hitfb_var
.blue
.offset
= 0;
317 hitfb_var
.blue
.length
= 5;
318 hitfb_var
.transp
.offset
= 0;
319 hitfb_var
.transp
.length
= 0;
323 fb_info
.fbops
= &hitfb_ops
;
324 fb_info
.var
= hitfb_var
;
325 fb_info
.fix
= hitfb_fix
;
326 fb_info
.pseudo_palette
= pseudo_palette
;
327 fb_info
.flags
= FBINFO_DEFAULT
;
329 fb_info
.screen_base
= (void *)hitfb_fix
.smem_start
;
331 size
= (fb_info
.var
.bits_per_pixel
== 8) ? 256 : 16;
332 fb_alloc_cmap(&fb_info
.cmap
, size
, 0);
334 if (register_framebuffer(&fb_info
) < 0)
337 printk(KERN_INFO
"fb%d: %s frame buffer device\n",
338 fb_info
.node
, fb_info
.fix
.id
);
342 static void __exit
hitfb_exit(void)
344 unregister_framebuffer(&fb_info
);
347 module_init(hitfb_init
);
348 module_exit(hitfb_exit
);
350 MODULE_LICENSE("GPL");