Commit c943b694 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

media: imx: utils: Make imx_media_pixfmt handle variable number of codes

The imx_media_pixfmt structures include a codes member that stores
media bus codes as a fixed array of 4 integers. The functions dealing
with the imx_media_pixfmt structures assume that the array of codes is
terminated by a 0 element. This mechanism is fragile, as demonstrated
by several instances of the structure containing 4 non-zero codes.

Fix this by turning the array into a pointer, and providing an
IMX_BUS_FMTS macro to initialize the codes member with a guaranteed 0
element at the end.

[Fixed a NULL deref of the codes pointer in a couple places]
[Added more comments for the struct imx_media_pixfmt members,
 including a bold NOTE! for future developers that codes pointer
 is NULL for the in-memory-only formats]
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarSteve Longerbeam <slongerbeam@gmail.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent f0f71ae4
...@@ -95,7 +95,7 @@ static int capture_enum_framesizes(struct file *file, void *fh, ...@@ -95,7 +95,7 @@ static int capture_enum_framesizes(struct file *file, void *fh,
if (!cc) if (!cc)
return -EINVAL; return -EINVAL;
fse.code = cc->codes[0]; fse.code = cc->codes ? cc->codes[0] : 0;
ret = v4l2_subdev_call(priv->src_sd, pad, enum_frame_size, NULL, &fse); ret = v4l2_subdev_call(priv->src_sd, pad, enum_frame_size, NULL, &fse);
if (ret) if (ret)
...@@ -137,7 +137,7 @@ static int capture_enum_frameintervals(struct file *file, void *fh, ...@@ -137,7 +137,7 @@ static int capture_enum_frameintervals(struct file *file, void *fh,
if (!cc) if (!cc)
return -EINVAL; return -EINVAL;
fie.code = cc->codes[0]; fie.code = cc->codes ? cc->codes[0] : 0;
ret = v4l2_subdev_call(priv->src_sd, pad, enum_frame_interval, ret = v4l2_subdev_call(priv->src_sd, pad, enum_frame_interval,
NULL, &fie); NULL, &fie);
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <linux/module.h> #include <linux/module.h>
#include "imx-media.h" #include "imx-media.h"
#define IMX_BUS_FMTS(fmt...) (const u32[]) {fmt, 0}
/* /*
* List of supported pixel formats for the subdevs. * List of supported pixel formats for the subdevs.
*/ */
...@@ -14,18 +16,18 @@ static const struct imx_media_pixfmt pixel_formats[] = { ...@@ -14,18 +16,18 @@ static const struct imx_media_pixfmt pixel_formats[] = {
/*** YUV formats start here ***/ /*** YUV formats start here ***/
{ {
.fourcc = V4L2_PIX_FMT_UYVY, .fourcc = V4L2_PIX_FMT_UYVY,
.codes = { .codes = IMX_BUS_FMTS(
MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_UYVY8_2X8,
MEDIA_BUS_FMT_UYVY8_1X16 MEDIA_BUS_FMT_UYVY8_1X16
}, ),
.cs = IPUV3_COLORSPACE_YUV, .cs = IPUV3_COLORSPACE_YUV,
.bpp = 16, .bpp = 16,
}, { }, {
.fourcc = V4L2_PIX_FMT_YUYV, .fourcc = V4L2_PIX_FMT_YUYV,
.codes = { .codes = IMX_BUS_FMTS(
MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YUYV8_2X8,
MEDIA_BUS_FMT_YUYV8_1X16 MEDIA_BUS_FMT_YUYV8_1X16
}, ),
.cs = IPUV3_COLORSPACE_YUV, .cs = IPUV3_COLORSPACE_YUV,
.bpp = 16, .bpp = 16,
}, { }, {
...@@ -55,7 +57,7 @@ static const struct imx_media_pixfmt pixel_formats[] = { ...@@ -55,7 +57,7 @@ static const struct imx_media_pixfmt pixel_formats[] = {
.planar = true, .planar = true,
}, { }, {
.fourcc = V4L2_PIX_FMT_YUV32, .fourcc = V4L2_PIX_FMT_YUV32,
.codes = {MEDIA_BUS_FMT_AYUV8_1X32}, .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_AYUV8_1X32),
.cs = IPUV3_COLORSPACE_YUV, .cs = IPUV3_COLORSPACE_YUV,
.bpp = 32, .bpp = 32,
.ipufmt = true, .ipufmt = true,
...@@ -63,16 +65,16 @@ static const struct imx_media_pixfmt pixel_formats[] = { ...@@ -63,16 +65,16 @@ static const struct imx_media_pixfmt pixel_formats[] = {
/*** RGB formats start here ***/ /*** RGB formats start here ***/
{ {
.fourcc = V4L2_PIX_FMT_RGB565, .fourcc = V4L2_PIX_FMT_RGB565,
.codes = {MEDIA_BUS_FMT_RGB565_2X8_LE}, .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_RGB565_2X8_LE),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 16, .bpp = 16,
.cycles = 2, .cycles = 2,
}, { }, {
.fourcc = V4L2_PIX_FMT_RGB24, .fourcc = V4L2_PIX_FMT_RGB24,
.codes = { .codes = IMX_BUS_FMTS(
MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_RGB888_1X24,
MEDIA_BUS_FMT_RGB888_2X12_LE MEDIA_BUS_FMT_RGB888_2X12_LE
}, ),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 24, .bpp = 24,
}, { }, {
...@@ -81,12 +83,12 @@ static const struct imx_media_pixfmt pixel_formats[] = { ...@@ -81,12 +83,12 @@ static const struct imx_media_pixfmt pixel_formats[] = {
.bpp = 24, .bpp = 24,
}, { }, {
.fourcc = V4L2_PIX_FMT_XRGB32, .fourcc = V4L2_PIX_FMT_XRGB32,
.codes = {MEDIA_BUS_FMT_ARGB8888_1X32}, .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_ARGB8888_1X32),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 32, .bpp = 32,
}, { }, {
.fourcc = V4L2_PIX_FMT_XRGB32, .fourcc = V4L2_PIX_FMT_XRGB32,
.codes = {MEDIA_BUS_FMT_ARGB8888_1X32}, .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_ARGB8888_1X32),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 32, .bpp = 32,
.ipufmt = true, .ipufmt = true,
...@@ -106,91 +108,91 @@ static const struct imx_media_pixfmt pixel_formats[] = { ...@@ -106,91 +108,91 @@ static const struct imx_media_pixfmt pixel_formats[] = {
/*** raw bayer and grayscale formats start here ***/ /*** raw bayer and grayscale formats start here ***/
{ {
.fourcc = V4L2_PIX_FMT_SBGGR8, .fourcc = V4L2_PIX_FMT_SBGGR8,
.codes = {MEDIA_BUS_FMT_SBGGR8_1X8}, .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SBGGR8_1X8),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 8, .bpp = 8,
.bayer = true, .bayer = true,
}, { }, {
.fourcc = V4L2_PIX_FMT_SGBRG8, .fourcc = V4L2_PIX_FMT_SGBRG8,
.codes = {MEDIA_BUS_FMT_SGBRG8_1X8}, .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SGBRG8_1X8),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 8, .bpp = 8,
.bayer = true, .bayer = true,
}, { }, {
.fourcc = V4L2_PIX_FMT_SGRBG8, .fourcc = V4L2_PIX_FMT_SGRBG8,
.codes = {MEDIA_BUS_FMT_SGRBG8_1X8}, .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SGRBG8_1X8),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 8, .bpp = 8,
.bayer = true, .bayer = true,
}, { }, {
.fourcc = V4L2_PIX_FMT_SRGGB8, .fourcc = V4L2_PIX_FMT_SRGGB8,
.codes = {MEDIA_BUS_FMT_SRGGB8_1X8}, .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_SRGGB8_1X8),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 8, .bpp = 8,
.bayer = true, .bayer = true,
}, { }, {
.fourcc = V4L2_PIX_FMT_SBGGR16, .fourcc = V4L2_PIX_FMT_SBGGR16,
.codes = { .codes = IMX_BUS_FMTS(
MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10,
MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR12_1X12,
MEDIA_BUS_FMT_SBGGR14_1X14, MEDIA_BUS_FMT_SBGGR14_1X14,
MEDIA_BUS_FMT_SBGGR16_1X16 MEDIA_BUS_FMT_SBGGR16_1X16
}, ),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 16, .bpp = 16,
.bayer = true, .bayer = true,
}, { }, {
.fourcc = V4L2_PIX_FMT_SGBRG16, .fourcc = V4L2_PIX_FMT_SGBRG16,
.codes = { .codes = IMX_BUS_FMTS(
MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10,
MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG12_1X12,
MEDIA_BUS_FMT_SGBRG14_1X14, MEDIA_BUS_FMT_SGBRG14_1X14,
MEDIA_BUS_FMT_SGBRG16_1X16, MEDIA_BUS_FMT_SGBRG16_1X16
}, ),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 16, .bpp = 16,
.bayer = true, .bayer = true,
}, { }, {
.fourcc = V4L2_PIX_FMT_SGRBG16, .fourcc = V4L2_PIX_FMT_SGRBG16,
.codes = { .codes = IMX_BUS_FMTS(
MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10,
MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG12_1X12,
MEDIA_BUS_FMT_SGRBG14_1X14, MEDIA_BUS_FMT_SGRBG14_1X14,
MEDIA_BUS_FMT_SGRBG16_1X16, MEDIA_BUS_FMT_SGRBG16_1X16
}, ),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 16, .bpp = 16,
.bayer = true, .bayer = true,
}, { }, {
.fourcc = V4L2_PIX_FMT_SRGGB16, .fourcc = V4L2_PIX_FMT_SRGGB16,
.codes = { .codes = IMX_BUS_FMTS(
MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10,
MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB12_1X12,
MEDIA_BUS_FMT_SRGGB14_1X14, MEDIA_BUS_FMT_SRGGB14_1X14,
MEDIA_BUS_FMT_SRGGB16_1X16, MEDIA_BUS_FMT_SRGGB16_1X16
}, ),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 16, .bpp = 16,
.bayer = true, .bayer = true,
}, { }, {
.fourcc = V4L2_PIX_FMT_GREY, .fourcc = V4L2_PIX_FMT_GREY,
.codes = { .codes = IMX_BUS_FMTS(
MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8,
MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y10_1X10,
MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y12_1X12
}, ),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 8, .bpp = 8,
.bayer = true, .bayer = true,
}, { }, {
.fourcc = V4L2_PIX_FMT_Y10, .fourcc = V4L2_PIX_FMT_Y10,
.codes = {MEDIA_BUS_FMT_Y10_1X10}, .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_Y10_1X10),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 16, .bpp = 16,
.bayer = true, .bayer = true,
}, { }, {
.fourcc = V4L2_PIX_FMT_Y12, .fourcc = V4L2_PIX_FMT_Y12,
.codes = {MEDIA_BUS_FMT_Y12_1X12}, .codes = IMX_BUS_FMTS(MEDIA_BUS_FMT_Y12_1X12),
.cs = IPUV3_COLORSPACE_RGB, .cs = IPUV3_COLORSPACE_RGB,
.bpp = 16, .bpp = 16,
.bayer = true, .bayer = true,
...@@ -220,16 +222,16 @@ static const struct imx_media_pixfmt *find_format(u32 fourcc, ...@@ -220,16 +222,16 @@ static const struct imx_media_pixfmt *find_format(u32 fourcc,
PIXFMT_SEL_YUV : PIXFMT_SEL_RGB); PIXFMT_SEL_YUV : PIXFMT_SEL_RGB);
if (!(fmt_sel & sel) || if (!(fmt_sel & sel) ||
(!allow_non_mbus && !fmt->codes[0])) (!allow_non_mbus && !fmt->codes))
continue; continue;
if (fourcc && fmt->fourcc == fourcc) if (fourcc && fmt->fourcc == fourcc)
return fmt; return fmt;
if (!code) if (!code || !fmt->codes)
continue; continue;
for (j = 0; j < ARRAY_SIZE(fmt->codes) && fmt->codes[j]; j++) { for (j = 0; fmt->codes[j]; j++) {
if (code == fmt->codes[j]) if (code == fmt->codes[j])
return fmt; return fmt;
} }
...@@ -260,7 +262,7 @@ static int enum_format(u32 *fourcc, u32 *code, u32 index, ...@@ -260,7 +262,7 @@ static int enum_format(u32 *fourcc, u32 *code, u32 index,
PIXFMT_SEL_YUV : PIXFMT_SEL_RGB); PIXFMT_SEL_YUV : PIXFMT_SEL_RGB);
if (!(fmt_sel & sel) || if (!(fmt_sel & sel) ||
(!allow_non_mbus && !fmt->codes[0])) (!allow_non_mbus && !fmt->codes))
continue; continue;
if (fourcc && index == 0) { if (fourcc && index == 0) {
...@@ -273,7 +275,7 @@ static int enum_format(u32 *fourcc, u32 *code, u32 index, ...@@ -273,7 +275,7 @@ static int enum_format(u32 *fourcc, u32 *code, u32 index,
continue; continue;
} }
for (j = 0; j < ARRAY_SIZE(fmt->codes) && fmt->codes[j]; j++) { for (j = 0; fmt->codes[j]; j++) {
if (index == 0) { if (index == 0) {
*code = fmt->codes[j]; *code = fmt->codes[j];
return 0; return 0;
...@@ -532,7 +534,7 @@ int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus, ...@@ -532,7 +534,7 @@ int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
const struct imx_media_pixfmt *fmt; const struct imx_media_pixfmt *fmt;
fmt = imx_media_find_format(image->pix.pixelformat, PIXFMT_SEL_ANY); fmt = imx_media_find_format(image->pix.pixelformat, PIXFMT_SEL_ANY);
if (!fmt) if (!fmt || !fmt->codes || !fmt->codes[0])
return -EINVAL; return -EINVAL;
memset(mbus, 0, sizeof(*mbus)); memset(mbus, 0, sizeof(*mbus));
......
...@@ -68,8 +68,13 @@ enum { ...@@ -68,8 +68,13 @@ enum {
#define IMX_MEDIA_EOF_TIMEOUT 1000 #define IMX_MEDIA_EOF_TIMEOUT 1000
struct imx_media_pixfmt { struct imx_media_pixfmt {
/* the in-memory FourCC pixel format */
u32 fourcc; u32 fourcc;
u32 codes[4]; /*
* the set of equivalent media bus codes for the fourcc.
* NOTE! codes pointer is NULL for in-memory-only formats.
*/
const u32 *codes;
int bpp; /* total bpp */ int bpp; /* total bpp */
/* cycles per pixel for generic (bayer) formats for the parallel bus */ /* cycles per pixel for generic (bayer) formats for the parallel bus */
int cycles; int cycles;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment