Shortly after getting frames we have discovered that the frames itself are incorrect.
Our 12 bit pixel values are wrong. They are shifted 2 bits to the left and the lower 2 bits are mirrored versions of the two most significant bits of the 12 bit value.
Otherwise explained:
00BB AAAA AAAA AABB
A are the 10 least significat bits of our 12 bit raw value.
B are the 2 most significant bits of our 12 bit raw value.
So essentially the 2 most significant bits are mirroed on the low ones.
I would expect something like:
0000 BBAA AAAA AAAA
So we are kinda not finished here.
14 bits of the 16 bits are set which is impossible considering the CSI data type is RAW12. So I assume a mistake on the side of the TX2.
Well but now to your question. In fact i had it set to bayer_bggr in the first place. But now I’ve altered the kernel to actually have support for raw12 which I didn’t find inside the kernel.
But it still has the same issue
Here is my device tree part of relevance:
mode0 { // AR0135_MODE_1280X960
mclk_khz = "25000";
num_lanes = "2";
tegra_sinterface = "serial_c";
discontinuous_clk = "no";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "1280";
//active_w = "1920"; //FIXME
active_h = "960";
pixel_t = "raw12";
readout_orientation = "90";
line_length = "1388";
inherent_gain = "1";
mclk_multiplier = "6.67";
//pix_clk_hz = "74250000";
pix_clk_hz = "160000000";
min_gain_val = "1.0";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1.816577";
max_framerate = "54";
min_exp_time = "34";
max_exp_time = "550385";
embedded_metadata_height = "0";
};
But this is not supported inside the official kernel.
I’ve added to core.c
{
TEGRA_VF_RAW12,
12,
MEDIA_BUS_FMT_SBGGR12_1X12,
2,
TEGRA_IMAGE_FORMAT_T_R16_I,
TEGRA_IMAGE_DT_RAW12,
V4L2_PIX_FMT_SBGGR12,
"BGBG.. GRGR..",
},
/* RAW12 - This is new */
{
TEGRA_VF_RAW12,
12,
MEDIA_BUS_FMT_Y12_1X12,
2,
TEGRA_IMAGE_FORMAT_T_R16_I,
TEGRA_IMAGE_DT_RAW12,
V4L2_PIX_FMT_Y12,
"RAW 12 Bit Grey",
},
/* RGB888 */
{
TEGRA_VF_RGB888,
24,
MEDIA_BUS_FMT_RGB888_1X24,
4,
TEGRA_IMAGE_FORMAT_T_A8R8G8B8,
TEGRA_IMAGE_DT_RGB888,
V4L2_PIX_FMT_ABGR32,
"BGRA-8-8-8-8",
},
And also in camera_common.c
static const struct camera_common_colorfmt camera_common_color_fmts[] = {
{
MEDIA_BUS_FMT_SRGGB12_1X12,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SRGGB12,
},
{
MEDIA_BUS_FMT_SRGGB10_1X10,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SRGGB10,
},
{
MEDIA_BUS_FMT_SRGGB8_1X8,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SRGGB8,
},
{ /* This is new */
MEDIA_BUS_FMT_Y12_1X12,
V4L2_COLORSPACE_RAW,
V4L2_PIX_FMT_Y12,
},
};
It was strange that only SRGGB was supported in the function camera_common_try_fmt(*). So I’ve modded this at the end:
if (mf->code != MEDIA_BUS_FMT_SRGGB8_1X8 &&
mf->code != MEDIA_BUS_FMT_SRGGB10_1X10 &&
mf->code != MEDIA_BUS_FMT_SRGGB12_1X12 &&
mf->code != MEDIA_BUS_FMT_Y12_1X12)
{
mf->code = MEDIA_BUS_FMT_SRGGB10_1X10;
err = -EINVAL;
}
mf->field = V4L2_FIELD_NONE;
mf->colorspace = V4L2_COLORSPACE_SRGB;
printk("camera_common_try_fmt wants to have SRGB.\n");
if (mf->code == MEDIA_BUS_FMT_Y12_1X12)
{
printk("camera_common_try_fmt - But I will force RAW at this point FIXME\n");
mf->colorspace = V4L2_COLORSPACE_RAW;
}
return err;
}
I’ve also added a type to soc_mediabus.c as only Y10 was supported here. But no Y12.
.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,
},
}, {
.code = MEDIA_BUS_FMT_Y12_1X12, /* This is new */
.fmt = {
.fourcc = V4L2_PIX_FMT_Y12,
.name = "Grey 12bit",
.bits_per_sample = 12,
.packing = SOC_MBUS_PACKING_EXTEND16,
.order = SOC_MBUS_ORDER_LE,
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
.code = MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,
.fmt = {
.fourcc = V4L2_PIX_FMT_SBGGR10,
.name = "Bayer 10 BGGR",
.bits_per_sample = 8,
.packing = SOC_MBUS_PACKING_2X8_PADHI,
.order = SOC_MBUS_ORDER_LE,
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
Then I changed the support for the device tree in sensor_common.c:
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)
*format = V4L2_PIX_FMT_SRGGB10;
else if (strncmp(pixel_t, "bayer_bggr12", size) == 0)
*format = V4L2_PIX_FMT_SBGGR12;
else if (strncmp(pixel_t, "bayer_rggb12", size) == 0)
*format = V4L2_PIX_FMT_SRGGB12;
else if (strncmp(pixel_t, "bayer_wdr_pwl_rggb12", size) == 0)
*format = V4L2_PIX_FMT_SRGGB12;
else if (strncmp(pixel_t, "bayer_xbggr10p", size) == 0)
*format = V4L2_PIX_FMT_XBGGR10P;
else if (strncmp(pixel_t, "bayer_xrggb10p", size) == 0)
*format = V4L2_PIX_FMT_XRGGB10P;
else if (strncmp(pixel_t, "raw12", size) == 0)
{
*format = V4L2_PIX_FMT_Y12;
printk("extract_pixel_format V4L2_PIX_FMT_Y12 *********************\n");
}
else {
pr_err("%s: Need to extend format%s\n", __func__, pixel_t);
return -EINVAL;
}
return 0;
}
Adding the driver to the kernel compile was done like this:
Adding
CONFIG_VIDEO_AR0135=y
to tegra18_defconfig.
Adding this to drivers/media/i2c/Kconfig:
config VIDEO_AR0135
tristate "AR0135 camera sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
---help---
This is a Video4Linux2 sensor-level driver for the Aptina
AR0135 imager.
Adding this to the Makefile next to that Kconfig:
obj-$(CONFIG_VIDEO_AR0135) += ar0135.o