diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp
index 3db26ab..efd45b8 100644
--- a/utils/v4l2-ctl/v4l2-ctl.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl.cpp
@@ -68,6 +68,7 @@ enum Option {
 	OptSetInput = 'i',
 	OptListCtrls = 'l',
 	OptListCtrlsMenus = 'L',
+	OptUseMultiplanarApi = 'm',
 	OptListOutputs = 'N',
 	OptListInputs = 'n',
 	OptGetOutput = 'O',
@@ -223,6 +224,7 @@ static struct option long_options[] = {
 	{"try-fmt-video-out", required_argument, 0, OptTryVideoOutFormat},
 	{"help", no_argument, 0, OptHelp},
 	{"wrapper", no_argument, 0, OptUseWrapper},
+	{"multiplanar-api", no_argument, 0, OptUseMultiplanarApi},
 	{"get-output", no_argument, 0, OptGetOutput},
 	{"set-output", required_argument, 0, OptSetOutput},
 	{"list-outputs", no_argument, 0, OptListOutputs},
@@ -509,6 +511,9 @@ static void usage(void)
 	       "  --sleep=<secs>     sleep for <secs> seconds, call QUERYCAP and close the file handle\n"
 	       "  --streamoff        turn the stream off [VIDIOC_STREAMOFF]\n"
 	       "  --streamon         turn the stream on [VIDIOC_STREAMON]\n"
+	       "  -m, --multiplanar-api\n"
+	       "                     force using the multiplanar API; it is applicable to video output\n"
+	       "                     and video capture devices\n"
 	       "  --log-status       log the board status in the kernel log [VIDIOC_LOG_STATUS]\n");
 	exit(0);
 }
