From adb4f2dd68f0ba306023f874b44bcbf300724766 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 28 May 2026 13:20:31 +0100 Subject: [PATCH 1/4] Revert "media: tc358743: Fix the RGB MBUS format" This reverts commit 3b411a7a60f0c4cba28640375801319292932d24. Upstream changed their minds as to how to solve this problem. Signed-off-by: Dave Stevenson --- drivers/media/i2c/tc358743.c | 53 ++++++------------------------------ 1 file changed, 9 insertions(+), 44 deletions(-) diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index feb089d8de724d..a0ca19359c4314 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -756,7 +756,6 @@ static void tc358743_set_ref_clk(struct v4l2_subdev *sd) static void tc358743_set_csi_color_space(struct v4l2_subdev *sd) { struct tc358743_state *state = to_state(sd); - struct device *dev = &state->i2c_client->dev; switch (state->mbus_fmt_code) { case MEDIA_BUS_FMT_UYVY8_1X16: @@ -772,17 +771,7 @@ static void tc358743_set_csi_color_space(struct v4l2_subdev *sd) mutex_unlock(&state->confctl_mutex); break; case MEDIA_BUS_FMT_RGB888_1X24: - /* - * The driver was initially introduced with RGB888 - * support, but CSI really means BGR. - * - * Since we might have applications that would have - * hard-coded the RGB888, let's support both. - */ - dev_warn_once(dev, "RGB format isn't actually supported by the hardware. The application should be fixed to use BGR."); - fallthrough; - case MEDIA_BUS_FMT_BGR888_1X24: - v4l2_dbg(2, debug, sd, "%s: BGR 888 24-bit\n", __func__); + v4l2_dbg(2, debug, sd, "%s: RGB 888 24-bit\n", __func__); i2c_wr8_and_or(sd, VOUT_SET2, ~(MASK_SEL422 | MASK_VOUT_422FIL_100) & 0xff, 0x00); @@ -1443,26 +1432,11 @@ static int tc358743_log_status(struct v4l2_subdev *sd) v4l2_info(sd, "Stopped: %s\n", (i2c_rd16(sd, CSI_STATUS) & MASK_S_HLT) ? "yes" : "no"); - - switch (state->mbus_fmt_code) { - case MEDIA_BUS_FMT_BGR888_1X24: - /* - * The driver was initially introduced with RGB888 - * support, but CSI really means BGR. - * - * Since we might have applications that would have - * hard-coded the RGB888, let's support both. - */ - case MEDIA_BUS_FMT_RGB888_1X24: - v4l2_info(sd, "Color space: BGR 888 24-bit\n"); - break; - case MEDIA_BUS_FMT_UYVY8_1X16: - v4l2_info(sd, "Color space: YCbCr 422 16-bit\n"); - break; - default: - v4l2_info(sd, "Color space: Unsupported\n"); - break; - } + v4l2_info(sd, "Color space: %s\n", + state->mbus_fmt_code == MEDIA_BUS_FMT_UYVY8_1X16 ? + "YCbCr 422 16-bit" : + state->mbus_fmt_code == MEDIA_BUS_FMT_RGB888_1X24 ? + "RGB 888 24-bit" : "Unsupported"); v4l2_info(sd, "-----%s status-----\n", is_hdmi(sd) ? "HDMI" : "DVI-D"); v4l2_info(sd, "HDCP encrypted content: %s\n", @@ -1799,18 +1773,11 @@ static int tc358743_enum_mbus_code(struct v4l2_subdev *sd, { switch (code->index) { case 0: - code->code = MEDIA_BUS_FMT_BGR888_1X24; + code->code = MEDIA_BUS_FMT_RGB888_1X24; break; case 1: code->code = MEDIA_BUS_FMT_UYVY8_1X16; break; - case 2: - /* - * We need to keep RGB888 for backward compatibility, - * but we should list it last for userspace to pick BGR. - */ - code->code = MEDIA_BUS_FMT_RGB888_1X24; - break; default: return -EINVAL; } @@ -1820,7 +1787,6 @@ static int tc358743_enum_mbus_code(struct v4l2_subdev *sd, static u32 tc358743_g_colorspace(u32 code) { switch (code) { - case MEDIA_BUS_FMT_BGR888_1X24: case MEDIA_BUS_FMT_RGB888_1X24: return V4L2_COLORSPACE_SRGB; case MEDIA_BUS_FMT_UYVY8_1X16: @@ -1858,8 +1824,7 @@ static int tc358743_set_fmt(struct v4l2_subdev *sd, u32 code = format->format.code; /* is overwritten by get_fmt */ int ret = tc358743_get_fmt(sd, sd_state, format); - if (code == MEDIA_BUS_FMT_BGR888_1X24 || - code == MEDIA_BUS_FMT_RGB888_1X24 || + if (code == MEDIA_BUS_FMT_RGB888_1X24 || code == MEDIA_BUS_FMT_UYVY8_1X16) format->format.code = code; format->format.colorspace = tc358743_g_colorspace(format->format.code); @@ -2279,7 +2244,7 @@ static int tc358743_probe(struct i2c_client *client) if (err < 0) goto err_hdl; - state->mbus_fmt_code = MEDIA_BUS_FMT_BGR888_1X24; + state->mbus_fmt_code = MEDIA_BUS_FMT_RGB888_1X24; sd->dev = &client->dev; From 4c2b2878b1a93b89ae1f47b244a17156d52b3a1f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 9 Mar 2026 16:07:41 +0100 Subject: [PATCH 2/4] media: bcm2835-unicam: Fix RGB format / mbus code association Commit 08f9794d9b799b56b301d7537e8771f0d41f51a1 upstream. The Unicam driver is a MIPI-CSI2 Receiver, that can capture RGB 4:4:4, YCbCr 4:2:2, and raw formats. RGB 4:4:4 is converted to the MIPI-CSI2 RGB888 video format, and associated to the MEDIA_BUS_FMT_RGB888_1X24 media bus code. However, V4L2_PIX_FMT_RGB24 is defined as having its color components in the R, G and B order, from left to right. MIPI-CSI2 however defines the RGB888 format with blue first, and that's what MEDIA_BUS_FMT_RGB888_1X24 defines too. This essentially means that the R and B will be swapped compared to what V4L2_PIX_FMT_RGB24 defines. The same situation occurs with V4L2_PIX_FMT_BGR24 being associated to MEDIA_BUS_FMT_BGR888_1X24. In order to fix the swapped components, we need to change the association of V4L2_PIX_FMT_BGR24 to MEDIA_BUS_FMT_RGB888_1X24, and of V4L2_PIX_FMT_RGB24 to MEDIA_BUS_FMT_BGR888_1X24. Since the media bus code is exposed to userspace, and validated by unicam's link_validate implementation, we need to explicitly accept (and warn) the old association still to preserve backward compatibility. Signed-off-by: Maxime Ripard Reviewed-by: Laurent Pinchart Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- .../media/platform/broadcom/bcm2835-unicam.c | 41 +++++++++++++++---- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/broadcom/bcm2835-unicam.c b/drivers/media/platform/broadcom/bcm2835-unicam.c index 1fe30149d5e243..c77778a8b5f678 100644 --- a/drivers/media/platform/broadcom/bcm2835-unicam.c +++ b/drivers/media/platform/broadcom/bcm2835-unicam.c @@ -342,12 +342,12 @@ static const struct unicam_format_info unicam_image_formats[] = { .csi_dt = MIPI_CSI2_DT_RGB565, }, { .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ - .code = MEDIA_BUS_FMT_RGB888_1X24, + .code = MEDIA_BUS_FMT_BGR888_1X24, .depth = 24, .csi_dt = MIPI_CSI2_DT_RGB888, }, { .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ - .code = MEDIA_BUS_FMT_BGR888_1X24, + .code = MEDIA_BUS_FMT_RGB888_1X24, .depth = 24, .csi_dt = MIPI_CSI2_DT_RGB888, }, { @@ -2148,22 +2148,45 @@ static int unicam_video_link_validate(struct media_link *link) const struct v4l2_pix_format *fmt = &node->fmt.fmt.pix; const struct unicam_format_info *fmtinfo; - fmtinfo = unicam_find_format_by_fourcc(fmt->pixelformat, - UNICAM_SD_PAD_SOURCE_IMAGE); + fmtinfo = unicam_find_format_by_code(format->code, + UNICAM_SD_PAD_SOURCE_IMAGE); if (WARN_ON(!fmtinfo)) { ret = -EPIPE; goto out; } - if (fmtinfo->code != format->code || - fmt->height != format->height || + /* + * Unicam initially associated BGR24 to BGR888_1X24 and RGB24 to + * RGB888_1X24. + * + * In order to allow the applications using the old behaviour to + * run, let's accept the old combination, but warn about it. + */ + if (fmtinfo->fourcc != fmt->pixelformat) { + if ((fmt->pixelformat == V4L2_PIX_FMT_BGR24 && + format->code == MEDIA_BUS_FMT_BGR888_1X24) || + (fmt->pixelformat == V4L2_PIX_FMT_RGB24 && + format->code == MEDIA_BUS_FMT_RGB888_1X24)) { + dev_warn_once(node->dev->dev, + "Incorrect pixel format %p4cc for 0x%04x. Fix your application to use %p4cc.\n", + &fmt->pixelformat, format->code, &fmtinfo->fourcc); + } else { + dev_dbg(node->dev->dev, + "image: format mismatch: 0x%04x <=> %p4cc\n", + format->code, &fmt->pixelformat); + ret = -EPIPE; + goto out; + } + } + + if (fmt->height != format->height || fmt->width != format->width || fmt->field != format->field) { dev_dbg(node->dev->dev, - "image: (%u x %u) 0x%08x %s != (%u x %u) 0x%08x %s\n", - fmt->width, fmt->height, fmtinfo->code, + "image: (%u x %u) %s != (%u x %u) %s\n", + fmt->width, fmt->height, v4l2_field_names[fmt->field], - format->width, format->height, format->code, + format->width, format->height, v4l2_field_names[format->field]); ret = -EPIPE; } From 40009ce5d873c709e7f9fed2c599a401e762cb2a Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 28 May 2026 15:33:26 +0100 Subject: [PATCH 3/4] media: rp1-cfe: Fix RGB format / mbus code association CFE version of 08f9794d9b79 ("media: bcm2835-unicam: Fix RGB format / mbus code association") The CFE driver is a MIPI-CSI2 Receiver, that can capture RGB 4:4:4, YCbCr 4:2:2, and raw formats. RGB 4:4:4 is converted to the MIPI-CSI2 RGB888 video format, and associated to the MEDIA_BUS_FMT_RGB888_1X24 media bus code. However, V4L2_PIX_FMT_RGB24 is defined as having its color components in the R, G and B order, from left to right. MIPI-CSI2 however defines the RGB888 format with blue first, and that's what MEDIA_BUS_FMT_RGB888_1X24 defines too. This essentially means that the R and B will be swapped compared to what V4L2_PIX_FMT_RGB24 defines. The same situation occurs with V4L2_PIX_FMT_BGR24 being associated to MEDIA_BUS_FMT_BGR888_1X24. In order to fix the swapped components, we need to change the association of V4L2_PIX_FMT_BGR24 to MEDIA_BUS_FMT_RGB888_1X24, and of V4L2_PIX_FMT_RGB24 to MEDIA_BUS_FMT_BGR888_1X24. Since the media bus code is exposed to userspace, and validated by the link_validate implementation, we need to explicitly accept (and warn) the old association still to preserve backward compatibility. Signed-off-by: Dave Stevenson --- .../platform/raspberrypi/rp1-cfe/cfe-fmts.h | 4 ++-- .../media/platform/raspberrypi/rp1-cfe/cfe.c | 23 ++++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/cfe-fmts.h b/drivers/media/platform/raspberrypi/rp1-cfe/cfe-fmts.h index 7aecf7f8373344..e641f2f8788708 100644 --- a/drivers/media/platform/raspberrypi/rp1-cfe/cfe-fmts.h +++ b/drivers/media/platform/raspberrypi/rp1-cfe/cfe-fmts.h @@ -62,13 +62,13 @@ static const struct cfe_fmt formats[] = { }, { .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ - .code = MEDIA_BUS_FMT_RGB888_1X24, + .code = MEDIA_BUS_FMT_BGR888_1X24, .depth = 24, .csi_dt = MIPI_CSI2_DT_RGB888, }, { .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ - .code = MEDIA_BUS_FMT_BGR888_1X24, + .code = MEDIA_BUS_FMT_RGB888_1X24, .depth = 24, .csi_dt = MIPI_CSI2_DT_RGB888, }, diff --git a/drivers/media/platform/raspberrypi/rp1-cfe/cfe.c b/drivers/media/platform/raspberrypi/rp1-cfe/cfe.c index 795601eaa1df16..11f5ff17f3727a 100644 --- a/drivers/media/platform/raspberrypi/rp1-cfe/cfe.c +++ b/drivers/media/platform/raspberrypi/rp1-cfe/cfe.c @@ -1807,13 +1807,30 @@ static int cfe_video_link_validate(struct media_link *link) goto out; } - fmt = find_format_by_code_and_fourcc(source_fmt->code, - pix_fmt->pixelformat); + fmt = find_format_by_code(source_fmt->code); + if (!fmt) { - cfe_err(cfe, "Format mismatch!\n"); + cfe_err(cfe, "Format mismatch - unknown code!\n"); ret = -EINVAL; goto out; } + + if (fmt->fourcc != pix_fmt->pixelformat) { + if ((pix_fmt->pixelformat == V4L2_PIX_FMT_BGR24 && + source_fmt->code == MEDIA_BUS_FMT_BGR888_1X24) || + (pix_fmt->pixelformat == V4L2_PIX_FMT_RGB24 && + source_fmt->code == MEDIA_BUS_FMT_RGB888_1X24)) { + dev_warn_once(&cfe->pdev->dev, + "Incorrect pixel format %p4cc for 0x%04x. Fix your application to use %p4cc.\n", + &pix_fmt->pixelformat, + source_fmt->code, &fmt->fourcc); + } else { + cfe_err(cfe, "Format mismatch! Code %u fourcc %p4cc\n", + source_fmt->code, &pix_fmt->pixelformat); + ret = -EINVAL; + goto out; + } + } } else if (is_csi2_node(node) && is_meta_output_node(node)) { struct v4l2_meta_format *meta_fmt = &node->meta_fmt.fmt.meta; const struct cfe_fmt *fmt; From 9ff6804eb59cd6efd44c0831900c578bb701746a Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 28 May 2026 16:53:18 +0100 Subject: [PATCH 4/4] media: rp1-cfe-downstream: Fix RGB format / mbus code association Downstream CFE version of 08f9794d9b79 ("media: bcm2835-unicam: Fix RGB format / mbus code association") The CFE driver is a MIPI-CSI2 Receiver, that can capture RGB 4:4:4, YCbCr 4:2:2, and raw formats. RGB 4:4:4 is converted to the MIPI-CSI2 RGB888 video format, and associated to the MEDIA_BUS_FMT_RGB888_1X24 media bus code. However, V4L2_PIX_FMT_RGB24 is defined as having its color components in the R, G and B order, from left to right. MIPI-CSI2 however defines the RGB888 format with blue first, and that's what MEDIA_BUS_FMT_RGB888_1X24 defines too. This essentially means that the R and B will be swapped compared to what V4L2_PIX_FMT_RGB24 defines. The same situation occurs with V4L2_PIX_FMT_BGR24 being associated to MEDIA_BUS_FMT_BGR888_1X24. In order to fix the swapped components, we need to change the association of V4L2_PIX_FMT_BGR24 to MEDIA_BUS_FMT_RGB888_1X24, and of V4L2_PIX_FMT_RGB24 to MEDIA_BUS_FMT_BGR888_1X24. Since the media bus code is exposed to userspace, and validated by the link_validate implementation, we need to explicitly accept (and warn) the old association still to preserve backward compatibility. Signed-off-by: Dave Stevenson --- .../media/platform/raspberrypi/rp1_cfe/cfe.c | 29 +++++++++++++------ .../platform/raspberrypi/rp1_cfe/cfe_fmts.h | 4 +-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c index f4999391563fb9..3d74a33edc6f3a 100644 --- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c @@ -1676,7 +1676,6 @@ static int cfe_video_link_validate(struct cfe_node *node, if (is_image_output_node(node)) { struct v4l2_pix_format *pix_fmt = &node->vid_fmt.fmt.pix; const struct cfe_fmt *fmt = NULL; - unsigned int i; if (remote_fmt->width != pix_fmt->width || remote_fmt->height != pix_fmt->height) { @@ -1687,17 +1686,29 @@ static int cfe_video_link_validate(struct cfe_node *node, return -EINVAL; } - for (i = 0; i < ARRAY_SIZE(formats); i++) { - if (formats[i].code == remote_fmt->code && - formats[i].fourcc == pix_fmt->pixelformat) { - fmt = &formats[i]; - break; - } - } + fmt = find_format_by_code(remote_fmt->code); + if (!fmt) { - cfe_err("Format mismatch!\n"); + cfe_err("Format not found. %08x %p4cc\n", + remote_fmt->code, &pix_fmt->pixelformat); return -EINVAL; } + + if (fmt->fourcc != pix_fmt->pixelformat) { + if ((pix_fmt->pixelformat == V4L2_PIX_FMT_BGR24 && + remote_fmt->code == MEDIA_BUS_FMT_BGR888_1X24) || + (pix_fmt->pixelformat == V4L2_PIX_FMT_RGB24 && + remote_fmt->code == MEDIA_BUS_FMT_RGB888_1X24)) { + dev_warn_once(&cfe->pdev->dev, + "Incorrect pixel format %p4cc for 0x%04x. Fix your application to use %p4cc.\n", + &pix_fmt->pixelformat, + remote_fmt->code, &fmt->fourcc); + } else { + cfe_err("Format mismatch! Code %u fourcc %p4cc\n", + remote_fmt->code, &pix_fmt->pixelformat); + return -EINVAL; + } + } } else if (is_csi2_node(node) && is_meta_output_node(node)) { struct v4l2_meta_format *meta_fmt = &node->meta_fmt.fmt.meta; const struct cfe_fmt *fmt; diff --git a/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h index e192f211abde2c..d4ecb6be80f82b 100644 --- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h +++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h @@ -63,13 +63,13 @@ static const struct cfe_fmt formats[] = { }, { .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ - .code = MEDIA_BUS_FMT_RGB888_1X24, + .code = MEDIA_BUS_FMT_BGR888_1X24, .depth = 24, .csi_dt = MIPI_CSI2_DT_RGB888, }, { .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ - .code = MEDIA_BUS_FMT_BGR888_1X24, + .code = MEDIA_BUS_FMT_RGB888_1X24, .depth = 24, .csi_dt = MIPI_CSI2_DT_RGB888, },