aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/hitfb.c214
1 files changed, 181 insertions, 33 deletions
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index c6ac0dcd8854..3afb472763c0 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -4,7 +4,7 @@
4 * (C) 1999 Mihai Spatar 4 * (C) 1999 Mihai Spatar
5 * (C) 2000 YAEGASHI Takeshi 5 * (C) 2000 YAEGASHI Takeshi
6 * (C) 2003, 2004 Paul Mundt 6 * (C) 2003, 2004 Paul Mundt
7 * (C) 2003, 2004 Andriy Skulysh 7 * (C) 2003, 2004, 2006 Andriy Skulysh
8 * 8 *
9 * This file is subject to the terms and conditions of the GNU General Public 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 10 * License. See the file COPYING in the main directory of this archive for
@@ -20,14 +20,14 @@
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/platform_device.h>
23#include <linux/fb.h> 24#include <linux/fb.h>
24 25
25#include <asm/machvec.h> 26#include <asm/machvec.h>
26#include <asm/uaccess.h> 27#include <asm/uaccess.h>
27#include <asm/pgtable.h> 28#include <asm/pgtable.h>
28#include <asm/io.h> 29#include <asm/io.h>
29#include <asm/hd64461/hd64461.h> 30#include <asm/hd64461.h>
30
31#include <asm/cpu/dac.h> 31#include <asm/cpu/dac.h>
32#include <asm/hp6xx/hp6xx.h> 32#include <asm/hp6xx/hp6xx.h>
33 33
@@ -43,7 +43,6 @@ static struct fb_var_screeninfo hitfb_var __initdata = {
43static struct fb_fix_screeninfo hitfb_fix __initdata = { 43static struct fb_fix_screeninfo hitfb_fix __initdata = {
44 .id = "Hitachi HD64461", 44 .id = "Hitachi HD64461",
45 .type = FB_TYPE_PACKED_PIXELS, 45 .type = FB_TYPE_PACKED_PIXELS,
46 .ypanstep = 8,
47 .accel = FB_ACCEL_NONE, 46 .accel = FB_ACCEL_NONE,
48}; 47};
49 48
@@ -71,26 +70,14 @@ static inline void hitfb_accel_set_dest(int truecolor, u16 dx, u16 dy,
71 if (truecolor) 70 if (truecolor)
72 saddr <<= 1; 71 saddr <<= 1;
73 72
74 fb_writew(width, HD64461_BBTDWR); 73 fb_writew(width-1, HD64461_BBTDWR);
75 fb_writew(height, HD64461_BBTDHR); 74 fb_writew(height-1, HD64461_BBTDHR);
76 75
77 fb_writew(saddr & 0xffff, HD64461_BBTDSARL); 76 fb_writew(saddr & 0xffff, HD64461_BBTDSARL);
78 fb_writew(saddr >> 16, HD64461_BBTDSARH); 77 fb_writew(saddr >> 16, HD64461_BBTDSARH);
79 78
80} 79}
81 80
82static inline void hitfb_accel_solidfill(int truecolor, u16 dx, u16 dy,
83 u16 width, u16 height, u16 color)
84{
85 hitfb_accel_set_dest(truecolor, dx, dy, width, height);
86
87 fb_writew(0x00f0, HD64461_BBTROPR);
88 fb_writew(16, HD64461_BBTMDR);
89 fb_writew(color, HD64461_GRSCR);
90
91 hitfb_accel_start(truecolor);
92}
93
94static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx, 81static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx,
95 u16 dy, u16 width, u16 height, u16 rop, 82 u16 dy, u16 width, u16 height, u16 rop,
96 u32 mask_addr) 83 u32 mask_addr)
@@ -98,6 +85,8 @@ static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx,
98 u32 saddr, daddr; 85 u32 saddr, daddr;
99 u32 maddr = 0; 86 u32 maddr = 0;
100 87
88 height--;
89 width--;
101 fb_writew(rop, HD64461_BBTROPR); 90 fb_writew(rop, HD64461_BBTROPR);
102 if ((sy < dy) || ((sy == dy) && (sx <= dx))) { 91 if ((sy < dy) || ((sy == dy) && (sx <= dx))) {
103 saddr = WIDTH * (sy + height) + sx + width; 92 saddr = WIDTH * (sy + height) + sx + width;
@@ -144,6 +133,7 @@ static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
144 if (rect->rop != ROP_COPY) 133 if (rect->rop != ROP_COPY)
145 cfb_fillrect(p, rect); 134 cfb_fillrect(p, rect);
146 else { 135 else {
136 hitfb_accel_wait();
147 fb_writew(0x00f0, HD64461_BBTROPR); 137 fb_writew(0x00f0, HD64461_BBTROPR);
148 fb_writew(16, HD64461_BBTMDR); 138 fb_writew(16, HD64461_BBTMDR);
149 139
@@ -159,16 +149,15 @@ static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
159 rect->height); 149 rect->height);
160 hitfb_accel_start(0); 150 hitfb_accel_start(0);
161 } 151 }
162 hitfb_accel_wait();
163 } 152 }
164} 153}
165 154
166static void hitfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) 155static void hitfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
167{ 156{
157 hitfb_accel_wait();
168 hitfb_accel_bitblt(p->var.bits_per_pixel == 16, area->sx, area->sy, 158 hitfb_accel_bitblt(p->var.bits_per_pixel == 16, area->sx, area->sy,
169 area->dx, area->dy, area->width, area->height, 159 area->dx, area->dy, area->width, area->height,
170 0x00cc, 0); 160 0x00cc, 0);
171 hitfb_accel_wait();
172} 161}
173 162
174static int hitfb_pan_display(struct fb_var_screeninfo *var, 163static int hitfb_pan_display(struct fb_var_screeninfo *var,
@@ -180,7 +169,7 @@ static int hitfb_pan_display(struct fb_var_screeninfo *var,
180 if (xoffset != 0) 169 if (xoffset != 0)
181 return -EINVAL; 170 return -EINVAL;
182 171
183 fb_writew(yoffset, HD64461_LCDCBAR); 172 fb_writew((yoffset*info->fix.line_length)>>10, HD64461_LCDCBAR);
184 173
185 return 0; 174 return 0;
186} 175}
@@ -206,13 +195,17 @@ int hitfb_blank(int blank_mode, struct fb_info *info)
206 v &= ~HD64461_STBCR_SLCDST; 195 v &= ~HD64461_STBCR_SLCDST;
207 fb_writew(v, HD64461_STBCR); 196 fb_writew(v, HD64461_STBCR);
208 197
198 v = fb_readw(HD64461_LCDCCR);
199 v &= ~(HD64461_LCDCCR_MOFF | HD64461_LCDCCR_STREQ);
200 fb_writew(v, HD64461_LCDCCR);
201
202 do {
203 v = fb_readw(HD64461_LCDCCR);
204 } while(v&HD64461_LCDCCR_STBACK);
205
209 v = fb_readw(HD64461_LDR1); 206 v = fb_readw(HD64461_LDR1);
210 v |= HD64461_LDR1_DON; 207 v |= HD64461_LDR1_DON;
211 fb_writew(v, HD64461_LDR1); 208 fb_writew(v, HD64461_LDR1);
212
213 v = fb_readw(HD64461_LCDCCR);
214 v &= ~HD64461_LCDCCR_MOFF;
215 fb_writew(v, HD64461_LCDCCR);
216 } 209 }
217 return 0; 210 return 0;
218} 211}
@@ -220,7 +213,7 @@ int hitfb_blank(int blank_mode, struct fb_info *info)
220static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green, 213static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
221 unsigned blue, unsigned transp, struct fb_info *info) 214 unsigned blue, unsigned transp, struct fb_info *info)
222{ 215{
223 if (regno >= info->cmap.len) 216 if (regno >= 256)
224 return 1; 217 return 1;
225 218
226 switch (info->var.bits_per_pixel) { 219 switch (info->var.bits_per_pixel) {
@@ -231,6 +224,8 @@ static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
231 fb_writew(blue >> 10, HD64461_CPTWDR); 224 fb_writew(blue >> 10, HD64461_CPTWDR);
232 break; 225 break;
233 case 16: 226 case 16:
227 if (regno >= 16)
228 return 1;
234 ((u32 *) (info->pseudo_palette))[regno] = 229 ((u32 *) (info->pseudo_palette))[regno] =
235 ((red & 0xf800)) | 230 ((red & 0xf800)) |
236 ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); 231 ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
@@ -239,26 +234,113 @@ static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
239 return 0; 234 return 0;
240} 235}
241 236
237static int hitfb_sync(struct fb_info *info)
238{
239 hitfb_accel_wait();
240
241 return 0;
242}
243
244static int hitfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
245{
246 int maxy;
247
248 var->xres = info->var.xres;
249 var->xres_virtual = info->var.xres;
250 var->yres = info->var.yres;
251
252 if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16))
253 var->bits_per_pixel = info->var.bits_per_pixel;
254
255 if (var->yres_virtual < var->yres)
256 var->yres_virtual = var->yres;
257
258 maxy = info->fix.smem_len / var->xres;
259
260 if (var->bits_per_pixel == 16)
261 maxy /= 2;
262
263 if (var->yres_virtual > maxy)
264 var->yres_virtual = maxy;
265
266 var->xoffset = 0;
267 var->yoffset = 0;
268
269 switch (var->bits_per_pixel) {
270 case 8:
271 var->red.offset = 0;
272 var->red.length = 8;
273 var->green.offset = 0;
274 var->green.length = 8;
275 var->blue.offset = 0;
276 var->blue.length = 8;
277 var->transp.offset = 0;
278 var->transp.length = 0;
279 break;
280 case 16: /* RGB 565 */
281 var->red.offset = 11;
282 var->red.length = 5;
283 var->green.offset = 5;
284 var->green.length = 6;
285 var->blue.offset = 0;
286 var->blue.length = 5;
287 var->transp.offset = 0;
288 var->transp.length = 0;
289 break;
290 }
291
292 return 0;
293}
294
295static int hitfb_set_par(struct fb_info *info)
296{
297 unsigned short ldr3;
298
299 switch (info->var.bits_per_pixel) {
300 case 8:
301 info->fix.line_length = info->var.xres;
302 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
303 info->fix.ypanstep = 16;
304 break;
305 case 16:
306 info->fix.line_length = info->var.xres*2;
307 info->fix.visual = FB_VISUAL_TRUECOLOR;
308 info->fix.ypanstep = 8;
309 break;
310 }
311
312 fb_writew(info->fix.line_length, HD64461_LCDCLOR);
313 ldr3 = fb_readw(HD64461_LDR3);
314 ldr3 &= ~15;
315 ldr3 |= (info->var.bits_per_pixel == 8) ? 4 : 8;
316 fb_writew(ldr3, HD64461_LDR3);
317 return 0;
318}
319
242static struct fb_ops hitfb_ops = { 320static struct fb_ops hitfb_ops = {
243 .owner = THIS_MODULE, 321 .owner = THIS_MODULE,
322 .fb_check_var = hitfb_check_var,
323 .fb_set_par = hitfb_set_par,
244 .fb_setcolreg = hitfb_setcolreg, 324 .fb_setcolreg = hitfb_setcolreg,
245 .fb_blank = hitfb_blank, 325 .fb_blank = hitfb_blank,
326 .fb_sync = hitfb_sync,
246 .fb_pan_display = hitfb_pan_display, 327 .fb_pan_display = hitfb_pan_display,
247 .fb_fillrect = hitfb_fillrect, 328 .fb_fillrect = hitfb_fillrect,
248 .fb_copyarea = hitfb_copyarea, 329 .fb_copyarea = hitfb_copyarea,
249 .fb_imageblit = cfb_imageblit, 330 .fb_imageblit = cfb_imageblit,
250}; 331};
251 332
252int __init hitfb_init(void) 333static int __init hitfb_probe(struct platform_device *dev)
253{ 334{
254 unsigned short lcdclor, ldr3, ldvndr; 335 unsigned short lcdclor, ldr3, ldvndr;
255 int size;
256 336
257 if (fb_get_options("hitfb", NULL)) 337 if (fb_get_options("hitfb", NULL))
258 return -ENODEV; 338 return -ENODEV;
259 339
340 hitfb_fix.mmio_start = CONFIG_HD64461_IOBASE+0x1000;
341 hitfb_fix.mmio_len = 0x1000;
260 hitfb_fix.smem_start = CONFIG_HD64461_IOBASE + 0x02000000; 342 hitfb_fix.smem_start = CONFIG_HD64461_IOBASE + 0x02000000;
261 hitfb_fix.smem_len = (MACH_HP690) ? 1024 * 1024 : 512 * 1024; 343 hitfb_fix.smem_len = 512 * 1024;
262 344
263 lcdclor = fb_readw(HD64461_LCDCLOR); 345 lcdclor = fb_readw(HD64461_LCDCLOR);
264 ldvndr = fb_readw(HD64461_LDVNDR); 346 ldvndr = fb_readw(HD64461_LDVNDR);
@@ -308,12 +390,12 @@ int __init hitfb_init(void)
308 fb_info.var = hitfb_var; 390 fb_info.var = hitfb_var;
309 fb_info.fix = hitfb_fix; 391 fb_info.fix = hitfb_fix;
310 fb_info.pseudo_palette = pseudo_palette; 392 fb_info.pseudo_palette = pseudo_palette;
311 fb_info.flags = FBINFO_DEFAULT; 393 fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
394 FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
312 395
313 fb_info.screen_base = (void *)hitfb_fix.smem_start; 396 fb_info.screen_base = (void *)hitfb_fix.smem_start;
314 397
315 size = (fb_info.var.bits_per_pixel == 8) ? 256 : 16; 398 fb_alloc_cmap(&fb_info.cmap, 256, 0);
316 fb_alloc_cmap(&fb_info.cmap, size, 0);
317 399
318 if (register_framebuffer(&fb_info) < 0) 400 if (register_framebuffer(&fb_info) < 0)
319 return -EINVAL; 401 return -EINVAL;
@@ -323,9 +405,75 @@ int __init hitfb_init(void)
323 return 0; 405 return 0;
324} 406}
325 407
408static int __devexit hitfb_remove(struct platform_device *dev)
409{
410 return unregister_framebuffer(&fb_info);
411}
412
413#ifdef CONFIG_PM
414static int hitfb_suspend(struct platform_device *dev, pm_message_t state)
415{
416 u16 v;
417
418 hitfb_blank(1,0);
419 v = fb_readw(HD64461_STBCR);
420 v |= HD64461_STBCR_SLCKE_IST;
421 fb_writew(v, HD64461_STBCR);
422
423 return 0;
424}
425
426static int hitfb_resume(struct platform_device *dev)
427{
428 u16 v;
429
430 v = fb_readw(HD64461_STBCR);
431 v &= ~HD64461_STBCR_SLCKE_OST;
432 msleep(100);
433 v = fb_readw(HD64461_STBCR);
434 v &= ~HD64461_STBCR_SLCKE_IST;
435 fb_writew(v, HD64461_STBCR);
436 hitfb_blank(0,0);
437
438 return 0;
439}
440#endif
441
442static struct platform_driver hitfb_driver = {
443 .probe = hitfb_probe,
444 .remove = __devexit_p(hitfb_remove),
445#ifdef CONFIG_PM
446 .suspend = hitfb_suspend,
447 .resume = hitfb_resume,
448#endif
449 .driver = {
450 .name = "hitfb",
451 },
452};
453
454static struct platform_device hitfb_device = {
455 .name = "hitfb",
456 .id = -1,
457};
458
459static int __init hitfb_init(void)
460{
461 int ret;
462
463 ret = platform_driver_register(&hitfb_driver);
464 if (!ret) {
465 ret = platform_device_register(&hitfb_device);
466 if (ret)
467 platform_driver_unregister(&hitfb_driver);
468 }
469 return ret;
470}
471
472
326static void __exit hitfb_exit(void) 473static void __exit hitfb_exit(void)
327{ 474{
328 unregister_framebuffer(&fb_info); 475 platform_device_unregister(&hitfb_device);
476 platform_driver_unregister(&hitfb_driver);
329} 477}
330 478
331module_init(hitfb_init); 479module_init(hitfb_init);