Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[ARM] pxafb: cleanup of the color format manipulation code

1. introduce var_to_depth() to calculate the color depth including the
transparency bit

2. the conversion from 'fb_var_screeninfo' to LCCR3 BPP bits can be re-
used by overlays (in OVLxC1), thus an individual pxafb_var_to_bpp()
has been separated out.

3. pxafb_setmode() should really set the color bitfields correctly at
begining, introduce a pxafb_set_pixfmt() for this

4. allow user apps to specify color formats within fb_var_screeninfo,
and checking of this in pxafb_check_var() has been simplified as
below:

a) pxafb_var_to_bpp() should pass - which means a basically correct
bits_per_pixel and color depth setting
b) the RGBT bitfields are then forced into supported values by
pxafb_set_pixfmt()

Signed-off-by: Eric Miao <eric.miao@marvell.com>
Signed-off-by: Eric Miao <ycmiao@ycmiao-hp520.(none)>

authored by

Eric Miao and committed by
Eric Miao
878f5783 a0427509

+107 -91
+1 -14
arch/arm/mach-pxa/include/mach/regs-lcd.h
··· 28 28 #define CMDCR (0x100) /* Command Control Register */ 29 29 #define PRSR (0x104) /* Panel Read Status Register */ 30 30 31 - #define LCCR3_1BPP (0 << 24) 32 - #define LCCR3_2BPP (1 << 24) 33 - #define LCCR3_4BPP (2 << 24) 34 - #define LCCR3_8BPP (3 << 24) 35 - #define LCCR3_16BPP (4 << 24) 36 - #define LCCR3_18BPP (5 << 24) 37 - #define LCCR3_18BPP_P (6 << 24) 38 - #define LCCR3_19BPP (7 << 24) 39 - #define LCCR3_19BPP_P (1 << 29) 40 - #define LCCR3_24BPP ((1 << 29) | (1 << 24)) 41 - #define LCCR3_25BPP ((1 << 29) | (2 << 24)) 31 + #define LCCR3_BPP(x) ((((x) & 0x7) << 24) | (((x) & 0x8) ? (1 << 29) : 0)) 42 32 43 33 #define LCCR3_PDFOR_0 (0 << 30) 44 34 #define LCCR3_PDFOR_1 (1 << 30) ··· 122 132 #define LCCR3_DPC (1 << 27) /* double pixel clock mode */ 123 133 #define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */ 124 134 #define LCCR3_PixClkDiv(Div) (((Div) << FShft (LCCR3_PCD))) 125 - 126 - #define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */ 127 - #define LCCR3_Bpp(Bpp) (((Bpp) << FShft (LCCR3_BPP))) 128 135 129 136 #define LCCR3_ACB Fld (8, 8) /* AC Bias */ 130 137 #define LCCR3_Acb(Acb) (((Acb) << FShft (LCCR3_ACB)))
+106 -77
drivers/video/pxafb.c
··· 66 66 LCCR0_SFM | LCCR0_LDM | LCCR0_ENB) 67 67 68 68 #define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP | LCCR3_VSP |\ 69 - LCCR3_PCD | LCCR3_BPP) 69 + LCCR3_PCD | LCCR3_BPP(0xf)) 70 70 71 71 static int pxafb_activate_var(struct fb_var_screeninfo *var, 72 72 struct pxafb_info *); ··· 221 221 return ret; 222 222 } 223 223 224 - /* 225 - * pxafb_bpp_to_lccr3(): 226 - * Convert a bits per pixel value to the correct bit pattern for LCCR3 227 - */ 228 - static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var) 224 + /* calculate pixel depth, transparency bit included, >=16bpp formats _only_ */ 225 + static inline int var_to_depth(struct fb_var_screeninfo *var) 229 226 { 230 - int ret = 0; 227 + return var->red.length + var->green.length + 228 + var->blue.length + var->transp.length; 229 + } 230 + 231 + /* calculate 4-bit BPP value for LCCR3 and OVLxC1 */ 232 + static int pxafb_var_to_bpp(struct fb_var_screeninfo *var) 233 + { 234 + int bpp = -EINVAL; 235 + 231 236 switch (var->bits_per_pixel) { 232 - case 1: ret = LCCR3_1BPP; break; 233 - case 2: ret = LCCR3_2BPP; break; 234 - case 4: ret = LCCR3_4BPP; break; 235 - case 8: ret = LCCR3_8BPP; break; 236 - case 16: ret = LCCR3_16BPP; break; 237 + case 1: bpp = 0; break; 238 + case 2: bpp = 1; break; 239 + case 4: bpp = 2; break; 240 + case 8: bpp = 3; break; 241 + case 16: bpp = 4; break; 237 242 case 24: 238 - switch (var->red.length + var->green.length + 239 - var->blue.length + var->transp.length) { 240 - case 18: ret = LCCR3_18BPP_P | LCCR3_PDFOR_3; break; 241 - case 19: ret = LCCR3_19BPP_P; break; 243 + switch (var_to_depth(var)) { 244 + case 18: bpp = 6; break; /* 18-bits/pixel packed */ 245 + case 19: bpp = 8; break; /* 19-bits/pixel packed */ 246 + case 24: bpp = 9; break; 242 247 } 243 248 break; 244 249 case 32: 245 - switch (var->red.length + var->green.length + 246 - var->blue.length + var->transp.length) { 247 - case 18: ret = LCCR3_18BPP | LCCR3_PDFOR_3; break; 248 - case 19: ret = LCCR3_19BPP; break; 249 - case 24: ret = LCCR3_24BPP | LCCR3_PDFOR_3; break; 250 - case 25: ret = LCCR3_25BPP; break; 250 + switch (var_to_depth(var)) { 251 + case 18: bpp = 5; break; /* 18-bits/pixel unpacked */ 252 + case 19: bpp = 7; break; /* 19-bits/pixel unpacked */ 253 + case 25: bpp = 10; break; 251 254 } 252 255 break; 253 256 } 254 - return ret; 257 + return bpp; 258 + } 259 + 260 + /* 261 + * pxafb_var_to_lccr3(): 262 + * Convert a bits per pixel value to the correct bit pattern for LCCR3 263 + * 264 + * NOTE: for PXA27x with overlays support, the LCCR3_PDFOR_x bits have an 265 + * implication of the acutal use of transparency bit, which we handle it 266 + * here separatedly. See PXA27x Developer's Manual, Section <<7.4.6 Pixel 267 + * Formats>> for the valid combination of PDFOR, PAL_FOR for various BPP. 268 + * 269 + * Transparency for palette pixel formats is not supported at the moment. 270 + */ 271 + static uint32_t pxafb_var_to_lccr3(struct fb_var_screeninfo *var) 272 + { 273 + int bpp = pxafb_var_to_bpp(var); 274 + uint32_t lccr3; 275 + 276 + if (bpp < 0) 277 + return 0; 278 + 279 + lccr3 = LCCR3_BPP(bpp); 280 + 281 + switch (var_to_depth(var)) { 282 + case 16: lccr3 |= var->transp.length ? LCCR3_PDFOR_3 : 0; break; 283 + case 18: lccr3 |= LCCR3_PDFOR_3; break; 284 + case 24: lccr3 |= var->transp.length ? LCCR3_PDFOR_2 : LCCR3_PDFOR_3; 285 + break; 286 + case 19: 287 + case 25: lccr3 |= LCCR3_PDFOR_0; break; 288 + } 289 + return lccr3; 290 + } 291 + 292 + #define SET_PIXFMT(v, r, g, b, t) \ 293 + ({ \ 294 + (v)->transp.offset = (t) ? (r) + (g) + (b) : 0; \ 295 + (v)->transp.length = (t) ? (t) : 0; \ 296 + (v)->blue.length = (b); (v)->blue.offset = 0; \ 297 + (v)->green.length = (g); (v)->green.offset = (b); \ 298 + (v)->red.length = (r); (v)->red.offset = (b) + (g); \ 299 + }) 300 + 301 + /* set the RGBT bitfields of fb_var_screeninf according to 302 + * var->bits_per_pixel and given depth 303 + */ 304 + static void pxafb_set_pixfmt(struct fb_var_screeninfo *var, int depth) 305 + { 306 + if (depth == 0) 307 + depth = var->bits_per_pixel; 308 + 309 + if (var->bits_per_pixel < 16) { 310 + /* indexed pixel formats */ 311 + var->red.offset = 0; var->red.length = 8; 312 + var->green.offset = 0; var->green.length = 8; 313 + var->blue.offset = 0; var->blue.length = 8; 314 + var->transp.offset = 0; var->transp.length = 8; 315 + } 316 + 317 + switch (depth) { 318 + case 16: var->transp.length ? 319 + SET_PIXFMT(var, 5, 5, 5, 1) : /* RGBT555 */ 320 + SET_PIXFMT(var, 5, 6, 5, 0); break; /* RGB565 */ 321 + case 18: SET_PIXFMT(var, 6, 6, 6, 0); break; /* RGB666 */ 322 + case 19: SET_PIXFMT(var, 6, 6, 6, 1); break; /* RGBT666 */ 323 + case 24: var->transp.length ? 324 + SET_PIXFMT(var, 8, 8, 7, 1) : /* RGBT887 */ 325 + SET_PIXFMT(var, 8, 8, 8, 0); break; /* RGB888 */ 326 + case 25: SET_PIXFMT(var, 8, 8, 8, 1); break; /* RGBT888 */ 327 + } 255 328 } 256 329 257 330 #ifdef CONFIG_CPU_FREQ ··· 386 313 var->lower_margin = mode->lower_margin; 387 314 var->sync = mode->sync; 388 315 var->grayscale = mode->cmap_greyscale; 316 + 317 + /* set the initial RGBA bitfields */ 318 + pxafb_set_pixfmt(var, mode->depth); 389 319 } 390 320 391 321 /* ··· 404 328 { 405 329 struct pxafb_info *fbi = (struct pxafb_info *)info; 406 330 struct pxafb_mach_info *inf = fbi->dev->platform_data; 331 + int err; 407 332 408 333 if (var->xres < MIN_XRES) 409 334 var->xres = MIN_XRES; ··· 436 359 else 437 360 var->yres_virtual = max(var->yres_virtual, var->yres); 438 361 439 - /* 440 - * Setup the RGB parameters for this display. 441 - * 442 - * The pixel packing format is described on page 7-11 of the 443 - * PXA2XX Developer's Manual. 444 - */ 445 - if (var->bits_per_pixel == 16) { 446 - var->red.offset = 11; var->red.length = 5; 447 - var->green.offset = 5; var->green.length = 6; 448 - var->blue.offset = 0; var->blue.length = 5; 449 - var->transp.offset = var->transp.length = 0; 450 - } else if (var->bits_per_pixel > 16) { 451 - struct pxafb_mode_info *mode; 362 + /* do a test conversion to BPP fields to check the color formats */ 363 + err = pxafb_var_to_bpp(var); 364 + if (err < 0) 365 + return err; 452 366 453 - mode = pxafb_getmode(inf, var); 454 - if (!mode) 455 - return -EINVAL; 456 - 457 - switch (mode->depth) { 458 - case 18: /* RGB666 */ 459 - var->transp.offset = var->transp.length = 0; 460 - var->red.offset = 12; var->red.length = 6; 461 - var->green.offset = 6; var->green.length = 6; 462 - var->blue.offset = 0; var->blue.length = 6; 463 - break; 464 - case 19: /* RGBT666 */ 465 - var->transp.offset = 18; var->transp.length = 1; 466 - var->red.offset = 12; var->red.length = 6; 467 - var->green.offset = 6; var->green.length = 6; 468 - var->blue.offset = 0; var->blue.length = 6; 469 - break; 470 - case 24: /* RGB888 */ 471 - var->transp.offset = var->transp.length = 0; 472 - var->red.offset = 16; var->red.length = 8; 473 - var->green.offset = 8; var->green.length = 8; 474 - var->blue.offset = 0; var->blue.length = 8; 475 - break; 476 - case 25: /* RGBT888 */ 477 - var->transp.offset = 24; var->transp.length = 1; 478 - var->red.offset = 16; var->red.length = 8; 479 - var->green.offset = 8; var->green.length = 8; 480 - var->blue.offset = 0; var->blue.length = 8; 481 - break; 482 - default: 483 - return -EINVAL; 484 - } 485 - } else { 486 - var->red.offset = var->green.offset = 0; 487 - var->blue.offset = var->transp.offset = 0; 488 - var->red.length = 8; 489 - var->green.length = 8; 490 - var->blue.length = 8; 491 - var->transp.length = 0; 492 - } 367 + pxafb_set_pixfmt(var, var_to_depth(var)); 493 368 494 369 #ifdef CONFIG_CPU_FREQ 495 370 pr_debug("pxafb: dma period = %d ps\n", ··· 1007 978 (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | 1008 979 LCCR0_QDM | LCCR0_BM | LCCR0_OUM); 1009 980 1010 - fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var); 981 + fbi->reg_lccr3 |= pxafb_var_to_lccr3(var); 1011 982 1012 983 fbi->reg_lccr4 = lcd_readl(fbi, LCCR4) & ~LCCR4_PAL_FOR_MASK; 1013 984 fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK);