aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/pxafb.c
diff options
context:
space:
mode:
authorEric Miao <ycmiao@ycmiao-hp520.(none)>2008-12-18 09:36:26 -0500
committerEric Miao <eric.miao@marvell.com>2008-12-29 04:59:17 -0500
commit878f5783199a95cfa91db45a6e34d2f72756fa18 (patch)
treec979a4d4fdadf270baff1471f44ac91fe5c5e6af /drivers/video/pxafb.c
parenta0427509a76c61984fbba4e206b617c689f419ef (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)>
Diffstat (limited to 'drivers/video/pxafb.c')
-rw-r--r--drivers/video/pxafb.c183
1 files changed, 106 insertions, 77 deletions
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
71static int pxafb_activate_var(struct fb_var_screeninfo *var, 71static 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(): 225static 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 */
228static 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 */
232static 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 */
271static 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 */
304static 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);