aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Miao <ycmiao@ycmiao-hp520.(none)>2008-12-23 04:49:43 -0500
committerEric Miao <eric.miao@marvell.com>2008-12-29 05:00:04 -0500
commit198fc108ee4c2cd3f08954eae6a819c81c03214b (patch)
tree153fdb793142ef5ee8e0ab6198dcde32866b062c
parent3f16ff608a75c8bf28c8cafed12e076d67a3602a (diff)
[ARM] pxafb: add support for overlay1 and overlay2 as framebuffer devices
PXA27x and later processors support overlay1 and overlay2 on-top of the base framebuffer (although under-neath the base is also possible). They support palette and no-palette RGB formats, as well as YUV formats (only available on overlay2). These overlays have dedicated DMA channels and behave in a similar way as a framebuffer. This heavily simplified and re-structured work is based on the original pxafb_overlay.c (which is pending for mainline merge for a long time). The major problems with this pxafb_overlay.c are (if you are interested in the history): 1. heavily redundant (the control logics for overlay1 and overlay2 are actually identical except for some small operations, which are now abstracted into a 'pxafb_layer_ops' structure) 2. a lot of useless and un-tested code (two workarounds which are now fixed on mature silicons) 3. cursorfb is actually useless, hardware cursor should not be used this way, and the code was actually un-tested for a long time. The code in this patch should be self-explanatory, I tried to add minimum comments. As said, this is basically simplified, there are several things still on the pending list: 1. palette mode is un-supported and un-tested (although re-using the palette code of the base framebuffer is actually very easy now with previous clean-up patches) 2. fb_pan_display for overlay(s) is un-supported 3. the base framebuffer can actually be abstracted by 'pxafb_layer' as well, which will help further re-use of the code and keep a better and consistent structure. (This is the reason I named it 'pxafb_layer' instead of 'pxafb_overlay' or something alike) See Documentation/fb/pxafb.txt for additional usage information. Signed-off-by: Eric Miao <eric.miao@marvell.com> Cc: Rodolfo Giometti <giometti@linux.it> Signed-off-by: Eric Miao <ycmiao@ycmiao-hp520.(none)>
-rw-r--r--Documentation/fb/pxafb.txt84
-rw-r--r--arch/arm/mach-pxa/include/mach/regs-lcd.h34
-rw-r--r--drivers/video/Kconfig5
-rw-r--r--drivers/video/pxafb.c364
-rw-r--r--drivers/video/pxafb.h45
5 files changed, 516 insertions, 16 deletions
diff --git a/Documentation/fb/pxafb.txt b/Documentation/fb/pxafb.txt
index ad94b5ca0095..d143a0a749f9 100644
--- a/Documentation/fb/pxafb.txt
+++ b/Documentation/fb/pxafb.txt
@@ -56,3 +56,87 @@ outputen:POLARITY
56pixclockpol:POLARITY 56pixclockpol:POLARITY
57 pixel clock polarity 57 pixel clock polarity
58 0 => falling edge, 1 => rising edge 58 0 => falling edge, 1 => rising edge
59
60
61Overlay Support for PXA27x and later LCD controllers
62====================================================
63
64 PXA27x and later processors support overlay1 and overlay2 on-top of the
65 base framebuffer (although under-neath the base is also possible). They
66 support palette and no-palette RGB formats, as well as YUV formats (only
67 available on overlay2). These overlays have dedicated DMA channels and
68 behave in a similar way as a framebuffer.
69
70 However, there are some differences between these overlay framebuffers
71 and normal framebuffers, as listed below:
72
73 1. overlay can start at a 32-bit word aligned position within the base
74 framebuffer, which means they have a start (x, y). This information
75 is encoded into var->nonstd (no, var->xoffset and var->yoffset are
76 not for such purpose).
77
78 2. overlay framebuffer is allocated dynamically according to specified
79 'struct fb_var_screeninfo', the amount is decided by:
80
81 var->xres_virtual * var->yres_virtual * bpp
82
83 bpp = 16 -- for RGB565 or RGBT555
84 = 24 -- for YUV444 packed
85 = 24 -- for YUV444 planar
86 = 16 -- for YUV422 planar (1 pixel = 1 Y + 1/2 Cb + 1/2 Cr)
87 = 12 -- for YUV420 planar (1 pixel = 1 Y + 1/4 Cb + 1/4 Cr)
88
89 NOTE:
90
91 a. overlay does not support panning in x-direction, thus
92 var->xres_virtual will always be equal to var->xres
93
94 b. line length of overlay(s) must be on a 32-bit word boundary,
95 for YUV planar modes, it is a requirement for the component
96 with minimum bits per pixel, e.g. for YUV420, Cr component
97 for one pixel is actually 2-bits, it means the line length
98 should be a multiple of 16-pixels
99
100 c. starting horizontal position (XPOS) should start on a 32-bit
101 word boundary, otherwise the fb_check_var() will just fail.
102
103 d. the rectangle of the overlay should be within the base plane,
104 otherwise fail
105
106 Applications should follow the sequence below to operate an overlay
107 framebuffer:
108
109 a. open("/dev/fb[1-2]", ...)
110 b. ioctl(fd, FBIOGET_VSCREENINFO, ...)
111 c. modify 'var' with desired parameters:
112 1) var->xres and var->yres
113 2) larger var->yres_virtual if more memory is required,
114 usually for double-buffering
115 3) var->nonstd for starting (x, y) and color format
116 4) var->{red, green, blue, transp} if RGB mode is to be used
117 d. ioctl(fd, FBIOPUT_VSCREENINFO, ...)
118 e. ioctl(fd, FBIOGET_FSCREENINFO, ...)
119 f. mmap
120 g. ...
121
122 3. for YUV planar formats, these are actually not supported within the
123 framebuffer framework, application has to take care of the offsets
124 and lengths of each component within the framebuffer.
125
126 4. var->nonstd is used to pass starting (x, y) position and color format,
127 the detailed bit fields are shown below:
128
129 31 23 20 10 0
130 +-----------------+---+----------+----------+
131 | ... unused ... |FOR| XPOS | YPOS |
132 +-----------------+---+----------+----------+
133
134 FOR - color format, as defined by OVERLAY_FORMAT_* in pxafb.h
135 0 - RGB
136 1 - YUV444 PACKED
137 2 - YUV444 PLANAR
138 3 - YUV422 PLANAR
139 4 - YUR420 PLANAR
140
141 XPOS - starting horizontal position
142 YPOS - starting vertical position
diff --git a/arch/arm/mach-pxa/include/mach/regs-lcd.h b/arch/arm/mach-pxa/include/mach/regs-lcd.h
index aff3b876a7bf..f82dcea792d9 100644
--- a/arch/arm/mach-pxa/include/mach/regs-lcd.h
+++ b/arch/arm/mach-pxa/include/mach/regs-lcd.h
@@ -12,7 +12,8 @@
12#define LCCR3 (0x00C) /* LCD Controller Control Register 3 */ 12#define LCCR3 (0x00C) /* LCD Controller Control Register 3 */
13#define LCCR4 (0x010) /* LCD Controller Control Register 4 */ 13#define LCCR4 (0x010) /* LCD Controller Control Register 4 */
14#define LCCR5 (0x014) /* LCD Controller Control Register 5 */ 14#define LCCR5 (0x014) /* LCD Controller Control Register 5 */
15#define LCSR (0x038) /* LCD Controller Status Register */ 15#define LCSR (0x038) /* LCD Controller Status Register 0 */
16#define LCSR1 (0x034) /* LCD Controller Status Register 1 */
16#define LIIDR (0x03C) /* LCD Controller Interrupt ID Register */ 17#define LIIDR (0x03C) /* LCD Controller Interrupt ID Register */
17#define TMEDRGBR (0x040) /* TMED RGB Seed Register */ 18#define TMEDRGBR (0x040) /* TMED RGB Seed Register */
18#define TMEDCR (0x044) /* TMED Control Register */ 19#define TMEDCR (0x044) /* TMED Control Register */
@@ -25,6 +26,11 @@
25#define FBR5 (0x110) /* DMA Channel 2 Frame Branch Register */ 26#define FBR5 (0x110) /* DMA Channel 2 Frame Branch Register */
26#define FBR6 (0x114) /* DMA Channel 2 Frame Branch Register */ 27#define FBR6 (0x114) /* DMA Channel 2 Frame Branch Register */
27 28
29#define OVL1C1 (0x050) /* Overlay 1 Control Register 1 */
30#define OVL1C2 (0x060) /* Overlay 1 Control Register 2 */
31#define OVL2C1 (0x070) /* Overlay 2 Control Register 1 */
32#define OVL2C2 (0x080) /* Overlay 2 Control Register 2 */
33
28#define CMDCR (0x100) /* Command Control Register */ 34#define CMDCR (0x100) /* Command Control Register */
29#define PRSR (0x104) /* Panel Read Status Register */ 35#define PRSR (0x104) /* Panel Read Status Register */
30 36
@@ -42,16 +48,12 @@
42#define LCCR4_PAL_FOR_MASK (3 << 15) 48#define LCCR4_PAL_FOR_MASK (3 << 15)
43 49
44#define FDADR0 (0x200) /* DMA Channel 0 Frame Descriptor Address Register */ 50#define FDADR0 (0x200) /* DMA Channel 0 Frame Descriptor Address Register */
45#define FSADR0 (0x204) /* DMA Channel 0 Frame Source Address Register */
46#define FIDR0 (0x208) /* DMA Channel 0 Frame ID Register */
47#define LDCMD0 (0x20C) /* DMA Channel 0 Command Register */
48#define FDADR1 (0x210) /* DMA Channel 1 Frame Descriptor Address Register */ 51#define FDADR1 (0x210) /* DMA Channel 1 Frame Descriptor Address Register */
49#define FSADR1 (0x214) /* DMA Channel 1 Frame Source Address Register */ 52#define FDADR2 (0x220) /* DMA Channel 2 Frame Descriptor Address Register */
50#define FIDR1 (0x218) /* DMA Channel 1 Frame ID Register */ 53#define FDADR3 (0x230) /* DMA Channel 3 Frame Descriptor Address Register */
51#define LDCMD1 (0x21C) /* DMA Channel 1 Command Register */ 54#define FDADR4 (0x240) /* DMA Channel 4 Frame Descriptor Address Register */
55#define FDADR5 (0x250) /* DMA Channel 5 Frame Descriptor Address Register */
52#define FDADR6 (0x260) /* DMA Channel 6 Frame Descriptor Address Register */ 56#define FDADR6 (0x260) /* DMA Channel 6 Frame Descriptor Address Register */
53#define FSADR6 (0x264) /* DMA Channel 6 Frame Source Address Register */
54#define FIDR6 (0x268) /* DMA Channel 6 Frame ID Register */
55 57
56#define LCCR0_ENB (1 << 0) /* LCD Controller enable */ 58#define LCCR0_ENB (1 << 0) /* LCD Controller enable */
57#define LCCR0_CMS (1 << 1) /* Color/Monochrome Display Select */ 59#define LCCR0_CMS (1 << 1) /* Color/Monochrome Display Select */
@@ -151,8 +153,22 @@
151#define LCSR_RD_ST (1 << 11) /* read status */ 153#define LCSR_RD_ST (1 << 11) /* read status */
152#define LCSR_CMD_INT (1 << 12) /* command interrupt */ 154#define LCSR_CMD_INT (1 << 12) /* command interrupt */
153 155
156#define LCSR1_IU(x) (1 << ((x) + 23)) /* Input FIFO underrun */
157#define LCSR1_BS(x) (1 << ((x) + 15)) /* Branch Status */
158#define LCSR1_EOF(x) (1 << ((x) + 7)) /* End of Frame Status */
159#define LCSR1_SOF(x) (1 << ((x) - 1)) /* Start of Frame Status */
160
154#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */ 161#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
155 162
163/* overlay control registers */
164#define OVLxC1_PPL(x) ((((x) - 1) & 0x3ff) << 0) /* Pixels Per Line */
165#define OVLxC1_LPO(x) ((((x) - 1) & 0x3ff) << 10) /* Number of Lines */
166#define OVLxC1_BPP(x) (((x) & 0xf) << 20) /* Bits Per Pixel */
167#define OVLxC1_OEN (1 << 31) /* Enable bit for Overlay */
168#define OVLxC2_XPOS(x) (((x) & 0x3ff) << 0) /* Horizontal Position */
169#define OVLxC2_YPOS(x) (((x) & 0x3ff) << 10) /* Vertical Position */
170#define OVL2C2_PFOR(x) (((x) & 0x7) << 20) /* Pixel Format */
171
156/* smartpanel related */ 172/* smartpanel related */
157#define PRSR_DATA(x) ((x) & 0xff) /* Panel Data */ 173#define PRSR_DATA(x) ((x) & 0xff) /* Panel Data */
158#define PRSR_A0 (1 << 8) /* Read Data Source */ 174#define PRSR_A0 (1 << 8) /* Read Data Source */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3f3ce13fef43..486d81ca02a3 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1817,6 +1817,11 @@ config FB_PXA
1817 1817
1818 If unsure, say N. 1818 If unsure, say N.
1819 1819
1820config FB_PXA_OVERLAY
1821 bool "Support PXA27x/PXA3xx Overlay(s) as framebuffer"
1822 default n
1823 depends on FB_PXA && (PXA27x || PXA3xx)
1824
1820config FB_PXA_SMARTPANEL 1825config FB_PXA_SMARTPANEL
1821 bool "PXA Smartpanel LCD support" 1826 bool "PXA Smartpanel LCD support"
1822 default n 1827 default n
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 7935706a7565..3a41ea10e8ec 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -20,6 +20,16 @@
20 * 20 *
21 * linux-arm-kernel@lists.arm.linux.org.uk 21 * linux-arm-kernel@lists.arm.linux.org.uk
22 * 22 *
23 * Add support for overlay1 and overlay2 based on pxafb_overlay.c:
24 *
25 * Copyright (C) 2004, Intel Corporation
26 *
27 * 2003/08/27: <yu.tang@intel.com>
28 * 2004/03/10: <stanley.cai@intel.com>
29 * 2004/10/28: <yan.yin@intel.com>
30 *
31 * Copyright (C) 2006-2008 Marvell International Ltd.
32 * All Rights Reserved
23 */ 33 */
24 34
25#include <linux/module.h> 35#include <linux/module.h>
@@ -72,6 +82,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
72 struct pxafb_info *); 82 struct pxafb_info *);
73static void set_ctrlr_state(struct pxafb_info *fbi, u_int state); 83static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
74static void setup_base_frame(struct pxafb_info *fbi, int branch); 84static void setup_base_frame(struct pxafb_info *fbi, int branch);
85static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
86 unsigned long offset, size_t size);
75 87
76static unsigned long video_mem_size = 0; 88static unsigned long video_mem_size = 0;
77 89
@@ -581,6 +593,330 @@ static struct fb_ops pxafb_ops = {
581 .fb_blank = pxafb_blank, 593 .fb_blank = pxafb_blank,
582}; 594};
583 595
596#ifdef CONFIG_FB_PXA_OVERLAY
597static void overlay1fb_setup(struct pxafb_layer *ofb)
598{
599 int size = ofb->fb.fix.line_length * ofb->fb.var.yres_virtual;
600 unsigned long start = ofb->video_mem_phys;
601 setup_frame_dma(ofb->fbi, DMA_OV1, PAL_NONE, start, size);
602}
603
604/* Depending on the enable status of overlay1/2, the DMA should be
605 * updated from FDADRx (when disabled) or FBRx (when enabled).
606 */
607static void overlay1fb_enable(struct pxafb_layer *ofb)
608{
609 int enabled = lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN;
610 uint32_t fdadr1 = ofb->fbi->fdadr[DMA_OV1] | (enabled ? 0x1 : 0);
611
612 lcd_writel(ofb->fbi, enabled ? FBR1 : FDADR1, fdadr1);
613 lcd_writel(ofb->fbi, OVL1C2, ofb->control[1]);
614 lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] | OVLxC1_OEN);
615}
616
617static void overlay1fb_disable(struct pxafb_layer *ofb)
618{
619 uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5);
620
621 lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN);
622
623 lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(1));
624 lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(1));
625 lcd_writel(ofb->fbi, FBR1, ofb->fbi->fdadr[DMA_OV1] | 0x3);
626
627 if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
628 pr_warning("%s: timeout disabling overlay1\n", __func__);
629
630 lcd_writel(ofb->fbi, LCCR5, lccr5);
631}
632
633static void overlay2fb_setup(struct pxafb_layer *ofb)
634{
635 int size, div = 1, pfor = NONSTD_TO_PFOR(ofb->fb.var.nonstd);
636 unsigned long start[3] = { ofb->video_mem_phys, 0, 0 };
637
638 if (pfor == OVERLAY_FORMAT_RGB || pfor == OVERLAY_FORMAT_YUV444_PACKED) {
639 size = ofb->fb.fix.line_length * ofb->fb.var.yres_virtual;
640 setup_frame_dma(ofb->fbi, DMA_OV2_Y, -1, start[0], size);
641 } else {
642 size = ofb->fb.var.xres_virtual * ofb->fb.var.yres_virtual;
643 switch (pfor) {
644 case OVERLAY_FORMAT_YUV444_PLANAR: div = 1; break;
645 case OVERLAY_FORMAT_YUV422_PLANAR: div = 2; break;
646 case OVERLAY_FORMAT_YUV420_PLANAR: div = 4; break;
647 }
648 start[1] = start[0] + size;
649 start[2] = start[1] + size / div;
650 setup_frame_dma(ofb->fbi, DMA_OV2_Y, -1, start[0], size);
651 setup_frame_dma(ofb->fbi, DMA_OV2_Cb, -1, start[1], size / div);
652 setup_frame_dma(ofb->fbi, DMA_OV2_Cr, -1, start[2], size / div);
653 }
654}
655
656static void overlay2fb_enable(struct pxafb_layer *ofb)
657{
658 int pfor = NONSTD_TO_PFOR(ofb->fb.var.nonstd);
659 int enabled = lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN;
660 uint32_t fdadr2 = ofb->fbi->fdadr[DMA_OV2_Y] | (enabled ? 0x1 : 0);
661 uint32_t fdadr3 = ofb->fbi->fdadr[DMA_OV2_Cb] | (enabled ? 0x1 : 0);
662 uint32_t fdadr4 = ofb->fbi->fdadr[DMA_OV2_Cr] | (enabled ? 0x1 : 0);
663
664 if (pfor == OVERLAY_FORMAT_RGB || pfor == OVERLAY_FORMAT_YUV444_PACKED)
665 lcd_writel(ofb->fbi, enabled ? FBR2 : FDADR2, fdadr2);
666 else {
667 lcd_writel(ofb->fbi, enabled ? FBR2 : FDADR2, fdadr2);
668 lcd_writel(ofb->fbi, enabled ? FBR3 : FDADR3, fdadr3);
669 lcd_writel(ofb->fbi, enabled ? FBR4 : FDADR4, fdadr4);
670 }
671 lcd_writel(ofb->fbi, OVL2C2, ofb->control[1]);
672 lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] | OVLxC1_OEN);
673}
674
675static void overlay2fb_disable(struct pxafb_layer *ofb)
676{
677 uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5);
678
679 lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] & ~OVLxC1_OEN);
680
681 lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(2));
682 lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(2));
683 lcd_writel(ofb->fbi, FBR2, ofb->fbi->fdadr[DMA_OV2_Y] | 0x3);
684 lcd_writel(ofb->fbi, FBR3, ofb->fbi->fdadr[DMA_OV2_Cb] | 0x3);
685 lcd_writel(ofb->fbi, FBR4, ofb->fbi->fdadr[DMA_OV2_Cr] | 0x3);
686
687 if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
688 pr_warning("%s: timeout disabling overlay2\n", __func__);
689}
690
691static struct pxafb_layer_ops ofb_ops[] = {
692 [0] = {
693 .enable = overlay1fb_enable,
694 .disable = overlay1fb_disable,
695 .setup = overlay1fb_setup,
696 },
697 [1] = {
698 .enable = overlay2fb_enable,
699 .disable = overlay2fb_disable,
700 .setup = overlay2fb_setup,
701 },
702};
703
704static int overlayfb_open(struct fb_info *info, int user)
705{
706 struct pxafb_layer *ofb = (struct pxafb_layer *)info;
707
708 /* no support for framebuffer console on overlay */
709 if (user == 0)
710 return -ENODEV;
711
712 /* allow only one user at a time */
713 if (atomic_inc_and_test(&ofb->usage))
714 return -EBUSY;
715
716 /* unblank the base framebuffer */
717 fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
718 return 0;
719}
720
721static int overlayfb_release(struct fb_info *info, int user)
722{
723 struct pxafb_layer *ofb = (struct pxafb_layer*) info;
724
725 atomic_dec(&ofb->usage);
726 ofb->ops->disable(ofb);
727
728 free_pages_exact(ofb->video_mem, ofb->video_mem_size);
729 ofb->video_mem = NULL;
730 ofb->video_mem_size = 0;
731 return 0;
732}
733
734static int overlayfb_check_var(struct fb_var_screeninfo *var,
735 struct fb_info *info)
736{
737 struct pxafb_layer *ofb = (struct pxafb_layer *)info;
738 struct fb_var_screeninfo *base_var = &ofb->fbi->fb.var;
739 int xpos, ypos, pfor, bpp;
740
741 xpos = NONSTD_TO_XPOS(var->nonstd);
742 ypos = NONSTD_TO_XPOS(var->nonstd);
743 pfor = NONSTD_TO_PFOR(var->nonstd);
744
745 bpp = pxafb_var_to_bpp(var);
746 if (bpp < 0)
747 return -EINVAL;
748
749 /* no support for YUV format on overlay1 */
750 if (ofb->id == OVERLAY1 && pfor != 0)
751 return -EINVAL;
752
753 /* for YUV packed formats, bpp = 'minimum bpp of YUV components' */
754 switch (pfor) {
755 case OVERLAY_FORMAT_RGB:
756 bpp = pxafb_var_to_bpp(var);
757 if (bpp < 0)
758 return -EINVAL;
759
760 pxafb_set_pixfmt(var, var_to_depth(var));
761 break;
762 case OVERLAY_FORMAT_YUV444_PACKED: bpp = 24; break;
763 case OVERLAY_FORMAT_YUV444_PLANAR: bpp = 8; break;
764 case OVERLAY_FORMAT_YUV422_PLANAR: bpp = 4; break;
765 case OVERLAY_FORMAT_YUV420_PLANAR: bpp = 2; break;
766 default:
767 return -EINVAL;
768 }
769
770 /* each line must start at a 32-bit word boundary */
771 if ((xpos * bpp) % 32)
772 return -EINVAL;
773
774 /* xres must align on 32-bit word boundary */
775 var->xres = roundup(var->xres * bpp, 32) / bpp;
776
777 if ((xpos + var->xres > base_var->xres) ||
778 (ypos + var->yres > base_var->yres))
779 return -EINVAL;
780
781 var->xres_virtual = var->xres;
782 var->yres_virtual = max(var->yres, var->yres_virtual);
783 return 0;
784}
785
786static int overlayfb_map_video_memory(struct pxafb_layer *ofb)
787{
788 struct fb_var_screeninfo *var = &ofb->fb.var;
789 int pfor = NONSTD_TO_PFOR(var->nonstd);
790 int size, bpp = 0;
791
792 switch (pfor) {
793 case OVERLAY_FORMAT_RGB: bpp = var->bits_per_pixel; break;
794 case OVERLAY_FORMAT_YUV444_PACKED: bpp = 24; break;
795 case OVERLAY_FORMAT_YUV444_PLANAR: bpp = 24; break;
796 case OVERLAY_FORMAT_YUV422_PLANAR: bpp = 16; break;
797 case OVERLAY_FORMAT_YUV420_PLANAR: bpp = 12; break;
798 }
799
800 ofb->fb.fix.line_length = var->xres_virtual * bpp / 8;
801
802 size = PAGE_ALIGN(ofb->fb.fix.line_length * var->yres_virtual);
803
804 /* don't re-allocate if the original video memory is enough */
805 if (ofb->video_mem) {
806 if (ofb->video_mem_size >= size)
807 return 0;
808
809 free_pages_exact(ofb->video_mem, ofb->video_mem_size);
810 }
811
812 ofb->video_mem = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
813 if (ofb->video_mem == NULL)
814 return -ENOMEM;
815
816 ofb->video_mem_phys = virt_to_phys(ofb->video_mem);
817 ofb->video_mem_size = size;
818
819 ofb->fb.fix.smem_start = ofb->video_mem_phys;
820 ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual;
821 ofb->fb.screen_base = ofb->video_mem;
822 return 0;
823}
824
825static int overlayfb_set_par(struct fb_info *info)
826{
827 struct pxafb_layer *ofb = (struct pxafb_layer *)info;
828 struct fb_var_screeninfo *var = &info->var;
829 int xpos, ypos, pfor, bpp, ret;
830
831 ret = overlayfb_map_video_memory(ofb);
832 if (ret)
833 return ret;
834
835 bpp = pxafb_var_to_bpp(var);
836 xpos = NONSTD_TO_XPOS(var->nonstd);
837 ypos = NONSTD_TO_XPOS(var->nonstd);
838 pfor = NONSTD_TO_PFOR(var->nonstd);
839
840 ofb->control[0] = OVLxC1_PPL(var->xres) | OVLxC1_LPO(var->yres) |
841 OVLxC1_BPP(bpp);
842 ofb->control[1] = OVLxC2_XPOS(xpos) | OVLxC2_YPOS(ypos);
843
844 if (ofb->id == OVERLAY2)
845 ofb->control[1] |= OVL2C2_PFOR(pfor);
846
847 ofb->ops->setup(ofb);
848 ofb->ops->enable(ofb);
849 return 0;
850}
851
852static struct fb_ops overlay_fb_ops = {
853 .owner = THIS_MODULE,
854 .fb_open = overlayfb_open,
855 .fb_release = overlayfb_release,
856 .fb_check_var = overlayfb_check_var,
857 .fb_set_par = overlayfb_set_par,
858};
859
860static void __devinit init_pxafb_overlay(struct pxafb_info *fbi,
861 struct pxafb_layer *ofb, int id)
862{
863 sprintf(ofb->fb.fix.id, "overlay%d", id + 1);
864
865 ofb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
866 ofb->fb.fix.xpanstep = 0;
867 ofb->fb.fix.ypanstep = 1;
868
869 ofb->fb.var.activate = FB_ACTIVATE_NOW;
870 ofb->fb.var.height = -1;
871 ofb->fb.var.width = -1;
872 ofb->fb.var.vmode = FB_VMODE_NONINTERLACED;
873
874 ofb->fb.fbops = &overlay_fb_ops;
875 ofb->fb.flags = FBINFO_FLAG_DEFAULT;
876 ofb->fb.node = -1;
877 ofb->fb.pseudo_palette = NULL;
878
879 ofb->id = id;
880 ofb->ops = &ofb_ops[id];
881 atomic_set(&ofb->usage, 0);
882 ofb->fbi = fbi;
883 init_completion(&ofb->branch_done);
884}
885
886static int __devinit pxafb_overlay_init(struct pxafb_info *fbi)
887{
888 int i, ret;
889
890 for (i = 0; i < 2; i++) {
891 init_pxafb_overlay(fbi, &fbi->overlay[i], i);
892 ret = register_framebuffer(&fbi->overlay[i].fb);
893 if (ret) {
894 dev_err(fbi->dev, "failed to register overlay %d\n", i);
895 return ret;
896 }
897 }
898
899 /* mask all IU/BS/EOF/SOF interrupts */
900 lcd_writel(fbi, LCCR5, ~0);
901
902 /* place overlay(s) on top of base */
903 fbi->lccr0 |= LCCR0_OUC;
904 pr_info("PXA Overlay driver loaded successfully!\n");
905 return 0;
906}
907
908static void __devexit pxafb_overlay_exit(struct pxafb_info *fbi)
909{
910 int i;
911
912 for (i = 0; i < 2; i++)
913 unregister_framebuffer(&fbi->overlay[i].fb);
914}
915#else
916static inline void pxafb_overlay_init(struct pxafb_info *fbi) {}
917static inline void pxafb_overlay_exit(struct pxafb_info *fbi) {}
918#endif /* CONFIG_FB_PXA_OVERLAY */
919
584/* 920/*
585 * Calculate the PCD value from the clock rate (in picoseconds). 921 * Calculate the PCD value from the clock rate (in picoseconds).
586 * We take account of the PPCR clock setting. 922 * We take account of the PPCR clock setting.
@@ -660,7 +996,7 @@ unsigned long pxafb_get_hsync_time(struct device *dev)
660EXPORT_SYMBOL(pxafb_get_hsync_time); 996EXPORT_SYMBOL(pxafb_get_hsync_time);
661 997
662static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal, 998static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
663 unsigned int offset, size_t size) 999 unsigned long start, size_t size)
664{ 1000{
665 struct pxafb_dma_descriptor *dma_desc, *pal_desc; 1001 struct pxafb_dma_descriptor *dma_desc, *pal_desc;
666 unsigned int dma_desc_off, pal_desc_off; 1002 unsigned int dma_desc_off, pal_desc_off;
@@ -671,7 +1007,7 @@ static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
671 dma_desc = &fbi->dma_buff->dma_desc[dma]; 1007 dma_desc = &fbi->dma_buff->dma_desc[dma];
672 dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[dma]); 1008 dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[dma]);
673 1009
674 dma_desc->fsadr = fbi->video_mem_phys + offset; 1010 dma_desc->fsadr = start;
675 dma_desc->fidr = 0; 1011 dma_desc->fidr = 0;
676 dma_desc->ldcmd = size; 1012 dma_desc->ldcmd = size;
677 1013
@@ -705,14 +1041,14 @@ static void setup_base_frame(struct pxafb_info *fbi, int branch)
705{ 1041{
706 struct fb_var_screeninfo *var = &fbi->fb.var; 1042 struct fb_var_screeninfo *var = &fbi->fb.var;
707 struct fb_fix_screeninfo *fix = &fbi->fb.fix; 1043 struct fb_fix_screeninfo *fix = &fbi->fb.fix;
708 unsigned int nbytes, offset; 1044 int nbytes, dma, pal, bpp = var->bits_per_pixel;
709 int dma, pal, bpp = var->bits_per_pixel; 1045 unsigned long offset;
710 1046
711 dma = DMA_BASE + (branch ? DMA_MAX : 0); 1047 dma = DMA_BASE + (branch ? DMA_MAX : 0);
712 pal = (bpp >= 16) ? PAL_NONE : PAL_BASE + (branch ? PAL_MAX : 0); 1048 pal = (bpp >= 16) ? PAL_NONE : PAL_BASE + (branch ? PAL_MAX : 0);
713 1049
714 nbytes = fix->line_length * var->yres; 1050 nbytes = fix->line_length * var->yres;
715 offset = fix->line_length * var->yoffset; 1051 offset = fix->line_length * var->yoffset + fbi->video_mem_phys;
716 1052
717 if (fbi->lccr0 & LCCR0_SDS) { 1053 if (fbi->lccr0 & LCCR0_SDS) {
718 nbytes = nbytes / 2; 1054 nbytes = nbytes / 2;
@@ -1090,8 +1426,9 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
1090static irqreturn_t pxafb_handle_irq(int irq, void *dev_id) 1426static irqreturn_t pxafb_handle_irq(int irq, void *dev_id)
1091{ 1427{
1092 struct pxafb_info *fbi = dev_id; 1428 struct pxafb_info *fbi = dev_id;
1093 unsigned int lccr0, lcsr = lcd_readl(fbi, LCSR); 1429 unsigned int lccr0, lcsr, lcsr1;
1094 1430
1431 lcsr = lcd_readl(fbi, LCSR);
1095 if (lcsr & LCSR_LDD) { 1432 if (lcsr & LCSR_LDD) {
1096 lccr0 = lcd_readl(fbi, LCCR0); 1433 lccr0 = lcd_readl(fbi, LCCR0);
1097 lcd_writel(fbi, LCCR0, lccr0 | LCCR0_LDM); 1434 lcd_writel(fbi, LCCR0, lccr0 | LCCR0_LDM);
@@ -1102,8 +1439,18 @@ static irqreturn_t pxafb_handle_irq(int irq, void *dev_id)
1102 if (lcsr & LCSR_CMD_INT) 1439 if (lcsr & LCSR_CMD_INT)
1103 complete(&fbi->command_done); 1440 complete(&fbi->command_done);
1104#endif 1441#endif
1105
1106 lcd_writel(fbi, LCSR, lcsr); 1442 lcd_writel(fbi, LCSR, lcsr);
1443
1444#ifdef CONFIG_FB_PXA_OVERLAY
1445 lcsr1 = lcd_readl(fbi, LCSR1);
1446 if (lcsr1 & LCSR1_BS(1))
1447 complete(&fbi->overlay[0].branch_done);
1448
1449 if (lcsr1 & LCSR1_BS(2))
1450 complete(&fbi->overlay[1].branch_done);
1451
1452 lcd_writel(fbi, LCSR1, lcsr1);
1453#endif
1107 return IRQ_HANDLED; 1454 return IRQ_HANDLED;
1108} 1455}
1109 1456
@@ -1802,6 +2149,8 @@ static int __devinit pxafb_probe(struct platform_device *dev)
1802 goto failed_free_cmap; 2149 goto failed_free_cmap;
1803 } 2150 }
1804 2151
2152 pxafb_overlay_init(fbi);
2153
1805#ifdef CONFIG_CPU_FREQ 2154#ifdef CONFIG_CPU_FREQ
1806 fbi->freq_transition.notifier_call = pxafb_freq_transition; 2155 fbi->freq_transition.notifier_call = pxafb_freq_transition;
1807 fbi->freq_policy.notifier_call = pxafb_freq_policy; 2156 fbi->freq_policy.notifier_call = pxafb_freq_policy;
@@ -1852,6 +2201,7 @@ static int __devexit pxafb_remove(struct platform_device *dev)
1852 2201
1853 info = &fbi->fb; 2202 info = &fbi->fb;
1854 2203
2204 pxafb_overlay_exit(fbi);
1855 unregister_framebuffer(info); 2205 unregister_framebuffer(info);
1856 2206
1857 pxafb_disable_controller(fbi); 2207 pxafb_disable_controller(fbi);
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
index ae3cbc1ca64f..2353521c5c8c 100644
--- a/drivers/video/pxafb.h
+++ b/drivers/video/pxafb.h
@@ -64,6 +64,47 @@ struct pxafb_dma_buff {
64 struct pxafb_dma_descriptor dma_desc[DMA_MAX * 2]; 64 struct pxafb_dma_descriptor dma_desc[DMA_MAX * 2];
65}; 65};
66 66
67enum {
68 OVERLAY1,
69 OVERLAY2,
70};
71
72enum {
73 OVERLAY_FORMAT_RGB = 0,
74 OVERLAY_FORMAT_YUV444_PACKED,
75 OVERLAY_FORMAT_YUV444_PLANAR,
76 OVERLAY_FORMAT_YUV422_PLANAR,
77 OVERLAY_FORMAT_YUV420_PLANAR,
78};
79
80#define NONSTD_TO_XPOS(x) (((x) >> 0) & 0x3ff)
81#define NONSTD_TO_YPOS(x) (((x) >> 10) & 0x3ff)
82#define NONSTD_TO_PFOR(x) (((x) >> 20) & 0x7)
83
84struct pxafb_layer;
85
86struct pxafb_layer_ops {
87 void (*enable)(struct pxafb_layer *);
88 void (*disable)(struct pxafb_layer *);
89 void (*setup)(struct pxafb_layer *);
90};
91
92struct pxafb_layer {
93 struct fb_info fb;
94 int id;
95 atomic_t usage;
96 uint32_t control[2];
97
98 struct pxafb_layer_ops *ops;
99
100 void __iomem *video_mem;
101 unsigned long video_mem_phys;
102 size_t video_mem_size;
103 struct completion branch_done;
104
105 struct pxafb_info *fbi;
106};
107
67struct pxafb_info { 108struct pxafb_info {
68 struct fb_info fb; 109 struct fb_info fb;
69 struct device *dev; 110 struct device *dev;
@@ -114,6 +155,10 @@ struct pxafb_info {
114 struct task_struct *smart_thread; 155 struct task_struct *smart_thread;
115#endif 156#endif
116 157
158#ifdef CONFIG_FB_PXA_OVERLAY
159 struct pxafb_layer overlay[2];
160#endif
161
117#ifdef CONFIG_CPU_FREQ 162#ifdef CONFIG_CPU_FREQ
118 struct notifier_block freq_transition; 163 struct notifier_block freq_transition;
119 struct notifier_block freq_policy; 164 struct notifier_block freq_policy;