aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans J. Koch <hjk@linutronix.de>2007-10-16 04:28:41 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:15 -0400
commit9ffa73960631502841d78b79ce857b15b9290abc (patch)
tree302a754e1573f87f8ce0b3e1b4f2611cfdb7711e
parentba282daa919f89c871780f344a71e5403a70b634 (diff)
pxafb: Add support for other palette formats
This patch adds support for the other three palette formats possible with the PXA LCD controller. This is required on boards where an LCD is connected with all its 18 bits. With this patch, it's possible to use an 8-bit mode with 18-bit palette entries. This used to be possible in 2.4 kernels but disappeared in 2.6. With current kernels, you can only get wrong colours out of an LCD connected this way. Users can choose the palette format by doing something like this in their board definition: static struct pxafb_mach_info my_fb_info = { [...] .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_PDFOR_3, .lccr4 = LCCR4_PAL_FOR_2, [...] }; Signed-off-by: Hans J. Koch <hjk@linutronix.de> Signed-off-by: Antonino Daplas <adaplas@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/video/pxafb.c64
-rw-r--r--drivers/video/pxafb.h2
-rw-r--r--include/asm-arm/arch-pxa/pxa-regs.h11
-rw-r--r--include/asm-arm/arch-pxa/pxafb.h7
4 files changed, 68 insertions, 16 deletions
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index f9b12ab59642..bfeb54ad3f0e 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -108,20 +108,38 @@ pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
108 u_int trans, struct fb_info *info) 108 u_int trans, struct fb_info *info)
109{ 109{
110 struct pxafb_info *fbi = (struct pxafb_info *)info; 110 struct pxafb_info *fbi = (struct pxafb_info *)info;
111 u_int val, ret = 1; 111 u_int val;
112 112
113 if (regno < fbi->palette_size) { 113 if (regno >= fbi->palette_size)
114 if (fbi->fb.var.grayscale) { 114 return 1;
115 val = ((blue >> 8) & 0x00ff); 115
116 } else { 116 if (fbi->fb.var.grayscale) {
117 val = ((red >> 0) & 0xf800); 117 fbi->palette_cpu[regno] = ((blue >> 8) & 0x00ff);
118 val |= ((green >> 5) & 0x07e0); 118 return 0;
119 val |= ((blue >> 11) & 0x001f); 119 }
120 } 120
121 switch (fbi->lccr4 & LCCR4_PAL_FOR_MASK) {
122 case LCCR4_PAL_FOR_0:
123 val = ((red >> 0) & 0xf800);
124 val |= ((green >> 5) & 0x07e0);
125 val |= ((blue >> 11) & 0x001f);
121 fbi->palette_cpu[regno] = val; 126 fbi->palette_cpu[regno] = val;
122 ret = 0; 127 break;
128 case LCCR4_PAL_FOR_1:
129 val = ((red << 8) & 0x00f80000);
130 val |= ((green >> 0) & 0x0000fc00);
131 val |= ((blue >> 8) & 0x000000f8);
132 ((u32*)(fbi->palette_cpu))[regno] = val;
133 break;
134 case LCCR4_PAL_FOR_2:
135 val = ((red << 8) & 0x00fc0000);
136 val |= ((green >> 0) & 0x0000fc00);
137 val |= ((blue >> 8) & 0x000000fc);
138 ((u32*)(fbi->palette_cpu))[regno] = val;
139 break;
123 } 140 }
124 return ret; 141
142 return 0;
125} 143}
126 144
127static int 145static int
@@ -363,7 +381,10 @@ static int pxafb_set_par(struct fb_info *info)
363 else 381 else
364 fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel; 382 fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel;
365 383
366 palette_mem_size = fbi->palette_size * sizeof(u16); 384 if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
385 palette_mem_size = fbi->palette_size * sizeof(u16);
386 else
387 palette_mem_size = fbi->palette_size * sizeof(u32);
367 388
368 pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size); 389 pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
369 390
@@ -680,7 +701,13 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
680 701
681 fbi->dmadesc_palette_cpu->fsadr = fbi->palette_dma; 702 fbi->dmadesc_palette_cpu->fsadr = fbi->palette_dma;
682 fbi->dmadesc_palette_cpu->fidr = 0; 703 fbi->dmadesc_palette_cpu->fidr = 0;
683 fbi->dmadesc_palette_cpu->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL; 704 if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
705 fbi->dmadesc_palette_cpu->ldcmd = fbi->palette_size *
706 sizeof(u16);
707 else
708 fbi->dmadesc_palette_cpu->ldcmd = fbi->palette_size *
709 sizeof(u32);
710 fbi->dmadesc_palette_cpu->ldcmd |= LDCMD_PAL;
684 711
685 if (var->bits_per_pixel == 16) { 712 if (var->bits_per_pixel == 16) {
686 /* palette shouldn't be loaded in true-color mode */ 713 /* palette shouldn't be loaded in true-color mode */
@@ -719,6 +746,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
719 fbi->reg_lccr1 = new_regs.lccr1; 746 fbi->reg_lccr1 = new_regs.lccr1;
720 fbi->reg_lccr2 = new_regs.lccr2; 747 fbi->reg_lccr2 = new_regs.lccr2;
721 fbi->reg_lccr3 = new_regs.lccr3; 748 fbi->reg_lccr3 = new_regs.lccr3;
749 fbi->reg_lccr4 = LCCR4 & (~LCCR4_PAL_FOR_MASK);
750 fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK);
722 set_hsync_time(fbi, pcd); 751 set_hsync_time(fbi, pcd);
723 local_irq_restore(flags); 752 local_irq_restore(flags);
724 753
@@ -825,6 +854,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
825 pr_debug("LCCR1 0x%08x\n", (unsigned int) LCCR1); 854 pr_debug("LCCR1 0x%08x\n", (unsigned int) LCCR1);
826 pr_debug("LCCR2 0x%08x\n", (unsigned int) LCCR2); 855 pr_debug("LCCR2 0x%08x\n", (unsigned int) LCCR2);
827 pr_debug("LCCR3 0x%08x\n", (unsigned int) LCCR3); 856 pr_debug("LCCR3 0x%08x\n", (unsigned int) LCCR3);
857 pr_debug("LCCR4 0x%08x\n", (unsigned int) LCCR4);
828} 858}
829 859
830static void pxafb_disable_controller(struct pxafb_info *fbi) 860static void pxafb_disable_controller(struct pxafb_info *fbi)
@@ -1094,10 +1124,13 @@ static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
1094 * dma_writecombine_mmap) 1124 * dma_writecombine_mmap)
1095 */ 1125 */
1096 fbi->fb.fix.smem_start = fbi->screen_dma; 1126 fbi->fb.fix.smem_start = fbi->screen_dma;
1097
1098 fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16; 1127 fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16;
1099 1128
1100 palette_mem_size = fbi->palette_size * sizeof(u16); 1129 if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
1130 palette_mem_size = fbi->palette_size * sizeof(u16);
1131 else
1132 palette_mem_size = fbi->palette_size * sizeof(u32);
1133
1101 pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size); 1134 pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
1102 1135
1103 fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); 1136 fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
@@ -1160,6 +1193,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
1160 1193
1161 fbi->lccr0 = inf->lccr0; 1194 fbi->lccr0 = inf->lccr0;
1162 fbi->lccr3 = inf->lccr3; 1195 fbi->lccr3 = inf->lccr3;
1196 fbi->lccr4 = inf->lccr4;
1163 fbi->state = C_STARTUP; 1197 fbi->state = C_STARTUP;
1164 fbi->task_state = (u_char)-1; 1198 fbi->task_state = (u_char)-1;
1165 1199
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
index f8605b807b0a..d920b8a14c35 100644
--- a/drivers/video/pxafb.h
+++ b/drivers/video/pxafb.h
@@ -71,6 +71,7 @@ struct pxafb_info {
71 71
72 u_int lccr0; 72 u_int lccr0;
73 u_int lccr3; 73 u_int lccr3;
74 u_int lccr4;
74 u_int cmap_inverse:1, 75 u_int cmap_inverse:1,
75 cmap_static:1, 76 cmap_static:1,
76 unused:30; 77 unused:30;
@@ -79,6 +80,7 @@ struct pxafb_info {
79 u_int reg_lccr1; 80 u_int reg_lccr1;
80 u_int reg_lccr2; 81 u_int reg_lccr2;
81 u_int reg_lccr3; 82 u_int reg_lccr3;
83 u_int reg_lccr4;
82 84
83 unsigned long hsync_time; 85 unsigned long hsync_time;
84 86
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index 67f53e07db86..bb68b598c436 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1823,6 +1823,7 @@
1823#define LCCR1 __REG(0x44000004) /* LCD Controller Control Register 1 */ 1823#define LCCR1 __REG(0x44000004) /* LCD Controller Control Register 1 */
1824#define LCCR2 __REG(0x44000008) /* LCD Controller Control Register 2 */ 1824#define LCCR2 __REG(0x44000008) /* LCD Controller Control Register 2 */
1825#define LCCR3 __REG(0x4400000C) /* LCD Controller Control Register 3 */ 1825#define LCCR3 __REG(0x4400000C) /* LCD Controller Control Register 3 */
1826#define LCCR4 __REG(0x44000010) /* LCD Controller Control Register 3 */
1826#define DFBR0 __REG(0x44000020) /* DMA Channel 0 Frame Branch Register */ 1827#define DFBR0 __REG(0x44000020) /* DMA Channel 0 Frame Branch Register */
1827#define DFBR1 __REG(0x44000024) /* DMA Channel 1 Frame Branch Register */ 1828#define DFBR1 __REG(0x44000024) /* DMA Channel 1 Frame Branch Register */
1828#define LCSR __REG(0x44000038) /* LCD Controller Status Register */ 1829#define LCSR __REG(0x44000038) /* LCD Controller Status Register */
@@ -1836,6 +1837,16 @@
1836#define LCCR3_8BPP (3 << 24) 1837#define LCCR3_8BPP (3 << 24)
1837#define LCCR3_16BPP (4 << 24) 1838#define LCCR3_16BPP (4 << 24)
1838 1839
1840#define LCCR3_PDFOR_0 (0 << 30)
1841#define LCCR3_PDFOR_1 (1 << 30)
1842#define LCCR3_PDFOR_2 (2 << 30)
1843#define LCCR3_PDFOR_3 (3 << 30)
1844
1845#define LCCR4_PAL_FOR_0 (0 << 15)
1846#define LCCR4_PAL_FOR_1 (1 << 15)
1847#define LCCR4_PAL_FOR_2 (2 << 15)
1848#define LCCR4_PAL_FOR_MASK (3 << 15)
1849
1839#define FDADR0 __REG(0x44000200) /* DMA Channel 0 Frame Descriptor Address Register */ 1850#define FDADR0 __REG(0x44000200) /* DMA Channel 0 Frame Descriptor Address Register */
1840#define FSADR0 __REG(0x44000204) /* DMA Channel 0 Frame Source Address Register */ 1851#define FSADR0 __REG(0x44000204) /* DMA Channel 0 Frame Source Address Register */
1841#define FIDR0 __REG(0x44000208) /* DMA Channel 0 Frame ID Register */ 1852#define FIDR0 __REG(0x44000208) /* DMA Channel 0 Frame ID Register */
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index 81c3928d608c..ea2336aa70e4 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -70,7 +70,12 @@ struct pxafb_mach_info {
70 * LCCR3_HSP, LCCR3_VSP, LCCR0_Pcd(x), LCCR3_Bpp 70 * LCCR3_HSP, LCCR3_VSP, LCCR0_Pcd(x), LCCR3_Bpp
71 */ 71 */
72 u_int lccr3; 72 u_int lccr3;
73 73 /* The following should be defined in LCCR4
74 * LCCR4_PAL_FOR_0 or LCCR4_PAL_FOR_1 or LCCR4_PAL_FOR_2
75 *
76 * All other bits in LCCR4 should be left alone.
77 */
78 u_int lccr4;
74 void (*pxafb_backlight_power)(int); 79 void (*pxafb_backlight_power)(int);
75 void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *); 80 void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
76 81