diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2011-11-29 09:58:10 -0500 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-03-12 17:40:56 -0400 |
commit | 105784bbb47cd76f0fc32954b047a13b704fa840 (patch) | |
tree | 72e09b02c179308a679c2203b5d2d860617b1bca /drivers/video/sh_mobile_lcdcfb.c | |
parent | 740f802af2d8c46f1423b6b3daa33e4e1ea223f0 (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.c | 174 |
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 | ||
452 | struct sh_mobile_lcdc_format_info { | ||
453 | u32 fourcc; | ||
454 | unsigned int bpp; | ||
455 | bool yuv; | ||
456 | u32 lddfr; | ||
457 | }; | ||
458 | |||
459 | static 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 | |||
508 | static const struct sh_mobile_lcdc_format_info * | ||
509 | sh_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 | |||
452 | static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var) | 521 | static 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 | ||
474 | static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var) | 543 | static 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 | |||
1665 | sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, | 1694 | sh_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 { |