diff options
| author | Eric Miao <ycmiao@ycmiao-hp520.(none)> | 2008-12-18 09:36:26 -0500 |
|---|---|---|
| committer | Eric Miao <eric.miao@marvell.com> | 2008-12-29 04:59:17 -0500 |
| commit | 878f5783199a95cfa91db45a6e34d2f72756fa18 (patch) | |
| tree | c979a4d4fdadf270baff1471f44ac91fe5c5e6af | |
| parent | a0427509a76c61984fbba4e206b617c689f419ef (diff) | |
[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)>
| -rw-r--r-- | arch/arm/mach-pxa/include/mach/regs-lcd.h | 15 | ||||
| -rw-r--r-- | drivers/video/pxafb.c | 183 |
2 files changed, 107 insertions, 91 deletions
diff --git a/arch/arm/mach-pxa/include/mach/regs-lcd.h b/arch/arm/mach-pxa/include/mach/regs-lcd.h index 5c522263e401..aff3b876a7bf 100644 --- a/arch/arm/mach-pxa/include/mach/regs-lcd.h +++ b/arch/arm/mach-pxa/include/mach/regs-lcd.h | |||
| @@ -28,17 +28,7 @@ | |||
| 28 | #define CMDCR (0x100) /* Command Control Register */ | 28 | #define CMDCR (0x100) /* Command Control Register */ |
| 29 | #define PRSR (0x104) /* Panel Read Status Register */ | 29 | #define PRSR (0x104) /* Panel Read Status Register */ |
| 30 | 30 | ||
| 31 | #define LCCR3_1BPP (0 << 24) | 31 | #define LCCR3_BPP(x) ((((x) & 0x7) << 24) | (((x) & 0x8) ? (1 << 29) : 0)) |
| 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)) | ||
| 42 | 32 | ||
| 43 | #define LCCR3_PDFOR_0 (0 << 30) | 33 | #define LCCR3_PDFOR_0 (0 << 30) |
| 44 | #define LCCR3_PDFOR_1 (1 << 30) | 34 | #define LCCR3_PDFOR_1 (1 << 30) |
| @@ -133,9 +123,6 @@ | |||
| 133 | #define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */ | 123 | #define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */ |
| 134 | #define LCCR3_PixClkDiv(Div) (((Div) << FShft (LCCR3_PCD))) | 124 | #define LCCR3_PixClkDiv(Div) (((Div) << FShft (LCCR3_PCD))) |
| 135 | 125 | ||
| 136 | #define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */ | ||
| 137 | #define LCCR3_Bpp(Bpp) (((Bpp) << FShft (LCCR3_BPP))) | ||
| 138 | |||
| 139 | #define LCCR3_ACB Fld (8, 8) /* AC Bias */ | 126 | #define LCCR3_ACB Fld (8, 8) /* AC Bias */ |
| 140 | #define LCCR3_Acb(Acb) (((Acb) << FShft (LCCR3_ACB))) | 127 | #define LCCR3_Acb(Acb) (((Acb) << FShft (LCCR3_ACB))) |
| 141 | 128 | ||
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index c57f909cb7a8..1faf52642f5f 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
| @@ -66,7 +66,7 @@ | |||
| 66 | LCCR0_SFM | LCCR0_LDM | LCCR0_ENB) | 66 | LCCR0_SFM | LCCR0_LDM | LCCR0_ENB) |
| 67 | 67 | ||
| 68 | #define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP | LCCR3_VSP |\ | 68 | #define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP | LCCR3_VSP |\ |
| 69 | LCCR3_PCD | LCCR3_BPP) | 69 | LCCR3_PCD | LCCR3_BPP(0xf)) |
| 70 | 70 | ||
| 71 | static int pxafb_activate_var(struct fb_var_screeninfo *var, | 71 | static int pxafb_activate_var(struct fb_var_screeninfo *var, |
| 72 | struct pxafb_info *); | 72 | struct pxafb_info *); |
| @@ -221,37 +221,110 @@ pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
| 221 | return ret; | 221 | return ret; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | /* | 224 | /* calculate pixel depth, transparency bit included, >=16bpp formats _only_ */ |
| 225 | * pxafb_bpp_to_lccr3(): | 225 | static inline int var_to_depth(struct fb_var_screeninfo *var) |
| 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) | ||
| 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 | switch (var->bits_per_pixel) { | 236 | switch (var->bits_per_pixel) { |
| 232 | case 1: ret = LCCR3_1BPP; break; | 237 | case 1: bpp = 0; break; |
| 233 | case 2: ret = LCCR3_2BPP; break; | 238 | case 2: bpp = 1; break; |
| 234 | case 4: ret = LCCR3_4BPP; break; | 239 | case 4: bpp = 2; break; |
| 235 | case 8: ret = LCCR3_8BPP; break; | 240 | case 8: bpp = 3; break; |
| 236 | case 16: ret = LCCR3_16BPP; break; | 241 | case 16: bpp = 4; break; |
| 237 | case 24: | 242 | case 24: |
| 238 | switch (var->red.length + var->green.length + | 243 | switch (var_to_depth(var)) { |
| 239 | var->blue.length + var->transp.length) { | 244 | case 18: bpp = 6; break; /* 18-bits/pixel packed */ |
| 240 | case 18: ret = LCCR3_18BPP_P | LCCR3_PDFOR_3; break; | 245 | case 19: bpp = 8; break; /* 19-bits/pixel packed */ |
| 241 | case 19: ret = LCCR3_19BPP_P; break; | 246 | case 24: bpp = 9; break; |
| 242 | } | 247 | } |
| 243 | break; | 248 | break; |
| 244 | case 32: | 249 | case 32: |
| 245 | switch (var->red.length + var->green.length + | 250 | switch (var_to_depth(var)) { |
| 246 | var->blue.length + var->transp.length) { | 251 | case 18: bpp = 5; break; /* 18-bits/pixel unpacked */ |
| 247 | case 18: ret = LCCR3_18BPP | LCCR3_PDFOR_3; break; | 252 | case 19: bpp = 7; break; /* 19-bits/pixel unpacked */ |
| 248 | case 19: ret = LCCR3_19BPP; break; | 253 | case 25: bpp = 10; break; |
| 249 | case 24: ret = LCCR3_24BPP | LCCR3_PDFOR_3; break; | ||
| 250 | case 25: ret = LCCR3_25BPP; break; | ||
| 251 | } | 254 | } |
| 252 | break; | 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 | #ifdef CONFIG_CPU_FREQ | 330 | #ifdef CONFIG_CPU_FREQ |
| @@ -313,6 +386,9 @@ static void pxafb_setmode(struct fb_var_screeninfo *var, | |||
| 313 | var->lower_margin = mode->lower_margin; | 386 | var->lower_margin = mode->lower_margin; |
| 314 | var->sync = mode->sync; | 387 | var->sync = mode->sync; |
| 315 | var->grayscale = mode->cmap_greyscale; | 388 | var->grayscale = mode->cmap_greyscale; |
| 389 | |||
| 390 | /* set the initial RGBA bitfields */ | ||
| 391 | pxafb_set_pixfmt(var, mode->depth); | ||
| 316 | } | 392 | } |
| 317 | 393 | ||
| 318 | /* | 394 | /* |
| @@ -328,6 +404,7 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
| 328 | { | 404 | { |
| 329 | struct pxafb_info *fbi = (struct pxafb_info *)info; | 405 | struct pxafb_info *fbi = (struct pxafb_info *)info; |
| 330 | struct pxafb_mach_info *inf = fbi->dev->platform_data; | 406 | struct pxafb_mach_info *inf = fbi->dev->platform_data; |
| 407 | int err; | ||
| 331 | 408 | ||
| 332 | if (var->xres < MIN_XRES) | 409 | if (var->xres < MIN_XRES) |
| 333 | var->xres = MIN_XRES; | 410 | var->xres = MIN_XRES; |
| @@ -359,60 +436,12 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
| 359 | else | 436 | else |
| 360 | var->yres_virtual = max(var->yres_virtual, var->yres); | 437 | var->yres_virtual = max(var->yres_virtual, var->yres); |
| 361 | 438 | ||
| 362 | /* | 439 | /* do a test conversion to BPP fields to check the color formats */ |
| 363 | * Setup the RGB parameters for this display. | 440 | err = pxafb_var_to_bpp(var); |
| 364 | * | 441 | if (err < 0) |
| 365 | * The pixel packing format is described on page 7-11 of the | 442 | return err; |
| 366 | * PXA2XX Developer's Manual. | ||
| 367 | */ | ||
| 368 | if (var->bits_per_pixel == 16) { | ||
| 369 | var->red.offset = 11; var->red.length = 5; | ||
| 370 | var->green.offset = 5; var->green.length = 6; | ||
| 371 | var->blue.offset = 0; var->blue.length = 5; | ||
| 372 | var->transp.offset = var->transp.length = 0; | ||
| 373 | } else if (var->bits_per_pixel > 16) { | ||
| 374 | struct pxafb_mode_info *mode; | ||
| 375 | 443 | ||
| 376 | mode = pxafb_getmode(inf, var); | 444 | pxafb_set_pixfmt(var, var_to_depth(var)); |
| 377 | if (!mode) | ||
| 378 | return -EINVAL; | ||
| 379 | |||
| 380 | switch (mode->depth) { | ||
| 381 | case 18: /* RGB666 */ | ||
| 382 | var->transp.offset = var->transp.length = 0; | ||
| 383 | var->red.offset = 12; var->red.length = 6; | ||
| 384 | var->green.offset = 6; var->green.length = 6; | ||
| 385 | var->blue.offset = 0; var->blue.length = 6; | ||
| 386 | break; | ||
| 387 | case 19: /* RGBT666 */ | ||
| 388 | var->transp.offset = 18; var->transp.length = 1; | ||
| 389 | var->red.offset = 12; var->red.length = 6; | ||
| 390 | var->green.offset = 6; var->green.length = 6; | ||
| 391 | var->blue.offset = 0; var->blue.length = 6; | ||
| 392 | break; | ||
| 393 | case 24: /* RGB888 */ | ||
| 394 | var->transp.offset = var->transp.length = 0; | ||
| 395 | var->red.offset = 16; var->red.length = 8; | ||
| 396 | var->green.offset = 8; var->green.length = 8; | ||
| 397 | var->blue.offset = 0; var->blue.length = 8; | ||
| 398 | break; | ||
| 399 | case 25: /* RGBT888 */ | ||
| 400 | var->transp.offset = 24; var->transp.length = 1; | ||
| 401 | var->red.offset = 16; var->red.length = 8; | ||
| 402 | var->green.offset = 8; var->green.length = 8; | ||
| 403 | var->blue.offset = 0; var->blue.length = 8; | ||
| 404 | break; | ||
| 405 | default: | ||
| 406 | return -EINVAL; | ||
| 407 | } | ||
| 408 | } else { | ||
| 409 | var->red.offset = var->green.offset = 0; | ||
| 410 | var->blue.offset = var->transp.offset = 0; | ||
| 411 | var->red.length = 8; | ||
| 412 | var->green.length = 8; | ||
| 413 | var->blue.length = 8; | ||
| 414 | var->transp.length = 0; | ||
| 415 | } | ||
| 416 | 445 | ||
| 417 | #ifdef CONFIG_CPU_FREQ | 446 | #ifdef CONFIG_CPU_FREQ |
| 418 | pr_debug("pxafb: dma period = %d ps\n", | 447 | pr_debug("pxafb: dma period = %d ps\n", |
| @@ -978,7 +1007,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, | |||
| 978 | (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | | 1007 | (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | |
| 979 | LCCR0_QDM | LCCR0_BM | LCCR0_OUM); | 1008 | LCCR0_QDM | LCCR0_BM | LCCR0_OUM); |
| 980 | 1009 | ||
| 981 | fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var); | 1010 | fbi->reg_lccr3 |= pxafb_var_to_lccr3(var); |
| 982 | 1011 | ||
| 983 | fbi->reg_lccr4 = lcd_readl(fbi, LCCR4) & ~LCCR4_PAL_FOR_MASK; | 1012 | fbi->reg_lccr4 = lcd_readl(fbi, LCCR4) & ~LCCR4_PAL_FOR_MASK; |
| 984 | fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK); | 1013 | fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK); |
