Support for Y16 format

I’m trying to implement Y16 support for a custom grayscale camera sending data in RAW10 format.
Up until now, I’ve implemented support for Y10 format, taking advantage of it being declared in the soc_mediabus.c file as “MEDIA_BUS_FMT_Y10_1X10”, with the format defined as “V4L2_PIX_FMT_Y10”, so I’ve included it in the camera_common.c and sensor_common.c files.

.code = MEDIA_BUS_FMT_Y10_1X10,
.fmt = {
	.fourcc			= V4L2_PIX_FMT_Y10,
	.name			= "Grey 10bit",
	.bits_per_sample	= 10,
	.packing		= SOC_MBUS_PACKING_EXTEND16,
	.order			= SOC_MBUS_ORDER_LE,
	.layout			= SOC_MBUS_LAYOUT_PACKED,
},

Anyway, I’d like to do some tests with Y16, as I’m receiving the image darker that what it should be.
For that i’ve seen that there is a format defined as “V4L2_PIX_FMT_Y16” and “V4L2_PIX_FMT_Y16_BE”, although I cannot see the code defined as “MEDIA_BUS_FMT_Y16_1x10” anywhere (I think it should be in ./kernel/kernel-4.9/include/uapi/linux/media-bus-format.h)

Does it mean there is actually no support at all for Y16? Should I use another code tag alongside with “V4L2_PIX_FMT_Y16” to implement it? If so, which one?

I’ve achieved to give both Y10 and Y16 support applying the following patch (specifying also both modes in the DT)

diff --git kernel/kernel-4.9/drivers/media/platform/soc_camera/soc_mediabus.c kernel/kernel-4.9/drivers/media/platform/soc_camera/soc_mediabus.c
index e3e665e..223edb2 100644
--- kernel/kernel-4.9/drivers/media/platform/soc_camera/soc_mediabus.c
+++ kernel/kernel-4.9/drivers/media/platform/soc_camera/soc_mediabus.c
@@ -172,6 +172,16 @@ static const struct soc_mbus_lookup mbus_fmt[] = {
 		.order			= SOC_MBUS_ORDER_LE,
 		.layout			= SOC_MBUS_LAYOUT_PACKED,
 	},
+}, {
+	.code = MEDIA_BUS_FMT_Y16_1X16,
+	.fmt = {
+		.fourcc			= V4L2_PIX_FMT_Y16,
+		.name			= "Grey 16bit",
+		.bits_per_sample	= 16,
+		.packing		= SOC_MBUS_PACKING_EXTEND16,
+		.order			= SOC_MBUS_ORDER_LE,
+		.layout			= SOC_MBUS_LAYOUT_PACKED,
+	},
 }, {
 	.code = MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,
 	.fmt = {
diff --git kernel/kernel-4.9/include/uapi/linux/media-bus-format.h kernel/kernel-4.9/include/uapi/linux/media-bus-format.h
index 0882827..47323b1 100644
--- kernel/kernel-4.9/include/uapi/linux/media-bus-format.h
+++ kernel/kernel-4.9/include/uapi/linux/media-bus-format.h
@@ -96,6 +96,7 @@
 #define MEDIA_BUS_FMT_YVYU12_1X24		0x2023
 #define MEDIA_BUS_FMT_YUV10_1X30		0x2016
 #define MEDIA_BUS_FMT_AYUV8_1X32		0x2017
+#define MEDIA_BUS_FMT_Y16_1X16			0x2042
 
 /* Bayer - next is	0x3021 */
 #define MEDIA_BUS_FMT_SBGGR8_1X8		0x3001
diff --git kernel/kernel-4.9/include/uapi/linux/v4l2-mediabus.h kernel/kernel-4.9/include/uapi/linux/v4l2-mediabus.h
index 9cac632..fa00bd3 100644
--- kernel/kernel-4.9/include/uapi/linux/v4l2-mediabus.h
+++ kernel/kernel-4.9/include/uapi/linux/v4l2-mediabus.h
@@ -104,6 +104,8 @@ enum v4l2_mbus_pixelcode {
 	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV12_1X24),
 	V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU12_1X24),
 
+	V4L2_MBUS_FROM_MEDIA_BUS_FMT(Y16_1X16),
+
 	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR8_1X8),
 	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGBRG8_1X8),
 	V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGRBG8_1X8),
diff --git kernel/nvidia/drivers/media/platform/tegra/camera/camera_common.c kernel/nvidia/drivers/media/platform/tegra/camera/camera_common.c
index d24d902..48a12ac 100644
--- kernel/nvidia/drivers/media/platform/tegra/camera/camera_common.c
+++ kernel/nvidia/drivers/media/platform/tegra/camera/camera_common.c
@@ -71,6 +71,18 @@ static const struct camera_common_colorfmt camera_common_color_fmts[] = {
 		V4L2_COLORSPACE_SRGB,
 		V4L2_PIX_FMT_SBGGR10,
 	},
+	// Grayscale support
+	{
+		MEDIA_BUS_FMT_Y10_1X10,
+		V4L2_COLORSPACE_RAW,
+		V4L2_PIX_FMT_Y10,
+	},
+	// Grayscale 16bit support
+	{
+		MEDIA_BUS_FMT_Y16_1X16,
+		V4L2_COLORSPACE_RAW,
+		V4L2_PIX_FMT_Y16,
+	},
 	{
 		MEDIA_BUS_FMT_SRGGB8_1X8,
 		V4L2_COLORSPACE_SRGB,
diff --git kernel/nvidia/drivers/media/platform/tegra/camera/sensor_common.c kernel/nvidia/drivers/media/platform/tegra/camera/sensor_common.c
index 3f3c1f9..1610e4b 100644
--- kernel/nvidia/drivers/media/platform/tegra/camera/sensor_common.c
+++ kernel/nvidia/drivers/media/platform/tegra/camera/sensor_common.c
@@ -196,7 +196,6 @@ static int extract_pixel_format(
 	const char *pixel_t, u32 *format)
 {
 	size_t size = strnlen(pixel_t, OF_MAX_STR_LEN);
-
 	if (strncmp(pixel_t, "bayer_bggr10", size) == 0)
 		*format = V4L2_PIX_FMT_SBGGR10;
 	else if (strncmp(pixel_t, "bayer_rggb10", size) == 0)
@@ -225,6 +224,10 @@ static int extract_pixel_format(
 		*format = V4L2_PIX_FMT_UYVY;
 	else if (strncmp(pixel_t, "yuv_vyuy16", size) == 0)
 		*format = V4L2_PIX_FMT_VYUY;
+	else if (strncmp(pixel_t, "raw_y1010", size) == 0)
+		*format = V4L2_PIX_FMT_Y10; //Grayscale
+	else if (strncmp(pixel_t, "raw_y1616", size) == 0)
+		*format = V4L2_PIX_FMT_Y16; //Grayscale16bit
 	else {
 		pr_err("%s: Need to extend format%s\n", __func__, pixel_t);
 		return -EINVAL;
diff --git kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi2_formats.h kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi2_formats.h
index fed27b9..716b0aa 100644
--- kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi2_formats.h
+++ kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi2_formats.h
@@ -91,6 +91,10 @@ static const struct tegra_video_format vi2_video_formats[] = {
 				RAW10, SGBRG10, "GBGB.. RGRG.."),
 	TEGRA_VIDEO_FORMAT(RAW10, 10, SBGGR10_1X10, 2, 1, T_R16_I,
 				RAW10, SBGGR10, "BGBG.. GRGR.."),
+	TEGRA_VIDEO_FORMAT(RAW10, 10, Y10_1X10, 2, 1, T_R16_I,
+				RAW10, Y10, "GRAY10"),
+	TEGRA_VIDEO_FORMAT(RAW10, 16, Y16_1X16, 2, 1, T_R16_I,
+				RAW10, Y16, "GRAY16"),
 
 	/* RAW 10 Packed format */
 	TEGRA_VIDEO_FORMAT(RAW10, 10, XBGGR10P_3X10, 4, 3, T_X2Lc10Lb10La10,
diff --git kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi4_formats.h kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi4_formats.h
index de33c42..4a99207 100644
--- kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi4_formats.h
+++ kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi4_formats.h
@@ -105,6 +105,10 @@ static const struct tegra_video_format vi4_video_formats[] = {
 				RAW10, SGBRG10, "GBGB.. RGRG.."),
 	TEGRA_VIDEO_FORMAT(RAW10, 10, SBGGR10_1X10, 2, 1, T_R16_I,
 				RAW10, SBGGR10, "BGBG.. GRGR.."),
+	TEGRA_VIDEO_FORMAT(RAW10, 10, Y10_1X10, 2, 1, T_R16_I,
+				RAW10, Y10, "GRAY10"),
+	TEGRA_VIDEO_FORMAT(RAW10, 16, Y16_1X16, 2, 1, T_R16_I,
+				RAW10, Y16, "GRAY16"),
 
 	/* RAW 12 */
 	TEGRA_VIDEO_FORMAT(RAW12, 12, SRGGB12_1X12, 2, 1, T_R16_I,
diff --git kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi5_formats.h kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi5_formats.h
index 51cbbad..c06e665 100644
--- kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi5_formats.h
+++ kernel/nvidia/drivers/media/platform/tegra/camera/vi/vi5_formats.h
@@ -105,6 +105,10 @@ static const struct tegra_video_format vi5_video_formats[] = {
 				RAW10, SGBRG10, "GBGB.. RGRG.."),
 	TEGRA_VIDEO_FORMAT(RAW10, 10, SBGGR10_1X10, 2, 1, T_R16,
 				RAW10, SBGGR10, "BGBG.. GRGR.."),
+	TEGRA_VIDEO_FORMAT(RAW10, 10, Y10_1X10, 2, 1, T_R16,
+				RAW10, Y10, "GRAY10"),
+	TEGRA_VIDEO_FORMAT(RAW10, 16, Y16_1X16, 2, 1, T_R16,
+				RAW10, Y16, "GRAY16"),
 
 	/* RAW 12 */
 	TEGRA_VIDEO_FORMAT(RAW12, 12, SRGGB12_1X12, 2, 1, T_R16,

So now v4l2 reports both formats:

3 Likes

Thank you for taking the time to post the solution.