Incorrect pixel unpacking for RAW12

Hello, I am experiencing some inexplicable behaviour when capturing greyscale RAW12 frames from the TX2.

Input: “0x00AA”
Output:“0xAA2A”

This doesn’t seem to follow the memory mappings laid out in the nVidia documents, any ideas why?

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,
	},
	{
		MEDIA_BUS_FMT_Y12_1X12,
		V4L2_COLORSPACE_RAW,
		V4L2_PIX_FMT_Y12,
	},
	
};
int camera_common_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
{
	...

	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;
	
        if (mf->code == MEDIA_BUS_FMT_Y12_1X12){
		mf->colorspace = V4L2_COLORSPACE_RAW;
	}
	else{
		mf->colorspace = V4L2_COLORSPACE_SRGB;
	}

	return err;
}

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 ("Requesting RAW12 extract_pixel_format\n");
	}
	else {
		pr_err("%s: Need to extend format%s\n", __func__, pixel_t);
		return -EINVAL;
	}

	return 0;
}

in the device tree .dtsi:

mode0 {
				mclk_khz = "25000";
				num_lanes = "4";
				tegra_sinterface = "serial_c";
				discontinuous_clk = "no";
				dpcm_enable = "false";
				cil_settletime = "0";
				active_w = "1920";
				active_h = "1080";				
				pixel_t = "raw12"; 
				readout_orientation = "90";
				line_length = "2688";
				inherent_gain = "1";
				mclk_multiplier = "6.67";
				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 = "300";
				min_exp_time = "34";
				max_exp_time = "550385";
				embedded_metadata_height = "0";
			};

Validation command:

v4l2-ctl --set-fmt-video=width=1920,height=1080,pixelformat='Y12 '  --stream-mmap --stream-count=1 -d /dev/video0 --stream-to=csi_dump.raw  --verbose

xtracrispy,

about more details on RAW memory format, please refer to the Tegra X2 Technical Reference Manual “Video Input” topic.
thanks

Thanks Jerry.

I have already reviewed that document, and the problem is that the output is not following the expected RAW12 memory format as outlined; the two most significant words seem to be corrupted.

Are there any locations in the pipeline/code which could impact the way pixel formats are encoded, other than the snippets which I’ve outlined?

hello xtracrispy,

if you’re using v4l2-ctl to dump the raw image. there’s vb2_buf as output buffer.

R28.1/kernel/kernel-4.4/drivers/media/platform/tegra/camera/vi/channel.c

void free_ring_buffers(struct tegra_channel *chan, int frames)
{
...
                 vb2_buffer_done(&vbuf-><b>vb2_buf</b>,
                         chan->buffer_state[chan->free_index++]);
...
}

you could also refer to below 2 functions to trace the pixel format allocation procedure.

static int tegra_channel_try_format(struct file *file, void *fh, struct v4l2_format *format){}
static int tegra_channel_set_format(struct file *file, void *fh, struct v4l2_format *format){}