summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-08-17 16:17:21 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-11-29 11:21:22 +0100
commitfefa2bf71af1de4e9faaf9efee2c11b79c170760 (patch)
treed0b477e15203274fca2eb9862643253726665399
parent07eef40a41cc04cc1844e42641f2b67c1e0e1934 (diff)
Add support for fourcc-based format API
Use the new API by default, and automatically fall back to the legacy RGB API when the new API isn't supported. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--fbdev.c529
1 files changed, 405 insertions, 124 deletions
diff --git a/fbdev.c b/fbdev.c
index 6bce2b0..4b83f29 100644
--- a/fbdev.c
+++ b/fbdev.c
@@ -33,6 +33,7 @@
#include <sys/time.h>
#include <linux/fb.h>
+#include <linux/videodev2.h>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
@@ -47,6 +48,8 @@ struct device {
struct fb_bitfield red;
struct fb_bitfield green;
struct fb_bitfield blue;
+
+ unsigned int fourcc;
};
enum fb_fill_mode {
@@ -61,6 +64,212 @@ enum fb_fill_pattern {
};
/* -----------------------------------------------------------------------------
+ * Format helpers
+ */
+
+struct fb_format_info {
+ unsigned int fourcc;
+ const char *name;
+};
+
+static const struct fb_format_info formats[] = {
+ { V4L2_PIX_FMT_BGR24, "BGR24" },
+ { V4L2_PIX_FMT_BGR32, "BGR32" },
+ { V4L2_PIX_FMT_RGB24, "RGB24" },
+ { V4L2_PIX_FMT_RGB32, "RGB32" },
+ { V4L2_PIX_FMT_RGB565, "RGB565" },
+};
+
+#ifdef FB_VISUAL_FOURCC
+static const char *fb_format_name(unsigned int fourcc)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+ if (formats[i].fourcc == fourcc)
+ return formats[i].name;
+ }
+
+ return "Unknown";
+}
+#endif
+
+/*
+ * fb_var_to_fourcc - Return the format fourcc associated with the var info
+ * @dev: FB device
+ * @var_info: Variable screen information
+ *
+ * If the device doesn't support the fourcc-based API, or if the format is a
+ * legacy RGB format, emulate fourcc support based on the bits per pixel value.
+ *
+ * Return the format fourcc or 0 if the format isn't known.
+ */
+static unsigned int fb_var_to_fourcc(const struct device *dev,
+ const struct fb_var_screeninfo *var_info)
+{
+#ifdef FB_VISUAL_FOURCC
+ if (dev->fix_info.visual == FB_VISUAL_FOURCC)
+ return var_info->grayscale;
+#else
+ (void)dev;
+#endif
+
+ switch (var_info->bits_per_pixel) {
+ case 16:
+ return V4L2_PIX_FMT_RGB565;
+ case 24:
+ if (var_info->red.offset == 0)
+ return V4L2_PIX_FMT_RGB24;
+ else
+ return V4L2_PIX_FMT_BGR24;
+ case 32:
+ if (var_info->red.offset == 0)
+ return V4L2_PIX_FMT_RGB32;
+ else
+ return V4L2_PIX_FMT_BGR32;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * fb_fourcc_to_rgba - Fill the given var info RGBA bitfields based on a fourcc
+ * @dev: FB device
+ * @fourcc: Format fourcc
+ * @var_info: Variable screen information
+ *
+ * Fill the bits_per_pixel, red, green, blue and transp fields based on the
+ * fourcc.
+ *
+ * Return -EINVAL if the fourcc doesn't correspond to an RGB format or 0
+ * otherwise.
+ */
+static int fb_fourcc_to_rgba(unsigned int fourcc,
+ struct fb_var_screeninfo *var_info)
+{
+ var_info->grayscale = 0;
+
+ switch (fourcc) {
+ case V4L2_PIX_FMT_BGR24:
+ case 24:
+ var_info->bits_per_pixel = 24;
+ var_info->red.offset = 16;
+ var_info->red.length = 8;
+ var_info->red.msb_right = 0;
+ var_info->green.offset = 8;
+ var_info->green.length = 8;
+ var_info->green.msb_right = 0;
+ var_info->blue.offset = 0;
+ var_info->blue.length = 8;
+ var_info->blue.msb_right = 0;
+ var_info->transp.offset = 0;
+ var_info->transp.length = 0;
+ var_info->transp.msb_right = 0;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ case 32:
+ var_info->bits_per_pixel = 32;
+ var_info->red.offset = 16;
+ var_info->red.length = 8;
+ var_info->red.msb_right = 0;
+ var_info->green.offset = 8;
+ var_info->green.length = 8;
+ var_info->green.msb_right = 0;
+ var_info->blue.offset = 0;
+ var_info->blue.length = 8;
+ var_info->blue.msb_right = 0;
+ var_info->transp.offset = 24;
+ var_info->transp.length = 8;
+ var_info->transp.msb_right = 0;
+ break;
+ case V4L2_PIX_FMT_RGB24:
+ var_info->bits_per_pixel = 24;
+ var_info->red.offset = 0;
+ var_info->red.length = 8;
+ var_info->red.msb_right = 0;
+ var_info->green.offset = 8;
+ var_info->green.length = 8;
+ var_info->green.msb_right = 0;
+ var_info->blue.offset = 16;
+ var_info->blue.length = 8;
+ var_info->blue.msb_right = 0;
+ var_info->transp.offset = 0;
+ var_info->transp.length = 0;
+ var_info->transp.msb_right = 0;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ var_info->bits_per_pixel = 32;
+ var_info->red.offset = 0;
+ var_info->red.length = 8;
+ var_info->red.msb_right = 0;
+ var_info->green.offset = 8;
+ var_info->green.length = 8;
+ var_info->green.msb_right = 0;
+ var_info->blue.offset = 16;
+ var_info->blue.length = 8;
+ var_info->blue.msb_right = 0;
+ var_info->transp.offset = 24;
+ var_info->transp.length = 8;
+ var_info->transp.msb_right = 0;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case 16:
+ var_info->bits_per_pixel = 16;
+ var_info->red.offset = 11;
+ var_info->red.length = 5;
+ var_info->red.msb_right = 0;
+ var_info->green.offset = 5;
+ var_info->green.length = 6;
+ var_info->green.msb_right = 0;
+ var_info->blue.offset = 0;
+ var_info->blue.length = 5;
+ var_info->blue.msb_right = 0;
+ var_info->transp.offset = 0;
+ var_info->transp.length = 0;
+ var_info->transp.msb_right = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * fb_fourcc_to_var - Fill the given var info format based on a fourcc
+ * @dev: FB device
+ * @var_info: Variable screen information
+ * @fourcc: Format fourcc
+ *
+ * If the device doesn't support the fourcc-based API, fill the red, green, blue
+ * and transp components fields based on the fourcc.
+ *
+ * If the fourcc is smaller than or equal to 32, it will be interpreted as a bpp
+ * value and the legacy API will be used.
+ *
+ * Return -EINVAL if the device doesn't support the fourcc-based API and the
+ * given fourcc isn't an RGB format.
+ */
+static int fb_fourcc_to_var(const struct device *dev, unsigned int fourcc,
+ struct fb_var_screeninfo *var_info)
+{
+#ifdef FB_CAP_FOURCC
+ if (dev->fix_info.capabilities & FB_CAP_FOURCC && fourcc > 32) {
+ memset(&var_info->red, 0, sizeof var_info->red);
+ memset(&var_info->green, 0, sizeof var_info->green);
+ memset(&var_info->blue, 0, sizeof var_info->blue);
+ memset(&var_info->transp, 0, sizeof var_info->transp);
+ var_info->grayscale = fourcc;
+ return 0;
+ }
+#else
+ (void)dev;
+#endif
+
+ return fb_fourcc_to_rgba(fourcc, var_info);
+}
+
+/* -----------------------------------------------------------------------------
* FB information display
*/
@@ -75,6 +284,9 @@ static const struct fb_value_name fb_type_names[] = {
{ FB_TYPE_INTERLEAVED_PLANES, "Interleaved Planes" },
{ FB_TYPE_TEXT, "Text/Attributes" },
{ FB_TYPE_VGA_PLANES, "EGA/VGA Planes" },
+#ifdef FB_TYPE_FOURCC
+ { FB_TYPE_FOURCC, "FourCC" },
+#endif
};
static const struct fb_value_name fb_visual_names[] = {
@@ -84,6 +296,9 @@ static const struct fb_value_name fb_visual_names[] = {
{ FB_VISUAL_PSEUDOCOLOR, "Pseudo Color" },
{ FB_VISUAL_DIRECTCOLOR, "Direct Color" },
{ FB_VISUAL_STATIC_PSEUDOCOLOR, "Pseudo Color (read-only)" },
+#ifdef FB_VISUAL_FOURCC
+ { FB_VISUAL_FOURCC, "FourCC" },
+#endif
};
static const struct fb_value_name fb_accel_names[] = {
@@ -278,6 +493,12 @@ static void fb_print_var(struct device *dev, struct fb_var_screeninfo *var)
}
printf("\n");
}
+#ifdef FB_VISUAL_FOURCC
+ else if (dev->fix_info.visual == FB_VISUAL_FOURCC) {
+ printf(" Format:\t\t%s (%08x)\n", fb_format_name(var->grayscale),
+ var->grayscale);
+ }
+#endif
}
/* -----------------------------------------------------------------------------
@@ -322,6 +543,7 @@ static void fb_unmap_memory(struct device *dev)
static int fb_update_info(struct device *dev)
{
+ struct fb_var_screeninfo var_info;
int ret;
ret = ioctl(dev->fd, FBIOGET_FSCREENINFO, &dev->fix_info);
@@ -336,9 +558,18 @@ static int fb_update_info(struct device *dev)
return ret;
}
- dev->red = dev->var_info.red;
- dev->green = dev->var_info.green;
- dev->blue = dev->var_info.blue;
+ dev->fourcc = fb_var_to_fourcc(dev, &dev->var_info);
+
+ ret = fb_fourcc_to_rgba(dev->fourcc, &var_info);
+ if (ret < 0) {
+ memset(&dev->red, 0, sizeof dev->red);
+ memset(&dev->green, 0, sizeof dev->green);
+ memset(&dev->blue, 0, sizeof dev->blue);
+ } else {
+ dev->red = var_info.red;
+ dev->green = var_info.green;
+ dev->blue = var_info.blue;
+ }
return 0;
}
@@ -484,24 +715,29 @@ static int fb_wait_for_vsync(struct device *dev, unsigned int screen)
}
/* -----------------------------------------------------------------------------
- * Resolution and pan
+ * Formats, resolution and pan
*/
/*
* fb_set_format - Set the frame buffer pixel format
* @dev: FB device
- * @bpp: Bits per pixel
+ * @fourcc: Format code
*/
-static int fb_set_format(struct device *dev, unsigned int bpp)
+static int fb_set_format(struct device *dev, unsigned int fourcc)
{
struct fb_var_screeninfo var_info;
int ret;
var_info = dev->var_info;
-
- var_info.bits_per_pixel = bpp;
var_info.activate = FB_ACTIVATE_NOW;
+ ret = fb_fourcc_to_var(dev, fourcc, &var_info);
+ if (ret < 0) {
+ printf("Error: device doesn't support non-RGB format %08x\n",
+ fourcc);
+ return ret;
+ }
+
ret = ioctl(dev->fd, FBIOPUT_VSCREENINFO, &var_info);
if (ret < 0) {
printf("Error: set format failed: %s (%d)\n",
@@ -514,11 +750,11 @@ static int fb_set_format(struct device *dev, unsigned int bpp)
printf("Format set to %u bits per pixel\n\n",
var_info.bits_per_pixel);
- fb_print_var(dev, &var_info);
-
/* Fixed screen information might have changed, re-read it. */
fb_update_info(dev);
+ fb_print_var(dev, &var_info);
+
return 0;
}
@@ -572,11 +808,11 @@ static int fb_set_resolution(struct device *dev, int xres, int yres,
var_info.xres, var_info.yres,
var_info.xres_virtual, var_info.yres_virtual);
- fb_print_var(dev, &var_info);
-
/* Fixed screen information might have changed, re-read it. */
fb_update_info(dev);
+ fb_print_var(dev, &var_info);
+
return 0;
}
@@ -614,7 +850,7 @@ static int fb_pan(struct device *dev, unsigned int x, unsigned int y)
* Test pattern
*/
-#define FB_MAKE_COLOR(dev, r, g, b) \
+#define FB_MAKE_RGB(dev, r, g, b) \
((((r) >> (8 - (dev)->red.length)) << (dev)->red.offset) | \
(((g) >> (8 - (dev)->green.length)) << (dev)->green.offset) | \
(((b) >> (8 - (dev)->blue.length)) << (dev)->blue.offset))
@@ -624,32 +860,32 @@ fb_fill_smpte_rgb16(struct device *dev, unsigned int xoffset,
unsigned int yoffset, unsigned int xres, unsigned int yres)
{
const uint16_t colors_top[] = {
- FB_MAKE_COLOR(dev, 192, 192, 192), /* grey */
- FB_MAKE_COLOR(dev, 192, 192, 0), /* yellow */
- FB_MAKE_COLOR(dev, 0, 192, 192), /* cyan */
- FB_MAKE_COLOR(dev, 0, 192, 0), /* green */
- FB_MAKE_COLOR(dev, 192, 0, 192), /* magenta */
- FB_MAKE_COLOR(dev, 192, 0, 0), /* red */
- FB_MAKE_COLOR(dev, 0, 0, 192), /* blue */
+ FB_MAKE_RGB(dev, 192, 192, 192), /* grey */
+ FB_MAKE_RGB(dev, 192, 192, 0), /* yellow */
+ FB_MAKE_RGB(dev, 0, 192, 192), /* cyan */
+ FB_MAKE_RGB(dev, 0, 192, 0), /* green */
+ FB_MAKE_RGB(dev, 192, 0, 192), /* magenta */
+ FB_MAKE_RGB(dev, 192, 0, 0), /* red */
+ FB_MAKE_RGB(dev, 0, 0, 192), /* blue */
};
const uint16_t colors_middle[] = {
- FB_MAKE_COLOR(dev, 0, 0, 192), /* blue */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 192, 0, 192), /* magenta */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 0, 192, 192), /* cyan */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 192, 192, 192), /* grey */
+ FB_MAKE_RGB(dev, 0, 0, 192), /* blue */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 192, 0, 192), /* magenta */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 0, 192, 192), /* cyan */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 192, 192, 192), /* grey */
};
const uint16_t colors_bottom[] = {
- FB_MAKE_COLOR(dev, 0, 33, 76), /* in-phase */
- FB_MAKE_COLOR(dev, 255, 255, 255), /* super white */
- FB_MAKE_COLOR(dev, 50, 0, 106), /* quadrature */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 9, 9, 9), /* 3.5% */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* 7.5% */
- FB_MAKE_COLOR(dev, 29, 29, 29), /* 11.5% */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 0, 33, 76), /* in-phase */
+ FB_MAKE_RGB(dev, 255, 255, 255), /* super white */
+ FB_MAKE_RGB(dev, 50, 0, 106), /* quadrature */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 9, 9, 9), /* 3.5% */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* 7.5% */
+ FB_MAKE_RGB(dev, 29, 29, 29), /* 11.5% */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
};
void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ xoffset * dev->var_info.bits_per_pixel / 8;
@@ -686,40 +922,40 @@ struct fb_color24 {
unsigned int value:24;
} __attribute__((__packed__));
-#define FB_MAKE_COLOR24(dev, r, g, b) \
- { .value = FB_MAKE_COLOR(dev, r, g, b) }
+#define FB_MAKE_RGB24(dev, r, g, b) \
+ { .value = FB_MAKE_RGB(dev, r, g, b) }
static void
fb_fill_smpte_rgb24(struct device *dev, unsigned int xoffset,
unsigned int yoffset, unsigned int xres, unsigned int yres)
{
const struct fb_color24 colors_top[] = {
- FB_MAKE_COLOR24(dev, 192, 192, 192), /* grey */
- FB_MAKE_COLOR24(dev, 192, 192, 0), /* yellow */
- FB_MAKE_COLOR24(dev, 0, 192, 192), /* cyan */
- FB_MAKE_COLOR24(dev, 0, 192, 0), /* green */
- FB_MAKE_COLOR24(dev, 192, 0, 192), /* magenta */
- FB_MAKE_COLOR24(dev, 192, 0, 0), /* red */
- FB_MAKE_COLOR24(dev, 0, 0, 192), /* blue */
+ FB_MAKE_RGB24(dev, 192, 192, 192), /* grey */
+ FB_MAKE_RGB24(dev, 192, 192, 0), /* yellow */
+ FB_MAKE_RGB24(dev, 0, 192, 192), /* cyan */
+ FB_MAKE_RGB24(dev, 0, 192, 0), /* green */
+ FB_MAKE_RGB24(dev, 192, 0, 192), /* magenta */
+ FB_MAKE_RGB24(dev, 192, 0, 0), /* red */
+ FB_MAKE_RGB24(dev, 0, 0, 192), /* blue */
};
const struct fb_color24 colors_middle[] = {
- FB_MAKE_COLOR24(dev, 0, 0, 192), /* blue */
- FB_MAKE_COLOR24(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR24(dev, 192, 0, 192), /* magenta */
- FB_MAKE_COLOR24(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR24(dev, 0, 192, 192), /* cyan */
- FB_MAKE_COLOR24(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR24(dev, 192, 192, 192), /* grey */
+ FB_MAKE_RGB24(dev, 0, 0, 192), /* blue */
+ FB_MAKE_RGB24(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB24(dev, 192, 0, 192), /* magenta */
+ FB_MAKE_RGB24(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB24(dev, 0, 192, 192), /* cyan */
+ FB_MAKE_RGB24(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB24(dev, 192, 192, 192), /* grey */
};
const struct fb_color24 colors_bottom[] = {
- FB_MAKE_COLOR24(dev, 0, 33, 76), /* in-phase */
- FB_MAKE_COLOR24(dev, 255, 255, 255), /* super white */
- FB_MAKE_COLOR24(dev, 50, 0, 106), /* quadrature */
- FB_MAKE_COLOR24(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR24(dev, 9, 9, 9), /* 3.5% */
- FB_MAKE_COLOR24(dev, 19, 19, 19), /* 7.5% */
- FB_MAKE_COLOR24(dev, 29, 29, 29), /* 11.5% */
- FB_MAKE_COLOR24(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB24(dev, 0, 33, 76), /* in-phase */
+ FB_MAKE_RGB24(dev, 255, 255, 255), /* super white */
+ FB_MAKE_RGB24(dev, 50, 0, 106), /* quadrature */
+ FB_MAKE_RGB24(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB24(dev, 9, 9, 9), /* 3.5% */
+ FB_MAKE_RGB24(dev, 19, 19, 19), /* 7.5% */
+ FB_MAKE_RGB24(dev, 29, 29, 29), /* 11.5% */
+ FB_MAKE_RGB24(dev, 19, 19, 19), /* black */
};
void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ xoffset * dev->var_info.bits_per_pixel / 8;
@@ -759,32 +995,32 @@ fb_fill_smpte_rgb32(struct device *dev, unsigned int xoffset,
unsigned int yoffset, unsigned int xres, unsigned int yres)
{
const uint32_t colors_top[] = {
- FB_MAKE_COLOR(dev, 192, 192, 192), /* grey */
- FB_MAKE_COLOR(dev, 192, 192, 0), /* yellow */
- FB_MAKE_COLOR(dev, 0, 192, 192), /* cyan */
- FB_MAKE_COLOR(dev, 0, 192, 0), /* green */
- FB_MAKE_COLOR(dev, 192, 0, 192), /* magenta */
- FB_MAKE_COLOR(dev, 192, 0, 0), /* red */
- FB_MAKE_COLOR(dev, 0, 0, 192), /* blue */
+ FB_MAKE_RGB(dev, 192, 192, 192), /* grey */
+ FB_MAKE_RGB(dev, 192, 192, 0), /* yellow */
+ FB_MAKE_RGB(dev, 0, 192, 192), /* cyan */
+ FB_MAKE_RGB(dev, 0, 192, 0), /* green */
+ FB_MAKE_RGB(dev, 192, 0, 192), /* magenta */
+ FB_MAKE_RGB(dev, 192, 0, 0), /* red */
+ FB_MAKE_RGB(dev, 0, 0, 192), /* blue */
};
const uint32_t colors_middle[] = {
- FB_MAKE_COLOR(dev, 0, 0, 192), /* blue */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 192, 0, 192), /* magenta */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 0, 192, 192), /* cyan */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 192, 192, 192), /* grey */
+ FB_MAKE_RGB(dev, 0, 0, 192), /* blue */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 192, 0, 192), /* magenta */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 0, 192, 192), /* cyan */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 192, 192, 192), /* grey */
};
const uint32_t colors_bottom[] = {
- FB_MAKE_COLOR(dev, 0, 33, 76), /* in-phase */
- FB_MAKE_COLOR(dev, 255, 255, 255), /* super white */
- FB_MAKE_COLOR(dev, 50, 0, 106), /* quadrature */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 9, 9, 9), /* 3.5% */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* 7.5% */
- FB_MAKE_COLOR(dev, 29, 29, 29), /* 11.5% */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 0, 33, 76), /* in-phase */
+ FB_MAKE_RGB(dev, 255, 255, 255), /* super white */
+ FB_MAKE_RGB(dev, 50, 0, 106), /* quadrature */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 9, 9, 9), /* 3.5% */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* 7.5% */
+ FB_MAKE_RGB(dev, 29, 29, 29), /* 11.5% */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
};
void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ xoffset * dev->var_info.bits_per_pixel / 8;
@@ -832,12 +1068,14 @@ static void
fb_fill_smpte(struct device *dev, unsigned int xoffset, unsigned int yoffset,
unsigned int xres, unsigned int yres)
{
- switch (dev->var_info.bits_per_pixel) {
- case 16:
+ switch (dev->fourcc) {
+ case V4L2_PIX_FMT_RGB565:
return fb_fill_smpte_rgb16(dev, xoffset, yoffset, xres, yres);
- case 24:
+ case V4L2_PIX_FMT_BGR24:
+ case V4L2_PIX_FMT_RGB24:
return fb_fill_smpte_rgb24(dev, xoffset, yoffset, xres, yres);
- case 32:
+ case V4L2_PIX_FMT_BGR32:
+ case V4L2_PIX_FMT_RGB32:
return fb_fill_smpte_rgb32(dev, xoffset, yoffset, xres, yres);
}
}
@@ -847,14 +1085,14 @@ fb_fill_lines_rgb16(struct device *dev, unsigned int xoffset,
unsigned int yoffset, unsigned int xres, unsigned int yres)
{
const uint16_t colors[] = {
- FB_MAKE_COLOR(dev, 192, 192, 0), /* yellow */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 0, 192, 0), /* green */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 192, 0, 0), /* red */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 0, 0, 192), /* blue */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 192, 192, 0), /* yellow */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 0, 192, 0), /* green */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 192, 0, 0), /* red */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 0, 0, 192), /* blue */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
};
void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ xoffset * dev->var_info.bits_per_pixel / 8;
@@ -879,14 +1117,14 @@ fb_fill_lines_rgb24(struct device *dev, unsigned int xoffset,
unsigned int yoffset, unsigned int xres, unsigned int yres)
{
const struct fb_color24 colors[] = {
- FB_MAKE_COLOR24(dev, 192, 192, 0), /* yellow */
- FB_MAKE_COLOR24(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR24(dev, 0, 192, 0), /* green */
- FB_MAKE_COLOR24(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR24(dev, 192, 0, 0), /* red */
- FB_MAKE_COLOR24(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR24(dev, 0, 0, 192), /* blue */
- FB_MAKE_COLOR24(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB24(dev, 192, 192, 0), /* yellow */
+ FB_MAKE_RGB24(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB24(dev, 0, 192, 0), /* green */
+ FB_MAKE_RGB24(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB24(dev, 192, 0, 0), /* red */
+ FB_MAKE_RGB24(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB24(dev, 0, 0, 192), /* blue */
+ FB_MAKE_RGB24(dev, 19, 19, 19), /* black */
};
void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ xoffset * dev->var_info.bits_per_pixel / 8;
@@ -911,14 +1149,14 @@ fb_fill_lines_rgb32(struct device *dev, unsigned int xoffset,
unsigned int yoffset, unsigned int xres, unsigned int yres)
{
const uint32_t colors[] = {
- FB_MAKE_COLOR(dev, 192, 192, 0), /* yellow */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 0, 192, 0), /* green */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 192, 0, 0), /* red */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
- FB_MAKE_COLOR(dev, 0, 0, 192), /* blue */
- FB_MAKE_COLOR(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 192, 192, 0), /* yellow */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 0, 192, 0), /* green */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 192, 0, 0), /* red */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
+ FB_MAKE_RGB(dev, 0, 0, 192), /* blue */
+ FB_MAKE_RGB(dev, 19, 19, 19), /* black */
};
void *mem = dev->mem + dev->fix_info.line_length * yoffset
+ xoffset * dev->var_info.bits_per_pixel / 8;
@@ -953,12 +1191,14 @@ static void
fb_fill_lines(struct device *dev, unsigned int xoffset, unsigned int yoffset,
unsigned int xres, unsigned int yres)
{
- switch (dev->var_info.bits_per_pixel) {
- case 16:
+ switch (dev->fourcc) {
+ case V4L2_PIX_FMT_RGB565:
return fb_fill_lines_rgb16(dev, xoffset, yoffset, xres, yres);
- case 24:
+ case V4L2_PIX_FMT_BGR24:
+ case V4L2_PIX_FMT_RGB24:
return fb_fill_lines_rgb24(dev, xoffset, yoffset, xres, yres);
- case 32:
+ case V4L2_PIX_FMT_BGR32:
+ case V4L2_PIX_FMT_RGB32:
return fb_fill_lines_rgb32(dev, xoffset, yoffset, xres, yres);
}
}
@@ -979,17 +1219,23 @@ fb_fill(struct device *dev, enum fb_fill_mode mode, enum fb_fill_pattern pattern
unsigned int xoffset, yoffset;
unsigned int xres, yres;
- if (dev->fix_info.visual != FB_VISUAL_TRUECOLOR) {
+ if (dev->fix_info.visual != FB_VISUAL_TRUECOLOR
+#ifdef FB_VISUAL_FOURCC
+ && dev->fix_info.visual != FB_VISUAL_FOURCC
+#endif
+ ) {
printf("Error: test pattern is only supported for true color "
- "visuals.\n");
+ "and fourcc visuals.\n");
return;
}
- if (dev->var_info.bits_per_pixel != 16 &&
- dev->var_info.bits_per_pixel != 24 &&
- dev->var_info.bits_per_pixel != 32) {
- printf("Error: display depth %u bpp not supported.\n",
- dev->var_info.bits_per_pixel);
+ if (dev->fourcc != V4L2_PIX_FMT_BGR24 &&
+ dev->fourcc != V4L2_PIX_FMT_BGR32 &&
+ dev->fourcc != V4L2_PIX_FMT_RGB24 &&
+ dev->fourcc != V4L2_PIX_FMT_RGB32 &&
+ dev->fourcc != V4L2_PIX_FMT_RGB565) {
+ printf("Error: display format %08x (%u bpp) not supported.\n",
+ dev->fourcc, dev->var_info.bits_per_pixel);
return;
}
@@ -1026,11 +1272,13 @@ fb_fill(struct device *dev, enum fb_fill_mode mode, enum fb_fill_pattern pattern
static void usage(const char *argv0)
{
+ unsigned int i;
+
printf("Usage: %s [options] device\n", argv0);
printf("Supported options:\n");
printf("-b, --blank mode Set blanking mode\n");
printf("-f, --fill[=mode] Fill the frame buffer with a test pattern\n");
- printf("-F, --format bpp Set the number of bits per pixel\n");
+ printf("-F, --format fourcc Set the frame buffer format\n");
printf("-h, --help Show this help screen\n");
printf("-p, --pan x,y Pan the display to position (x,y)\n");
printf("-P, --pattern name Test pattern name\n");
@@ -1041,6 +1289,11 @@ static void usage(const char *argv0)
printf("Support fill modes are:\n");
printf(" display Fill the displayed frame buffer only\n");
printf(" virtual Fill the whole virtual frame buffer\n");
+ printf("Support formats:\n ");
+ for (i = 0; i < ARRAY_SIZE(formats); ++i)
+ printf("%s ", formats[i].name);
+ printf("\n");
+ printf(" 16 24 32 (bpp value, will use the legacy API)\n");
printf("Support test pattern are:\n");
printf(" smpte SMPTE color bars\n");
printf(" lines Color lines\n");
@@ -1086,6 +1339,30 @@ static int fb_blank_parse(const char *arg, int *value)
return -1;
}
+static int fb_format_parse(const char *arg, unsigned int *fourcc)
+{
+ unsigned int bpp;
+ unsigned int i;
+ char *endp;
+
+ for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+ if (strcasecmp(formats[i].name, arg) == 0) {
+ *fourcc = formats[i].fourcc;
+ return 0;
+ }
+ }
+
+ bpp = strtoul(arg, &endp, 10);
+ if (*endp != '\0')
+ return -1;
+
+ if (bpp != 16 && bpp != 24 && bpp != 32)
+ return -1;
+
+ *fourcc = bpp;
+ return 0;
+}
+
static int fb_point_parse(const char *arg, unsigned int *x, unsigned int *y)
{
unsigned long value;
@@ -1137,7 +1414,7 @@ int main(int argc, char *argv[])
enum fb_fill_pattern fill_pattern = FB_PATTERN_SMPTE;
bool do_format = false;
- unsigned int bpp = 0;
+ unsigned int fourcc = 0;
bool do_pan = false;
unsigned int pan_x = 0;
@@ -1181,7 +1458,11 @@ int main(int argc, char *argv[])
break;
case 'F':
do_format = true;
- bpp = atoi(optarg);
+ if (fb_format_parse(optarg, &fourcc) < 0) {
+ printf("Invalid format `%s'\n", optarg);
+ printf("Run %s -h for help.\n", argv[0]);
+ return 1;
+ }
break;
case 'h':
usage(argv[0]);
@@ -1246,7 +1527,7 @@ int main(int argc, char *argv[])
fb_blank(&dev, blank);
if (do_format)
- fb_set_format(&dev, bpp);
+ fb_set_format(&dev, fourcc);
if (do_resolution)
fb_set_resolution(&dev, xres, yres, xres_virtual, yres_virtual);