Commit edd153a3e4f7346551f98014b3ccf0494219a9d1

Authored by Laurent Pinchart
Committed by Florian Tobias Schandinat
1 parent 0b9eabd77f

fbdev: sh_mobile_lcdc: Support FOURCC-based format API

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>

Showing 10 changed files with 253 additions and 133 deletions Side-by-side Diff

arch/arm/mach-shmobile/board-ag5evm.c
... ... @@ -271,7 +271,7 @@
271 271 .flags = LCDC_FLAGS_DWPOL,
272 272 .lcd_size_cfg.width = 44,
273 273 .lcd_size_cfg.height = 79,
274   - .bpp = 16,
  274 + .fourcc = V4L2_PIX_FMT_RGB565,
275 275 .lcd_cfg = lcdc0_modes,
276 276 .num_cfg = ARRAY_SIZE(lcdc0_modes),
277 277 .board_cfg = {
arch/arm/mach-shmobile/board-ap4evb.c
... ... @@ -491,7 +491,7 @@
491 491 .meram_dev = &meram_info,
492 492 .ch[0] = {
493 493 .chan = LCDC_CHAN_MAINLCD,
494   - .bpp = 16,
  494 + .fourcc = V4L2_PIX_FMT_RGB565,
495 495 .lcd_cfg = ap4evb_lcdc_modes,
496 496 .num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes),
497 497 .meram_cfg = &lcd_meram_cfg,
... ... @@ -813,7 +813,7 @@
813 813 .meram_dev = &meram_info,
814 814 .ch[0] = {
815 815 .chan = LCDC_CHAN_MAINLCD,
816   - .bpp = 16,
  816 + .fourcc = V4L2_PIX_FMT_RGB565,
817 817 .interface_type = RGB24,
818 818 .clock_divider = 1,
819 819 .flags = LCDC_FLAGS_DWPOL,
arch/arm/mach-shmobile/board-mackerel.c
... ... @@ -388,7 +388,7 @@
388 388 .clock_source = LCDC_CLK_BUS,
389 389 .ch[0] = {
390 390 .chan = LCDC_CHAN_MAINLCD,
391   - .bpp = 16,
  391 + .fourcc = V4L2_PIX_FMT_RGB565,
392 392 .lcd_cfg = mackerel_lcdc_modes,
393 393 .num_cfg = ARRAY_SIZE(mackerel_lcdc_modes),
394 394 .interface_type = RGB24,
... ... @@ -451,7 +451,7 @@
451 451 .clock_source = LCDC_CLK_EXTERNAL,
452 452 .ch[0] = {
453 453 .chan = LCDC_CHAN_MAINLCD,
454   - .bpp = 16,
  454 + .fourcc = V4L2_PIX_FMT_RGB565,
455 455 .interface_type = RGB24,
456 456 .clock_divider = 1,
457 457 .flags = LCDC_FLAGS_DWPOL,
arch/sh/boards/mach-ap325rxa/setup.c
... ... @@ -207,7 +207,7 @@
207 207 .clock_source = LCDC_CLK_EXTERNAL,
208 208 .ch[0] = {
209 209 .chan = LCDC_CHAN_MAINLCD,
210   - .bpp = 16,
  210 + .fourcc = V4L2_PIX_FMT_RGB565,
211 211 .interface_type = RGB18,
212 212 .clock_divider = 1,
213 213 .lcd_cfg = ap325rxa_lcdc_modes,
arch/sh/boards/mach-ecovec24/setup.c
... ... @@ -330,7 +330,7 @@
330 330 .ch[0] = {
331 331 .interface_type = RGB18,
332 332 .chan = LCDC_CHAN_MAINLCD,
333   - .bpp = 16,
  333 + .fourcc = V4L2_PIX_FMT_RGB565,
334 334 .lcd_size_cfg = { /* 7.0 inch */
335 335 .width = 152,
336 336 .height = 91,
arch/sh/boards/mach-kfr2r09/setup.c
... ... @@ -146,7 +146,7 @@
146 146 .clock_source = LCDC_CLK_BUS,
147 147 .ch[0] = {
148 148 .chan = LCDC_CHAN_MAINLCD,
149   - .bpp = 16,
  149 + .fourcc = V4L2_PIX_FMT_RGB565,
150 150 .interface_type = SYS18,
151 151 .clock_divider = 6,
152 152 .flags = LCDC_FLAGS_DWPOL,
arch/sh/boards/mach-migor/setup.c
... ... @@ -244,7 +244,7 @@
244 244 .clock_source = LCDC_CLK_BUS,
245 245 .ch[0] = {
246 246 .chan = LCDC_CHAN_MAINLCD,
247   - .bpp = 16,
  247 + .fourcc = V4L2_PIX_FMT_RGB565,
248 248 .interface_type = RGB16,
249 249 .clock_divider = 2,
250 250 .lcd_cfg = migor_lcd_modes,
... ... @@ -258,7 +258,7 @@
258 258 .clock_source = LCDC_CLK_PERIPHERAL,
259 259 .ch[0] = {
260 260 .chan = LCDC_CHAN_MAINLCD,
261   - .bpp = 16,
  261 + .fourcc = V4L2_PIX_FMT_RGB565,
262 262 .interface_type = SYS16A,
263 263 .clock_divider = 10,
264 264 .lcd_cfg = migor_lcd_modes,
arch/sh/boards/mach-se/7724/setup.c
... ... @@ -179,7 +179,7 @@
179 179 .clock_source = LCDC_CLK_EXTERNAL,
180 180 .ch[0] = {
181 181 .chan = LCDC_CHAN_MAINLCD,
182   - .bpp = 16,
  182 + .fourcc = V4L2_PIX_FMT_RGB565,
183 183 .clock_divider = 1,
184 184 .lcd_size_cfg = { /* 7.0 inch */
185 185 .width = 152,
drivers/video/sh_mobile_lcdcfb.c
... ... @@ -17,6 +17,7 @@
17 17 #include <linux/platform_device.h>
18 18 #include <linux/dma-mapping.h>
19 19 #include <linux/interrupt.h>
  20 +#include <linux/videodev2.h>
20 21 #include <linux/vmalloc.h>
21 22 #include <linux/ioctl.h>
22 23 #include <linux/slab.h>
... ... @@ -102,7 +103,7 @@
102 103 struct sh_mobile_lcdc_chan ch[2];
103 104 struct notifier_block notifier;
104 105 int started;
105   - int forced_bpp; /* 2 channel LCDC must share bpp setting */
  106 + int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
106 107 struct sh_mobile_meram_info *meram_dev;
107 108 };
108 109  
... ... @@ -215,6 +216,47 @@
215 216 lcdc_sys_read_data,
216 217 };
217 218  
  219 +static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
  220 +{
  221 + if (var->grayscale > 1)
  222 + return var->grayscale;
  223 +
  224 + switch (var->bits_per_pixel) {
  225 + case 16:
  226 + return V4L2_PIX_FMT_RGB565;
  227 + case 24:
  228 + return V4L2_PIX_FMT_BGR24;
  229 + case 32:
  230 + return V4L2_PIX_FMT_BGR32;
  231 + default:
  232 + return 0;
  233 + }
  234 +}
  235 +
  236 +static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
  237 +{
  238 + return var->grayscale > 1;
  239 +}
  240 +
  241 +static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
  242 +{
  243 + if (var->grayscale <= 1)
  244 + return false;
  245 +
  246 + switch (var->grayscale) {
  247 + case V4L2_PIX_FMT_NV12:
  248 + case V4L2_PIX_FMT_NV21:
  249 + case V4L2_PIX_FMT_NV16:
  250 + case V4L2_PIX_FMT_NV61:
  251 + case V4L2_PIX_FMT_NV24:
  252 + case V4L2_PIX_FMT_NV42:
  253 + return true;
  254 +
  255 + default:
  256 + return false;
  257 + }
  258 +}
  259 +
218 260 static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
219 261 {
220 262 if (atomic_inc_and_test(&priv->hw_usecnt)) {
... ... @@ -435,7 +477,6 @@
435 477 {
436 478 struct sh_mobile_lcdc_chan *ch;
437 479 unsigned long tmp;
438   - int bpp = 0;
439 480 int k, m;
440 481  
441 482 /* Enable LCDC channels. Read data from external memory, avoid using the
... ... @@ -454,9 +495,6 @@
454 495 if (!ch->enabled)
455 496 continue;
456 497  
457   - if (!bpp)
458   - bpp = ch->info->var.bits_per_pixel;
459   -
460 498 /* Power supply */
461 499 lcdc_write_chan(ch, LDPMR, 0);
462 500  
463 501  
464 502  
465 503  
466 504  
... ... @@ -487,39 +525,45 @@
487 525  
488 526 sh_mobile_lcdc_geometry(ch);
489 527  
490   - if (ch->info->var.nonstd) {
491   - tmp = (ch->info->var.nonstd << 16);
492   - switch (ch->info->var.bits_per_pixel) {
493   - case 12:
494   - tmp |= LDDFR_YF_420;
  528 + switch (sh_mobile_format_fourcc(&ch->info->var)) {
  529 + case V4L2_PIX_FMT_RGB565:
  530 + tmp = LDDFR_PKF_RGB16;
  531 + break;
  532 + case V4L2_PIX_FMT_BGR24:
  533 + tmp = LDDFR_PKF_RGB24;
  534 + break;
  535 + case V4L2_PIX_FMT_BGR32:
  536 + tmp = LDDFR_PKF_ARGB32;
  537 + break;
  538 + case V4L2_PIX_FMT_NV12:
  539 + case V4L2_PIX_FMT_NV21:
  540 + tmp = LDDFR_CC | LDDFR_YF_420;
  541 + break;
  542 + case V4L2_PIX_FMT_NV16:
  543 + case V4L2_PIX_FMT_NV61:
  544 + tmp = LDDFR_CC | LDDFR_YF_422;
  545 + break;
  546 + case V4L2_PIX_FMT_NV24:
  547 + case V4L2_PIX_FMT_NV42:
  548 + tmp = LDDFR_CC | LDDFR_YF_444;
  549 + break;
  550 + }
  551 +
  552 + if (sh_mobile_format_is_yuv(&ch->info->var)) {
  553 + switch (ch->info->var.colorspace) {
  554 + case V4L2_COLORSPACE_REC709:
  555 + tmp |= LDDFR_CF1;
495 556 break;
496   - case 16:
497   - tmp |= LDDFR_YF_422;
  557 + case V4L2_COLORSPACE_JPEG:
  558 + tmp |= LDDFR_CF0;
498 559 break;
499   - case 24:
500   - default:
501   - tmp |= LDDFR_YF_444;
502   - break;
503 560 }
504   - } else {
505   - switch (ch->info->var.bits_per_pixel) {
506   - case 16:
507   - tmp = LDDFR_PKF_RGB16;
508   - break;
509   - case 24:
510   - tmp = LDDFR_PKF_RGB24;
511   - break;
512   - case 32:
513   - default:
514   - tmp = LDDFR_PKF_ARGB32;
515   - break;
516   - }
517 561 }
518 562  
519 563 lcdc_write_chan(ch, LDDFR, tmp);
520 564 lcdc_write_chan(ch, LDMLSR, ch->pitch);
521 565 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
522   - if (ch->info->var.nonstd)
  566 + if (sh_mobile_format_is_yuv(&ch->info->var))
523 567 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
524 568  
525 569 /* When using deferred I/O mode, configure the LCDC for one-shot
526 570  
... ... @@ -536,21 +580,23 @@
536 580 }
537 581  
538 582 /* Word and long word swap. */
539   - if (priv->ch[0].info->var.nonstd)
  583 + switch (sh_mobile_format_fourcc(&priv->ch[0].info->var)) {
  584 + case V4L2_PIX_FMT_RGB565:
  585 + case V4L2_PIX_FMT_NV21:
  586 + case V4L2_PIX_FMT_NV61:
  587 + case V4L2_PIX_FMT_NV42:
  588 + tmp = LDDDSR_LS | LDDDSR_WS;
  589 + break;
  590 + case V4L2_PIX_FMT_BGR24:
  591 + case V4L2_PIX_FMT_NV12:
  592 + case V4L2_PIX_FMT_NV16:
  593 + case V4L2_PIX_FMT_NV24:
540 594 tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
541   - else {
542   - switch (bpp) {
543   - case 16:
544   - tmp = LDDDSR_LS | LDDDSR_WS;
545   - break;
546   - case 24:
547   - tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
548   - break;
549   - case 32:
550   - default:
551   - tmp = LDDDSR_LS;
552   - break;
553   - }
  595 + break;
  596 + case V4L2_PIX_FMT_BGR32:
  597 + default:
  598 + tmp = LDDDSR_LS;
  599 + break;
554 600 }
555 601 lcdc_write(priv, _LDDDSR, tmp);
556 602  
557 603  
... ... @@ -622,12 +668,24 @@
622 668 ch->meram_enabled = 0;
623 669 }
624 670  
625   - if (!ch->info->var.nonstd)
626   - pixelformat = SH_MOBILE_MERAM_PF_RGB;
627   - else if (ch->info->var.bits_per_pixel == 24)
628   - pixelformat = SH_MOBILE_MERAM_PF_NV24;
629   - else
  671 + switch (sh_mobile_format_fourcc(&ch->info->var)) {
  672 + case V4L2_PIX_FMT_NV12:
  673 + case V4L2_PIX_FMT_NV21:
  674 + case V4L2_PIX_FMT_NV16:
  675 + case V4L2_PIX_FMT_NV61:
630 676 pixelformat = SH_MOBILE_MERAM_PF_NV;
  677 + break;
  678 + case V4L2_PIX_FMT_NV24:
  679 + case V4L2_PIX_FMT_NV42:
  680 + pixelformat = SH_MOBILE_MERAM_PF_NV24;
  681 + break;
  682 + case V4L2_PIX_FMT_RGB565:
  683 + case V4L2_PIX_FMT_BGR24:
  684 + case V4L2_PIX_FMT_BGR32:
  685 + default:
  686 + pixelformat = SH_MOBILE_MERAM_PF_RGB;
  687 + break;
  688 + }
631 689  
632 690 ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
633 691 ch->info->var.yres, pixelformat,
... ... @@ -845,6 +903,7 @@
845 903 .xpanstep = 0,
846 904 .ypanstep = 1,
847 905 .ywrapstep = 0,
  906 + .capabilities = FB_CAP_FOURCC,
848 907 };
849 908  
850 909 static void sh_mobile_lcdc_fillrect(struct fb_info *info,
851 910  
... ... @@ -877,8 +936,9 @@
877 936 unsigned long new_pan_offset;
878 937 unsigned long base_addr_y, base_addr_c;
879 938 unsigned long c_offset;
  939 + bool yuv = sh_mobile_format_is_yuv(&info->var);
880 940  
881   - if (!info->var.nonstd)
  941 + if (!yuv)
882 942 new_pan_offset = var->yoffset * info->fix.line_length
883 943 + var->xoffset * (info->var.bits_per_pixel / 8);
884 944 else
... ... @@ -892,7 +952,7 @@
892 952  
893 953 /* Set the source address for the next refresh */
894 954 base_addr_y = ch->dma_handle + new_pan_offset;
895   - if (info->var.nonstd) {
  955 + if (yuv) {
896 956 /* Set y offset */
897 957 c_offset = var->yoffset * info->fix.line_length
898 958 * (info->var.bits_per_pixel - 8) / 8;
... ... @@ -900,7 +960,7 @@
900 960 + info->var.xres * info->var.yres_virtual
901 961 + c_offset;
902 962 /* Set x offset */
903   - if (info->var.bits_per_pixel == 24)
  963 + if (sh_mobile_format_fourcc(&info->var) == V4L2_PIX_FMT_NV24)
904 964 base_addr_c += 2 * var->xoffset;
905 965 else
906 966 base_addr_c += var->xoffset;
... ... @@ -924,7 +984,7 @@
924 984 ch->base_addr_c = base_addr_c;
925 985  
926 986 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
927   - if (info->var.nonstd)
  987 + if (yuv)
928 988 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
929 989  
930 990 if (lcdc_chan_is_sublcd(ch))
931 991  
932 992  
933 993  
... ... @@ -1100,51 +1160,84 @@
1100 1160 if (var->yres_virtual < var->yres)
1101 1161 var->yres_virtual = var->yres;
1102 1162  
1103   - if (var->bits_per_pixel <= 16) { /* RGB 565 */
1104   - var->bits_per_pixel = 16;
1105   - var->red.offset = 11;
1106   - var->red.length = 5;
1107   - var->green.offset = 5;
1108   - var->green.length = 6;
1109   - var->blue.offset = 0;
1110   - var->blue.length = 5;
1111   - var->transp.offset = 0;
1112   - var->transp.length = 0;
1113   - } else if (var->bits_per_pixel <= 24) { /* RGB 888 */
1114   - var->bits_per_pixel = 24;
1115   - var->red.offset = 16;
1116   - var->red.length = 8;
1117   - var->green.offset = 8;
1118   - var->green.length = 8;
1119   - var->blue.offset = 0;
1120   - var->blue.length = 8;
1121   - var->transp.offset = 0;
1122   - var->transp.length = 0;
1123   - } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
1124   - var->bits_per_pixel = 32;
1125   - var->red.offset = 16;
1126   - var->red.length = 8;
1127   - var->green.offset = 8;
1128   - var->green.length = 8;
1129   - var->blue.offset = 0;
1130   - var->blue.length = 8;
1131   - var->transp.offset = 24;
1132   - var->transp.length = 8;
1133   - } else
1134   - return -EINVAL;
  1163 + if (sh_mobile_format_is_fourcc(var)) {
  1164 + switch (var->grayscale) {
  1165 + case V4L2_PIX_FMT_NV12:
  1166 + case V4L2_PIX_FMT_NV21:
  1167 + var->bits_per_pixel = 12;
  1168 + break;
  1169 + case V4L2_PIX_FMT_RGB565:
  1170 + case V4L2_PIX_FMT_NV16:
  1171 + case V4L2_PIX_FMT_NV61:
  1172 + var->bits_per_pixel = 16;
  1173 + break;
  1174 + case V4L2_PIX_FMT_BGR24:
  1175 + case V4L2_PIX_FMT_NV24:
  1176 + case V4L2_PIX_FMT_NV42:
  1177 + var->bits_per_pixel = 24;
  1178 + break;
  1179 + case V4L2_PIX_FMT_BGR32:
  1180 + var->bits_per_pixel = 32;
  1181 + break;
  1182 + default:
  1183 + return -EINVAL;
  1184 + }
1135 1185  
1136   - var->red.msb_right = 0;
1137   - var->green.msb_right = 0;
1138   - var->blue.msb_right = 0;
1139   - var->transp.msb_right = 0;
  1186 + /* Default to RGB and JPEG color-spaces for RGB and YUV formats
  1187 + * respectively.
  1188 + */
  1189 + if (!sh_mobile_format_is_yuv(var))
  1190 + var->colorspace = V4L2_COLORSPACE_SRGB;
  1191 + else if (var->colorspace != V4L2_COLORSPACE_REC709)
  1192 + var->colorspace = V4L2_COLORSPACE_JPEG;
  1193 + } else {
  1194 + if (var->bits_per_pixel <= 16) { /* RGB 565 */
  1195 + var->bits_per_pixel = 16;
  1196 + var->red.offset = 11;
  1197 + var->red.length = 5;
  1198 + var->green.offset = 5;
  1199 + var->green.length = 6;
  1200 + var->blue.offset = 0;
  1201 + var->blue.length = 5;
  1202 + var->transp.offset = 0;
  1203 + var->transp.length = 0;
  1204 + } else if (var->bits_per_pixel <= 24) { /* RGB 888 */
  1205 + var->bits_per_pixel = 24;
  1206 + var->red.offset = 16;
  1207 + var->red.length = 8;
  1208 + var->green.offset = 8;
  1209 + var->green.length = 8;
  1210 + var->blue.offset = 0;
  1211 + var->blue.length = 8;
  1212 + var->transp.offset = 0;
  1213 + var->transp.length = 0;
  1214 + } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
  1215 + var->bits_per_pixel = 32;
  1216 + var->red.offset = 16;
  1217 + var->red.length = 8;
  1218 + var->green.offset = 8;
  1219 + var->green.length = 8;
  1220 + var->blue.offset = 0;
  1221 + var->blue.length = 8;
  1222 + var->transp.offset = 24;
  1223 + var->transp.length = 8;
  1224 + } else
  1225 + return -EINVAL;
1140 1226  
  1227 + var->red.msb_right = 0;
  1228 + var->green.msb_right = 0;
  1229 + var->blue.msb_right = 0;
  1230 + var->transp.msb_right = 0;
  1231 + }
  1232 +
1141 1233 /* Make sure we don't exceed our allocated memory. */
1142 1234 if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
1143 1235 info->fix.smem_len)
1144 1236 return -EINVAL;
1145 1237  
1146   - /* only accept the forced_bpp for dual channel configurations */
1147   - if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel)
  1238 + /* only accept the forced_fourcc for dual channel configurations */
  1239 + if (p->forced_fourcc &&
  1240 + p->forced_fourcc != sh_mobile_format_fourcc(var))
1148 1241 return -EINVAL;
1149 1242  
1150 1243 return 0;
... ... @@ -1158,7 +1251,7 @@
1158 1251  
1159 1252 sh_mobile_lcdc_stop(ch->lcdc);
1160 1253  
1161   - if (info->var.nonstd)
  1254 + if (sh_mobile_format_is_yuv(&info->var))
1162 1255 info->fix.line_length = info->var.xres;
1163 1256 else
1164 1257 info->fix.line_length = info->var.xres
... ... @@ -1170,6 +1263,14 @@
1170 1263 info->fix.line_length = line_length;
1171 1264 }
1172 1265  
  1266 + if (sh_mobile_format_is_fourcc(&info->var)) {
  1267 + info->fix.type = FB_TYPE_FOURCC;
  1268 + info->fix.visual = FB_VISUAL_FOURCC;
  1269 + } else {
  1270 + info->fix.type = FB_TYPE_PACKED_PIXELS;
  1271 + info->fix.visual = FB_VISUAL_TRUECOLOR;
  1272 + }
  1273 +
1173 1274 return ret;
1174 1275 }
1175 1276  
... ... @@ -1464,9 +1565,9 @@
1464 1565 for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) {
1465 1566 unsigned int size = mode->yres * mode->xres;
1466 1567  
1467   - /* NV12 buffers must have even number of lines */
1468   - if ((cfg->nonstd) && cfg->bpp == 12 &&
1469   - (mode->yres & 0x1)) {
  1568 + /* NV12/NV21 buffers must have even number of lines */
  1569 + if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
  1570 + cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
1470 1571 dev_err(dev, "yres must be multiple of 2 for YCbCr420 "
1471 1572 "mode.\n");
1472 1573 return -EINVAL;
... ... @@ -1484,14 +1585,6 @@
1484 1585 dev_dbg(dev, "Found largest videomode %ux%u\n",
1485 1586 max_mode->xres, max_mode->yres);
1486 1587  
1487   - /* Initialize fixed screen information. Restrict pan to 2 lines steps
1488   - * for NV12.
1489   - */
1490   - info->fix = sh_mobile_lcdc_fix;
1491   - info->fix.smem_len = max_size * 2 * cfg->bpp / 8;
1492   - if (cfg->nonstd && cfg->bpp == 12)
1493   - info->fix.ypanstep = 2;
1494   -
1495 1588 /* Create the mode list. */
1496 1589 if (cfg->lcd_cfg == NULL) {
1497 1590 mode = &default_720p;
1498 1591  
1499 1592  
1500 1593  
... ... @@ -1509,19 +1602,38 @@
1509 1602 */
1510 1603 var = &info->var;
1511 1604 fb_videomode_to_var(var, mode);
1512   - var->bits_per_pixel = cfg->bpp;
1513 1605 var->width = cfg->lcd_size_cfg.width;
1514 1606 var->height = cfg->lcd_size_cfg.height;
1515 1607 var->yres_virtual = var->yres * 2;
1516 1608 var->activate = FB_ACTIVATE_NOW;
1517 1609  
  1610 + switch (cfg->fourcc) {
  1611 + case V4L2_PIX_FMT_RGB565:
  1612 + var->bits_per_pixel = 16;
  1613 + break;
  1614 + case V4L2_PIX_FMT_BGR24:
  1615 + var->bits_per_pixel = 24;
  1616 + break;
  1617 + case V4L2_PIX_FMT_BGR32:
  1618 + var->bits_per_pixel = 32;
  1619 + break;
  1620 + default:
  1621 + var->grayscale = cfg->fourcc;
  1622 + break;
  1623 + }
  1624 +
  1625 + /* Make sure the memory size check won't fail. smem_len is initialized
  1626 + * later based on var.
  1627 + */
  1628 + info->fix.smem_len = UINT_MAX;
1518 1629 ret = sh_mobile_check_var(var, info);
1519 1630 if (ret)
1520 1631 return ret;
1521 1632  
  1633 + max_size = max_size * var->bits_per_pixel / 8 * 2;
  1634 +
1522 1635 /* Allocate frame buffer memory and color map. */
1523   - buf = dma_alloc_coherent(dev, info->fix.smem_len, &ch->dma_handle,
1524   - GFP_KERNEL);
  1636 + buf = dma_alloc_coherent(dev, max_size, &ch->dma_handle, GFP_KERNEL);
1525 1637 if (!buf) {
1526 1638 dev_err(dev, "unable to allocate buffer\n");
1527 1639 return -ENOMEM;
1528 1640  
1529 1641  
1530 1642  
... ... @@ -1530,16 +1642,27 @@
1530 1642 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1531 1643 if (ret < 0) {
1532 1644 dev_err(dev, "unable to allocate cmap\n");
1533   - dma_free_coherent(dev, info->fix.smem_len,
1534   - buf, ch->dma_handle);
  1645 + dma_free_coherent(dev, max_size, buf, ch->dma_handle);
1535 1646 return ret;
1536 1647 }
1537 1648  
  1649 + /* Initialize fixed screen information. Restrict pan to 2 lines steps
  1650 + * for NV12 and NV21.
  1651 + */
  1652 + info->fix = sh_mobile_lcdc_fix;
1538 1653 info->fix.smem_start = ch->dma_handle;
1539   - if (var->nonstd)
  1654 + info->fix.smem_len = max_size;
  1655 + if (cfg->fourcc == V4L2_PIX_FMT_NV12 ||
  1656 + cfg->fourcc == V4L2_PIX_FMT_NV21)
  1657 + info->fix.ypanstep = 2;
  1658 +
  1659 + if (sh_mobile_format_is_yuv(var)) {
1540 1660 info->fix.line_length = var->xres;
1541   - else
1542   - info->fix.line_length = var->xres * (cfg->bpp / 8);
  1661 + info->fix.visual = FB_VISUAL_FOURCC;
  1662 + } else {
  1663 + info->fix.line_length = var->xres * var->bits_per_pixel / 8;
  1664 + info->fix.visual = FB_VISUAL_TRUECOLOR;
  1665 + }
1543 1666  
1544 1667 info->screen_base = buf;
1545 1668 info->device = dev;
1546 1669  
... ... @@ -1626,9 +1749,9 @@
1626 1749 goto err1;
1627 1750 }
1628 1751  
1629   - /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */
  1752 + /* for dual channel LCDC (MAIN + SUB) force shared format setting */
1630 1753 if (num_channels == 2)
1631   - priv->forced_bpp = pdata->ch[0].bpp;
  1754 + priv->forced_fourcc = pdata->ch[0].fourcc;
1632 1755  
1633 1756 priv->base = ioremap_nocache(res->start, resource_size(res));
1634 1757 if (!priv->base)
... ... @@ -1675,13 +1798,10 @@
1675 1798 if (error < 0)
1676 1799 goto err1;
1677 1800  
1678   - dev_info(info->dev,
1679   - "registered %s/%s as %dx%d %dbpp.\n",
1680   - pdev->name,
1681   - (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
1682   - "mainlcd" : "sublcd",
1683   - info->var.xres, info->var.yres,
1684   - ch->cfg.bpp);
  1801 + dev_info(info->dev, "registered %s/%s as %dx%d %dbpp.\n",
  1802 + pdev->name, (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
  1803 + "mainlcd" : "sublcd", info->var.xres, info->var.yres,
  1804 + info->var.bits_per_pixel);
1685 1805  
1686 1806 /* deferred io mode: disable clock to save power */
1687 1807 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
include/video/sh_mobile_lcdc.h
... ... @@ -174,7 +174,8 @@
174 174  
175 175 struct sh_mobile_lcdc_chan_cfg {
176 176 int chan;
177   - int bpp;
  177 + int fourcc;
  178 + int colorspace;
178 179 int interface_type; /* selects RGBn or SYSn I/F, see above */
179 180 int clock_divider;
180 181 unsigned long flags; /* LCDC_FLAGS_... */
... ... @@ -184,7 +185,6 @@
184 185 struct sh_mobile_lcdc_board_cfg board_cfg;
185 186 struct sh_mobile_lcdc_bl_info bl_info;
186 187 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
187   - int nonstd;
188 188 struct sh_mobile_meram_cfg *meram_cfg;
189 189 };
190 190