* [PATCH 1/4] platform/x86: int3472: Map the VD55G1 power enable GPIO to "vana"
2026-09-24 17:18 [PATCH 0/4] Lenovo ThinkPad X1 Carbon Gen 14 IR camera: ST VD55G1 on Intel IPU7 Ruslan Koreev
@ 2026-09-24 17:18 ` Ruslan Koreev
2026-09-24 17:18 ` [PATCH 2/4] media: ipu-bridge: Add the ST VD55G1 (TBE20A1) Ruslan Koreev
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Ruslan Koreev @ 2026-09-24 17:18 UTC (permalink / raw)
To: sakari.ailus, benjamin.mugnier, sylvain.petinot, dan.scally
Cc: mchehab, hansg, ilpo.jarvinen, gregkh, linux-media,
platform-driver-x86, linux-staging, linux-kernel, Peter Marshall,
Ruslan Koreev
The Lenovo ThinkPad X1 Carbon Gen 14 has an ST VD55G1 IR camera, ACPI
HID TBE20A1, behind an INT3472 discrete device that provides a power
enable GPIO, a reset GPIO and a privacy LED. The vd55g1 driver names its
analog supply "vana", so map the power enable regulator to that name, as
is already done for the imx471 on the same laptop.
Signed-off-by: Ruslan Koreev <koreev.r@gmail.com>
---
drivers/platform/x86/intel/int3472/discrete.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c
index 6c729fcfc..d005595ba 100644
--- a/drivers/platform/x86/intel/int3472/discrete.c
+++ b/drivers/platform/x86/intel/int3472/discrete.c
@@ -130,6 +130,7 @@ skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472,
static const char * const power_enable_hids_vana[] = {
"SONY471A", /* imx471 on Lenovo X9-14 and X9-15 */
"TBE20A0", /* imx471 on Lenovo X1 Carbon G14 */
+ "TBE20A1", /* vd55g1 on Lenovo X1 Carbon G14 */
NULL
};
--
2.55.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH 2/4] media: ipu-bridge: Add the ST VD55G1 (TBE20A1)
2026-09-24 17:18 [PATCH 0/4] Lenovo ThinkPad X1 Carbon Gen 14 IR camera: ST VD55G1 on Intel IPU7 Ruslan Koreev
2026-09-24 17:18 ` [PATCH 1/4] platform/x86: int3472: Map the VD55G1 power enable GPIO to "vana" Ruslan Koreev
@ 2026-09-24 17:18 ` Ruslan Koreev
2026-09-24 17:18 ` [PATCH 3/4] media: i2c: vd55g1: Add ACPI support for the Lenovo TBE20A1 HID Ruslan Koreev
2026-09-24 17:18 ` [PATCH 4/4] media: staging/ipu7: Add monochrome pixel formats Ruslan Koreev
3 siblings, 0 replies; 5+ messages in thread
From: Ruslan Koreev @ 2026-09-24 17:18 UTC (permalink / raw)
To: sakari.ailus, benjamin.mugnier, sylvain.petinot, dan.scally
Cc: mchehab, hansg, ilpo.jarvinen, gregkh, linux-media,
platform-driver-x86, linux-staging, linux-kernel, Peter Marshall,
Ruslan Koreev
Add the ACPI HID Lenovo uses for the ST VD55G1 IR camera of the ThinkPad
X1 Carbon Gen 14. The firmware describes one CSI-2 data lane and, as
usual, no link frequency, so the value has to come from this table; the
vd55g1 driver requires exactly one.
Use 402 MHz (804 Mbps). The sensor derives its MIPI rate and clock tree
from this value and the IPU7 CSI-2 receiver reads the same value back
through V4L2_CID_LINK_FREQ, so both ends agree by construction. At
804 Mbps a full-width 10-bit line takes about 11 us on the link, which
allows well over 100 fps at full resolution; lower rates lengthen every
line proportionally. The rate is in the lower half of the 250 to
1200 Mbps range the sensor supports and is the one validated on the
hardware, where 804x704 streams at 58 fps.
Signed-off-by: Ruslan Koreev <koreev.r@gmail.com>
---
drivers/media/pci/intel/ipu-bridge.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
index bd64c0400..5941428ed 100644
--- a/drivers/media/pci/intel/ipu-bridge.c
+++ b/drivers/media/pci/intel/ipu-bridge.c
@@ -101,6 +101,8 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = {
IPU_SENSOR_CONFIG("SONY471A", 1, 200000000),
/* Sony IMX471 (found on Lenovo X1 Carbon G14) */
IPU_SENSOR_CONFIG("TBE20A0", 1, 200000000),
+ /* STMicroelectronics VD55G1 (found on Lenovo X1 Carbon G14) */
+ IPU_SENSOR_CONFIG("TBE20A1", 1, 402000000),
/* Toshiba T4KA3 */
IPU_SENSOR_CONFIG("XMCC0003", 1, 321468000),
};
--
2.55.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH 3/4] media: i2c: vd55g1: Add ACPI support for the Lenovo TBE20A1 HID
2026-09-24 17:18 [PATCH 0/4] Lenovo ThinkPad X1 Carbon Gen 14 IR camera: ST VD55G1 on Intel IPU7 Ruslan Koreev
2026-09-24 17:18 ` [PATCH 1/4] platform/x86: int3472: Map the VD55G1 power enable GPIO to "vana" Ruslan Koreev
2026-09-24 17:18 ` [PATCH 2/4] media: ipu-bridge: Add the ST VD55G1 (TBE20A1) Ruslan Koreev
@ 2026-09-24 17:18 ` Ruslan Koreev
2026-09-24 17:18 ` [PATCH 4/4] media: staging/ipu7: Add monochrome pixel formats Ruslan Koreev
3 siblings, 0 replies; 5+ messages in thread
From: Ruslan Koreev @ 2026-09-24 17:18 UTC (permalink / raw)
To: sakari.ailus, benjamin.mugnier, sylvain.petinot, dan.scally
Cc: mchehab, hansg, ilpo.jarvinen, gregkh, linux-media,
platform-driver-x86, linux-staging, linux-kernel, Peter Marshall,
Ruslan Koreev
The IR camera of the Lenovo ThinkPad X1 Carbon Gen 14 is an ST VD55G1
enumerated by ACPI as TBE20A1, connected to the Intel IPU7 with one
CSI-2 lane and powered through an INT3472 discrete device. Match the
HID and take the sensor version from the match data, as for OF. Only
the analog supply is switchable on this platform; vcore and vddio are
always on and fall back to dummy regulators.
On these platforms the CSI-2 endpoint is a software node that
ipu-bridge attaches to the sensor device when the IPU driver probes,
which can happen after the sensor driver has been bound. Defer probing
instead of failing when there is no endpoint yet, as the other sensor
drivers used with the IPU bridge do and as v4l2_fwnode_endpoint_parse()
itself does for a missing endpoint.
Tested on a ThinkPad X1 Carbon Gen 14 (Core Ultra X7 358H, IPU7),
streaming 804x704 through libcamera.
Signed-off-by: Ruslan Koreev <koreev.r@gmail.com>
---
drivers/media/i2c/vd55g1.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/media/i2c/vd55g1.c b/drivers/media/i2c/vd55g1.c
index 6f458f611..64889c35d 100644
--- a/drivers/media/i2c/vd55g1.c
+++ b/drivers/media/i2c/vd55g1.c
@@ -1903,10 +1903,9 @@ static int vd55g1_parse_dt(struct vd55g1 *sensor)
endpoint = fwnode_graph_get_endpoint_by_id(dev_fwnode(sensor->dev),
0, 0, 0);
- if (!endpoint) {
- dev_err(sensor->dev, "Endpoint node not found\n");
- return -EINVAL;
- }
+ if (!endpoint)
+ return dev_err_probe(sensor->dev, -EPROBE_DEFER,
+ "waiting for fwnode graph endpoint\n");
ret = vd55g1_check_csi_conf(sensor, endpoint);
fwnode_handle_put(endpoint);
@@ -2084,6 +2083,13 @@ static const struct of_device_id vd55g1_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, vd55g1_dt_ids);
+static const struct acpi_device_id vd55g1_acpi_ids[] = {
+ /* Lenovo ThinkPad X1 Carbon Gen 14 IR camera, Intel IPU7 */
+ { "TBE20A1", (kernel_ulong_t)&vd55g1_versions[0] },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, vd55g1_acpi_ids);
+
static const struct dev_pm_ops vd55g1_pm_ops = {
SET_RUNTIME_PM_OPS(vd55g1_power_off, vd55g1_power_on, NULL)
};
@@ -2092,6 +2098,7 @@ static struct i2c_driver vd55g1_i2c_driver = {
.driver = {
.name = "vd55g1",
.of_match_table = vd55g1_dt_ids,
+ .acpi_match_table = vd55g1_acpi_ids,
.pm = &vd55g1_pm_ops,
},
.probe = vd55g1_probe,
--
2.55.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH 4/4] media: staging/ipu7: Add monochrome pixel formats
2026-09-24 17:18 [PATCH 0/4] Lenovo ThinkPad X1 Carbon Gen 14 IR camera: ST VD55G1 on Intel IPU7 Ruslan Koreev
` (2 preceding siblings ...)
2026-09-24 17:18 ` [PATCH 3/4] media: i2c: vd55g1: Add ACPI support for the Lenovo TBE20A1 HID Ruslan Koreev
@ 2026-09-24 17:18 ` Ruslan Koreev
3 siblings, 0 replies; 5+ messages in thread
From: Ruslan Koreev @ 2026-09-24 17:18 UTC (permalink / raw)
To: sakari.ailus, benjamin.mugnier, sylvain.petinot, dan.scally
Cc: mchehab, hansg, ilpo.jarvinen, gregkh, linux-media,
platform-driver-x86, linux-staging, linux-kernel, Peter Marshall,
Ruslan Koreev
The CSI-2 receiver already accepts MEDIA_BUS_FMT_Y10_1X10 but the video
nodes offer no pixel format for it, and MEDIA_BUS_FMT_Y8_1X8 is not
accepted at all, so a monochrome sensor cannot stream through the IPU7:
the ST VD55G1 IR camera of the Lenovo ThinkPad X1 Carbon Gen 14 only
produces Y8 and Y10 and no configuration can be negotiated for it.
Add the GREY, Y10 and Y10P pixel formats, mapped to the RAW8, RAW16
and RAW10 frame formats like their Bayer counterparts, and accept
MEDIA_BUS_FMT_Y8_1X8 on the CSI-2 receiver with the RAW8 data type.
ipu7_isys_is_bayer_format() treats every raw code as Bayer, so the mono
codes take the raw path in the CSI-2 cropping code; leave them alone in
ipu7_isys_convert_bayer_order(), which otherwise warns about them. The
two parts belong together: with the mono codes exposed but not excluded
there, any crop offset on a mono stream triggers the warning.
Tested with the VD55G1 on that laptop: libcamera negotiates Y8 and
streams 804x704 at 58 fps, and Y10 and Y10P stream with plain V4L2.
Signed-off-by: Ruslan Koreev <koreev.r@gmail.com>
---
drivers/staging/media/ipu7/ipu7-isys-csi2.c | 1 +
drivers/staging/media/ipu7/ipu7-isys-subdev.c | 5 +++++
drivers/staging/media/ipu7/ipu7-isys-video.c | 6 ++++++
3 files changed, 12 insertions(+)
diff --git a/drivers/staging/media/ipu7/ipu7-isys-csi2.c b/drivers/staging/media/ipu7/ipu7-isys-csi2.c
index f34eabfe8..3067ae942 100644
--- a/drivers/staging/media/ipu7/ipu7-isys-csi2.c
+++ b/drivers/staging/media/ipu7/ipu7-isys-csi2.c
@@ -27,6 +27,7 @@
#include "ipu7-isys-csi-phy.h"
static const u32 csi2_supported_codes[] = {
+ MEDIA_BUS_FMT_Y8_1X8,
MEDIA_BUS_FMT_Y10_1X10,
MEDIA_BUS_FMT_RGB565_1X16,
MEDIA_BUS_FMT_RGB888_1X24,
diff --git a/drivers/staging/media/ipu7/ipu7-isys-subdev.c b/drivers/staging/media/ipu7/ipu7-isys-subdev.c
index 67a776033..10908383b 100644
--- a/drivers/staging/media/ipu7/ipu7-isys-subdev.c
+++ b/drivers/staging/media/ipu7/ipu7-isys-subdev.c
@@ -42,6 +42,7 @@ unsigned int ipu7_isys_mbus_code_to_mipi(u32 code)
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SRGGB10_1X10:
return MIPI_CSI2_DT_RAW10;
+ case MEDIA_BUS_FMT_Y8_1X8:
case MEDIA_BUS_FMT_SBGGR8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
@@ -88,6 +89,10 @@ u32 ipu7_isys_convert_bayer_order(u32 code, int x, int y)
};
unsigned int i;
+ /* Monochrome raw formats have no Bayer order to convert */
+ if (code == MEDIA_BUS_FMT_Y8_1X8 || code == MEDIA_BUS_FMT_Y10_1X10)
+ return code;
+
for (i = 0; i < ARRAY_SIZE(code_map); i++)
if (code_map[i] == code)
break;
diff --git a/drivers/staging/media/ipu7/ipu7-isys-video.c b/drivers/staging/media/ipu7/ipu7-isys-video.c
index 8c6730833..c9abd4560 100644
--- a/drivers/staging/media/ipu7/ipu7-isys-video.c
+++ b/drivers/staging/media/ipu7/ipu7-isys-video.c
@@ -54,6 +54,8 @@ const struct ipu7_isys_pixelformat ipu7_isys_pfmts[] = {
IPU_INSYS_FRAME_FORMAT_RAW16},
{V4L2_PIX_FMT_SRGGB10, 16, 10, MEDIA_BUS_FMT_SRGGB10_1X10,
IPU_INSYS_FRAME_FORMAT_RAW16},
+ {V4L2_PIX_FMT_Y10, 16, 10, MEDIA_BUS_FMT_Y10_1X10,
+ IPU_INSYS_FRAME_FORMAT_RAW16},
{V4L2_PIX_FMT_SBGGR8, 8, 8, MEDIA_BUS_FMT_SBGGR8_1X8,
IPU_INSYS_FRAME_FORMAT_RAW8},
{V4L2_PIX_FMT_SGBRG8, 8, 8, MEDIA_BUS_FMT_SGBRG8_1X8,
@@ -62,6 +64,8 @@ const struct ipu7_isys_pixelformat ipu7_isys_pfmts[] = {
IPU_INSYS_FRAME_FORMAT_RAW8},
{V4L2_PIX_FMT_SRGGB8, 8, 8, MEDIA_BUS_FMT_SRGGB8_1X8,
IPU_INSYS_FRAME_FORMAT_RAW8},
+ {V4L2_PIX_FMT_GREY, 8, 8, MEDIA_BUS_FMT_Y8_1X8,
+ IPU_INSYS_FRAME_FORMAT_RAW8},
{V4L2_PIX_FMT_SBGGR12P, 12, 12, MEDIA_BUS_FMT_SBGGR12_1X12,
IPU_INSYS_FRAME_FORMAT_RAW12},
{V4L2_PIX_FMT_SGBRG12P, 12, 12, MEDIA_BUS_FMT_SGBRG12_1X12,
@@ -78,6 +82,8 @@ const struct ipu7_isys_pixelformat ipu7_isys_pfmts[] = {
IPU_INSYS_FRAME_FORMAT_RAW10},
{V4L2_PIX_FMT_SRGGB10P, 10, 10, MEDIA_BUS_FMT_SRGGB10_1X10,
IPU_INSYS_FRAME_FORMAT_RAW10},
+ {V4L2_PIX_FMT_Y10P, 10, 10, MEDIA_BUS_FMT_Y10_1X10,
+ IPU_INSYS_FRAME_FORMAT_RAW10},
{V4L2_PIX_FMT_UYVY, 16, 16, MEDIA_BUS_FMT_UYVY8_1X16,
IPU_INSYS_FRAME_FORMAT_UYVY},
{V4L2_PIX_FMT_YUYV, 16, 16, MEDIA_BUS_FMT_YUYV8_1X16,
--
2.55.0
^ permalink raw reply [flat|nested] 5+ messages in thread