aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/sh_mobile_lcdcfb.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-11-29 09:58:10 -0500
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-03-12 17:40:56 -0400
commit105784bbb47cd76f0fc32954b047a13b704fa840 (patch)
tree72e09b02c179308a679c2203b5d2d860617b1bca /drivers/video/sh_mobile_lcdcfb.c
parent740f802af2d8c46f1423b6b3daa33e4e1ea223f0 (diff)
fbdev: sh_mobile_lcdc: Add sh_mobile_format_info() function
The function returns a pointer to a structure describing a format based on its fourcc. Use the function where applicable instead of hardcoded switch-case statements. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'drivers/video/sh_mobile_lcdcfb.c')
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c174
1 files changed, 102 insertions, 72 deletions
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index ab7b17975846..c66f0f4fe3d9 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -449,6 +449,75 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
449 * Format helpers 449 * Format helpers
450 */ 450 */
451 451
452struct sh_mobile_lcdc_format_info {
453 u32 fourcc;
454 unsigned int bpp;
455 bool yuv;
456 u32 lddfr;
457};
458
459static const struct sh_mobile_lcdc_format_info sh_mobile_format_infos[] = {
460 {
461 .fourcc = V4L2_PIX_FMT_RGB565,
462 .bpp = 16,
463 .yuv = false,
464 .lddfr = LDDFR_PKF_RGB16,
465 }, {
466 .fourcc = V4L2_PIX_FMT_BGR24,
467 .bpp = 24,
468 .yuv = false,
469 .lddfr = LDDFR_PKF_RGB24,
470 }, {
471 .fourcc = V4L2_PIX_FMT_BGR32,
472 .bpp = 32,
473 .yuv = false,
474 .lddfr = LDDFR_PKF_ARGB32,
475 }, {
476 .fourcc = V4L2_PIX_FMT_NV12,
477 .bpp = 12,
478 .yuv = true,
479 .lddfr = LDDFR_CC | LDDFR_YF_420,
480 }, {
481 .fourcc = V4L2_PIX_FMT_NV21,
482 .bpp = 12,
483 .yuv = true,
484 .lddfr = LDDFR_CC | LDDFR_YF_420,
485 }, {
486 .fourcc = V4L2_PIX_FMT_NV16,
487 .bpp = 16,
488 .yuv = true,
489 .lddfr = LDDFR_CC | LDDFR_YF_422,
490 }, {
491 .fourcc = V4L2_PIX_FMT_NV61,
492 .bpp = 16,
493 .yuv = true,
494 .lddfr = LDDFR_CC | LDDFR_YF_422,
495 }, {
496 .fourcc = V4L2_PIX_FMT_NV24,
497 .bpp = 24,
498 .yuv = true,
499 .lddfr = LDDFR_CC | LDDFR_YF_444,
500 }, {
501 .fourcc = V4L2_PIX_FMT_NV42,
502 .bpp = 24,
503 .yuv = true,
504 .lddfr = LDDFR_CC | LDDFR_YF_444,
505 },
506};
507
508static const struct sh_mobile_lcdc_format_info *
509sh_mobile_format_info(u32 fourcc)
510{
511 unsigned int i;
512
513 for (i = 0; i < ARRAY_SIZE(sh_mobile_format_infos); ++i) {
514 if (sh_mobile_format_infos[i].fourcc == fourcc)
515 return &sh_mobile_format_infos[i];
516 }
517
518 return NULL;
519}
520
452static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var) 521static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
453{ 522{
454 if (var->grayscale > 1) 523 if (var->grayscale > 1)
@@ -473,21 +542,13 @@ static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
473 542
474static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var) 543static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
475{ 544{
545 const struct sh_mobile_lcdc_format_info *format;
546
476 if (var->grayscale <= 1) 547 if (var->grayscale <= 1)
477 return false; 548 return false;
478 549
479 switch (var->grayscale) { 550 format = sh_mobile_format_info(var->grayscale);
480 case V4L2_PIX_FMT_NV12: 551 return format ? format->yuv : false;
481 case V4L2_PIX_FMT_NV21:
482 case V4L2_PIX_FMT_NV16:
483 case V4L2_PIX_FMT_NV61:
484 case V4L2_PIX_FMT_NV24:
485 case V4L2_PIX_FMT_NV42:
486 return true;
487
488 default:
489 return false;
490 }
491} 552}
492 553
493/* ----------------------------------------------------------------------------- 554/* -----------------------------------------------------------------------------
@@ -667,37 +728,20 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
667 728
668 /* Setup geometry, format, frame buffer memory and operation mode. */ 729 /* Setup geometry, format, frame buffer memory and operation mode. */
669 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 730 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
731 const struct sh_mobile_lcdc_format_info *format;
732 u32 fourcc;
733
670 ch = &priv->ch[k]; 734 ch = &priv->ch[k];
671 if (!ch->enabled) 735 if (!ch->enabled)
672 continue; 736 continue;
673 737
674 sh_mobile_lcdc_geometry(ch); 738 sh_mobile_lcdc_geometry(ch);
675 739
676 switch (sh_mobile_format_fourcc(&ch->info->var)) { 740 fourcc = sh_mobile_format_fourcc(&ch->info->var);
677 case V4L2_PIX_FMT_RGB565: 741 format = sh_mobile_format_info(fourcc);
678 tmp = LDDFR_PKF_RGB16; 742 tmp = format->lddfr;
679 break;
680 case V4L2_PIX_FMT_BGR24:
681 tmp = LDDFR_PKF_RGB24;
682 break;
683 case V4L2_PIX_FMT_BGR32:
684 tmp = LDDFR_PKF_ARGB32;
685 break;
686 case V4L2_PIX_FMT_NV12:
687 case V4L2_PIX_FMT_NV21:
688 tmp = LDDFR_CC | LDDFR_YF_420;
689 break;
690 case V4L2_PIX_FMT_NV16:
691 case V4L2_PIX_FMT_NV61:
692 tmp = LDDFR_CC | LDDFR_YF_422;
693 break;
694 case V4L2_PIX_FMT_NV24:
695 case V4L2_PIX_FMT_NV42:
696 tmp = LDDFR_CC | LDDFR_YF_444;
697 break;
698 }
699 743
700 if (sh_mobile_format_is_yuv(&ch->info->var)) { 744 if (format->yuv) {
701 switch (ch->info->var.colorspace) { 745 switch (ch->info->var.colorspace) {
702 case V4L2_COLORSPACE_REC709: 746 case V4L2_COLORSPACE_REC709:
703 tmp |= LDDFR_CF1; 747 tmp |= LDDFR_CF1;
@@ -711,7 +755,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
711 lcdc_write_chan(ch, LDDFR, tmp); 755 lcdc_write_chan(ch, LDDFR, tmp);
712 lcdc_write_chan(ch, LDMLSR, ch->pitch); 756 lcdc_write_chan(ch, LDMLSR, ch->pitch);
713 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); 757 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
714 if (sh_mobile_format_is_yuv(&ch->info->var)) 758 if (format->yuv)
715 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); 759 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
716 760
717 /* When using deferred I/O mode, configure the LCDC for one-shot 761 /* When using deferred I/O mode, configure the LCDC for one-shot
@@ -1228,32 +1272,17 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1228 var->yres_virtual = var->yres; 1272 var->yres_virtual = var->yres;
1229 1273
1230 if (sh_mobile_format_is_fourcc(var)) { 1274 if (sh_mobile_format_is_fourcc(var)) {
1231 switch (var->grayscale) { 1275 const struct sh_mobile_lcdc_format_info *format;
1232 case V4L2_PIX_FMT_NV12: 1276
1233 case V4L2_PIX_FMT_NV21: 1277 format = sh_mobile_format_info(var->grayscale);
1234 var->bits_per_pixel = 12; 1278 if (format == NULL)
1235 break;
1236 case V4L2_PIX_FMT_RGB565:
1237 case V4L2_PIX_FMT_NV16:
1238 case V4L2_PIX_FMT_NV61:
1239 var->bits_per_pixel = 16;
1240 break;
1241 case V4L2_PIX_FMT_BGR24:
1242 case V4L2_PIX_FMT_NV24:
1243 case V4L2_PIX_FMT_NV42:
1244 var->bits_per_pixel = 24;
1245 break;
1246 case V4L2_PIX_FMT_BGR32:
1247 var->bits_per_pixel = 32;
1248 break;
1249 default:
1250 return -EINVAL; 1279 return -EINVAL;
1251 } 1280 var->bits_per_pixel = format->bpp;
1252 1281
1253 /* Default to RGB and JPEG color-spaces for RGB and YUV formats 1282 /* Default to RGB and JPEG color-spaces for RGB and YUV formats
1254 * respectively. 1283 * respectively.
1255 */ 1284 */
1256 if (!sh_mobile_format_is_yuv(var)) 1285 if (!format->yuv)
1257 var->colorspace = V4L2_COLORSPACE_SRGB; 1286 var->colorspace = V4L2_COLORSPACE_SRGB;
1258 else if (var->colorspace != V4L2_COLORSPACE_REC709) 1287 else if (var->colorspace != V4L2_COLORSPACE_REC709)
1259 var->colorspace = V4L2_COLORSPACE_JPEG; 1288 var->colorspace = V4L2_COLORSPACE_JPEG;
@@ -1665,6 +1694,7 @@ static int __devinit
1665sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, 1694sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
1666 struct sh_mobile_lcdc_chan *ch) 1695 struct sh_mobile_lcdc_chan *ch)
1667{ 1696{
1697 const struct sh_mobile_lcdc_format_info *format;
1668 struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg; 1698 struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg;
1669 const struct fb_videomode *max_mode; 1699 const struct fb_videomode *max_mode;
1670 const struct fb_videomode *mode; 1700 const struct fb_videomode *mode;
@@ -1679,6 +1709,13 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
1679 mutex_init(&ch->open_lock); 1709 mutex_init(&ch->open_lock);
1680 ch->notify = sh_mobile_lcdc_display_notify; 1710 ch->notify = sh_mobile_lcdc_display_notify;
1681 1711
1712 /* Validate the format. */
1713 format = sh_mobile_format_info(cfg->fourcc);
1714 if (format == NULL) {
1715 dev_err(priv->dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
1716 return -EINVAL;
1717 }
1718
1682 /* Allocate the frame buffer device. */ 1719 /* Allocate the frame buffer device. */
1683 ch->info = framebuffer_alloc(0, priv->dev); 1720 ch->info = framebuffer_alloc(0, priv->dev);
1684 if (!ch->info) { 1721 if (!ch->info) {
@@ -1756,20 +1793,13 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
1756 var->yres_virtual = var->yres * 2; 1793 var->yres_virtual = var->yres * 2;
1757 var->activate = FB_ACTIVATE_NOW; 1794 var->activate = FB_ACTIVATE_NOW;
1758 1795
1759 switch (cfg->fourcc) { 1796 /* Use the legacy API by default for RGB formats, and the FOURCC API
1760 case V4L2_PIX_FMT_RGB565: 1797 * for YUV formats.
1761 var->bits_per_pixel = 16; 1798 */
1762 break; 1799 if (!format->yuv)
1763 case V4L2_PIX_FMT_BGR24: 1800 var->bits_per_pixel = format->bpp;
1764 var->bits_per_pixel = 24; 1801 else
1765 break;
1766 case V4L2_PIX_FMT_BGR32:
1767 var->bits_per_pixel = 32;
1768 break;
1769 default:
1770 var->grayscale = cfg->fourcc; 1802 var->grayscale = cfg->fourcc;
1771 break;
1772 }
1773 1803
1774 /* Make sure the memory size check won't fail. smem_len is initialized 1804 /* Make sure the memory size check won't fail. smem_len is initialized
1775 * later based on var. 1805 * later based on var.
@@ -1806,7 +1836,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
1806 cfg->fourcc == V4L2_PIX_FMT_NV21) 1836 cfg->fourcc == V4L2_PIX_FMT_NV21)
1807 info->fix.ypanstep = 2; 1837 info->fix.ypanstep = 2;
1808 1838
1809 if (sh_mobile_format_is_yuv(var)) { 1839 if (format->yuv) {
1810 info->fix.line_length = var->xres; 1840 info->fix.line_length = var->xres;
1811 info->fix.visual = FB_VISUAL_FOURCC; 1841 info->fix.visual = FB_VISUAL_FOURCC;
1812 } else { 1842 } else {