diff options
author | Robby Cai <robby.cai@nxp.com> | 2017-04-10 21:02:39 +0800 |
---|---|---|
committer | ivan.liu <xiaowen.liu@nxp.com> | 2017-05-24 18:01:47 +0800 |
commit | 412c4f67670839ae20ca40908ddb3b99619ad3ad (patch) | |
tree | bd5d58d8d6b7974f7d2b12e52bbc84a36b638e56 | |
parent | 801cca972070470e4b6e8cd4b6d3790e89025bb5 (diff) | |
download | imx-v4.1-412c4f67670839ae20ca40908ddb3b99619ad3ad.tar.gz |
MLK-14941: mxsfb: add ARGB32 and ABGR32 format support
add a property in dts called 'fbpix' to assign the pixel format for framebuffer.
note 'bits-per-pixel' has priority over 'fbpix', so please set them in pair.
if 'bits-per-pixel' is set to 16 and no 'fbpix' is set, defaults to RGB565.
example for 32bit setting (tested on i.mx7d):
display0: display {
- bits-per-pixel = <16>;
+ bits-per-pixel = <32>;
bus-width = <24>;
+ fbpix = "ABGR32";
Signed-off-by: Robby Cai <robby.cai@nxp.com>
-rw-r--r-- | drivers/video/fbdev/mxsfb.c | 90 | ||||
-rw-r--r-- | include/uapi/linux/videodev2.h | 1 |
2 files changed, 85 insertions, 6 deletions
diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c index 9ab4b6fd1d4f..3cec53435a3c 100644 --- a/drivers/video/fbdev/mxsfb.c +++ b/drivers/video/fbdev/mxsfb.c @@ -136,6 +136,8 @@ #define CTRL1_IRQ_STATUS_SHIFT 8 #define CTRL2_OUTSTANDING_REQS__REQ_16 (4 << 21) +#define CTRL2_ODD_LINE_PATTERN_BGR (5 << 16) +#define CTRL2_EVEN_LINE_PATTERN_BGR (5 << 12) #define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16) #define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff) @@ -261,6 +263,7 @@ struct mxsfb_info { int id; struct fb_var_screeninfo var; struct pm_qos_request pm_qos_req; + u32 pix_fmt; #ifdef CONFIG_FB_MXC_OVERLAY struct mxsfb_layer overlay; @@ -533,6 +536,25 @@ static const struct fb_bitfield def_argb32[] = { } }; +static const struct fb_bitfield def_abgr32[] = { + [RED] = { + .offset = 0, + .length = 8, + }, + [GREEN] = { + .offset = 8, + .length = 8, + }, + [BLUE] = { + .offset = 16, + .length = 8, + }, + [TRANSP] = { + .offset = 24, + .length = 8, + } +}; + #define bitfield_is_equal(f1, f2) (!memcmp(&(f1), &(f2), sizeof(f1))) static inline bool pixfmt_is_equal(struct fb_var_screeninfo *var, @@ -546,6 +568,32 @@ static inline bool pixfmt_is_equal(struct fb_var_screeninfo *var, return false; } +static const struct fb_bitfield* pixfmt_to_bf(u32 pix_fmt) +{ + if (pix_fmt == V4L2_PIX_FMT_RGB565) + return def_rgb565; + else if (pix_fmt == V4L2_PIX_FMT_RGB666) + return def_rgb666; + else if (pix_fmt == V4L2_PIX_FMT_RGB24) + return def_rgb888; + else if (pix_fmt == V4L2_PIX_FMT_ARGB32) + return def_argb32; + else if (pix_fmt == V4L2_PIX_FMT_ABGR32) + return def_abgr32; + else { + pr_err("unsupported pix format\n"); + return NULL; + } +} + +static inline bool need_swizzle_rgb(struct fb_var_screeninfo *var) +{ + if (pixfmt_is_equal(var, def_abgr32)) + return true; + + return false; +} + static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf) { chan &= 0xffff; @@ -637,7 +685,10 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var, break; case STMLCDIF_24BIT: /* real 24 bit */ - rgb = def_rgb888; + if (host->pix_fmt && pixfmt_to_bf(host->pix_fmt)) + rgb = pixfmt_to_bf(host->pix_fmt); + else + rgb = def_rgb888; break; default: /* @@ -722,8 +773,10 @@ static void mxsfb_enable_controller(struct fb_info *fb_info) } clk_enable_pix(host); - writel(CTRL2_OUTSTANDING_REQS__REQ_16, - host->base + LCDC_V4_CTRL2 + REG_SET); + reg = CTRL2_OUTSTANDING_REQS__REQ_16; + if (need_swizzle_rgb(&(fb_info->var))) + reg |= CTRL2_ODD_LINE_PATTERN_BGR | CTRL2_EVEN_LINE_PATTERN_BGR; + writel(reg, host->base + LCDC_V4_CTRL2 + REG_SET); /* if it was disabled, re-enable the mode again */ writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET); @@ -836,9 +889,12 @@ static int mxsfb_set_par(struct fb_info *fb_info) fb_info->fix.line_length = line_size; fb_size = fb_info->var.yres_virtual * line_size; - if (fb_size > fb_info->fix.smem_len) { - dev_err(&host->pdev->dev, "exceeds the fb buffer size limit!\n"); - return -ENOMEM; + if (!fb_info->fix.smem_start || fb_size > fb_info->fix.smem_len) { + if (fb_info->fix.smem_start) + mxsfb_unmap_videomem(fb_info); + + if (mxsfb_map_videomem(fb_info) < 0) + return -ENOMEM; } /* @@ -1346,6 +1402,7 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host) struct device_node *display_np; struct device_node *timings_np; struct display_timings *timings = NULL; + const char *pixfmt; const char *disp_dev; u32 width; int i; @@ -1391,6 +1448,27 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host) goto put_display_node; } + ret = of_property_read_string(display_np, "fbpix", &pixfmt); + if (ret) { + host->pix_fmt = 0; + dev_warn(dev, "not find property pix fmt\n"); + } else { + if (!strncmp(pixfmt, "RGB565", 6)) + host->pix_fmt = V4L2_PIX_FMT_RGB565; + else if (!strncmp(pixfmt, "RGB666", 6)) + host->pix_fmt = V4L2_PIX_FMT_RGB666; + else if (!strncmp(pixfmt, "RGB888", 6)) + host->pix_fmt = V4L2_PIX_FMT_RGB24; + else if (!strncmp(pixfmt, "ARGB32", 6)) + host->pix_fmt = V4L2_PIX_FMT_ARGB32; + else if (!strncmp(pixfmt, "ABGR32", 6)) + host->pix_fmt = V4L2_PIX_FMT_ABGR32; + else { + dev_warn(dev, "no pix fmt assigned, use default\n"); + host->pix_fmt = 0; + } + } + ret = of_property_read_string(np, "disp-dev", &disp_dev); if (!ret) { memcpy(host->disp_dev, disp_dev, strlen(disp_dev)); diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 30cba6d34193..37602689c755 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -388,6 +388,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_XRGB555X v4l2_fourcc_be('X', 'R', '1', '5') /* 16 XRGB-5-5-5 BE */ #define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16 RGB-5-6-5 BE */ #define V4L2_PIX_FMT_BGR666 v4l2_fourcc('B', 'G', 'R', 'H') /* 18 BGR-6-6-6 */ +#define V4L2_PIX_FMT_RGB666 v4l2_fourcc('R', 'G', 'B', 'H') /* 18 RGB-6-6-6 */ #define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */ #define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */ #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */ |