f8a6c1ad69a5eb6ff3fb92d9a8cead56461e7af8
[openwrt.git] / target / linux / pxa / patches-2.6.21 / 043-pxafb-18bpp-mode.patch
1 Index: linux-2.6.21.7/drivers/video/pxafb.c
2 ===================================================================
3 --- linux-2.6.21.7.orig/drivers/video/pxafb.c
4 +++ linux-2.6.21.7/drivers/video/pxafb.c
5 @@ -191,6 +191,10 @@ static int pxafb_bpp_to_lccr3(struct fb_
6          case 4:  ret = LCCR3_4BPP; break;
7          case 8:  ret = LCCR3_8BPP; break;
8          case 16: ret = LCCR3_16BPP; break;
9 +       case 18: ret = (var->nonstd == 24 ? LCCR3_18BPP_PACKED : LCCR3_18BPP); break; 
10 +       case 19: ret = (var->nonstd == 24 ? LCCR3_19BPP_PACKED : LCCR3_19BPP); break; 
11 +        case 24: ret = LCCR3_24BPP; break;
12 +        case 25: ret = LCCR3_25BPP; break;
13          }
14          return ret;
15  }
16 @@ -204,11 +208,12 @@ static int pxafb_bpp_to_lccr3(struct fb_
17   */
18  static unsigned int pxafb_display_dma_period(struct fb_var_screeninfo *var)
19  {
20 -       /*
21 -        * Period = pixclock * bits_per_byte * bytes_per_transfer
22 -        *              / memory_bits_per_pixel;
23 -        */
24 -       return var->pixclock * 8 * 16 / var->bits_per_pixel;
25 +       /*
26 +        * Period = pixclock * bits_per_byte * bytes_per_transfer
27 +        *              / memory_bits_per_pixel;
28 +        */
29 +       struct pxafb_mach_info *inf = fbi->dev->platform_data;
30 +       return var->pixclock * 8 * 16 / (var->nonstd ? var->nonstd : var->bits_per_pixel);
31  }
32  
33  extern unsigned int get_clk_frequency_khz(int info);
34 @@ -307,6 +312,26 @@ static int pxafb_check_var(struct fb_var
35                 var->green.offset = 5;  var->green.length = 6;
36                 var->blue.offset  = 0;  var->blue.length  = 5;
37                 var->transp.offset = var->transp.length = 0;
38 +       } else if (var->bits_per_pixel == 18) {
39 +               var->transp.offset = var->transp.length = 0;
40 +               var->red.offset = 12; var->red.length=6;
41 +               var->green.offset = 6; var->green.length=6;
42 +               var->blue.offset = 0; var->blue.length=6;
43 +       } else if (var->bits_per_pixel == 19) {
44 +               var->transp.offset = 18; var->transp.length = 1;
45 +               var->red.offset = 12; var->red.length=6;
46 +               var->green.offset = 6; var->green.length=6;
47 +               var->blue.offset = 0; var->blue.length=6;
48 +       } else if (var->bits_per_pixel == 24) {
49 +               var->transp.offset = var->transp.length = 0;
50 +               var->red.offset = 16; var->red.length=8;
51 +               var->green.offset = 8; var->green.length=8;
52 +               var->blue.offset = 0; var->blue.length=8;
53 +       } else if (var->bits_per_pixel == 25) {
54 +               var->transp.offset = 18; var->transp.length = 1;
55 +               var->red.offset = 16; var->red.length=8;
56 +               var->green.offset = 8; var->green.length=8;
57 +               var->blue.offset = 0; var->blue.length=8;
58         } else {
59                 var->red.offset = var->green.offset = var->blue.offset = var->transp.offset = 0;
60                 var->red.length   = 8;
61 @@ -342,7 +367,7 @@ static int pxafb_set_par(struct fb_info 
62  
63         pr_debug("pxafb: set_par\n");
64  
65 -       if (var->bits_per_pixel == 16)
66 +       if (var->bits_per_pixel >= 16)
67                 fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
68         else if (!fbi->cmap_static)
69                 fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
70 @@ -355,9 +380,10 @@ static int pxafb_set_par(struct fb_info 
71                 fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
72         }
73  
74 -       fbi->fb.fix.line_length = var->xres_virtual *
75 -                                 var->bits_per_pixel / 8;
76 -       if (var->bits_per_pixel == 16)
77 +               fbi->fb.fix.line_length = var->xres_virtual *
78 +                                         (var->nonstd ? var->nonstd : var->bits_per_pixel) / 8;
79 +
80 +       if (var->bits_per_pixel >= 16)
81                 fbi->palette_size = 0;
82         else
83                 fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel;
84 @@ -374,7 +400,7 @@ static int pxafb_set_par(struct fb_info 
85          */
86         pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
87  
88 -       if (fbi->fb.var.bits_per_pixel == 16)
89 +       if (fbi->fb.var.bits_per_pixel >= 16)
90                 fb_dealloc_cmap(&fbi->fb.cmap);
91         else
92                 fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
93 @@ -584,6 +610,14 @@ static int pxafb_activate_var(struct fb_
94         case 8:
95         case 16:
96                 break;
97 +       case 18:
98 +       case 19:
99 +       case 24:
100 +       case 25:
101 +               if(var->nonstd) break;
102 +               printk(KERN_ERR "%s: must specify nonstd when bit depth==%d\n",
103 +                       fbi->fb.fix.id, var->bits_per_pixel);
104 +               break;
105         default:
106                 printk(KERN_ERR "%s: invalid bit depth %d\n",
107                        fbi->fb.fix.id, var->bits_per_pixel);
108 @@ -679,7 +713,7 @@ static int pxafb_activate_var(struct fb_
109         fbi->dmadesc_palette_cpu->fidr  = 0;
110         fbi->dmadesc_palette_cpu->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL;
111  
112 -       if (var->bits_per_pixel == 16) {
113 +       if (var->bits_per_pixel >= 16) {
114                 /* palette shouldn't be loaded in true-color mode */
115                 fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
116                 fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */
117 @@ -785,8 +819,19 @@ static void pxafb_setup_gpio(struct pxaf
118                 return;
119          }
120  
121 -       for (gpio = 58; ldd_bits; gpio++, ldd_bits--)
122 +       for (gpio = 58; min(ldd_bits,16); gpio++, ldd_bits--)
123                 pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT);
124 +
125 +       switch(fbi->fb.var.bits_per_pixel)
126 +       {
127 +               case 25:
128 +               case 24:
129 +               case 19:
130 +               case 18:
131 +                       pxa_gpio_mode(GPIO86_LDD_16_MD);
132 +                       pxa_gpio_mode(GPIO87_LDD_17_MD);
133 +               default: break;
134 +       }
135         pxa_gpio_mode(GPIO74_LCD_FCLK_MD);
136         pxa_gpio_mode(GPIO75_LCD_LCLK_MD);
137         pxa_gpio_mode(GPIO76_LCD_PCLK_MD);
138 @@ -1135,7 +1180,7 @@ static struct pxafb_info * __init pxafb_
139         fbi->fb.fix.ywrapstep   = 0;
140         fbi->fb.fix.accel       = FB_ACCEL_NONE;
141  
142 -       fbi->fb.var.nonstd      = 0;
143 +       fbi->fb.var.nonstd      = mode->nonstd;
144         fbi->fb.var.activate    = FB_ACTIVATE_NOW;
145         fbi->fb.var.height      = -1;
146         fbi->fb.var.width       = -1;
147 @@ -1161,7 +1206,7 @@ static struct pxafb_info * __init pxafb_
148         fbi->task_state                 = (u_char)-1;
149  
150         for (i = 0; i < inf->num_modes; i++) {
151 -               smemlen = mode[i].xres * mode[i].yres * mode[i].bpp / 8;
152 +               smemlen = mode[i].xres * mode[i].yres * (mode[i].nonstd ? mode[i].nonstd : mode[i].bpp) / 8;
153                 if (smemlen > fbi->fb.fix.smem_len)
154                         fbi->fb.fix.smem_len = smemlen;
155         }
156 @@ -1189,12 +1234,19 @@ static int __init pxafb_parse_options(st
157                  if (!strncmp(this_opt, "mode:", 5)) {
158                         const char *name = this_opt+5;
159                         unsigned int namelen = strlen(name);
160 -                       int res_specified = 0, bpp_specified = 0;
161 -                       unsigned int xres = 0, yres = 0, bpp = 0;
162 +                       int res_specified = 0, bpp_specified = 0, nonstd_specified = 0;
163 +                       unsigned int xres = 0, yres = 0, bpp = 0, nonstd = 0;
164                         int yres_specified = 0;
165                         int i;
166                         for (i = namelen-1; i >= 0; i--) {
167                                 switch (name[i]) {
168 +                               case '/':
169 +                                       if (!nonstd_specified) {
170 +                                               nonstd = simple_strtoul(&name[i+1], NULL, 0);
171 +                                               nonstd_specified = 1;
172 +                                       } else
173 +                                               goto done;
174 +                                       break;
175                                 case '-':
176                                         namelen = i;
177                                         if (!bpp_specified && !yres_specified) {
178 @@ -1227,12 +1279,29 @@ static int __init pxafb_parse_options(st
179                         }
180                         if (bpp_specified)
181                                 switch (bpp) {
182 +                               case 18:
183 +                               case 19:
184 +                               case 24:
185 +                               case 25:
186 +                                       if(nonstd_specified && (((bpp == 18 || bpp == 19) && nonstd == 24) || nonstd == 32))
187 +                                       {
188 +                                               inf->modes[0].nonstd = nonstd;
189 +                                               dev_info(dev, "overriding nonstd pixel packing: %d\n",nonstd);
190 +                                       } else {
191 +                                               dev_err(dev, "Depth %d requires nonstd to be specified\n",bpp);
192 +                                               break;
193 +                                       }
194                                 case 1:
195                                 case 2:
196                                 case 4:
197                                 case 8:
198                                 case 16:
199                                         inf->modes[0].bpp = bpp;
200 +                                       if(nonstd_specified) {
201 +                                               dev_err(dev, "Depth %d requires nonstd to *not* be specified\n",bpp);
202 +                                       } else {
203 +                                               inf->modes[0].nonstd = 0;
204 +                                       }
205                                         dev_info(dev, "overriding bit depth: %d\n", bpp);
206                                         break;
207                                 default:
208 Index: linux-2.6.21.7/include/asm-arm/arch-pxa/pxa-regs.h
209 ===================================================================
210 --- linux-2.6.21.7.orig/include/asm-arm/arch-pxa/pxa-regs.h
211 +++ linux-2.6.21.7/include/asm-arm/arch-pxa/pxa-regs.h
212 @@ -1323,6 +1323,8 @@
213  #define GPIO83_NSTXD           83      /* NSSP transmit */
214  #define GPIO84_NSRXD           84      /* NSSP receive */
215  #define GPIO85_nPCE_1          85      /* Card Enable for Card Space (PXA27x) */
216 +#define GPIO86_LDD_16          86      /* LCD data pin 16 */
217 +#define GPIO87_LDD_17          87      /* LCD data pin 17 */
218  #define GPIO92_MMCDAT0         92      /* MMC DAT0 (PXA27x) */
219  #define GPIO102_nPCE_1         102     /* PCMCIA (PXA27x) */
220  #define GPIO105_nPCE_2         105     /* Card Enable for Card Space (PXA27x) */
221 @@ -1468,6 +1470,8 @@
222  #define GPIO84_NSSP_TX         (84 | GPIO_ALT_FN_1_OUT)
223  #define GPIO84_NSSP_RX         (84 | GPIO_ALT_FN_2_IN)
224  #define GPIO85_nPCE_1_MD       (85 | GPIO_ALT_FN_1_OUT)
225 +#define GPIO86_LDD_16_MD       (86 | GPIO_ALT_FN_2_OUT)
226 +#define GPIO87_LDD_17_MD       (87 | GPIO_ALT_FN_2_OUT)
227  #define GPIO92_MMCDAT0_MD      (92 | GPIO_ALT_FN_1_OUT)
228  #define GPIO102_nPCE_1_MD      (102 | GPIO_ALT_FN_1_OUT)
229  #define GPIO104_pSKTSEL_MD     (104 | GPIO_ALT_FN_1_OUT)
230 @@ -1878,6 +1882,12 @@
231  #define LCCR3_4BPP (2 << 24)
232  #define LCCR3_8BPP (3 << 24)
233  #define LCCR3_16BPP (4 << 24)
234 +#define LCCR3_18BPP (5 << 24)
235 +#define LCCR3_18BPP_PACKED (6 << 24)
236 +#define LCCR3_19BPP (7 << 24)
237 +#define LCCR3_19BPP_PACKED (1 << 29)
238 +#define LCCR3_24BPP ((1 << 29) | (1 << 24))
239 +#define LCCR3_25BPP ((1 << 29) | (2 << 24))
240  
241  #define FDADR0         __REG(0x44000200)  /* DMA Channel 0 Frame Descriptor Address Register */
242  #define FSADR0         __REG(0x44000204)  /* DMA Channel 0 Frame Source Address Register */
243 Index: linux-2.6.21.7/include/asm-arm/arch-pxa/pxafb.h
244 ===================================================================
245 --- linux-2.6.21.7.orig/include/asm-arm/arch-pxa/pxafb.h
246 +++ linux-2.6.21.7/include/asm-arm/arch-pxa/pxafb.h
247 @@ -25,6 +25,7 @@ struct pxafb_mode_info {
248         u_short         xres;
249         u_short         yres;
250  
251 +       /* bpp is the path-to-screen bits per pixel, not the in-memory storage required */
252         u_char          bpp;
253         u_char          hsync_len;
254         u_char          left_margin;
255 @@ -36,7 +37,9 @@ struct pxafb_mode_info {
256         u_char          sync;
257  
258         u_int           cmap_greyscale:1,
259 -                       unused:31;
260 +                       nonstd:8,       /* nonstd represents the in-memory bits per pixel
261 +                                               ie 24 or 32 for 18/19bpp mode, or 32 for 24/25bpp mode */
262 +                       unused:23;
263  };
264  
265  struct pxafb_mach_info {
266 Index: linux-2.6.21.7/arch/arm/mach-pxa/gumstix.c
267 ===================================================================
268 --- linux-2.6.21.7.orig/arch/arm/mach-pxa/gumstix.c
269 +++ linux-2.6.21.7/arch/arm/mach-pxa/gumstix.c
270 @@ -146,7 +146,8 @@ static struct pxafb_mode_info gumstix_fb
271         .pixclock       = 110000,
272         .xres           = 480,
273         .yres           = 272,
274 -       .bpp            = 16,
275 +       .bpp            = 18,
276 +       .nonstd         = 24,
277         .hsync_len      = 41,
278         .left_margin    = 2,
279         .right_margin   = 2,
280 @@ -174,7 +175,8 @@ static struct pxafb_mode_info gumstix_fb
281         .vsync_len      = 10, // VLW from datasheet: 10 typ
282         .upper_margin   = 2, // VBP - VLW from datasheet: 12 - 10 = 2
283         .lower_margin   = 4, // VFP from datasheet: 4 typ
284 -       .bpp            = 16,
285 +       .bpp            = 18,
286 +       .nonstd         = 24,
287         .sync           = 0, // Hsync and Vsync both active low
288  };
289  
290 Index: linux-2.6.21.7/drivers/video/cfbfillrect.c
291 ===================================================================
292 --- linux-2.6.21.7.orig/drivers/video/cfbfillrect.c
293 +++ linux-2.6.21.7/drivers/video/cfbfillrect.c
294 @@ -62,7 +62,10 @@ pixel_to_pat( u32 bpp, u32 pixel)
295                 return 0x0001001001001001ul*pixel;
296         case 16:
297                 return 0x0001000100010001ul*pixel;
298 +       case 18:
299 +       case 19:
300         case 24:
301 +       case 25:
302                 return 0x0000000001000001ul*pixel;
303         case 32:
304                 return 0x0000000100000001ul*pixel;
305 @@ -87,7 +90,10 @@ pixel_to_pat( u32 bpp, u32 pixel)
306                 return 0x00001001ul*pixel;
307         case 16:
308                 return 0x00010001ul*pixel;
309 +       case 18:
310 +       case 19:
311         case 24:
312 +       case 25:
313                 return 0x00000001ul*pixel;
314         case 32:
315                 return 0x00000001ul*pixel;
316 @@ -346,7 +352,7 @@ void cfb_fillrect(struct fb_info *p, con
317         unsigned long pat, fg;
318         unsigned long width = rect->width, height = rect->height;
319         int bits = BITS_PER_LONG, bytes = bits >> 3;
320 -       u32 bpp = p->var.bits_per_pixel;
321 +       u32 bpp = (p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
322         unsigned long __iomem *dst;
323         int dst_idx, left;
324  
325 Index: linux-2.6.21.7/drivers/video/cfbimgblt.c
326 ===================================================================
327 --- linux-2.6.21.7.orig/drivers/video/cfbimgblt.c
328 +++ linux-2.6.21.7/drivers/video/cfbimgblt.c
329 @@ -83,7 +83,7 @@ static inline void color_imageblit(const
330         /* Draw the penguin */
331         u32 __iomem *dst, *dst2;
332         u32 color = 0, val, shift;
333 -       int i, n, bpp = p->var.bits_per_pixel;
334 +       int i, n, bpp = (p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
335         u32 null_bits = 32 - bpp;
336         u32 *palette = (u32 *) p->pseudo_palette;
337         const u8 *src = image->data;
338 @@ -140,7 +140,7 @@ static inline void slow_imageblit(const 
339                                   u32 start_index,
340                                   u32 pitch_index)
341  {
342 -       u32 shift, color = 0, bpp = p->var.bits_per_pixel;
343 +       u32 shift, color = 0, bpp = (p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
344         u32 __iomem *dst, *dst2;
345         u32 val, pitch = p->fix.line_length;
346         u32 null_bits = 32 - bpp;
347 @@ -213,7 +213,7 @@ static inline void fast_imageblit(const 
348                                   u8 __iomem *dst1, u32 fgcolor, 
349                                   u32 bgcolor) 
350  {
351 -       u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
352 +       u32 fgx = fgcolor, bgx = bgcolor, bpp = (p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
353         u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
354         u32 bit_mask, end_mask, eorx, shift;
355         const char *s = image->data, *src;
356 @@ -262,7 +262,7 @@ static inline void fast_imageblit(const 
357  void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
358  {
359         u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
360 -       u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
361 +       u32 bpl = sizeof(u32), bpp = (p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
362         u32 width = image->width;
363         u32 dx = image->dx, dy = image->dy;
364         u8 __iomem *dst1;
365 Index: linux-2.6.21.7/drivers/video/cfbcopyarea.c
366 ===================================================================
367 --- linux-2.6.21.7.orig/drivers/video/cfbcopyarea.c
368 +++ linux-2.6.21.7/drivers/video/cfbcopyarea.c
369 @@ -365,8 +365,8 @@ void cfb_copyarea(struct fb_info *p, con
370         dst = src = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
371         dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
372         // add offset of source and target area
373 -       dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
374 -       src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
375 +       dst_idx += dy*bits_per_line + dx*(p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
376 +       src_idx += sy*bits_per_line + sx*(p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel);
377  
378         if (p->fbops->fb_sync)
379                 p->fbops->fb_sync(p);
380 @@ -380,7 +380,7 @@ void cfb_copyarea(struct fb_info *p, con
381                         src += src_idx >> (ffs(bits) - 1);
382                         src_idx &= (bytes - 1);
383                         bitcpy_rev(dst, dst_idx, src, src_idx, bits,
384 -                               width*p->var.bits_per_pixel);
385 +                               width*(p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel));
386                 }
387         } else {
388                 while (height--) {
389 @@ -389,7 +389,7 @@ void cfb_copyarea(struct fb_info *p, con
390                         src += src_idx >> (ffs(bits) - 1);
391                         src_idx &= (bytes - 1);
392                         bitcpy(dst, dst_idx, src, src_idx, bits,
393 -                               width*p->var.bits_per_pixel);
394 +                               width*(p->var.nonstd ? p->var.nonstd : p->var.bits_per_pixel));
395                         dst_idx += bits_per_line;
396                         src_idx += bits_per_line;
397                 }
398 Index: linux-2.6.21.7/drivers/video/console/fbcon.c
399 ===================================================================
400 --- linux-2.6.21.7.orig/drivers/video/console/fbcon.c
401 +++ linux-2.6.21.7/drivers/video/console/fbcon.c
402 @@ -983,9 +983,10 @@ static const char *fbcon_startup(void)
403  
404         DPRINTK("mode:   %s\n", info->fix.id);
405         DPRINTK("visual: %d\n", info->fix.visual);
406 -       DPRINTK("res:    %dx%d-%d\n", info->var.xres,
407 +       DPRINTK("res:    %dx%d-%d(%d)\n", info->var.xres,
408                 info->var.yres,
409 -               info->var.bits_per_pixel);
410 +               info->var.bits_per_pixel,
411 +               info->var.nonstd ? info->var.nonstd : info->var.bits_per_pixel);
412  
413  #ifdef CONFIG_ATARI
414         if (MACH_IS_ATARI) {
415 Index: linux-2.6.21.7/Documentation/fb/pxafb.txt
416 ===================================================================
417 --- linux-2.6.21.7.orig/Documentation/fb/pxafb.txt
418 +++ linux-2.6.21.7/Documentation/fb/pxafb.txt
419 @@ -9,11 +9,13 @@ For example:
420  or on the kernel command line
421         video=pxafb:mode:640x480-8,passive
422  
423 -mode:XRESxYRES[-BPP]
424 +mode:XRESxYRES[-BPP[/PACKING]]
425         XRES == LCCR1_PPL + 1
426         YRES == LLCR2_LPP + 1
427                 The resolution of the display in pixels
428         BPP == The bit depth. Valid values are 1, 2, 4, 8 and 16.
429 +       PACKING == The in-memory bits per pixel.  Valid values are 24, 32 when
430 +                       BPP == 18,19,24,25
431  
432  pixclock:PIXCLOCK
433         Pixel clock in picoseconds