Commit edd153a3e4f7346551f98014b3ccf0494219a9d1
Committed by
Florian Tobias Schandinat
1 parent
0b9eabd77f
Exists in
master
and in
6 other branches
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
- arch/arm/mach-shmobile/board-ap4evb.c
- arch/arm/mach-shmobile/board-mackerel.c
- arch/sh/boards/mach-ap325rxa/setup.c
- arch/sh/boards/mach-ecovec24/setup.c
- arch/sh/boards/mach-kfr2r09/setup.c
- arch/sh/boards/mach-migor/setup.c
- arch/sh/boards/mach-se/7724/setup.c
- drivers/video/sh_mobile_lcdcfb.c
- include/video/sh_mobile_lcdc.h
arch/arm/mach-shmobile/board-ag5evm.c
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
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-kfr2r09/setup.c
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
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 |