@@ -541,8 +546,12 @@ static std::string buftype2s(int type)
 	switch (type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 		return "Video Capture";
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		return "Video Capture Multiplanar";
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 		return "Video Output";
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		return "Video Output Multiplanar";
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 		return "Video Overlay";
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
@@ -1064,6 +1073,19 @@ static void printfmt(const struct v4l2_format &vfmt)
 		if (vfmt.fmt.pix.priv)
 			printf("\tCustom Info   : %08x\n", vfmt.fmt.pix.priv);
 		break;
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		printf("\tWidth/Height      : %u/%u\n", vfmt.fmt.pix_mp.width, vfmt.fmt.pix_mp.height);
+		printf("\tPixel Format      : '%s'\n", fcc2s(vfmt.fmt.pix_mp.pixelformat).c_str());
+		printf("\tField             : %s\n", field2s(vfmt.fmt.pix_mp.field).c_str());
+		printf("\tNumber of planes  : %u\n", vfmt.fmt.pix_mp.num_planes);
+		printf("\tColorspace        : %s\n", colorspace2s(vfmt.fmt.pix_mp.colorspace).c_str());
+		for (int i = 0; i < vfmt.fmt.pix_mp.num_planes; i++) {
+			printf("\tPlane %d           :\n", i);
+			printf("\t   Bytes per Line : %u\n", vfmt.fmt.pix_mp.plane_fmt[i].bytesperline);
+			printf("\t   Size Image     : %u\n", vfmt.fmt.pix_mp.plane_fmt[i].sizeimage);
+		}
+		break;
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 		printf("\tLeft/Top    : %d/%d\n",
@@ -1302,8 +1324,12 @@ static std::string cap2s(unsigned cap)

 	if (cap & V4L2_CAP_VIDEO_CAPTURE)
 		s += "\t\tVideo Capture\n";
+	if (cap & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
+		s += "\t\tVideo Capture Multiplanar\n";
 	if (cap & V4L2_CAP_VIDEO_OUTPUT)
 		s += "\t\tVideo Output\n";
+	if (cap & V4L2_CAP_VIDEO_OUTPUT_MPLANE)
+		s += "\t\tVideo Output Multiplanar\n";
 	if (cap & V4L2_CAP_VIDEO_OVERLAY)
 		s += "\t\tVideo Overlay\n";
 	if (cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
@@ -1845,12 +1871,13 @@ static __u32 parse_event(const char *e)
 	return event;
 }

-static __u32 find_pixel_format(int fd, unsigned index)
+static __u32 find_pixel_format(int fd, unsigned index, bool multiplanar)
 {
 	struct v4l2_fmtdesc fmt;

 	fmt.index = index;
-	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	fmt.type = multiplanar ?
+		V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	if (doioctl(fd, VIDIOC_ENUM_FMT, &fmt))
 		return 0;
 	return fmt.pixelformat;
@@ -2657,7 +2684,8 @@ int main(int argc, char **argv)
 		}
 	}

-	if (options[OptSetVideoFormat] || options[OptTryVideoFormat]) {
+	if (!options[OptUseMultiplanarApi] &&
+	    (options[OptSetVideoFormat] || options[OptTryVideoFormat])) {
 		struct v4l2_format in_vfmt;

 		in_vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -2670,7 +2698,36 @@ int main(int argc, char **argv)
 				in_vfmt.fmt.pix.pixelformat = vfmt.fmt.pix.pixelformat;
 				if (in_vfmt.fmt.pix.pixelformat < 256) {
 					in_vfmt.fmt.pix.pixelformat =
-						find_pixel_format(fd, in_vfmt.fmt.pix.pixelformat);
+						find_pixel_format(fd, in_vfmt.fmt.pix.pixelformat,
+								  false);
+				}
+			}
+			if (options[OptSetVideoFormat])
+				ret = doioctl(fd, VIDIOC_S_FMT, &in_vfmt);
+			else
+				ret = doioctl(fd, VIDIOC_TRY_FMT, &in_vfmt);
+			if (ret == 0 && verbose)
+				printfmt(in_vfmt);
+		}
+	}
+
+
+	if (options[OptUseMultiplanarApi] &&
+	    (options[OptSetVideoFormat] || options[OptTryVideoFormat])) {
+		struct v4l2_format in_vfmt;
+
+		in_vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+		if (doioctl(fd, VIDIOC_G_FMT, &in_vfmt) == 0) {
+			if (set_fmts & FmtWidth)
+				in_vfmt.fmt.pix_mp.width = vfmt.fmt.pix_mp.width;
+			if (set_fmts & FmtHeight)
+				in_vfmt.fmt.pix_mp.height = vfmt.fmt.pix_mp.height;
+			if (set_fmts & FmtPixelFormat) {
+				in_vfmt.fmt.pix_mp.pixelformat = vfmt.fmt.pix_mp.pixelformat;
+				if (in_vfmt.fmt.pix_mp.pixelformat < 256) {
+					in_vfmt.fmt.pix_mp.pixelformat =
+						find_pixel_format(fd, in_vfmt.fmt.pix_mp.pixelformat,
+								  true);
 				}
 			}
 			if (options[OptSetVideoFormat])
@@ -2884,13 +2941,19 @@ int main(int argc, char **argv)
 	/* Get options */

 	if (options[OptGetVideoFormat]) {
-		vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		if (options[OptUseMultiplanarApi] || options[OptAll])
+			vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+		else
+			vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		if (doioctl(fd, VIDIOC_G_FMT, &vfmt) == 0)
 			printfmt(vfmt);
 	}

 	if (options[OptGetVideoOutFormat]) {
-		vfmt_out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+		if (options[OptUseMultiplanarApi] || options[OptAll])
+			vfmt_out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+		else
+			vfmt_out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 		if (doioctl(fd, VIDIOC_G_FMT, &vfmt_out) == 0)
 			printfmt(vfmt_out);
 	}
@@ -3384,14 +3447,20 @@ int main(int argc, char **argv)

 	if (options[OptListFormats]) {
 		printf("ioctl: VIDIOC_ENUM_FMT\n");
-		print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-		print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		print_video_formats(fd, options[OptUseMultiplanarApi] ?
+			V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+		print_video_formats(fd, options[OptUseMultiplanarApi] ?
+			V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : V4L2_BUF_TYPE_VIDEO_OUTPUT);
+
 		print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_OVERLAY);
 	}

 	if (options[OptListFormatsExt]) {
 		printf("ioctl: VIDIOC_ENUM_FMT\n");
-		print_video_formats_ext(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		print_video_formats_ext(fd, options[OptUseMultiplanarApi] ?
+			V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
 		print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 		print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_OVERLAY);
 	}
@@ -3399,7 +3468,8 @@ int main(int argc, char **argv)
 	if (options[OptListFrameSizes]) {
 		printf("ioctl: VIDIOC_ENUM_FRAMESIZES\n");
 		if (frmsize.pixel_format < 256)
-			frmsize.pixel_format = find_pixel_format(fd, frmsize.pixel_format);
+			frmsize.pixel_format = find_pixel_format(fd, frmsize.pixel_format,
+								 options[OptUseMultiplanarApi]);
 		frmsize.index = 0;
 		while (test_ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0) {
 			print_frmsize(frmsize, "");
@@ -3410,7 +3480,8 @@ int main(int argc, char **argv)
 	if (options[OptListFrameIntervals]) {
 		printf("ioctl: VIDIOC_ENUM_FRAMEINTERVALS\n");
 		if (frmival.pixel_format < 256)
-			frmival.pixel_format = find_pixel_format(fd, frmival.pixel_format);
+			frmival.pixel_format = find_pixel_format(fd, frmival.pixel_format,
+								 options[OptUseMultiplanarApi]);
 		frmival.index = 0;
 		while (test_ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) >= 0) {
 			print_frmival(frmival, "");
