openwrt/target/linux/pxa/patches-2.6.21/043-pxafb-18bpp-mode.patch

416 lines
14 KiB
Diff

--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -191,6 +191,10 @@ static int pxafb_bpp_to_lccr3(struct fb_
case 4: ret = LCCR3_4BPP; break;
case 8: ret = LCCR3_8BPP; break;
case 16: ret = LCCR3_16BPP; break;
+ case 18: ret = (var->nonstd == 24 ? LCCR3_18BPP_PACKED : LCCR3_18BPP); break;
+ case 19: ret = (var->nonstd == 24 ? LCCR3_19BPP_PACKED : LCCR3_19BPP); break;
+ case 24: ret = LCCR3_24BPP; break;
+ case 25: ret = LCCR3_25BPP; break;
}
return ret;
}
@@ -204,11 +208,12 @@ static int pxafb_bpp_to_lccr3(struct fb_
*/
static unsigned int pxafb_display_dma_period(struct fb_var_screeninfo *var)
{
- /*
- * Period = pixclock * bits_per_byte * bytes_per_transfer
- * / memory_bits_per_pixel;
- */
- return var->pixclock * 8 * 16 / var->bits_per_pixel;
+ /*
+ * Period = pixclock * bits_per_byte * bytes_per_transfer
+ * / memory_bits_per_pixel;
+ */
+ struct pxafb_mach_info *inf = fbi->dev->platform_data;
+ return var->pixclock * 8 * 16 / (var->nonstd ? var->nonstd : var->bits_per_pixel);
}
extern unsigned int get_clk_frequency_khz(int info);
@@ -307,6 +312,26 @@ static int pxafb_check_var(struct fb_var
var->green.offset = 5; var->green.length = 6;
var->blue.offset = 0; var->blue.length = 5;
var->transp.offset = var->transp.length = 0;
+ } else if (var->bits_per_pixel == 18) {
+ var->transp.offset = var->transp.length = 0;
+ var->red.offset = 12; var->red.length=6;
+ var->green.offset = 6; var->green.length=6;
+ var->blue.offset = 0; var->blue.length=6;
+ } else if (var->bits_per_pixel == 19) {
+ var->transp.offset = 18; var->transp.length = 1;
+ var->red.offset = 12; var->red.length=6;
+ var->green.offset = 6; var->green.length=6;
+ var->blue.offset = 0; var->blue.length=6;
+ } else if (var->bits_per_pixel == 24) {
+ var->transp.offset = var->transp.length = 0;
+ var->red.offset = 16; var->red.length=8;
+ var->green.offset = 8; var->green.length=8;
+ var->blue.offset = 0; var->blue.length=8;
+ } else if (var->bits_per_pixel == 25) {
+ var->transp.offset = 18; var->transp.length = 1;
+ var->red.offset = 16; var->red.length=8;
+ var->green.offset = 8; var->green.length=8;
+ var->blue.offset = 0; var->blue.length=8;
} else {
var->red.offset = var->green.offset = var->blue.offset = var->transp.offset = 0;
var->red.length = 8;
@@ -342,7 +367,7 @@ static int pxafb_set_par(struct fb_info
pr_debug("pxafb: set_par\n");
- if (var->bits_per_pixel == 16)
+ if (var->bits_per_pixel >= 16)
fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
else if (!fbi->cmap_static)
fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -355,9 +380,10 @@ static int pxafb_set_par(struct fb_info
fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
}
- fbi->fb.fix.line_length = var->xres_virtual *
- var->bits_per_pixel / 8;
- if (var->bits_per_pixel == 16)
+ fbi->fb.fix.line_length = var->xres_virtual *
+ (var->nonstd ? var->nonstd : var->bits_per_pixel) / 8;
+
+ if (var->bits_per_pixel >= 16)
fbi->palette_size = 0;
else
fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel;
@@ -374,7 +400,7 @@ static int pxafb_set_par(struct fb_info
*/
pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
- if (fbi->fb.var.bits_per_pixel == 16)
+ if (fbi->fb.var.bits_per_pixel >= 16)
fb_dealloc_cmap(&fbi->fb.cmap);
else
fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
@@ -584,6 +610,14 @@ static int pxafb_activate_var(struct fb_
case 8:
case 16:
break;
+ case 18:
+ case 19:
+ case 24:
+ case 25:
+ if(var->nonstd) break;
+ printk(KERN_ERR "%s: must specify nonstd when bit depth==%d\n",
+ fbi->fb.fix.id, var->bits_per_pixel);
+ break;
default:
printk(KERN_ERR "%s: invalid bit depth %d\n",
fbi->fb.fix.id, var->bits_per_pixel);
@@ -679,7 +713,7 @@ static int pxafb_activate_var(struct fb_
fbi->dmadesc_palette_cpu->fidr = 0;
fbi->dmadesc_palette_cpu->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL;
- if (var->bits_per_pixel == 16) {
+ if (var->bits_per_pixel >= 16) {
/* palette shouldn't be loaded in true-color mode */
fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */
@@ -785,8 +819,19 @@ static void pxafb_setup_gpio(struct pxaf
return;
}
- for (gpio = 58; ldd_bits; gpio++, ldd_bits--)
+ for (gpio = 58; min(ldd_bits,16); gpio++, ldd_bits--)
pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT);
+
+ switch(fbi->fb.var.bits_per_pixel)
+ {
+ case 25:
+ case 24:
+ case 19:
+ case 18:
+ pxa_gpio_mode(GPIO86_LDD_16_MD);
+ pxa_gpio_mode(GPIO87_LDD_17_MD);
+ default: break;
+ }
pxa_gpio_mode(GPIO74_LCD_FCLK_MD);
pxa_gpio_mode(GPIO75_LCD_LCLK_MD);
pxa_gpio_mode(GPIO76_LCD_PCLK_MD);
@@ -1135,7 +1180,7 @@ static struct pxafb_info * __init pxafb_
fbi->fb.fix.ywrapstep = 0;
fbi->fb.fix.accel = FB_ACCEL_NONE;
- fbi->fb.var.nonstd = 0;
+ fbi->fb.var.nonstd = mode->nonstd;
fbi->fb.var.activate = FB_ACTIVATE_NOW;
fbi->fb.var.height = -1;
fbi->fb.var.width = -1;
@@ -1161,7 +1206,7 @@ static struct pxafb_info * __init pxafb_
fbi->task_state = (u_char)-1;
for (i = 0; i < inf->num_modes; i++) {
- smemlen = mode[i].xres * mode[i].yres * mode[i].bpp / 8;
+ smemlen = mode[i].xres * mode[i].yres * (mode[i].nonstd ? mode[i].nonstd : mode[i].bpp) / 8;
if (smemlen > fbi->fb.fix.smem_len)
fbi->fb.fix.smem_len = smemlen;
}
@@ -1189,12 +1234,19 @@ static int __init pxafb_parse_options(st
if (!strncmp(this_opt, "mode:", 5)) {
const char *name = this_opt+5;
unsigned int namelen = strlen(name);
- int res_specified = 0, bpp_specified = 0;
- unsigned int xres = 0, yres = 0, bpp = 0;
+ int res_specified = 0, bpp_specified = 0, nonstd_specified = 0;
+ unsigned int xres = 0, yres = 0, bpp = 0, nonstd = 0;
int yres_specified = 0;
int i;
for (i = namelen-1; i >= 0; i--) {
switch (name[i]) {
+ case '/':
+ if (!nonstd_specified) {
+ nonstd = simple_strtoul(&name[i+1], NULL, 0);
+ nonstd_specified = 1;
+ } else
+ goto done;
+ break;
case '-':
namelen = i;
if (!bpp_specified && !yres_specified) {
@@ -1227,12 +1279,29 @@ static int __init pxafb_parse_options(st
}
if (bpp_specified)
switch (bpp) {
+ case 18:
+ case 19:
+ case 24:
+ case 25:
+ if(nonstd_specified && (((bpp == 18 || bpp == 19) && nonstd == 24) || nonstd == 32))
+ {
+ inf->modes[0].nonstd = nonstd;
+ dev_info(dev, "overriding nonstd pixel packing: %d\n",nonstd);
+ } else {
+ dev_err(dev, "Depth %d requires nonstd to be specified\n",bpp);
+ break;
+ }
case 1:
case 2:
case 4:
case 8:
case 16:
inf->modes[0].bpp = bpp;
+ if(nonstd_specified) {
+ dev_err(dev, "Depth %d requires nonstd to *not* be specified\n",bpp);
+ } else {
+ inf->modes[0].nonstd = 0;
+ }
dev_info(dev, "overriding bit depth: %d\n", bpp);
break;
default:
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1323,6 +1323,8 @@
#define GPIO83_NSTXD 83 /* NSSP transmit */
#define GPIO84_NSRXD 84 /* NSSP receive */
#define GPIO85_nPCE_1 85 /* Card Enable for Card Space (PXA27x) */
+#define GPIO86_LDD_16 86 /* LCD data pin 16 */
+#define GPIO87_LDD_17 87 /* LCD data pin 17 */
#define GPIO92_MMCDAT0 92 /* MMC DAT0 (PXA27x) */
#define GPIO102_nPCE_1 102 /* PCMCIA (PXA27x) */
#define GPIO105_nPCE_2 105 /* Card Enable for Card Space (PXA27x) */
@@ -1468,6 +1470,8 @@
#define GPIO84_NSSP_TX (84 | GPIO_ALT_FN_1_OUT)
#define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN)
#define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT)
+#define GPIO86_LDD_16_MD (86 | GPIO_ALT_FN_2_OUT)
+#define GPIO87_LDD_17_MD (87 | GPIO_ALT_FN_2_OUT)
#define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT)
#define GPIO102_nPCE_1_MD (102 | GPIO_ALT_FN_1_OUT)
#define GPIO104_pSKTSEL_MD (104 | GPIO_ALT_FN_1_OUT)
@@ -1878,6 +1882,12 @@
#define LCCR3_4BPP (2 << 24)
#define LCCR3_8BPP (3 << 24)
#define LCCR3_16BPP (4 << 24)
+#define LCCR3_18BPP (5 << 24)
+#define LCCR3_18BPP_PACKED (6 << 24)
+#define LCCR3_19BPP (7 << 24)
+#define LCCR3_19BPP_PACKED (1 << 29)
+#define LCCR3_24BPP ((1 << 29) | (1 << 24))
+#define LCCR3_25BPP ((1 << 29) | (2 << 24))
#define FDADR0 __REG(0x44000200) /* DMA Channel 0 Frame Descriptor Address Register */
#define FSADR0 __REG(0x44000204) /* DMA Channel 0 Frame Source Address Register */
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -25,6 +25,7 @@ struct pxafb_mode_info {
u_short xres;
u_short yres;
+ /* bpp is the path-to-screen bits per pixel, not the in-memory storage required */
u_char bpp;
u_char hsync_len;
u_char left_margin;
@@ -36,7 +37,9 @@ struct pxafb_mode_info {
u_char sync;
u_int cmap_greyscale:1,
- unused:31;
+ nonstd:8, /* nonstd represents the in-memory bits per pixel
+ ie 24 or 32 for 18/19bpp mode, or 32 for 24/25bpp mode */
+ unused:23;
};
struct pxafb_mach_info {
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -146,7 +146,8 @@ static struct pxafb_mode_info gumstix_fb
.pixclock = 110000,
.xres = 480,
.yres = 272,
- .bpp = 16,
+ .bpp = 18,
+ .nonstd = 24,
.hsync_len = 41,
.left_margin = 2,
.right_margin = 2,
@@ -174,7 +175,8 @@ static struct pxafb_mode_info gumstix_fb
.vsync_len = 10, // VLW from datasheet: 10 typ
.upper_margin = 2, // VBP - VLW from datasheet: 12 - 10 = 2
.lower_margin = 4, // VFP from datasheet: 4 typ
- .bpp = 16,
+ .bpp = 18,
+ .nonstd = 24,
.sync = 0, // Hsync and Vsync both active low
};
--- a/drivers/video/cfbfillrect.c
+++ b/drivers/video/cfbfillrect.c
@@ -62,7 +62,10 @@ pixel_to_pat( u32 bpp, u32 pixel)
return 0x0001001001001001ul*pixel;
case 16:
return 0x0001000100010001ul*pixel;
+ case 18:
+ case 19:
case 24:
+ case 25:
return 0x0000000001000001ul*pixel;
case 32:
return 0x0000000100000001ul*pixel;
@@ -87,7 +90,10 @@ pixel_to_pat( u32 bpp, u32 pixel)
return 0x00001001ul*pixel;
case 16:
return 0x00010001ul*pixel;
+ case 18:
+ case 19:
case 24:
+ case 25:
return 0x00000001ul*pixel;
case 32:
return 0x00000001ul*pixel;
@@ -346,7 +352,7 @@ void cfb_fillrect(struct fb_info *p, con
unsigned long pat, fg;
unsigned long width = rect->width, height = rect->height;
int bits = BITS_PER_LONG, bytes = bits >> 3;
- u32 bpp = p->var.bits_per_pixel;
+ u32 bpp = (p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
unsigned long __iomem *dst;
int dst_idx, left;
--- a/drivers/video/cfbimgblt.c
+++ b/drivers/video/cfbimgblt.c
@@ -83,7 +83,7 @@ static inline void color_imageblit(const
/* Draw the penguin */
u32 __iomem *dst, *dst2;
u32 color = 0, val, shift;
- int i, n, bpp = p->var.bits_per_pixel;
+ int i, n, bpp = (p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
u32 null_bits = 32 - bpp;
u32 *palette = (u32 *) p->pseudo_palette;
const u8 *src = image->data;
@@ -140,7 +140,7 @@ static inline void slow_imageblit(const
u32 start_index,
u32 pitch_index)
{
- u32 shift, color = 0, bpp = p->var.bits_per_pixel;
+ u32 shift, color = 0, bpp = (p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
u32 __iomem *dst, *dst2;
u32 val, pitch = p->fix.line_length;
u32 null_bits = 32 - bpp;
@@ -213,7 +213,7 @@ static inline void fast_imageblit(const
u8 __iomem *dst1, u32 fgcolor,
u32 bgcolor)
{
- u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
+ u32 fgx = fgcolor, bgx = bgcolor, bpp = (p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
u32 bit_mask, end_mask, eorx, shift;
const char *s = image->data, *src;
@@ -262,7 +262,7 @@ static inline void fast_imageblit(const
void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
{
u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
- u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
+ u32 bpl = sizeof(u32), bpp = (p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
u32 width = image->width;
u32 dx = image->dx, dy = image->dy;
u8 __iomem *dst1;
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/cfbcopyarea.c
@@ -365,8 +365,8 @@ void cfb_copyarea(struct fb_info *p, con
dst = src = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
// add offset of source and target area
- dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
- src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
+ dst_idx += dy*bits_per_line + dx*(p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
+ src_idx += sy*bits_per_line + sx*(p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
if (p->fbops->fb_sync)
p->fbops->fb_sync(p);
@@ -380,7 +380,7 @@ void cfb_copyarea(struct fb_info *p, con
src += src_idx >> (ffs(bits) - 1);
src_idx &= (bytes - 1);
bitcpy_rev(dst, dst_idx, src, src_idx, bits,
- width*p->var.bits_per_pixel);
+ width*(p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel));
}
} else {
while (height--) {
@@ -389,7 +389,7 @@ void cfb_copyarea(struct fb_info *p, con
src += src_idx >> (ffs(bits) - 1);
src_idx &= (bytes - 1);
bitcpy(dst, dst_idx, src, src_idx, bits,
- width*p->var.bits_per_pixel);
+ width*(p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel));
dst_idx += bits_per_line;
src_idx += bits_per_line;
}
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -983,9 +983,10 @@ static const char *fbcon_startup(void)
DPRINTK("mode: %s\n", info->fix.id);
DPRINTK("visual: %d\n", info->fix.visual);
- DPRINTK("res: %dx%d-%d\n", info->var.xres,
+ DPRINTK("res: %dx%d-%d(%d)\n", info->var.xres,
info->var.yres,
- info->var.bits_per_pixel);
+ info->var.bits_per_pixel,
+ info->var.nonstd ? info->var.nonstd : info->var.bits_per_pixel);
#ifdef CONFIG_ATARI
if (MACH_IS_ATARI) {
--- a/Documentation/fb/pxafb.txt
+++ b/Documentation/fb/pxafb.txt
@@ -9,11 +9,13 @@ For example:
or on the kernel command line
video=pxafb:mode:640x480-8,passive
-mode:XRESxYRES[-BPP]
+mode:XRESxYRES[-BPP[/PACKING]]
XRES == LCCR1_PPL + 1
YRES == LLCR2_LPP + 1
The resolution of the display in pixels
BPP == The bit depth. Valid values are 1, 2, 4, 8 and 16.
+ PACKING == The in-memory bits per pixel. Valid values are 24, 32 when
+ BPP == 18,19,24,25
pixclock:PIXCLOCK
Pixel clock in picoseconds