diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-16 22:50:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-16 22:50:13 -0400 |
commit | 517d08699b250021303f9a7cf0d758b6dc0748ed (patch) | |
tree | 5e5b0134c3fffb78fe9d8b1641a64ff28fdd7bbc /drivers/video/s1d13xxxfb.c | |
parent | 8eeee4e2f04fc551f50c9d9847da2d73d7d33728 (diff) | |
parent | a34601c5d84134055782ee031d58d82f5440e918 (diff) |
Merge branch 'akpm'
* akpm: (182 commits)
fbdev: bf54x-lq043fb: use kzalloc over kmalloc/memset
fbdev: *bfin*: fix __dev{init,exit} markings
fbdev: *bfin*: drop unnecessary calls to memset
fbdev: bfin-t350mcqb-fb: drop unused local variables
fbdev: blackfin has __raw I/O accessors, so use them in fb.h
fbdev: s1d13xxxfb: add accelerated bitblt functions
tcx: use standard fields for framebuffer physical address and length
fbdev: add support for handoff from firmware to hw framebuffers
intelfb: fix a bug when changing video timing
fbdev: use framebuffer_release() for freeing fb_info structures
radeon: P2G2CLK_ALWAYS_ONb tested twice, should 2nd be P2G2CLK_DAC_ALWAYS_ONb?
s3c-fb: CPUFREQ frequency scaling support
s3c-fb: fix resource releasing on error during probing
carminefb: fix possible access beyond end of carmine_modedb[]
acornfb: remove fb_mmap function
mb862xxfb: use CONFIG_OF instead of CONFIG_PPC_OF
mb862xxfb: restrict compliation of platform driver to PPC
Samsung SoC Framebuffer driver: add Alpha Channel support
atmel-lcdc: fix pixclock upper bound detection
offb: use framebuffer_alloc() to allocate fb_info struct
...
Manually fix up conflicts due to kmemcheck in mm/slab.c
Diffstat (limited to 'drivers/video/s1d13xxxfb.c')
-rw-r--r-- | drivers/video/s1d13xxxfb.c | 341 |
1 files changed, 308 insertions, 33 deletions
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index 0726aecf3b7e..0deb0a8867b7 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * (c) 2004 Simtec Electronics | 3 | * (c) 2004 Simtec Electronics |
4 | * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org> | 4 | * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org> |
5 | * (c) 2009 Kristoffer Ericson <kristoffer.ericson@gmail.com> | ||
5 | * | 6 | * |
6 | * Driver for Epson S1D13xxx series framebuffer chips | 7 | * Driver for Epson S1D13xxx series framebuffer chips |
7 | * | 8 | * |
@@ -10,18 +11,10 @@ | |||
10 | * linux/drivers/video/epson1355fb.c | 11 | * linux/drivers/video/epson1355fb.c |
11 | * linux/drivers/video/epson/s1d13xxxfb.c (2.4 driver by Epson) | 12 | * linux/drivers/video/epson/s1d13xxxfb.c (2.4 driver by Epson) |
12 | * | 13 | * |
13 | * Note, currently only tested on S1D13806 with 16bit CRT. | ||
14 | * As such, this driver might still contain some hardcoded bits relating to | ||
15 | * S1D13806. | ||
16 | * Making it work on other S1D13XXX chips should merely be a matter of adding | ||
17 | * a few switch()s, some missing glue here and there maybe, and split header | ||
18 | * files. | ||
19 | * | ||
20 | * TODO: - handle dual screen display (CRT and LCD at the same time). | 14 | * TODO: - handle dual screen display (CRT and LCD at the same time). |
21 | * - check_var(), mode change, etc. | 15 | * - check_var(), mode change, etc. |
22 | * - PM untested. | 16 | * - probably not SMP safe :) |
23 | * - Accelerated interfaces. | 17 | * - support all bitblt operations on all cards |
24 | * - Probably not SMP safe :) | ||
25 | * | 18 | * |
26 | * This file is subject to the terms and conditions of the GNU General Public | 19 | * This file is subject to the terms and conditions of the GNU General Public |
27 | * License. See the file COPYING in the main directory of this archive for | 20 | * License. See the file COPYING in the main directory of this archive for |
@@ -31,19 +24,24 @@ | |||
31 | #include <linux/module.h> | 24 | #include <linux/module.h> |
32 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
33 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
34 | |||
35 | #include <linux/types.h> | 27 | #include <linux/types.h> |
36 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
37 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
38 | #include <linux/mman.h> | 30 | #include <linux/mman.h> |
39 | #include <linux/fb.h> | 31 | #include <linux/fb.h> |
32 | #include <linux/spinlock_types.h> | ||
33 | #include <linux/spinlock.h> | ||
40 | 34 | ||
41 | #include <asm/io.h> | 35 | #include <asm/io.h> |
42 | 36 | ||
43 | #include <video/s1d13xxxfb.h> | 37 | #include <video/s1d13xxxfb.h> |
44 | 38 | ||
45 | #define PFX "s1d13xxxfb: " | 39 | #define PFX "s1d13xxxfb: " |
40 | #define BLIT "s1d13xxxfb_bitblt: " | ||
46 | 41 | ||
42 | /* | ||
43 | * set this to enable debugging on general functions | ||
44 | */ | ||
47 | #if 0 | 45 | #if 0 |
48 | #define dbg(fmt, args...) do { printk(KERN_INFO fmt, ## args); } while(0) | 46 | #define dbg(fmt, args...) do { printk(KERN_INFO fmt, ## args); } while(0) |
49 | #else | 47 | #else |
@@ -51,7 +49,21 @@ | |||
51 | #endif | 49 | #endif |
52 | 50 | ||
53 | /* | 51 | /* |
54 | * List of card production ids | 52 | * set this to enable debugging on 2D acceleration |
53 | */ | ||
54 | #if 0 | ||
55 | #define dbg_blit(fmt, args...) do { printk(KERN_INFO BLIT fmt, ## args); } while (0) | ||
56 | #else | ||
57 | #define dbg_blit(fmt, args...) do { } while (0) | ||
58 | #endif | ||
59 | |||
60 | /* | ||
61 | * we make sure only one bitblt operation is running | ||
62 | */ | ||
63 | static DEFINE_SPINLOCK(s1d13xxxfb_bitblt_lock); | ||
64 | |||
65 | /* | ||
66 | * list of card production ids | ||
55 | */ | 67 | */ |
56 | static const int s1d13xxxfb_prod_ids[] = { | 68 | static const int s1d13xxxfb_prod_ids[] = { |
57 | S1D13505_PROD_ID, | 69 | S1D13505_PROD_ID, |
@@ -69,7 +81,7 @@ static const char *s1d13xxxfb_prod_names[] = { | |||
69 | }; | 81 | }; |
70 | 82 | ||
71 | /* | 83 | /* |
72 | * Here we define the default struct fb_fix_screeninfo | 84 | * here we define the default struct fb_fix_screeninfo |
73 | */ | 85 | */ |
74 | static struct fb_fix_screeninfo __devinitdata s1d13xxxfb_fix = { | 86 | static struct fb_fix_screeninfo __devinitdata s1d13xxxfb_fix = { |
75 | .id = S1D_FBID, | 87 | .id = S1D_FBID, |
@@ -145,8 +157,10 @@ crt_enable(struct s1d13xxxfb_par *par, int enable) | |||
145 | s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode); | 157 | s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode); |
146 | } | 158 | } |
147 | 159 | ||
148 | /* framebuffer control routines */ | ||
149 | 160 | ||
161 | /************************************************************* | ||
162 | framebuffer control functions | ||
163 | *************************************************************/ | ||
150 | static inline void | 164 | static inline void |
151 | s1d13xxxfb_setup_pseudocolour(struct fb_info *info) | 165 | s1d13xxxfb_setup_pseudocolour(struct fb_info *info) |
152 | { | 166 | { |
@@ -242,13 +256,13 @@ s1d13xxxfb_set_par(struct fb_info *info) | |||
242 | } | 256 | } |
243 | 257 | ||
244 | /** | 258 | /** |
245 | * s1d13xxxfb_setcolreg - sets a color register. | 259 | * s1d13xxxfb_setcolreg - sets a color register. |
246 | * @regno: Which register in the CLUT we are programming | 260 | * @regno: Which register in the CLUT we are programming |
247 | * @red: The red value which can be up to 16 bits wide | 261 | * @red: The red value which can be up to 16 bits wide |
248 | * @green: The green value which can be up to 16 bits wide | 262 | * @green: The green value which can be up to 16 bits wide |
249 | * @blue: The blue value which can be up to 16 bits wide. | 263 | * @blue: The blue value which can be up to 16 bits wide. |
250 | * @transp: If supported the alpha value which can be up to 16 bits wide. | 264 | * @transp: If supported the alpha value which can be up to 16 bits wide. |
251 | * @info: frame buffer info structure | 265 | * @info: frame buffer info structure |
252 | * | 266 | * |
253 | * Returns negative errno on error, or zero on success. | 267 | * Returns negative errno on error, or zero on success. |
254 | */ | 268 | */ |
@@ -351,15 +365,15 @@ s1d13xxxfb_blank(int blank_mode, struct fb_info *info) | |||
351 | } | 365 | } |
352 | 366 | ||
353 | /** | 367 | /** |
354 | * s1d13xxxfb_pan_display - Pans the display. | 368 | * s1d13xxxfb_pan_display - Pans the display. |
355 | * @var: frame buffer variable screen structure | 369 | * @var: frame buffer variable screen structure |
356 | * @info: frame buffer structure that represents a single frame buffer | 370 | * @info: frame buffer structure that represents a single frame buffer |
357 | * | 371 | * |
358 | * Pan (or wrap, depending on the `vmode' field) the display using the | 372 | * Pan (or wrap, depending on the `vmode' field) the display using the |
359 | * `yoffset' field of the `var' structure (`xoffset' not yet supported). | 373 | * `yoffset' field of the `var' structure (`xoffset' not yet supported). |
360 | * If the values don't fit, return -EINVAL. | 374 | * If the values don't fit, return -EINVAL. |
361 | * | 375 | * |
362 | * Returns negative errno on error, or zero on success. | 376 | * Returns negative errno on error, or zero on success. |
363 | */ | 377 | */ |
364 | static int | 378 | static int |
365 | s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | 379 | s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) |
@@ -390,8 +404,259 @@ s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
390 | return 0; | 404 | return 0; |
391 | } | 405 | } |
392 | 406 | ||
393 | /* framebuffer information structures */ | 407 | /************************************************************ |
408 | functions to handle bitblt acceleration | ||
409 | ************************************************************/ | ||
410 | |||
411 | /** | ||
412 | * bltbit_wait_bitset - waits for change in register value | ||
413 | * @info : framebuffer structure | ||
414 | * @bit : value expected in register | ||
415 | * @timeout : ... | ||
416 | * | ||
417 | * waits until value changes INTO bit | ||
418 | */ | ||
419 | static u8 | ||
420 | bltbit_wait_bitset(struct fb_info *info, u8 bit, int timeout) | ||
421 | { | ||
422 | while (!(s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0) & bit)) { | ||
423 | udelay(10); | ||
424 | if (!--timeout) { | ||
425 | dbg_blit("wait_bitset timeout\n"); | ||
426 | break; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | return timeout; | ||
431 | } | ||
432 | |||
433 | /** | ||
434 | * bltbit_wait_bitclear - waits for change in register value | ||
435 | * @info : frambuffer structure | ||
436 | * @bit : value currently in register | ||
437 | * @timeout : ... | ||
438 | * | ||
439 | * waits until value changes FROM bit | ||
440 | * | ||
441 | */ | ||
442 | static u8 | ||
443 | bltbit_wait_bitclear(struct fb_info *info, u8 bit, int timeout) | ||
444 | { | ||
445 | while (s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0) & bit) { | ||
446 | udelay(10); | ||
447 | if (!--timeout) { | ||
448 | dbg_blit("wait_bitclear timeout\n"); | ||
449 | break; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | return timeout; | ||
454 | } | ||
455 | |||
456 | /** | ||
457 | * bltbit_fifo_status - checks the current status of the fifo | ||
458 | * @info : framebuffer structure | ||
459 | * | ||
460 | * returns number of free words in buffer | ||
461 | */ | ||
462 | static u8 | ||
463 | bltbit_fifo_status(struct fb_info *info) | ||
464 | { | ||
465 | u8 status; | ||
394 | 466 | ||
467 | status = s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0); | ||
468 | |||
469 | /* its empty so room for 16 words */ | ||
470 | if (status & BBLT_FIFO_EMPTY) | ||
471 | return 16; | ||
472 | |||
473 | /* its full so we dont want to add */ | ||
474 | if (status & BBLT_FIFO_FULL) | ||
475 | return 0; | ||
476 | |||
477 | /* its atleast half full but we can add one atleast */ | ||
478 | if (status & BBLT_FIFO_NOT_FULL) | ||
479 | return 1; | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | * s1d13xxxfb_bitblt_copyarea - accelerated copyarea function | ||
486 | * @info : framebuffer structure | ||
487 | * @area : fb_copyarea structure | ||
488 | * | ||
489 | * supports (atleast) S1D13506 | ||
490 | * | ||
491 | */ | ||
492 | static void | ||
493 | s1d13xxxfb_bitblt_copyarea(struct fb_info *info, const struct fb_copyarea *area) | ||
494 | { | ||
495 | u32 dst, src; | ||
496 | u32 stride; | ||
497 | u16 reverse = 0; | ||
498 | u16 sx = area->sx, sy = area->sy; | ||
499 | u16 dx = area->dx, dy = area->dy; | ||
500 | u16 width = area->width, height = area->height; | ||
501 | u16 bpp; | ||
502 | |||
503 | spin_lock(&s1d13xxxfb_bitblt_lock); | ||
504 | |||
505 | /* bytes per xres line */ | ||
506 | bpp = (info->var.bits_per_pixel >> 3); | ||
507 | stride = bpp * info->var.xres; | ||
508 | |||
509 | /* reverse, calculate the last pixel in rectangle */ | ||
510 | if ((dy > sy) || ((dy == sy) && (dx >= sx))) { | ||
511 | dst = (((dy + height - 1) * stride) + (bpp * (dx + width - 1))); | ||
512 | src = (((sy + height - 1) * stride) + (bpp * (sx + width - 1))); | ||
513 | reverse = 1; | ||
514 | /* not reverse, calculate the first pixel in rectangle */ | ||
515 | } else { /* (y * xres) + (bpp * x) */ | ||
516 | dst = (dy * stride) + (bpp * dx); | ||
517 | src = (sy * stride) + (bpp * sx); | ||
518 | } | ||
519 | |||
520 | /* set source adress */ | ||
521 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START0, (src & 0xff)); | ||
522 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START1, (src >> 8) & 0x00ff); | ||
523 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START2, (src >> 16) & 0x00ff); | ||
524 | |||
525 | /* set destination adress */ | ||
526 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dst & 0xff)); | ||
527 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, (dst >> 8) & 0x00ff); | ||
528 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, (dst >> 16) & 0x00ff); | ||
529 | |||
530 | /* program height and width */ | ||
531 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH0, (width & 0xff) - 1); | ||
532 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH1, (width >> 8)); | ||
533 | |||
534 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT0, (height & 0xff) - 1); | ||
535 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT1, (height >> 8)); | ||
536 | |||
537 | /* negative direction ROP */ | ||
538 | if (reverse == 1) { | ||
539 | dbg_blit("(copyarea) negative rop\n"); | ||
540 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, 0x03); | ||
541 | } else /* positive direction ROP */ { | ||
542 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, 0x02); | ||
543 | dbg_blit("(copyarea) positive rop\n"); | ||
544 | } | ||
545 | |||
546 | /* set for rectangel mode and not linear */ | ||
547 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x0); | ||
548 | |||
549 | /* setup the bpp 1 = 16bpp, 0 = 8bpp*/ | ||
550 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL1, (bpp >> 1)); | ||
551 | |||
552 | /* set words per xres */ | ||
553 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF0, (stride >> 1) & 0xff); | ||
554 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF1, (stride >> 9)); | ||
555 | |||
556 | dbg_blit("(copyarea) dx=%d, dy=%d\n", dx, dy); | ||
557 | dbg_blit("(copyarea) sx=%d, sy=%d\n", sx, sy); | ||
558 | dbg_blit("(copyarea) width=%d, height=%d\n", width - 1, height - 1); | ||
559 | dbg_blit("(copyarea) stride=%d\n", stride); | ||
560 | dbg_blit("(copyarea) bpp=%d=0x0%d, mem_offset1=%d, mem_offset2=%d\n", bpp, (bpp >> 1), | ||
561 | (stride >> 1) & 0xff, stride >> 9); | ||
562 | |||
563 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CC_EXP, 0x0c); | ||
564 | |||
565 | /* initialize the engine */ | ||
566 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x80); | ||
567 | |||
568 | /* wait to complete */ | ||
569 | bltbit_wait_bitclear(info, 0x80, 8000); | ||
570 | |||
571 | spin_unlock(&s1d13xxxfb_bitblt_lock); | ||
572 | } | ||
573 | |||
574 | /** | ||
575 | * | ||
576 | * s1d13xxxfb_bitblt_solidfill - accelerated solidfill function | ||
577 | * @info : framebuffer structure | ||
578 | * @rect : fb_fillrect structure | ||
579 | * | ||
580 | * supports (atleast 13506) | ||
581 | * | ||
582 | **/ | ||
583 | static void | ||
584 | s1d13xxxfb_bitblt_solidfill(struct fb_info *info, const struct fb_fillrect *rect) | ||
585 | { | ||
586 | u32 screen_stride, dest; | ||
587 | u32 fg; | ||
588 | u16 bpp = (info->var.bits_per_pixel >> 3); | ||
589 | |||
590 | /* grab spinlock */ | ||
591 | spin_lock(&s1d13xxxfb_bitblt_lock); | ||
592 | |||
593 | /* bytes per x width */ | ||
594 | screen_stride = (bpp * info->var.xres); | ||
595 | |||
596 | /* bytes to starting point */ | ||
597 | dest = ((rect->dy * screen_stride) + (bpp * rect->dx)); | ||
598 | |||
599 | dbg_blit("(solidfill) dx=%d, dy=%d, stride=%d, dest=%d\n" | ||
600 | "(solidfill) : rect_width=%d, rect_height=%d\n", | ||
601 | rect->dx, rect->dy, screen_stride, dest, | ||
602 | rect->width - 1, rect->height - 1); | ||
603 | |||
604 | dbg_blit("(solidfill) : xres=%d, yres=%d, bpp=%d\n", | ||
605 | info->var.xres, info->var.yres, | ||
606 | info->var.bits_per_pixel); | ||
607 | dbg_blit("(solidfill) : rop=%d\n", rect->rop); | ||
608 | |||
609 | /* We split the destination into the three registers */ | ||
610 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dest & 0x00ff)); | ||
611 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, ((dest >> 8) & 0x00ff)); | ||
612 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, ((dest >> 16) & 0x00ff)); | ||
613 | |||
614 | /* give information regarding rectangel width */ | ||
615 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH0, ((rect->width) & 0x00ff) - 1); | ||
616 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_WIDTH1, (rect->width >> 8)); | ||
617 | |||
618 | /* give information regarding rectangel height */ | ||
619 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT0, ((rect->height) & 0x00ff) - 1); | ||
620 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_HEIGHT1, (rect->height >> 8)); | ||
621 | |||
622 | if (info->fix.visual == FB_VISUAL_TRUECOLOR || | ||
623 | info->fix.visual == FB_VISUAL_DIRECTCOLOR) { | ||
624 | fg = ((u32 *)info->pseudo_palette)[rect->color]; | ||
625 | dbg_blit("(solidfill) truecolor/directcolor\n"); | ||
626 | dbg_blit("(solidfill) pseudo_palette[%d] = %d\n", rect->color, fg); | ||
627 | } else { | ||
628 | fg = rect->color; | ||
629 | dbg_blit("(solidfill) color = %d\n", rect->color); | ||
630 | } | ||
631 | |||
632 | /* set foreground color */ | ||
633 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_FGC0, (fg & 0xff)); | ||
634 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_FGC1, (fg >> 8) & 0xff); | ||
635 | |||
636 | /* set rectangual region of memory (rectangle and not linear) */ | ||
637 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x0); | ||
638 | |||
639 | /* set operation mode SOLID_FILL */ | ||
640 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_OP, BBLT_SOLID_FILL); | ||
641 | |||
642 | /* set bits per pixel (1 = 16bpp, 0 = 8bpp) */ | ||
643 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL1, (info->var.bits_per_pixel >> 4)); | ||
644 | |||
645 | /* set the memory offset for the bblt in word sizes */ | ||
646 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF0, (screen_stride >> 1) & 0x00ff); | ||
647 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_MEM_OFF1, (screen_stride >> 9)); | ||
648 | |||
649 | /* and away we go.... */ | ||
650 | s1d13xxxfb_writereg(info->par, S1DREG_BBLT_CTL0, 0x80); | ||
651 | |||
652 | /* wait until its done */ | ||
653 | bltbit_wait_bitclear(info, 0x80, 8000); | ||
654 | |||
655 | /* let others play */ | ||
656 | spin_unlock(&s1d13xxxfb_bitblt_lock); | ||
657 | } | ||
658 | |||
659 | /* framebuffer information structures */ | ||
395 | static struct fb_ops s1d13xxxfb_fbops = { | 660 | static struct fb_ops s1d13xxxfb_fbops = { |
396 | .owner = THIS_MODULE, | 661 | .owner = THIS_MODULE, |
397 | .fb_set_par = s1d13xxxfb_set_par, | 662 | .fb_set_par = s1d13xxxfb_set_par, |
@@ -400,7 +665,7 @@ static struct fb_ops s1d13xxxfb_fbops = { | |||
400 | 665 | ||
401 | .fb_pan_display = s1d13xxxfb_pan_display, | 666 | .fb_pan_display = s1d13xxxfb_pan_display, |
402 | 667 | ||
403 | /* to be replaced by any acceleration we can */ | 668 | /* gets replaced at chip detection time */ |
404 | .fb_fillrect = cfb_fillrect, | 669 | .fb_fillrect = cfb_fillrect, |
405 | .fb_copyarea = cfb_copyarea, | 670 | .fb_copyarea = cfb_copyarea, |
406 | .fb_imageblit = cfb_imageblit, | 671 | .fb_imageblit = cfb_imageblit, |
@@ -412,9 +677,9 @@ static int s1d13xxxfb_width_tab[2][4] __devinitdata = { | |||
412 | }; | 677 | }; |
413 | 678 | ||
414 | /** | 679 | /** |
415 | * s1d13xxxfb_fetch_hw_state - Configure the framebuffer according to | 680 | * s1d13xxxfb_fetch_hw_state - Configure the framebuffer according to |
416 | * hardware setup. | 681 | * hardware setup. |
417 | * @info: frame buffer structure | 682 | * @info: frame buffer structure |
418 | * | 683 | * |
419 | * We setup the framebuffer structures according to the current | 684 | * We setup the framebuffer structures according to the current |
420 | * hardware setup. On some machines, the BIOS will have filled | 685 | * hardware setup. On some machines, the BIOS will have filled |
@@ -569,7 +834,6 @@ s1d13xxxfb_probe(struct platform_device *pdev) | |||
569 | if (pdata && pdata->platform_init_video) | 834 | if (pdata && pdata->platform_init_video) |
570 | pdata->platform_init_video(); | 835 | pdata->platform_init_video(); |
571 | 836 | ||
572 | |||
573 | if (pdev->num_resources != 2) { | 837 | if (pdev->num_resources != 2) { |
574 | dev_err(&pdev->dev, "invalid num_resources: %i\n", | 838 | dev_err(&pdev->dev, "invalid num_resources: %i\n", |
575 | pdev->num_resources); | 839 | pdev->num_resources); |
@@ -655,16 +919,27 @@ s1d13xxxfb_probe(struct platform_device *pdev) | |||
655 | 919 | ||
656 | info->fix = s1d13xxxfb_fix; | 920 | info->fix = s1d13xxxfb_fix; |
657 | info->fix.mmio_start = pdev->resource[1].start; | 921 | info->fix.mmio_start = pdev->resource[1].start; |
658 | info->fix.mmio_len = pdev->resource[1].end - pdev->resource[1].start +1; | 922 | info->fix.mmio_len = pdev->resource[1].end - pdev->resource[1].start + 1; |
659 | info->fix.smem_start = pdev->resource[0].start; | 923 | info->fix.smem_start = pdev->resource[0].start; |
660 | info->fix.smem_len = pdev->resource[0].end - pdev->resource[0].start +1; | 924 | info->fix.smem_len = pdev->resource[0].end - pdev->resource[0].start + 1; |
661 | 925 | ||
662 | printk(KERN_INFO PFX "regs mapped at 0x%p, fb %d KiB mapped at 0x%p\n", | 926 | printk(KERN_INFO PFX "regs mapped at 0x%p, fb %d KiB mapped at 0x%p\n", |
663 | default_par->regs, info->fix.smem_len / 1024, info->screen_base); | 927 | default_par->regs, info->fix.smem_len / 1024, info->screen_base); |
664 | 928 | ||
665 | info->par = default_par; | 929 | info->par = default_par; |
666 | info->fbops = &s1d13xxxfb_fbops; | ||
667 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; | 930 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; |
931 | info->fbops = &s1d13xxxfb_fbops; | ||
932 | |||
933 | switch(prod_id) { | ||
934 | case S1D13506_PROD_ID: /* activate acceleration */ | ||
935 | s1d13xxxfb_fbops.fb_fillrect = s1d13xxxfb_bitblt_solidfill; | ||
936 | s1d13xxxfb_fbops.fb_copyarea = s1d13xxxfb_bitblt_copyarea; | ||
937 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | | ||
938 | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA; | ||
939 | break; | ||
940 | default: | ||
941 | break; | ||
942 | } | ||
668 | 943 | ||
669 | /* perform "manual" chip initialization, if needed */ | 944 | /* perform "manual" chip initialization, if needed */ |
670 | if (pdata && pdata->initregs) | 945 | if (pdata && pdata->initregs) |