All of lore.kernel.org
 help / color / mirror / Atom feed
* [v4l-utils RFC 0/6] Mediatext test program for request API tests
@ 2018-04-05 10:58 Sakari Ailus
  2018-04-05 10:58 ` [v4l-utils RFC 1/6] Linux kernel header update Sakari Ailus
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Sakari Ailus @ 2018-04-05 10:58 UTC (permalink / raw)
  To: linux-media; +Cc: tfiga, hverkuil

Hi folks,

Here's a refreshed RFC set to add the mediatext test program. It is well
suited for testing requests, as it can work with multiple devices
simultaneously as well as is easy to control through a bash script.

Only buffers are supported with requests, controls are not yet; still
adding support for controls wouldn't be much of work. I'm posting this as
RFC as the API coverage isn't great. What works now (as in this test
program) is requests with vim2m --- two bash scripts are included in the
last patch for that. The request API set v9 requires some adjusting, I
haven't tested v10 yet.

I'd say this is much closer being a meaningful part of v4l-utils, assuming
more test programs are seen to fit there.

Comments would be welcome.

Sakari Ailus (6):
  Linux kernel header update
  Make v4l-utils compile with request-related changes
  libmediactl: Add open, close and fd to public API
  mediatext: Extract list of V4L2 pixel format strings and 4cc codes
  mediatext: Add library
  mediatext: Add vivid tests

 include/linux/cec-funcs.h                    |  300 ++--
 include/linux/cec.h                          |   40 +-
 include/linux/media.h                        |    8 +
 include/linux/v4l2-dv-timings.h              |  979 ++++++++++++
 include/linux/videodev2.h                    |   14 +-
 lib/libv4l2/libv4l2.c                        |    4 +-
 libmediatext.pc.in                           |   10 +
 utils/media-ctl/Makefile.am                  |   18 +-
 utils/media-ctl/libmediactl.c                |    9 +-
 utils/media-ctl/libmediatext.pc.in           |   10 +
 utils/media-ctl/mediactl.h                   |    4 +
 utils/media-ctl/mediatext-test.c             |  127 ++
 utils/media-ctl/mediatext.c                  | 2176 ++++++++++++++++++++++++++
 utils/media-ctl/mediatext.h                  |   33 +
 utils/media-ctl/tests/test-vivid-mc.bash     |   86 +
 utils/media-ctl/tests/test-vivid.bash        |   59 +
 utils/v4l2-compliance/v4l2-test-buffers.cpp  |    2 +-
 utils/v4l2-compliance/v4l2-test-controls.cpp |    4 -
 18 files changed, 3699 insertions(+), 184 deletions(-)
 create mode 100644 include/linux/v4l2-dv-timings.h
 create mode 100644 libmediatext.pc.in
 create mode 100644 utils/media-ctl/libmediatext.pc.in
 create mode 100644 utils/media-ctl/mediatext-test.c
 create mode 100644 utils/media-ctl/mediatext.c
 create mode 100644 utils/media-ctl/mediatext.h
 create mode 100755 utils/media-ctl/tests/test-vivid-mc.bash
 create mode 100755 utils/media-ctl/tests/test-vivid.bash

-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [v4l-utils RFC 1/6] Linux kernel header update
  2018-04-05 10:58 [v4l-utils RFC 0/6] Mediatext test program for request API tests Sakari Ailus
@ 2018-04-05 10:58 ` Sakari Ailus
  2018-04-05 10:58 ` [v4l-utils RFC 2/6] Make v4l-utils compile with request-related changes Sakari Ailus
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sakari Ailus @ 2018-04-05 10:58 UTC (permalink / raw)
  To: linux-media; +Cc: tfiga, hverkuil

This includes kernel headers up to Hans's request API v9 patchset.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 include/linux/cec-funcs.h       | 300 ++++++------
 include/linux/cec.h             |  40 +-
 include/linux/media.h           |   8 +
 include/linux/v4l2-dv-timings.h | 979 ++++++++++++++++++++++++++++++++++++++++
 include/linux/videodev2.h       |  14 +-
 5 files changed, 1169 insertions(+), 172 deletions(-)
 create mode 100644 include/linux/v4l2-dv-timings.h

diff --git a/include/linux/cec-funcs.h b/include/linux/cec-funcs.h
index 8997d50..6daa73d 100644
--- a/include/linux/cec-funcs.h
+++ b/include/linux/cec-funcs.h
@@ -11,7 +11,7 @@
 #include <linux/cec.h>
 
 /* One Touch Play Feature */
-static inline void cec_msg_active_source(struct cec_msg *msg, __u16 phys_addr)
+static __inline__ void cec_msg_active_source(struct cec_msg *msg, __u16 phys_addr)
 {
 	msg->len = 4;
 	msg->msg[0] |= 0xf; /* broadcast */
@@ -20,19 +20,19 @@ static inline void cec_msg_active_source(struct cec_msg *msg, __u16 phys_addr)
 	msg->msg[3] = phys_addr & 0xff;
 }
 
-static inline void cec_ops_active_source(const struct cec_msg *msg,
+static __inline__ void cec_ops_active_source(const struct cec_msg *msg,
 					 __u16 *phys_addr)
 {
 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
 }
 
-static inline void cec_msg_image_view_on(struct cec_msg *msg)
+static __inline__ void cec_msg_image_view_on(struct cec_msg *msg)
 {
 	msg->len = 2;
 	msg->msg[1] = CEC_MSG_IMAGE_VIEW_ON;
 }
 
-static inline void cec_msg_text_view_on(struct cec_msg *msg)
+static __inline__ void cec_msg_text_view_on(struct cec_msg *msg)
 {
 	msg->len = 2;
 	msg->msg[1] = CEC_MSG_TEXT_VIEW_ON;
@@ -40,7 +40,7 @@ static inline void cec_msg_text_view_on(struct cec_msg *msg)
 
 
 /* Routing Control Feature */
-static inline void cec_msg_inactive_source(struct cec_msg *msg,
+static __inline__ void cec_msg_inactive_source(struct cec_msg *msg,
 					   __u16 phys_addr)
 {
 	msg->len = 4;
@@ -49,13 +49,13 @@ static inline void cec_msg_inactive_source(struct cec_msg *msg,
 	msg->msg[3] = phys_addr & 0xff;
 }
 
-static inline void cec_ops_inactive_source(const struct cec_msg *msg,
+static __inline__ void cec_ops_inactive_source(const struct cec_msg *msg,
 					   __u16 *phys_addr)
 {
 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
 }
 
-static inline void cec_msg_request_active_source(struct cec_msg *msg,
+static __inline__ void cec_msg_request_active_source(struct cec_msg *msg,
 						 int reply)
 {
 	msg->len = 2;
@@ -64,7 +64,7 @@ static inline void cec_msg_request_active_source(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_ACTIVE_SOURCE : 0;
 }
 
-static inline void cec_msg_routing_information(struct cec_msg *msg,
+static __inline__ void cec_msg_routing_information(struct cec_msg *msg,
 					       __u16 phys_addr)
 {
 	msg->len = 4;
@@ -74,13 +74,13 @@ static inline void cec_msg_routing_information(struct cec_msg *msg,
 	msg->msg[3] = phys_addr & 0xff;
 }
 
-static inline void cec_ops_routing_information(const struct cec_msg *msg,
+static __inline__ void cec_ops_routing_information(const struct cec_msg *msg,
 					       __u16 *phys_addr)
 {
 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
 }
 
-static inline void cec_msg_routing_change(struct cec_msg *msg,
+static __inline__ void cec_msg_routing_change(struct cec_msg *msg,
 					  int reply,
 					  __u16 orig_phys_addr,
 					  __u16 new_phys_addr)
@@ -95,7 +95,7 @@ static inline void cec_msg_routing_change(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_ROUTING_INFORMATION : 0;
 }
 
-static inline void cec_ops_routing_change(const struct cec_msg *msg,
+static __inline__ void cec_ops_routing_change(const struct cec_msg *msg,
 					  __u16 *orig_phys_addr,
 					  __u16 *new_phys_addr)
 {
@@ -103,7 +103,7 @@ static inline void cec_ops_routing_change(const struct cec_msg *msg,
 	*new_phys_addr = (msg->msg[4] << 8) | msg->msg[5];
 }
 
-static inline void cec_msg_set_stream_path(struct cec_msg *msg, __u16 phys_addr)
+static __inline__ void cec_msg_set_stream_path(struct cec_msg *msg, __u16 phys_addr)
 {
 	msg->len = 4;
 	msg->msg[0] |= 0xf; /* broadcast */
@@ -112,7 +112,7 @@ static inline void cec_msg_set_stream_path(struct cec_msg *msg, __u16 phys_addr)
 	msg->msg[3] = phys_addr & 0xff;
 }
 
-static inline void cec_ops_set_stream_path(const struct cec_msg *msg,
+static __inline__ void cec_ops_set_stream_path(const struct cec_msg *msg,
 					   __u16 *phys_addr)
 {
 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
@@ -120,7 +120,7 @@ static inline void cec_ops_set_stream_path(const struct cec_msg *msg,
 
 
 /* Standby Feature */
-static inline void cec_msg_standby(struct cec_msg *msg)
+static __inline__ void cec_msg_standby(struct cec_msg *msg)
 {
 	msg->len = 2;
 	msg->msg[1] = CEC_MSG_STANDBY;
@@ -128,7 +128,7 @@ static inline void cec_msg_standby(struct cec_msg *msg)
 
 
 /* One Touch Record Feature */
-static inline void cec_msg_record_off(struct cec_msg *msg, int reply)
+static __inline__ void cec_msg_record_off(struct cec_msg *msg, int reply)
 {
 	msg->len = 2;
 	msg->msg[1] = CEC_MSG_RECORD_OFF;
@@ -187,7 +187,7 @@ struct cec_op_record_src {
 	};
 };
 
-static inline void cec_set_digital_service_id(__u8 *msg,
+static __inline__ void cec_set_digital_service_id(__u8 *msg,
 	      const struct cec_op_digital_service_id *digital)
 {
 	*msg++ = (digital->service_id_method << 7) | digital->dig_bcast_system;
@@ -224,7 +224,7 @@ static inline void cec_set_digital_service_id(__u8 *msg,
 	}
 }
 
-static inline void cec_get_digital_service_id(const __u8 *msg,
+static __inline__ void cec_get_digital_service_id(const __u8 *msg,
 	      struct cec_op_digital_service_id *digital)
 {
 	digital->service_id_method = msg[0] >> 7;
@@ -240,14 +240,14 @@ static inline void cec_get_digital_service_id(const __u8 *msg,
 	digital->dvb.orig_network_id = (msg[5] << 8) | msg[6];
 }
 
-static inline void cec_msg_record_on_own(struct cec_msg *msg)
+static __inline__ void cec_msg_record_on_own(struct cec_msg *msg)
 {
 	msg->len = 3;
 	msg->msg[1] = CEC_MSG_RECORD_ON;
 	msg->msg[2] = CEC_OP_RECORD_SRC_OWN;
 }
 
-static inline void cec_msg_record_on_digital(struct cec_msg *msg,
+static __inline__ void cec_msg_record_on_digital(struct cec_msg *msg,
 			     const struct cec_op_digital_service_id *digital)
 {
 	msg->len = 10;
@@ -256,7 +256,7 @@ static inline void cec_msg_record_on_digital(struct cec_msg *msg,
 	cec_set_digital_service_id(msg->msg + 3, digital);
 }
 
-static inline void cec_msg_record_on_analog(struct cec_msg *msg,
+static __inline__ void cec_msg_record_on_analog(struct cec_msg *msg,
 					    __u8 ana_bcast_type,
 					    __u16 ana_freq,
 					    __u8 bcast_system)
@@ -270,7 +270,7 @@ static inline void cec_msg_record_on_analog(struct cec_msg *msg,
 	msg->msg[6] = bcast_system;
 }
 
-static inline void cec_msg_record_on_plug(struct cec_msg *msg,
+static __inline__ void cec_msg_record_on_plug(struct cec_msg *msg,
 					  __u8 plug)
 {
 	msg->len = 4;
@@ -279,7 +279,7 @@ static inline void cec_msg_record_on_plug(struct cec_msg *msg,
 	msg->msg[3] = plug;
 }
 
-static inline void cec_msg_record_on_phys_addr(struct cec_msg *msg,
+static __inline__ void cec_msg_record_on_phys_addr(struct cec_msg *msg,
 					       __u16 phys_addr)
 {
 	msg->len = 5;
@@ -289,7 +289,7 @@ static inline void cec_msg_record_on_phys_addr(struct cec_msg *msg,
 	msg->msg[4] = phys_addr & 0xff;
 }
 
-static inline void cec_msg_record_on(struct cec_msg *msg,
+static __inline__ void cec_msg_record_on(struct cec_msg *msg,
 				     int reply,
 				     const struct cec_op_record_src *rec_src)
 {
@@ -317,7 +317,7 @@ static inline void cec_msg_record_on(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_RECORD_STATUS : 0;
 }
 
-static inline void cec_ops_record_on(const struct cec_msg *msg,
+static __inline__ void cec_ops_record_on(const struct cec_msg *msg,
 				     struct cec_op_record_src *rec_src)
 {
 	rec_src->type = msg->msg[2];
@@ -343,20 +343,20 @@ static inline void cec_ops_record_on(const struct cec_msg *msg,
 	}
 }
 
-static inline void cec_msg_record_status(struct cec_msg *msg, __u8 rec_status)
+static __inline__ void cec_msg_record_status(struct cec_msg *msg, __u8 rec_status)
 {
 	msg->len = 3;
 	msg->msg[1] = CEC_MSG_RECORD_STATUS;
 	msg->msg[2] = rec_status;
 }
 
-static inline void cec_ops_record_status(const struct cec_msg *msg,
+static __inline__ void cec_ops_record_status(const struct cec_msg *msg,
 					 __u8 *rec_status)
 {
 	*rec_status = msg->msg[2];
 }
 
-static inline void cec_msg_record_tv_screen(struct cec_msg *msg,
+static __inline__ void cec_msg_record_tv_screen(struct cec_msg *msg,
 					    int reply)
 {
 	msg->len = 2;
@@ -366,7 +366,7 @@ static inline void cec_msg_record_tv_screen(struct cec_msg *msg,
 
 
 /* Timer Programming Feature */
-static inline void cec_msg_timer_status(struct cec_msg *msg,
+static __inline__ void cec_msg_timer_status(struct cec_msg *msg,
 					__u8 timer_overlap_warning,
 					__u8 media_info,
 					__u8 prog_info,
@@ -389,7 +389,7 @@ static inline void cec_msg_timer_status(struct cec_msg *msg,
 	}
 }
 
-static inline void cec_ops_timer_status(const struct cec_msg *msg,
+static __inline__ void cec_ops_timer_status(const struct cec_msg *msg,
 					__u8 *timer_overlap_warning,
 					__u8 *media_info,
 					__u8 *prog_info,
@@ -416,7 +416,7 @@ static inline void cec_ops_timer_status(const struct cec_msg *msg,
 	}
 }
 
-static inline void cec_msg_timer_cleared_status(struct cec_msg *msg,
+static __inline__ void cec_msg_timer_cleared_status(struct cec_msg *msg,
 						__u8 timer_cleared_status)
 {
 	msg->len = 3;
@@ -424,13 +424,13 @@ static inline void cec_msg_timer_cleared_status(struct cec_msg *msg,
 	msg->msg[2] = timer_cleared_status;
 }
 
-static inline void cec_ops_timer_cleared_status(const struct cec_msg *msg,
+static __inline__ void cec_ops_timer_cleared_status(const struct cec_msg *msg,
 						__u8 *timer_cleared_status)
 {
 	*timer_cleared_status = msg->msg[2];
 }
 
-static inline void cec_msg_clear_analogue_timer(struct cec_msg *msg,
+static __inline__ void cec_msg_clear_analogue_timer(struct cec_msg *msg,
 						int reply,
 						__u8 day,
 						__u8 month,
@@ -460,7 +460,7 @@ static inline void cec_msg_clear_analogue_timer(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
 }
 
-static inline void cec_ops_clear_analogue_timer(const struct cec_msg *msg,
+static __inline__ void cec_ops_clear_analogue_timer(const struct cec_msg *msg,
 						__u8 *day,
 						__u8 *month,
 						__u8 *start_hr,
@@ -485,7 +485,7 @@ static inline void cec_ops_clear_analogue_timer(const struct cec_msg *msg,
 	*bcast_system = msg->msg[12];
 }
 
-static inline void cec_msg_clear_digital_timer(struct cec_msg *msg,
+static __inline__ void cec_msg_clear_digital_timer(struct cec_msg *msg,
 				int reply,
 				__u8 day,
 				__u8 month,
@@ -510,7 +510,7 @@ static inline void cec_msg_clear_digital_timer(struct cec_msg *msg,
 	cec_set_digital_service_id(msg->msg + 9, digital);
 }
 
-static inline void cec_ops_clear_digital_timer(const struct cec_msg *msg,
+static __inline__ void cec_ops_clear_digital_timer(const struct cec_msg *msg,
 				__u8 *day,
 				__u8 *month,
 				__u8 *start_hr,
@@ -531,7 +531,7 @@ static inline void cec_ops_clear_digital_timer(const struct cec_msg *msg,
 	cec_get_digital_service_id(msg->msg + 9, digital);
 }
 
-static inline void cec_msg_clear_ext_timer(struct cec_msg *msg,
+static __inline__ void cec_msg_clear_ext_timer(struct cec_msg *msg,
 					   int reply,
 					   __u8 day,
 					   __u8 month,
@@ -561,7 +561,7 @@ static inline void cec_msg_clear_ext_timer(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
 }
 
-static inline void cec_ops_clear_ext_timer(const struct cec_msg *msg,
+static __inline__ void cec_ops_clear_ext_timer(const struct cec_msg *msg,
 					   __u8 *day,
 					   __u8 *month,
 					   __u8 *start_hr,
@@ -586,7 +586,7 @@ static inline void cec_ops_clear_ext_timer(const struct cec_msg *msg,
 	*phys_addr = (msg->msg[11] << 8) | msg->msg[12];
 }
 
-static inline void cec_msg_set_analogue_timer(struct cec_msg *msg,
+static __inline__ void cec_msg_set_analogue_timer(struct cec_msg *msg,
 					      int reply,
 					      __u8 day,
 					      __u8 month,
@@ -616,7 +616,7 @@ static inline void cec_msg_set_analogue_timer(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
 }
 
-static inline void cec_ops_set_analogue_timer(const struct cec_msg *msg,
+static __inline__ void cec_ops_set_analogue_timer(const struct cec_msg *msg,
 					      __u8 *day,
 					      __u8 *month,
 					      __u8 *start_hr,
@@ -641,7 +641,7 @@ static inline void cec_ops_set_analogue_timer(const struct cec_msg *msg,
 	*bcast_system = msg->msg[12];
 }
 
-static inline void cec_msg_set_digital_timer(struct cec_msg *msg,
+static __inline__ void cec_msg_set_digital_timer(struct cec_msg *msg,
 			int reply,
 			__u8 day,
 			__u8 month,
@@ -666,7 +666,7 @@ static inline void cec_msg_set_digital_timer(struct cec_msg *msg,
 	cec_set_digital_service_id(msg->msg + 9, digital);
 }
 
-static inline void cec_ops_set_digital_timer(const struct cec_msg *msg,
+static __inline__ void cec_ops_set_digital_timer(const struct cec_msg *msg,
 			__u8 *day,
 			__u8 *month,
 			__u8 *start_hr,
@@ -687,7 +687,7 @@ static inline void cec_ops_set_digital_timer(const struct cec_msg *msg,
 	cec_get_digital_service_id(msg->msg + 9, digital);
 }
 
-static inline void cec_msg_set_ext_timer(struct cec_msg *msg,
+static __inline__ void cec_msg_set_ext_timer(struct cec_msg *msg,
 					 int reply,
 					 __u8 day,
 					 __u8 month,
@@ -717,7 +717,7 @@ static inline void cec_msg_set_ext_timer(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
 }
 
-static inline void cec_ops_set_ext_timer(const struct cec_msg *msg,
+static __inline__ void cec_ops_set_ext_timer(const struct cec_msg *msg,
 					 __u8 *day,
 					 __u8 *month,
 					 __u8 *start_hr,
@@ -742,7 +742,7 @@ static inline void cec_ops_set_ext_timer(const struct cec_msg *msg,
 	*phys_addr = (msg->msg[11] << 8) | msg->msg[12];
 }
 
-static inline void cec_msg_set_timer_program_title(struct cec_msg *msg,
+static __inline__ void cec_msg_set_timer_program_title(struct cec_msg *msg,
 						   const char *prog_title)
 {
 	unsigned int len = strlen(prog_title);
@@ -754,7 +754,7 @@ static inline void cec_msg_set_timer_program_title(struct cec_msg *msg,
 	memcpy(msg->msg + 2, prog_title, len);
 }
 
-static inline void cec_ops_set_timer_program_title(const struct cec_msg *msg,
+static __inline__ void cec_ops_set_timer_program_title(const struct cec_msg *msg,
 						   char *prog_title)
 {
 	unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
@@ -766,20 +766,20 @@ static inline void cec_ops_set_timer_program_title(const struct cec_msg *msg,
 }
 
 /* System Information Feature */
-static inline void cec_msg_cec_version(struct cec_msg *msg, __u8 cec_version)
+static __inline__ void cec_msg_cec_version(struct cec_msg *msg, __u8 cec_version)
 {
 	msg->len = 3;
 	msg->msg[1] = CEC_MSG_CEC_VERSION;
 	msg->msg[2] = cec_version;
 }
 
-static inline void cec_ops_cec_version(const struct cec_msg *msg,
+static __inline__ void cec_ops_cec_version(const struct cec_msg *msg,
 				       __u8 *cec_version)
 {
 	*cec_version = msg->msg[2];
 }
 
-static inline void cec_msg_get_cec_version(struct cec_msg *msg,
+static __inline__ void cec_msg_get_cec_version(struct cec_msg *msg,
 					   int reply)
 {
 	msg->len = 2;
@@ -787,7 +787,7 @@ static inline void cec_msg_get_cec_version(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_CEC_VERSION : 0;
 }
 
-static inline void cec_msg_report_physical_addr(struct cec_msg *msg,
+static __inline__ void cec_msg_report_physical_addr(struct cec_msg *msg,
 					__u16 phys_addr, __u8 prim_devtype)
 {
 	msg->len = 5;
@@ -798,14 +798,14 @@ static inline void cec_msg_report_physical_addr(struct cec_msg *msg,
 	msg->msg[4] = prim_devtype;
 }
 
-static inline void cec_ops_report_physical_addr(const struct cec_msg *msg,
+static __inline__ void cec_ops_report_physical_addr(const struct cec_msg *msg,
 					__u16 *phys_addr, __u8 *prim_devtype)
 {
 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
 	*prim_devtype = msg->msg[4];
 }
 
-static inline void cec_msg_give_physical_addr(struct cec_msg *msg,
+static __inline__ void cec_msg_give_physical_addr(struct cec_msg *msg,
 					      int reply)
 {
 	msg->len = 2;
@@ -813,7 +813,7 @@ static inline void cec_msg_give_physical_addr(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_REPORT_PHYSICAL_ADDR : 0;
 }
 
-static inline void cec_msg_set_menu_language(struct cec_msg *msg,
+static __inline__ void cec_msg_set_menu_language(struct cec_msg *msg,
 					     const char *language)
 {
 	msg->len = 5;
@@ -822,14 +822,14 @@ static inline void cec_msg_set_menu_language(struct cec_msg *msg,
 	memcpy(msg->msg + 2, language, 3);
 }
 
-static inline void cec_ops_set_menu_language(const struct cec_msg *msg,
+static __inline__ void cec_ops_set_menu_language(const struct cec_msg *msg,
 					     char *language)
 {
 	memcpy(language, msg->msg + 2, 3);
 	language[3] = '\0';
 }
 
-static inline void cec_msg_get_menu_language(struct cec_msg *msg,
+static __inline__ void cec_msg_get_menu_language(struct cec_msg *msg,
 					     int reply)
 {
 	msg->len = 2;
@@ -845,7 +845,7 @@ static inline void cec_msg_get_menu_language(struct cec_msg *msg,
  * in the future, then this function needs to be adapted or a new function
  * should be added.
  */
-static inline void cec_msg_report_features(struct cec_msg *msg,
+static __inline__ void cec_msg_report_features(struct cec_msg *msg,
 				__u8 cec_version, __u8 all_device_types,
 				__u8 rc_profile, __u8 dev_features)
 {
@@ -858,7 +858,7 @@ static inline void cec_msg_report_features(struct cec_msg *msg,
 	msg->msg[5] = dev_features;
 }
 
-static inline void cec_ops_report_features(const struct cec_msg *msg,
+static __inline__ void cec_ops_report_features(const struct cec_msg *msg,
 			__u8 *cec_version, __u8 *all_device_types,
 			const __u8 **rc_profile, const __u8 **dev_features)
 {
@@ -879,7 +879,7 @@ static inline void cec_ops_report_features(const struct cec_msg *msg,
 		*rc_profile = *dev_features = NULL;
 }
 
-static inline void cec_msg_give_features(struct cec_msg *msg,
+static __inline__ void cec_msg_give_features(struct cec_msg *msg,
 					 int reply)
 {
 	msg->len = 2;
@@ -888,7 +888,7 @@ static inline void cec_msg_give_features(struct cec_msg *msg,
 }
 
 /* Deck Control Feature */
-static inline void cec_msg_deck_control(struct cec_msg *msg,
+static __inline__ void cec_msg_deck_control(struct cec_msg *msg,
 					__u8 deck_control_mode)
 {
 	msg->len = 3;
@@ -896,13 +896,13 @@ static inline void cec_msg_deck_control(struct cec_msg *msg,
 	msg->msg[2] = deck_control_mode;
 }
 
-static inline void cec_ops_deck_control(const struct cec_msg *msg,
+static __inline__ void cec_ops_deck_control(const struct cec_msg *msg,
 					__u8 *deck_control_mode)
 {
 	*deck_control_mode = msg->msg[2];
 }
 
-static inline void cec_msg_deck_status(struct cec_msg *msg,
+static __inline__ void cec_msg_deck_status(struct cec_msg *msg,
 				       __u8 deck_info)
 {
 	msg->len = 3;
@@ -910,13 +910,13 @@ static inline void cec_msg_deck_status(struct cec_msg *msg,
 	msg->msg[2] = deck_info;
 }
 
-static inline void cec_ops_deck_status(const struct cec_msg *msg,
+static __inline__ void cec_ops_deck_status(const struct cec_msg *msg,
 				       __u8 *deck_info)
 {
 	*deck_info = msg->msg[2];
 }
 
-static inline void cec_msg_give_deck_status(struct cec_msg *msg,
+static __inline__ void cec_msg_give_deck_status(struct cec_msg *msg,
 					    int reply,
 					    __u8 status_req)
 {
@@ -926,13 +926,13 @@ static inline void cec_msg_give_deck_status(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_DECK_STATUS : 0;
 }
 
-static inline void cec_ops_give_deck_status(const struct cec_msg *msg,
+static __inline__ void cec_ops_give_deck_status(const struct cec_msg *msg,
 					    __u8 *status_req)
 {
 	*status_req = msg->msg[2];
 }
 
-static inline void cec_msg_play(struct cec_msg *msg,
+static __inline__ void cec_msg_play(struct cec_msg *msg,
 				__u8 play_mode)
 {
 	msg->len = 3;
@@ -940,7 +940,7 @@ static inline void cec_msg_play(struct cec_msg *msg,
 	msg->msg[2] = play_mode;
 }
 
-static inline void cec_ops_play(const struct cec_msg *msg,
+static __inline__ void cec_ops_play(const struct cec_msg *msg,
 				__u8 *play_mode)
 {
 	*play_mode = msg->msg[2];
@@ -962,7 +962,7 @@ struct cec_op_tuner_device_info {
 	};
 };
 
-static inline void cec_msg_tuner_device_status_analog(struct cec_msg *msg,
+static __inline__ void cec_msg_tuner_device_status_analog(struct cec_msg *msg,
 						      __u8 rec_flag,
 						      __u8 tuner_display_info,
 						      __u8 ana_bcast_type,
@@ -978,7 +978,7 @@ static inline void cec_msg_tuner_device_status_analog(struct cec_msg *msg,
 	msg->msg[6] = bcast_system;
 }
 
-static inline void cec_msg_tuner_device_status_digital(struct cec_msg *msg,
+static __inline__ void cec_msg_tuner_device_status_digital(struct cec_msg *msg,
 		   __u8 rec_flag, __u8 tuner_display_info,
 		   const struct cec_op_digital_service_id *digital)
 {
@@ -988,7 +988,7 @@ static inline void cec_msg_tuner_device_status_digital(struct cec_msg *msg,
 	cec_set_digital_service_id(msg->msg + 3, digital);
 }
 
-static inline void cec_msg_tuner_device_status(struct cec_msg *msg,
+static __inline__ void cec_msg_tuner_device_status(struct cec_msg *msg,
 			const struct cec_op_tuner_device_info *tuner_dev_info)
 {
 	if (tuner_dev_info->is_analog)
@@ -1005,7 +1005,7 @@ static inline void cec_msg_tuner_device_status(struct cec_msg *msg,
 			&tuner_dev_info->digital);
 }
 
-static inline void cec_ops_tuner_device_status(const struct cec_msg *msg,
+static __inline__ void cec_ops_tuner_device_status(const struct cec_msg *msg,
 				struct cec_op_tuner_device_info *tuner_dev_info)
 {
 	tuner_dev_info->is_analog = msg->len < 10;
@@ -1020,7 +1020,7 @@ static inline void cec_ops_tuner_device_status(const struct cec_msg *msg,
 	cec_get_digital_service_id(msg->msg + 3, &tuner_dev_info->digital);
 }
 
-static inline void cec_msg_give_tuner_device_status(struct cec_msg *msg,
+static __inline__ void cec_msg_give_tuner_device_status(struct cec_msg *msg,
 						    int reply,
 						    __u8 status_req)
 {
@@ -1030,13 +1030,13 @@ static inline void cec_msg_give_tuner_device_status(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_TUNER_DEVICE_STATUS : 0;
 }
 
-static inline void cec_ops_give_tuner_device_status(const struct cec_msg *msg,
+static __inline__ void cec_ops_give_tuner_device_status(const struct cec_msg *msg,
 						    __u8 *status_req)
 {
 	*status_req = msg->msg[2];
 }
 
-static inline void cec_msg_select_analogue_service(struct cec_msg *msg,
+static __inline__ void cec_msg_select_analogue_service(struct cec_msg *msg,
 						   __u8 ana_bcast_type,
 						   __u16 ana_freq,
 						   __u8 bcast_system)
@@ -1049,7 +1049,7 @@ static inline void cec_msg_select_analogue_service(struct cec_msg *msg,
 	msg->msg[5] = bcast_system;
 }
 
-static inline void cec_ops_select_analogue_service(const struct cec_msg *msg,
+static __inline__ void cec_ops_select_analogue_service(const struct cec_msg *msg,
 						   __u8 *ana_bcast_type,
 						   __u16 *ana_freq,
 						   __u8 *bcast_system)
@@ -1059,7 +1059,7 @@ static inline void cec_ops_select_analogue_service(const struct cec_msg *msg,
 	*bcast_system = msg->msg[5];
 }
 
-static inline void cec_msg_select_digital_service(struct cec_msg *msg,
+static __inline__ void cec_msg_select_digital_service(struct cec_msg *msg,
 				const struct cec_op_digital_service_id *digital)
 {
 	msg->len = 9;
@@ -1067,19 +1067,19 @@ static inline void cec_msg_select_digital_service(struct cec_msg *msg,
 	cec_set_digital_service_id(msg->msg + 2, digital);
 }
 
-static inline void cec_ops_select_digital_service(const struct cec_msg *msg,
+static __inline__ void cec_ops_select_digital_service(const struct cec_msg *msg,
 				struct cec_op_digital_service_id *digital)
 {
 	cec_get_digital_service_id(msg->msg + 2, digital);
 }
 
-static inline void cec_msg_tuner_step_decrement(struct cec_msg *msg)
+static __inline__ void cec_msg_tuner_step_decrement(struct cec_msg *msg)
 {
 	msg->len = 2;
 	msg->msg[1] = CEC_MSG_TUNER_STEP_DECREMENT;
 }
 
-static inline void cec_msg_tuner_step_increment(struct cec_msg *msg)
+static __inline__ void cec_msg_tuner_step_increment(struct cec_msg *msg)
 {
 	msg->len = 2;
 	msg->msg[1] = CEC_MSG_TUNER_STEP_INCREMENT;
@@ -1087,7 +1087,7 @@ static inline void cec_msg_tuner_step_increment(struct cec_msg *msg)
 
 
 /* Vendor Specific Commands Feature */
-static inline void cec_msg_device_vendor_id(struct cec_msg *msg, __u32 vendor_id)
+static __inline__ void cec_msg_device_vendor_id(struct cec_msg *msg, __u32 vendor_id)
 {
 	msg->len = 5;
 	msg->msg[0] |= 0xf; /* broadcast */
@@ -1097,13 +1097,13 @@ static inline void cec_msg_device_vendor_id(struct cec_msg *msg, __u32 vendor_id
 	msg->msg[4] = vendor_id & 0xff;
 }
 
-static inline void cec_ops_device_vendor_id(const struct cec_msg *msg,
+static __inline__ void cec_ops_device_vendor_id(const struct cec_msg *msg,
 					    __u32 *vendor_id)
 {
 	*vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
 }
 
-static inline void cec_msg_give_device_vendor_id(struct cec_msg *msg,
+static __inline__ void cec_msg_give_device_vendor_id(struct cec_msg *msg,
 						 int reply)
 {
 	msg->len = 2;
@@ -1111,7 +1111,7 @@ static inline void cec_msg_give_device_vendor_id(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_DEVICE_VENDOR_ID : 0;
 }
 
-static inline void cec_msg_vendor_command(struct cec_msg *msg,
+static __inline__ void cec_msg_vendor_command(struct cec_msg *msg,
 					  __u8 size, const __u8 *vendor_cmd)
 {
 	if (size > 14)
@@ -1121,7 +1121,7 @@ static inline void cec_msg_vendor_command(struct cec_msg *msg,
 	memcpy(msg->msg + 2, vendor_cmd, size);
 }
 
-static inline void cec_ops_vendor_command(const struct cec_msg *msg,
+static __inline__ void cec_ops_vendor_command(const struct cec_msg *msg,
 					  __u8 *size,
 					  const __u8 **vendor_cmd)
 {
@@ -1132,7 +1132,7 @@ static inline void cec_ops_vendor_command(const struct cec_msg *msg,
 	*vendor_cmd = msg->msg + 2;
 }
 
-static inline void cec_msg_vendor_command_with_id(struct cec_msg *msg,
+static __inline__ void cec_msg_vendor_command_with_id(struct cec_msg *msg,
 						  __u32 vendor_id, __u8 size,
 						  const __u8 *vendor_cmd)
 {
@@ -1146,7 +1146,7 @@ static inline void cec_msg_vendor_command_with_id(struct cec_msg *msg,
 	memcpy(msg->msg + 5, vendor_cmd, size);
 }
 
-static inline void cec_ops_vendor_command_with_id(const struct cec_msg *msg,
+static __inline__ void cec_ops_vendor_command_with_id(const struct cec_msg *msg,
 						  __u32 *vendor_id,  __u8 *size,
 						  const __u8 **vendor_cmd)
 {
@@ -1158,7 +1158,7 @@ static inline void cec_ops_vendor_command_with_id(const struct cec_msg *msg,
 	*vendor_cmd = msg->msg + 5;
 }
 
-static inline void cec_msg_vendor_remote_button_down(struct cec_msg *msg,
+static __inline__ void cec_msg_vendor_remote_button_down(struct cec_msg *msg,
 						     __u8 size,
 						     const __u8 *rc_code)
 {
@@ -1169,7 +1169,7 @@ static inline void cec_msg_vendor_remote_button_down(struct cec_msg *msg,
 	memcpy(msg->msg + 2, rc_code, size);
 }
 
-static inline void cec_ops_vendor_remote_button_down(const struct cec_msg *msg,
+static __inline__ void cec_ops_vendor_remote_button_down(const struct cec_msg *msg,
 						     __u8 *size,
 						     const __u8 **rc_code)
 {
@@ -1180,7 +1180,7 @@ static inline void cec_ops_vendor_remote_button_down(const struct cec_msg *msg,
 	*rc_code = msg->msg + 2;
 }
 
-static inline void cec_msg_vendor_remote_button_up(struct cec_msg *msg)
+static __inline__ void cec_msg_vendor_remote_button_up(struct cec_msg *msg)
 {
 	msg->len = 2;
 	msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_UP;
@@ -1188,7 +1188,7 @@ static inline void cec_msg_vendor_remote_button_up(struct cec_msg *msg)
 
 
 /* OSD Display Feature */
-static inline void cec_msg_set_osd_string(struct cec_msg *msg,
+static __inline__ void cec_msg_set_osd_string(struct cec_msg *msg,
 					  __u8 disp_ctl,
 					  const char *osd)
 {
@@ -1202,7 +1202,7 @@ static inline void cec_msg_set_osd_string(struct cec_msg *msg,
 	memcpy(msg->msg + 3, osd, len);
 }
 
-static inline void cec_ops_set_osd_string(const struct cec_msg *msg,
+static __inline__ void cec_ops_set_osd_string(const struct cec_msg *msg,
 					  __u8 *disp_ctl,
 					  char *osd)
 {
@@ -1217,7 +1217,7 @@ static inline void cec_ops_set_osd_string(const struct cec_msg *msg,
 
 
 /* Device OSD Transfer Feature */
-static inline void cec_msg_set_osd_name(struct cec_msg *msg, const char *name)
+static __inline__ void cec_msg_set_osd_name(struct cec_msg *msg, const char *name)
 {
 	unsigned int len = strlen(name);
 
@@ -1228,7 +1228,7 @@ static inline void cec_msg_set_osd_name(struct cec_msg *msg, const char *name)
 	memcpy(msg->msg + 2, name, len);
 }
 
-static inline void cec_ops_set_osd_name(const struct cec_msg *msg,
+static __inline__ void cec_ops_set_osd_name(const struct cec_msg *msg,
 					char *name)
 {
 	unsigned int len = msg->len > 2 ? msg->len - 2 : 0;
@@ -1239,7 +1239,7 @@ static inline void cec_ops_set_osd_name(const struct cec_msg *msg,
 	name[len] = '\0';
 }
 
-static inline void cec_msg_give_osd_name(struct cec_msg *msg,
+static __inline__ void cec_msg_give_osd_name(struct cec_msg *msg,
 					 int reply)
 {
 	msg->len = 2;
@@ -1249,7 +1249,7 @@ static inline void cec_msg_give_osd_name(struct cec_msg *msg,
 
 
 /* Device Menu Control Feature */
-static inline void cec_msg_menu_status(struct cec_msg *msg,
+static __inline__ void cec_msg_menu_status(struct cec_msg *msg,
 				       __u8 menu_state)
 {
 	msg->len = 3;
@@ -1257,13 +1257,13 @@ static inline void cec_msg_menu_status(struct cec_msg *msg,
 	msg->msg[2] = menu_state;
 }
 
-static inline void cec_ops_menu_status(const struct cec_msg *msg,
+static __inline__ void cec_ops_menu_status(const struct cec_msg *msg,
 				       __u8 *menu_state)
 {
 	*menu_state = msg->msg[2];
 }
 
-static inline void cec_msg_menu_request(struct cec_msg *msg,
+static __inline__ void cec_msg_menu_request(struct cec_msg *msg,
 					int reply,
 					__u8 menu_req)
 {
@@ -1273,7 +1273,7 @@ static inline void cec_msg_menu_request(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_MENU_STATUS : 0;
 }
 
-static inline void cec_ops_menu_request(const struct cec_msg *msg,
+static __inline__ void cec_ops_menu_request(const struct cec_msg *msg,
 					__u8 *menu_req)
 {
 	*menu_req = msg->msg[2];
@@ -1293,7 +1293,7 @@ struct cec_op_ui_command {
 	};
 };
 
-static inline void cec_msg_user_control_pressed(struct cec_msg *msg,
+static __inline__ void cec_msg_user_control_pressed(struct cec_msg *msg,
 					const struct cec_op_ui_command *ui_cmd)
 {
 	msg->len = 3;
@@ -1323,7 +1323,7 @@ static inline void cec_msg_user_control_pressed(struct cec_msg *msg,
 	}
 }
 
-static inline void cec_ops_user_control_pressed(const struct cec_msg *msg,
+static __inline__ void cec_ops_user_control_pressed(const struct cec_msg *msg,
 						struct cec_op_ui_command *ui_cmd)
 {
 	ui_cmd->ui_cmd = msg->msg[2];
@@ -1352,7 +1352,7 @@ static inline void cec_ops_user_control_pressed(const struct cec_msg *msg,
 	}
 }
 
-static inline void cec_msg_user_control_released(struct cec_msg *msg)
+static __inline__ void cec_msg_user_control_released(struct cec_msg *msg)
 {
 	msg->len = 2;
 	msg->msg[1] = CEC_MSG_USER_CONTROL_RELEASED;
@@ -1361,7 +1361,7 @@ static inline void cec_msg_user_control_released(struct cec_msg *msg)
 /* Remote Control Passthrough Feature */
 
 /* Power Status Feature */
-static inline void cec_msg_report_power_status(struct cec_msg *msg,
+static __inline__ void cec_msg_report_power_status(struct cec_msg *msg,
 					       __u8 pwr_state)
 {
 	msg->len = 3;
@@ -1369,13 +1369,13 @@ static inline void cec_msg_report_power_status(struct cec_msg *msg,
 	msg->msg[2] = pwr_state;
 }
 
-static inline void cec_ops_report_power_status(const struct cec_msg *msg,
+static __inline__ void cec_ops_report_power_status(const struct cec_msg *msg,
 					       __u8 *pwr_state)
 {
 	*pwr_state = msg->msg[2];
 }
 
-static inline void cec_msg_give_device_power_status(struct cec_msg *msg,
+static __inline__ void cec_msg_give_device_power_status(struct cec_msg *msg,
 						    int reply)
 {
 	msg->len = 2;
@@ -1384,7 +1384,7 @@ static inline void cec_msg_give_device_power_status(struct cec_msg *msg,
 }
 
 /* General Protocol Messages */
-static inline void cec_msg_feature_abort(struct cec_msg *msg,
+static __inline__ void cec_msg_feature_abort(struct cec_msg *msg,
 					 __u8 abort_msg, __u8 reason)
 {
 	msg->len = 4;
@@ -1393,7 +1393,7 @@ static inline void cec_msg_feature_abort(struct cec_msg *msg,
 	msg->msg[3] = reason;
 }
 
-static inline void cec_ops_feature_abort(const struct cec_msg *msg,
+static __inline__ void cec_ops_feature_abort(const struct cec_msg *msg,
 					 __u8 *abort_msg, __u8 *reason)
 {
 	*abort_msg = msg->msg[2];
@@ -1401,7 +1401,7 @@ static inline void cec_ops_feature_abort(const struct cec_msg *msg,
 }
 
 /* This changes the current message into a feature abort message */
-static inline void cec_msg_reply_feature_abort(struct cec_msg *msg, __u8 reason)
+static __inline__ void cec_msg_reply_feature_abort(struct cec_msg *msg, __u8 reason)
 {
 	cec_msg_set_reply_to(msg, msg);
 	msg->len = 4;
@@ -1410,7 +1410,7 @@ static inline void cec_msg_reply_feature_abort(struct cec_msg *msg, __u8 reason)
 	msg->msg[1] = CEC_MSG_FEATURE_ABORT;
 }
 
-static inline void cec_msg_abort(struct cec_msg *msg)
+static __inline__ void cec_msg_abort(struct cec_msg *msg)
 {
 	msg->len = 2;
 	msg->msg[1] = CEC_MSG_ABORT;
@@ -1418,7 +1418,7 @@ static inline void cec_msg_abort(struct cec_msg *msg)
 
 
 /* System Audio Control Feature */
-static inline void cec_msg_report_audio_status(struct cec_msg *msg,
+static __inline__ void cec_msg_report_audio_status(struct cec_msg *msg,
 					       __u8 aud_mute_status,
 					       __u8 aud_vol_status)
 {
@@ -1427,7 +1427,7 @@ static inline void cec_msg_report_audio_status(struct cec_msg *msg,
 	msg->msg[2] = (aud_mute_status << 7) | (aud_vol_status & 0x7f);
 }
 
-static inline void cec_ops_report_audio_status(const struct cec_msg *msg,
+static __inline__ void cec_ops_report_audio_status(const struct cec_msg *msg,
 					       __u8 *aud_mute_status,
 					       __u8 *aud_vol_status)
 {
@@ -1435,7 +1435,7 @@ static inline void cec_ops_report_audio_status(const struct cec_msg *msg,
 	*aud_vol_status = msg->msg[2] & 0x7f;
 }
 
-static inline void cec_msg_give_audio_status(struct cec_msg *msg,
+static __inline__ void cec_msg_give_audio_status(struct cec_msg *msg,
 					     int reply)
 {
 	msg->len = 2;
@@ -1443,7 +1443,7 @@ static inline void cec_msg_give_audio_status(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_REPORT_AUDIO_STATUS : 0;
 }
 
-static inline void cec_msg_set_system_audio_mode(struct cec_msg *msg,
+static __inline__ void cec_msg_set_system_audio_mode(struct cec_msg *msg,
 						 __u8 sys_aud_status)
 {
 	msg->len = 3;
@@ -1451,13 +1451,13 @@ static inline void cec_msg_set_system_audio_mode(struct cec_msg *msg,
 	msg->msg[2] = sys_aud_status;
 }
 
-static inline void cec_ops_set_system_audio_mode(const struct cec_msg *msg,
+static __inline__ void cec_ops_set_system_audio_mode(const struct cec_msg *msg,
 						 __u8 *sys_aud_status)
 {
 	*sys_aud_status = msg->msg[2];
 }
 
-static inline void cec_msg_system_audio_mode_request(struct cec_msg *msg,
+static __inline__ void cec_msg_system_audio_mode_request(struct cec_msg *msg,
 						     int reply,
 						     __u16 phys_addr)
 {
@@ -1469,7 +1469,7 @@ static inline void cec_msg_system_audio_mode_request(struct cec_msg *msg,
 
 }
 
-static inline void cec_ops_system_audio_mode_request(const struct cec_msg *msg,
+static __inline__ void cec_ops_system_audio_mode_request(const struct cec_msg *msg,
 						     __u16 *phys_addr)
 {
 	if (msg->len < 4)
@@ -1478,7 +1478,7 @@ static inline void cec_ops_system_audio_mode_request(const struct cec_msg *msg,
 		*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
 }
 
-static inline void cec_msg_system_audio_mode_status(struct cec_msg *msg,
+static __inline__ void cec_msg_system_audio_mode_status(struct cec_msg *msg,
 						    __u8 sys_aud_status)
 {
 	msg->len = 3;
@@ -1486,13 +1486,13 @@ static inline void cec_msg_system_audio_mode_status(struct cec_msg *msg,
 	msg->msg[2] = sys_aud_status;
 }
 
-static inline void cec_ops_system_audio_mode_status(const struct cec_msg *msg,
+static __inline__ void cec_ops_system_audio_mode_status(const struct cec_msg *msg,
 						    __u8 *sys_aud_status)
 {
 	*sys_aud_status = msg->msg[2];
 }
 
-static inline void cec_msg_give_system_audio_mode_status(struct cec_msg *msg,
+static __inline__ void cec_msg_give_system_audio_mode_status(struct cec_msg *msg,
 							 int reply)
 {
 	msg->len = 2;
@@ -1500,7 +1500,7 @@ static inline void cec_msg_give_system_audio_mode_status(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_SYSTEM_AUDIO_MODE_STATUS : 0;
 }
 
-static inline void cec_msg_report_short_audio_descriptor(struct cec_msg *msg,
+static __inline__ void cec_msg_report_short_audio_descriptor(struct cec_msg *msg,
 					__u8 num_descriptors,
 					const __u32 *descriptors)
 {
@@ -1517,7 +1517,7 @@ static inline void cec_msg_report_short_audio_descriptor(struct cec_msg *msg,
 	}
 }
 
-static inline void cec_ops_report_short_audio_descriptor(const struct cec_msg *msg,
+static __inline__ void cec_ops_report_short_audio_descriptor(const struct cec_msg *msg,
 							 __u8 *num_descriptors,
 							 __u32 *descriptors)
 {
@@ -1532,7 +1532,7 @@ static inline void cec_ops_report_short_audio_descriptor(const struct cec_msg *m
 			msg->msg[4 + i * 3];
 }
 
-static inline void cec_msg_request_short_audio_descriptor(struct cec_msg *msg,
+static __inline__ void cec_msg_request_short_audio_descriptor(struct cec_msg *msg,
 					int reply,
 					__u8 num_descriptors,
 					const __u8 *audio_format_id,
@@ -1550,7 +1550,7 @@ static inline void cec_msg_request_short_audio_descriptor(struct cec_msg *msg,
 				  (audio_format_code[i] & 0x3f);
 }
 
-static inline void cec_ops_request_short_audio_descriptor(const struct cec_msg *msg,
+static __inline__ void cec_ops_request_short_audio_descriptor(const struct cec_msg *msg,
 					__u8 *num_descriptors,
 					__u8 *audio_format_id,
 					__u8 *audio_format_code)
@@ -1568,7 +1568,7 @@ static inline void cec_ops_request_short_audio_descriptor(const struct cec_msg *
 
 
 /* Audio Rate Control Feature */
-static inline void cec_msg_set_audio_rate(struct cec_msg *msg,
+static __inline__ void cec_msg_set_audio_rate(struct cec_msg *msg,
 					  __u8 audio_rate)
 {
 	msg->len = 3;
@@ -1576,7 +1576,7 @@ static inline void cec_msg_set_audio_rate(struct cec_msg *msg,
 	msg->msg[2] = audio_rate;
 }
 
-static inline void cec_ops_set_audio_rate(const struct cec_msg *msg,
+static __inline__ void cec_ops_set_audio_rate(const struct cec_msg *msg,
 					  __u8 *audio_rate)
 {
 	*audio_rate = msg->msg[2];
@@ -1584,13 +1584,13 @@ static inline void cec_ops_set_audio_rate(const struct cec_msg *msg,
 
 
 /* Audio Return Channel Control Feature */
-static inline void cec_msg_report_arc_initiated(struct cec_msg *msg)
+static __inline__ void cec_msg_report_arc_initiated(struct cec_msg *msg)
 {
 	msg->len = 2;
 	msg->msg[1] = CEC_MSG_REPORT_ARC_INITIATED;
 }
 
-static inline void cec_msg_initiate_arc(struct cec_msg *msg,
+static __inline__ void cec_msg_initiate_arc(struct cec_msg *msg,
 					int reply)
 {
 	msg->len = 2;
@@ -1598,7 +1598,7 @@ static inline void cec_msg_initiate_arc(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_REPORT_ARC_INITIATED : 0;
 }
 
-static inline void cec_msg_request_arc_initiation(struct cec_msg *msg,
+static __inline__ void cec_msg_request_arc_initiation(struct cec_msg *msg,
 						  int reply)
 {
 	msg->len = 2;
@@ -1606,13 +1606,13 @@ static inline void cec_msg_request_arc_initiation(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_INITIATE_ARC : 0;
 }
 
-static inline void cec_msg_report_arc_terminated(struct cec_msg *msg)
+static __inline__ void cec_msg_report_arc_terminated(struct cec_msg *msg)
 {
 	msg->len = 2;
 	msg->msg[1] = CEC_MSG_REPORT_ARC_TERMINATED;
 }
 
-static inline void cec_msg_terminate_arc(struct cec_msg *msg,
+static __inline__ void cec_msg_terminate_arc(struct cec_msg *msg,
 					 int reply)
 {
 	msg->len = 2;
@@ -1620,7 +1620,7 @@ static inline void cec_msg_terminate_arc(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_REPORT_ARC_TERMINATED : 0;
 }
 
-static inline void cec_msg_request_arc_termination(struct cec_msg *msg,
+static __inline__ void cec_msg_request_arc_termination(struct cec_msg *msg,
 						   int reply)
 {
 	msg->len = 2;
@@ -1631,7 +1631,7 @@ static inline void cec_msg_request_arc_termination(struct cec_msg *msg,
 
 /* Dynamic Audio Lipsync Feature */
 /* Only for CEC 2.0 and up */
-static inline void cec_msg_report_current_latency(struct cec_msg *msg,
+static __inline__ void cec_msg_report_current_latency(struct cec_msg *msg,
 						  __u16 phys_addr,
 						  __u8 video_latency,
 						  __u8 low_latency_mode,
@@ -1649,7 +1649,7 @@ static inline void cec_msg_report_current_latency(struct cec_msg *msg,
 		msg->msg[msg->len++] = audio_out_delay;
 }
 
-static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
+static __inline__ void cec_ops_report_current_latency(const struct cec_msg *msg,
 						  __u16 *phys_addr,
 						  __u8 *video_latency,
 						  __u8 *low_latency_mode,
@@ -1666,7 +1666,7 @@ static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
 		*audio_out_delay = 0;
 }
 
-static inline void cec_msg_request_current_latency(struct cec_msg *msg,
+static __inline__ void cec_msg_request_current_latency(struct cec_msg *msg,
 						   int reply,
 						   __u16 phys_addr)
 {
@@ -1678,7 +1678,7 @@ static inline void cec_msg_request_current_latency(struct cec_msg *msg,
 	msg->reply = reply ? CEC_MSG_REPORT_CURRENT_LATENCY : 0;
 }
 
-static inline void cec_ops_request_current_latency(const struct cec_msg *msg,
+static __inline__ void cec_ops_request_current_latency(const struct cec_msg *msg,
 						   __u16 *phys_addr)
 {
 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
@@ -1686,7 +1686,7 @@ static inline void cec_ops_request_current_latency(const struct cec_msg *msg,
 
 
 /* Capability Discovery and Control Feature */
-static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg,
+static __inline__ void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg,
 						 __u16 phys_addr1,
 						 __u16 phys_addr2)
 {
@@ -1701,7 +1701,7 @@ static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg,
 	msg->msg[8] = phys_addr2 & 0xff;
 }
 
-static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg,
+static __inline__ void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg,
 						 __u16 *phys_addr,
 						 __u16 *phys_addr1,
 						 __u16 *phys_addr2)
@@ -1711,7 +1711,7 @@ static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg,
 	*phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
 }
 
-static inline void cec_msg_cdc_hec_report_state(struct cec_msg *msg,
+static __inline__ void cec_msg_cdc_hec_report_state(struct cec_msg *msg,
 						__u16 target_phys_addr,
 						__u8 hec_func_state,
 						__u8 host_func_state,
@@ -1737,7 +1737,7 @@ static inline void cec_msg_cdc_hec_report_state(struct cec_msg *msg,
 	}
 }
 
-static inline void cec_ops_cdc_hec_report_state(const struct cec_msg *msg,
+static __inline__ void cec_ops_cdc_hec_report_state(const struct cec_msg *msg,
 						__u16 *phys_addr,
 						__u16 *target_phys_addr,
 						__u8 *hec_func_state,
@@ -1757,7 +1757,7 @@ static inline void cec_ops_cdc_hec_report_state(const struct cec_msg *msg,
 	*hec_field = *has_field ? ((msg->msg[8] << 8) | msg->msg[9]) : 0;
 }
 
-static inline void cec_msg_cdc_hec_set_state(struct cec_msg *msg,
+static __inline__ void cec_msg_cdc_hec_set_state(struct cec_msg *msg,
 					     __u16 phys_addr1,
 					     __u16 phys_addr2,
 					     __u8 hec_set_state,
@@ -1789,7 +1789,7 @@ static inline void cec_msg_cdc_hec_set_state(struct cec_msg *msg,
 	}
 }
 
-static inline void cec_ops_cdc_hec_set_state(const struct cec_msg *msg,
+static __inline__ void cec_ops_cdc_hec_set_state(const struct cec_msg *msg,
 					     __u16 *phys_addr,
 					     __u16 *phys_addr1,
 					     __u16 *phys_addr2,
@@ -1811,7 +1811,7 @@ static inline void cec_ops_cdc_hec_set_state(const struct cec_msg *msg,
 		*phys_addr5 = (msg->msg[14] << 8) | msg->msg[15];
 }
 
-static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg,
+static __inline__ void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg,
 						      __u16 phys_addr1,
 						      __u8 hec_set_state)
 {
@@ -1825,7 +1825,7 @@ static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg,
 	msg->msg[7] = hec_set_state;
 }
 
-static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg,
+static __inline__ void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg,
 						      __u16 *phys_addr,
 						      __u16 *phys_addr1,
 						      __u8 *hec_set_state)
@@ -1835,7 +1835,7 @@ static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg,
 	*hec_set_state = msg->msg[7];
 }
 
-static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg,
+static __inline__ void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg,
 							__u16 phys_addr1,
 							__u16 phys_addr2,
 							__u16 phys_addr3)
@@ -1853,7 +1853,7 @@ static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg,
 	msg->msg[10] = phys_addr3 & 0xff;
 }
 
-static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *msg,
+static __inline__ void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *msg,
 							__u16 *phys_addr,
 							__u16 *phys_addr1,
 							__u16 *phys_addr2,
@@ -1865,7 +1865,7 @@ static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *ms
 	*phys_addr3 = (msg->msg[9] << 8) | msg->msg[10];
 }
 
-static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg)
+static __inline__ void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg)
 {
 	msg->len = 5;
 	msg->msg[0] |= 0xf; /* broadcast */
@@ -1874,13 +1874,13 @@ static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg)
 	msg->msg[4] = CEC_MSG_CDC_HEC_NOTIFY_ALIVE;
 }
 
-static inline void cec_ops_cdc_hec_notify_alive(const struct cec_msg *msg,
+static __inline__ void cec_ops_cdc_hec_notify_alive(const struct cec_msg *msg,
 						__u16 *phys_addr)
 {
 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
 }
 
-static inline void cec_msg_cdc_hec_discover(struct cec_msg *msg)
+static __inline__ void cec_msg_cdc_hec_discover(struct cec_msg *msg)
 {
 	msg->len = 5;
 	msg->msg[0] |= 0xf; /* broadcast */
@@ -1889,13 +1889,13 @@ static inline void cec_msg_cdc_hec_discover(struct cec_msg *msg)
 	msg->msg[4] = CEC_MSG_CDC_HEC_DISCOVER;
 }
 
-static inline void cec_ops_cdc_hec_discover(const struct cec_msg *msg,
+static __inline__ void cec_ops_cdc_hec_discover(const struct cec_msg *msg,
 					    __u16 *phys_addr)
 {
 	*phys_addr = (msg->msg[2] << 8) | msg->msg[3];
 }
 
-static inline void cec_msg_cdc_hpd_set_state(struct cec_msg *msg,
+static __inline__ void cec_msg_cdc_hpd_set_state(struct cec_msg *msg,
 					     __u8 input_port,
 					     __u8 hpd_state)
 {
@@ -1907,7 +1907,7 @@ static inline void cec_msg_cdc_hpd_set_state(struct cec_msg *msg,
 	msg->msg[5] = (input_port << 4) | hpd_state;
 }
 
-static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg,
+static __inline__ void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg,
 					    __u16 *phys_addr,
 					    __u8 *input_port,
 					    __u8 *hpd_state)
@@ -1917,7 +1917,7 @@ static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg,
 	*hpd_state = msg->msg[5] & 0xf;
 }
 
-static inline void cec_msg_cdc_hpd_report_state(struct cec_msg *msg,
+static __inline__ void cec_msg_cdc_hpd_report_state(struct cec_msg *msg,
 						__u8 hpd_state,
 						__u8 hpd_error)
 {
@@ -1929,7 +1929,7 @@ static inline void cec_msg_cdc_hpd_report_state(struct cec_msg *msg,
 	msg->msg[5] = (hpd_state << 4) | hpd_error;
 }
 
-static inline void cec_ops_cdc_hpd_report_state(const struct cec_msg *msg,
+static __inline__ void cec_ops_cdc_hpd_report_state(const struct cec_msg *msg,
 						__u16 *phys_addr,
 						__u8 *hpd_state,
 						__u8 *hpd_error)
diff --git a/include/linux/cec.h b/include/linux/cec.h
index 20fe091..0161700 100644
--- a/include/linux/cec.h
+++ b/include/linux/cec.h
@@ -75,7 +75,7 @@ struct cec_msg {
  * cec_msg_initiator - return the initiator's logical address.
  * @msg:	the message structure
  */
-static inline __u8 cec_msg_initiator(const struct cec_msg *msg)
+static __inline__ __u8 cec_msg_initiator(const struct cec_msg *msg)
 {
 	return msg->msg[0] >> 4;
 }
@@ -84,7 +84,7 @@ static inline __u8 cec_msg_initiator(const struct cec_msg *msg)
  * cec_msg_destination - return the destination's logical address.
  * @msg:	the message structure
  */
-static inline __u8 cec_msg_destination(const struct cec_msg *msg)
+static __inline__ __u8 cec_msg_destination(const struct cec_msg *msg)
 {
 	return msg->msg[0] & 0xf;
 }
@@ -93,7 +93,7 @@ static inline __u8 cec_msg_destination(const struct cec_msg *msg)
  * cec_msg_opcode - return the opcode of the message, -1 for poll
  * @msg:	the message structure
  */
-static inline int cec_msg_opcode(const struct cec_msg *msg)
+static __inline__ int cec_msg_opcode(const struct cec_msg *msg)
 {
 	return msg->len > 1 ? msg->msg[1] : -1;
 }
@@ -102,7 +102,7 @@ static inline int cec_msg_opcode(const struct cec_msg *msg)
  * cec_msg_is_broadcast - return true if this is a broadcast message.
  * @msg:	the message structure
  */
-static inline int cec_msg_is_broadcast(const struct cec_msg *msg)
+static __inline__ int cec_msg_is_broadcast(const struct cec_msg *msg)
 {
 	return (msg->msg[0] & 0xf) == 0xf;
 }
@@ -116,7 +116,7 @@ static inline int cec_msg_is_broadcast(const struct cec_msg *msg)
  * The whole structure is zeroed, the len field is set to 1 (i.e. a poll
  * message) and the initiator and destination are filled in.
  */
-static inline void cec_msg_init(struct cec_msg *msg,
+static __inline__ void cec_msg_init(struct cec_msg *msg,
 				__u8 initiator, __u8 destination)
 {
 	memset(msg, 0, sizeof(*msg));
@@ -133,7 +133,7 @@ static inline void cec_msg_init(struct cec_msg *msg,
  * orig destination. Note that msg and orig may be the same pointer, in which
  * case the change is done in place.
  */
-static inline void cec_msg_set_reply_to(struct cec_msg *msg,
+static __inline__ void cec_msg_set_reply_to(struct cec_msg *msg,
 					struct cec_msg *orig)
 {
 	/* The destination becomes the initiator and vice versa */
@@ -157,7 +157,7 @@ static inline void cec_msg_set_reply_to(struct cec_msg *msg,
 #define CEC_RX_STATUS_TIMEOUT		(1 << 1)
 #define CEC_RX_STATUS_FEATURE_ABORT	(1 << 2)
 
-static inline int cec_msg_status_is_ok(const struct cec_msg *msg)
+static __inline__ int cec_msg_status_is_ok(const struct cec_msg *msg)
 {
 	if (msg->tx_status && !(msg->tx_status & CEC_TX_STATUS_OK))
 		return 0;
@@ -227,47 +227,47 @@ static inline int cec_msg_status_is_ok(const struct cec_msg *msg)
 #define CEC_LOG_ADDR_MASK_SPECIFIC	(1 << CEC_LOG_ADDR_SPECIFIC)
 #define CEC_LOG_ADDR_MASK_UNREGISTERED	(1 << CEC_LOG_ADDR_UNREGISTERED)
 
-static inline int cec_has_tv(__u16 log_addr_mask)
+static __inline__ int cec_has_tv(__u16 log_addr_mask)
 {
 	return log_addr_mask & CEC_LOG_ADDR_MASK_TV;
 }
 
-static inline int cec_has_record(__u16 log_addr_mask)
+static __inline__ int cec_has_record(__u16 log_addr_mask)
 {
 	return log_addr_mask & CEC_LOG_ADDR_MASK_RECORD;
 }
 
-static inline int cec_has_tuner(__u16 log_addr_mask)
+static __inline__ int cec_has_tuner(__u16 log_addr_mask)
 {
 	return log_addr_mask & CEC_LOG_ADDR_MASK_TUNER;
 }
 
-static inline int cec_has_playback(__u16 log_addr_mask)
+static __inline__ int cec_has_playback(__u16 log_addr_mask)
 {
 	return log_addr_mask & CEC_LOG_ADDR_MASK_PLAYBACK;
 }
 
-static inline int cec_has_audiosystem(__u16 log_addr_mask)
+static __inline__ int cec_has_audiosystem(__u16 log_addr_mask)
 {
 	return log_addr_mask & CEC_LOG_ADDR_MASK_AUDIOSYSTEM;
 }
 
-static inline int cec_has_backup(__u16 log_addr_mask)
+static __inline__ int cec_has_backup(__u16 log_addr_mask)
 {
 	return log_addr_mask & CEC_LOG_ADDR_MASK_BACKUP;
 }
 
-static inline int cec_has_specific(__u16 log_addr_mask)
+static __inline__ int cec_has_specific(__u16 log_addr_mask)
 {
 	return log_addr_mask & CEC_LOG_ADDR_MASK_SPECIFIC;
 }
 
-static inline int cec_is_unregistered(__u16 log_addr_mask)
+static __inline__ int cec_is_unregistered(__u16 log_addr_mask)
 {
 	return log_addr_mask & CEC_LOG_ADDR_MASK_UNREGISTERED;
 }
 
-static inline int cec_is_unconfigured(__u16 log_addr_mask)
+static __inline__ int cec_is_unconfigured(__u16 log_addr_mask)
 {
 	return log_addr_mask == 0;
 }
@@ -999,7 +999,7 @@ struct cec_event {
 
 /* Helper functions to identify the 'special' CEC devices */
 
-static inline int cec_is_2nd_tv(const struct cec_log_addrs *las)
+static __inline__ int cec_is_2nd_tv(const struct cec_log_addrs *las)
 {
 	/*
 	 * It is a second TV if the logical address is 14 or 15 and the
@@ -1010,7 +1010,7 @@ static inline int cec_is_2nd_tv(const struct cec_log_addrs *las)
 	       las->primary_device_type[0] == CEC_OP_PRIM_DEVTYPE_TV;
 }
 
-static inline int cec_is_processor(const struct cec_log_addrs *las)
+static __inline__ int cec_is_processor(const struct cec_log_addrs *las)
 {
 	/*
 	 * It is a processor if the logical address is 12-15 and the
@@ -1021,7 +1021,7 @@ static inline int cec_is_processor(const struct cec_log_addrs *las)
 	       las->primary_device_type[0] == CEC_OP_PRIM_DEVTYPE_PROCESSOR;
 }
 
-static inline int cec_is_switch(const struct cec_log_addrs *las)
+static __inline__ int cec_is_switch(const struct cec_log_addrs *las)
 {
 	/*
 	 * It is a switch if the logical address is 15 and the
@@ -1033,7 +1033,7 @@ static inline int cec_is_switch(const struct cec_log_addrs *las)
 	       !(las->flags & CEC_LOG_ADDRS_FL_CDC_ONLY);
 }
 
-static inline int cec_is_cdc_only(const struct cec_log_addrs *las)
+static __inline__ int cec_is_cdc_only(const struct cec_log_addrs *las)
 {
 	/*
 	 * It is a CDC-only device if the logical address is 15 and the
diff --git a/include/linux/media.h b/include/linux/media.h
index 11dd72f..370e14f 100644
--- a/include/linux/media.h
+++ b/include/linux/media.h
@@ -323,11 +323,19 @@ struct media_v2_topology {
 
 /* ioctls */
 
+struct __attribute__ ((packed)) media_request_alloc {
+	__s32 fd;
+};
+
 #define MEDIA_IOC_DEVICE_INFO	_IOWR('|', 0x00, struct media_device_info)
 #define MEDIA_IOC_ENUM_ENTITIES	_IOWR('|', 0x01, struct media_entity_desc)
 #define MEDIA_IOC_ENUM_LINKS	_IOWR('|', 0x02, struct media_links_enum)
 #define MEDIA_IOC_SETUP_LINK	_IOWR('|', 0x03, struct media_link_desc)
 #define MEDIA_IOC_G_TOPOLOGY	_IOWR('|', 0x04, struct media_v2_topology)
+#define MEDIA_IOC_REQUEST_ALLOC	_IOWR('|', 0x05, struct media_request_alloc)
+
+#define MEDIA_REQUEST_IOC_QUEUE		_IO('|',  0x80)
+#define MEDIA_REQUEST_IOC_REINIT	_IO('|',  0x81)
 
 
 /*
diff --git a/include/linux/v4l2-dv-timings.h b/include/linux/v4l2-dv-timings.h
new file mode 100644
index 0000000..b52b67c
--- /dev/null
+++ b/include/linux/v4l2-dv-timings.h
@@ -0,0 +1,979 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * V4L2 DV timings header.
+ *
+ * Copyright (C) 2012-2016  Hans Verkuil <hans.verkuil@cisco.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _V4L2_DV_TIMINGS_H
+#define _V4L2_DV_TIMINGS_H
+
+#if __GNUC__ < 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ < 6))
+/* Sadly gcc versions older than 4.6 have a bug in how they initialize
+   anonymous unions where they require additional curly brackets.
+   This violates the C1x standard. This workaround adds the curly brackets
+   if needed. */
+#define V4L2_INIT_BT_TIMINGS(_width, args...) \
+	{ .bt = { _width , ## args } }
+#else
+#define V4L2_INIT_BT_TIMINGS(_width, args...) \
+	.bt = { _width , ## args }
+#endif
+
+/* CEA-861-F timings (i.e. standard HDTV timings) */
+
+#define V4L2_DV_BT_CEA_640X480P59_94 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(640, 480, 0, 0, \
+		25175000, 16, 96, 48, 10, 2, 33, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 1) \
+}
+
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.  */
+#define V4L2_DV_BT_CEA_720X480I59_94 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 1, 0, \
+		13500000, 19, 62, 57, 4, 3, 15, 4, 3, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 6) \
+}
+
+#define V4L2_DV_BT_CEA_720X480P59_94 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
+		27000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 2) \
+}
+
+/* Note: these are the nominal timings, for HDMI links this format is typically
+ * double-clocked to meet the minimum pixelclock requirements.  */
+#define V4L2_DV_BT_CEA_720X576I50 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 1, 0, \
+		13500000, 12, 63, 69, 2, 3, 19, 2, 3, 20, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_PICTURE_ASPECT | V4L2_DV_FL_HAS_CEA861_VIC, \
+		{ 4, 3 }, 21) \
+}
+
+#define V4L2_DV_BT_CEA_720X576P50 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
+		27000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_PICTURE_ASPECT | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 4, 3 }, 17) \
+}
+
+#define V4L2_DV_BT_CEA_1280X720P24 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		59400000, 1760, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 60) \
+}
+
+#define V4L2_DV_BT_CEA_1280X720P25 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 2420, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 61) \
+}
+
+#define V4L2_DV_BT_CEA_1280X720P30 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 1760, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 62) \
+}
+
+#define V4L2_DV_BT_CEA_1280X720P50 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 19) \
+}
+
+#define V4L2_DV_BT_CEA_1280X720P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 4) \
+}
+
+#define V4L2_DV_BT_CEA_1920X1080P24 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 32) \
+}
+
+#define V4L2_DV_BT_CEA_1920X1080P25 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 33) \
+}
+
+#define V4L2_DV_BT_CEA_1920X1080P30 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 34) \
+}
+
+#define V4L2_DV_BT_CEA_1920X1080I50 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 528, 44, 148, 2, 5, 15, 2, 5, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 20) \
+}
+
+#define V4L2_DV_BT_CEA_1920X1080P50 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 31) \
+}
+
+#define V4L2_DV_BT_CEA_1920X1080I60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 88, 44, 148, 2, 5, 15, 2, 5, 16, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | \
+		V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 5) \
+}
+
+#define V4L2_DV_BT_CEA_1920X1080P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 16) \
+}
+
+#define V4L2_DV_BT_CEA_3840X2160P24 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC | V4L2_DV_FL_HAS_HDMI_VIC, \
+		{ 0, 0 }, 93, 3) \
+}
+
+#define V4L2_DV_BT_CEA_3840X2160P25 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_CEA861_VIC | \
+		V4L2_DV_FL_HAS_HDMI_VIC, { 0, 0 }, 94, 2) \
+}
+
+#define V4L2_DV_BT_CEA_3840X2160P30 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC | V4L2_DV_FL_HAS_HDMI_VIC, \
+		{ 0, 0 }, 95, 1) \
+}
+
+#define V4L2_DV_BT_CEA_3840X2160P50 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 96) \
+}
+
+#define V4L2_DV_BT_CEA_3840X2160P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 97) \
+}
+
+#define V4L2_DV_BT_CEA_4096X2160P24 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 1020, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC | V4L2_DV_FL_HAS_HDMI_VIC, \
+		{ 0, 0 }, 98, 4) \
+}
+
+#define V4L2_DV_BT_CEA_4096X2160P25 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 968, 88, 128, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 99) \
+}
+
+#define V4L2_DV_BT_CEA_4096X2160P30 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 88, 88, 128, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 100) \
+}
+
+#define V4L2_DV_BT_CEA_4096X2160P50 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 968, 88, 128, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_IS_CE_VIDEO | V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 101) \
+}
+
+#define V4L2_DV_BT_CEA_4096X2160P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 88, 88, 128, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861, \
+		V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO | \
+		V4L2_DV_FL_HAS_CEA861_VIC, { 0, 0 }, 102) \
+}
+
+
+/* VESA Discrete Monitor Timings as per version 1.0, revision 12 */
+
+#define V4L2_DV_BT_DMT_640X350P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(640, 350, 0, V4L2_DV_HSYNC_POS_POL, \
+		31500000, 32, 64, 96, 32, 3, 60, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_640X400P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(640, 400, 0, V4L2_DV_VSYNC_POS_POL, \
+		31500000, 32, 64, 96, 1, 3, 41, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_720X400P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 400, 0, V4L2_DV_VSYNC_POS_POL, \
+		35500000, 36, 72, 108, 1, 3, 42, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+/* VGA resolutions */
+#define V4L2_DV_BT_DMT_640X480P60 V4L2_DV_BT_CEA_640X480P59_94
+
+#define V4L2_DV_BT_DMT_640X480P72 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(640, 480, 0, 0, \
+		31500000, 24, 40, 128, 9, 3, 28, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_640X480P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(640, 480, 0, 0, \
+		31500000, 16, 64, 120, 1, 3, 16, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_640X480P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(640, 480, 0, 0, \
+		36000000, 56, 56, 80, 1, 3, 25, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+/* SVGA resolutions */
+#define V4L2_DV_BT_DMT_800X600P56 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(800, 600, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		36000000, 24, 72, 128, 1, 2, 22, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_800X600P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(800, 600, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		40000000, 40, 128, 88, 1, 4, 23, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_800X600P72 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(800, 600, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		50000000, 56, 120, 64, 37, 6, 23, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_800X600P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(800, 600, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		49500000, 16, 80, 160, 1, 3, 21, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_800X600P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(800, 600, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		56250000, 32, 64, 152, 1, 3, 27, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_800X600P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(800, 600, 0, V4L2_DV_HSYNC_POS_POL, \
+		73250000, 48, 32, 80, 3, 4, 29, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_848X480P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(848, 480, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		33750000, 16, 112, 112, 6, 8, 23, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1024X768I43 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1024, 768, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		44900000, 8, 176, 56, 0, 4, 20, 0, 4, 21, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+/* XGA resolutions */
+#define V4L2_DV_BT_DMT_1024X768P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1024, 768, 0, 0, \
+		65000000, 24, 136, 160, 3, 6, 29, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1024X768P70 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1024, 768, 0, 0, \
+		75000000, 24, 136, 144, 3, 6, 29, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1024X768P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1024, 768, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		78750000, 16, 96, 176, 1, 3, 28, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1024X768P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1024, 768, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		94500000, 48, 96, 208, 1, 3, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1024X768P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1024, 768, 0, V4L2_DV_HSYNC_POS_POL, \
+		115500000, 48, 32, 80, 3, 4, 38, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+/* XGA+ resolution */
+#define V4L2_DV_BT_DMT_1152X864P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1152, 864, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		108000000, 64, 128, 256, 1, 3, 32, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X720P60 V4L2_DV_BT_CEA_1280X720P60
+
+/* WXGA resolutions */
+#define V4L2_DV_BT_DMT_1280X768P60_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 768, 0, V4L2_DV_HSYNC_POS_POL, \
+		68250000, 48, 32, 80, 3, 7, 12, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1280X768P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 768, 0, V4L2_DV_VSYNC_POS_POL, \
+		79500000, 64, 128, 192, 3, 7, 20, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X768P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 768, 0, V4L2_DV_VSYNC_POS_POL, \
+		102250000, 80, 128, 208, 3, 7, 27, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X768P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 768, 0, V4L2_DV_VSYNC_POS_POL, \
+		117500000, 80, 136, 216, 3, 7, 31, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X768P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 768, 0, V4L2_DV_HSYNC_POS_POL, \
+		140250000, 48, 32, 80, 3, 7, 35, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1280X800P60_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 800, 0, V4L2_DV_HSYNC_POS_POL, \
+		71000000, 48, 32, 80, 3, 6, 14, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1280X800P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 800, 0, V4L2_DV_VSYNC_POS_POL, \
+		83500000, 72, 128, 200, 3, 6, 22, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X800P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 800, 0, V4L2_DV_VSYNC_POS_POL, \
+		106500000, 80, 128, 208, 3, 6, 29, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X800P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 800, 0, V4L2_DV_VSYNC_POS_POL, \
+		122500000, 80, 136, 216, 3, 6, 34, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X800P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 800, 0, V4L2_DV_HSYNC_POS_POL, \
+		146250000, 48, 32, 80, 3, 6, 38, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1280X960P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 960, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		108000000, 96, 112, 312, 1, 3, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X960P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 960, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 64, 160, 224, 1, 3, 47, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X960P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 960, 0, V4L2_DV_HSYNC_POS_POL, \
+		175500000, 48, 32, 80, 3, 4, 50, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+/* SXGA resolutions */
+#define V4L2_DV_BT_DMT_1280X1024P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 1024, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		108000000, 48, 112, 248, 1, 3, 38, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X1024P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 1024, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		135000000, 16, 144, 248, 1, 3, 38, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X1024P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 1024, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		157500000, 64, 160, 224, 1, 3, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1280X1024P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1280, 1024, 0, V4L2_DV_HSYNC_POS_POL, \
+		187250000, 48, 32, 80, 3, 7, 50, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1360X768P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1360, 768, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		85500000, 64, 112, 256, 3, 6, 18, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1360X768P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1360, 768, 0, V4L2_DV_HSYNC_POS_POL, \
+		148250000, 48, 32, 80, 3, 5, 37, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1366X768P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1366, 768, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		85500000, 70, 143, 213, 3, 3, 24, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1366X768P60_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1366, 768, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		72000000, 14, 56, 64, 1, 3, 28, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+/* SXGA+ resolutions */
+#define V4L2_DV_BT_DMT_1400X1050P60_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1400, 1050, 0, V4L2_DV_HSYNC_POS_POL, \
+		101000000, 48, 32, 80, 3, 4, 23, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1400X1050P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1400, 1050, 0, V4L2_DV_VSYNC_POS_POL, \
+		121750000, 88, 144, 232, 3, 4, 32, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1400X1050P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1400, 1050, 0, V4L2_DV_VSYNC_POS_POL, \
+		156000000, 104, 144, 248, 3, 4, 42, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1400X1050P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1400, 1050, 0, V4L2_DV_VSYNC_POS_POL, \
+		179500000, 104, 152, 256, 3, 4, 48, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1400X1050P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1400, 1050, 0, V4L2_DV_HSYNC_POS_POL, \
+		208000000, 48, 32, 80, 3, 4, 55, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+/* WXGA+ resolutions */
+#define V4L2_DV_BT_DMT_1440X900P60_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 900, 0, V4L2_DV_HSYNC_POS_POL, \
+		88750000, 48, 32, 80, 3, 6, 17, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1440X900P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 900, 0, V4L2_DV_VSYNC_POS_POL, \
+		106500000, 80, 152, 232, 3, 6, 25, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1440X900P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 900, 0, V4L2_DV_VSYNC_POS_POL, \
+		136750000, 96, 152, 248, 3, 6, 33, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1440X900P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 900, 0, V4L2_DV_VSYNC_POS_POL, \
+		157000000, 104, 152, 256, 3, 6, 39, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1440X900P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1440, 900, 0, V4L2_DV_HSYNC_POS_POL, \
+		182750000, 48, 32, 80, 3, 6, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1600X900P60_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1600, 900, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		108000000, 24, 80, 96, 1, 3, 96, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+/* UXGA resolutions */
+#define V4L2_DV_BT_DMT_1600X1200P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1600, 1200, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		162000000, 64, 192, 304, 1, 3, 46, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1600X1200P65 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1600, 1200, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		175500000, 64, 192, 304, 1, 3, 46, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1600X1200P70 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1600, 1200, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		189000000, 64, 192, 304, 1, 3, 46, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1600X1200P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1600, 1200, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		202500000, 64, 192, 304, 1, 3, 46, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1600X1200P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1600, 1200, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		229500000, 64, 192, 304, 1, 3, 46, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1600X1200P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1600, 1200, 0, V4L2_DV_HSYNC_POS_POL, \
+		268250000, 48, 32, 80, 3, 4, 64, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+/* WSXGA+ resolutions */
+#define V4L2_DV_BT_DMT_1680X1050P60_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 1050, 0, V4L2_DV_HSYNC_POS_POL, \
+		119000000, 48, 32, 80, 3, 6, 21, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1680X1050P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 1050, 0, V4L2_DV_VSYNC_POS_POL, \
+		146250000, 104, 176, 280, 3, 6, 30, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1680X1050P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 1050, 0, V4L2_DV_VSYNC_POS_POL, \
+		187000000, 120, 176, 296, 3, 6, 40, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1680X1050P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 1050, 0, V4L2_DV_VSYNC_POS_POL, \
+		214750000, 128, 176, 304, 3, 6, 46, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1680X1050P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1680, 1050, 0, V4L2_DV_HSYNC_POS_POL, \
+		245500000, 48, 32, 80, 3, 6, 53, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1792X1344P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1792, 1344, 0, V4L2_DV_VSYNC_POS_POL, \
+		204750000, 128, 200, 328, 1, 3, 46, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1792X1344P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1792, 1344, 0, V4L2_DV_VSYNC_POS_POL, \
+		261000000, 96, 216, 352, 1, 3, 69, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1792X1344P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1792, 1344, 0, V4L2_DV_HSYNC_POS_POL, \
+		333250000, 48, 32, 80, 3, 4, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1856X1392P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1856, 1392, 0, V4L2_DV_VSYNC_POS_POL, \
+		218250000, 96, 224, 352, 1, 3, 43, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1856X1392P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1856, 1392, 0, V4L2_DV_VSYNC_POS_POL, \
+		288000000, 128, 224, 352, 1, 3, 104, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1856X1392P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1856, 1392, 0, V4L2_DV_HSYNC_POS_POL, \
+		356500000, 48, 32, 80, 3, 4, 75, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1920X1080P60 V4L2_DV_BT_CEA_1920X1080P60
+
+/* WUXGA resolutions */
+#define V4L2_DV_BT_DMT_1920X1200P60_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1200, 0, V4L2_DV_HSYNC_POS_POL, \
+		154000000, 48, 32, 80, 3, 6, 26, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1920X1200P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1200, 0, V4L2_DV_VSYNC_POS_POL, \
+		193250000, 136, 200, 336, 3, 6, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1920X1200P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1200, 0, V4L2_DV_VSYNC_POS_POL, \
+		245250000, 136, 208, 344, 3, 6, 46, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1920X1200P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1200, 0, V4L2_DV_VSYNC_POS_POL, \
+		281250000, 144, 208, 352, 3, 6, 53, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1920X1200P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1200, 0, V4L2_DV_HSYNC_POS_POL, \
+		317000000, 48, 32, 80, 3, 6, 62, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_1920X1440P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1440, 0, V4L2_DV_VSYNC_POS_POL, \
+		234000000, 128, 208, 344, 1, 3, 56, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1920X1440P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1440, 0, V4L2_DV_VSYNC_POS_POL, \
+		297000000, 144, 224, 352, 1, 3, 56, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_1920X1440P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1440, 0, V4L2_DV_HSYNC_POS_POL, \
+		380500000, 48, 32, 80, 3, 4, 78, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_2048X1152P60_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1152, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		162000000, 26, 80, 96, 1, 3, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT, V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+/* WQXGA resolutions */
+#define V4L2_DV_BT_DMT_2560X1600P60_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1600, 0, V4L2_DV_HSYNC_POS_POL, \
+		268500000, 48, 32, 80, 3, 6, 37, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_2560X1600P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1600, 0, V4L2_DV_VSYNC_POS_POL, \
+		348500000, 192, 280, 472, 3, 6, 49, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_2560X1600P75 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1600, 0, V4L2_DV_VSYNC_POS_POL, \
+		443250000, 208, 280, 488, 3, 6, 63, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_2560X1600P85 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1600, 0, V4L2_DV_VSYNC_POS_POL, \
+		505250000, 208, 280, 488, 3, 6, 73, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, 0) \
+}
+
+#define V4L2_DV_BT_DMT_2560X1600P120_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2560, 1600, 0, V4L2_DV_HSYNC_POS_POL, \
+		552750000, 48, 32, 80, 3, 6, 85, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+/* 4K resolutions */
+#define V4L2_DV_BT_DMT_4096X2160P60_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+		556744000, 8, 32, 40, 48, 8, 6, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+#define V4L2_DV_BT_DMT_4096X2160P59_94_RB { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
+		556188000, 8, 32, 40, 48, 8, 6, 0, 0, 0, \
+		V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CVT, \
+		V4L2_DV_FL_REDUCED_BLANKING) \
+}
+
+/* SDI timings definitions */
+
+/* SMPTE-125M */
+#define V4L2_DV_BT_SDI_720X487I60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(720, 487, 1, \
+		V4L2_DV_HSYNC_POS_POL, \
+		13500000, 16, 121, 0, 0, 19, 0, 0, 19, 0, \
+		V4L2_DV_BT_STD_SDI, \
+		V4L2_DV_FL_FIRST_FIELD_EXTRA_LINE) \
+}
+
+#endif
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index a9e07d7..a15c1a6 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -906,6 +906,7 @@ struct v4l2_plane {
  * @length:	size in bytes of the buffer (NOT its payload) for single-plane
  *		buffers (when type != *_MPLANE); number of elements in the
  *		planes array for multi-plane buffers
+ * @request_fd: fd of the request that this buffer should use
  *
  * Contains data exchanged by application and driver using one of the Streaming
  * I/O methods.
@@ -930,7 +931,10 @@ struct v4l2_buffer {
 	} m;
 	__u32			length;
 	__u32			reserved2;
-	__u32			reserved;
+	union {
+		__s32		request_fd;
+		__u32		reserved;
+	};
 };
 
 /*  Flags for 'flags' field */
@@ -948,6 +952,8 @@ struct v4l2_buffer {
 #define V4L2_BUF_FLAG_BFRAME			0x00000020
 /* Buffer is ready, but the data contained within is corrupted. */
 #define V4L2_BUF_FLAG_ERROR			0x00000040
+/* Buffer is added to an unqueued request */
+#define V4L2_BUF_FLAG_IN_REQUEST		0x00000080
 /* timecode field is valid */
 #define V4L2_BUF_FLAG_TIMECODE			0x00000100
 /* Buffer is prepared for queuing */
@@ -966,6 +972,8 @@ struct v4l2_buffer {
 #define V4L2_BUF_FLAG_TSTAMP_SRC_SOE		0x00010000
 /* mem2mem encoder/decoder */
 #define V4L2_BUF_FLAG_LAST			0x00100000
+/* request_fd is valid */
+#define V4L2_BUF_FLAG_REQUEST_FD		0x00800000
 
 /**
  * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor
@@ -1586,7 +1594,8 @@ struct v4l2_ext_controls {
 	};
 	__u32 count;
 	__u32 error_idx;
-	__u32 reserved[2];
+	__s32 request_fd;
+	__u32 reserved[1];
 	struct v4l2_ext_control *controls;
 };
 
@@ -1597,6 +1606,7 @@ struct v4l2_ext_controls {
 #define V4L2_CTRL_MAX_DIMS	  (4)
 #define V4L2_CTRL_WHICH_CUR_VAL   0
 #define V4L2_CTRL_WHICH_DEF_VAL   0x0f000000
+#define V4L2_CTRL_WHICH_REQUEST   0x0f010000
 
 enum v4l2_ctrl_type {
 	V4L2_CTRL_TYPE_INTEGER	     = 1,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [v4l-utils RFC 2/6] Make v4l-utils compile with request-related changes
  2018-04-05 10:58 [v4l-utils RFC 0/6] Mediatext test program for request API tests Sakari Ailus
  2018-04-05 10:58 ` [v4l-utils RFC 1/6] Linux kernel header update Sakari Ailus
@ 2018-04-05 10:58 ` Sakari Ailus
  2018-04-05 10:58 ` [v4l-utils RFC 3/6] libmediactl: Add open, close and fd to public API Sakari Ailus
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sakari Ailus @ 2018-04-05 10:58 UTC (permalink / raw)
  To: linux-media; +Cc: tfiga, hverkuil

Mostly remove zero reserved field checks.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 lib/libv4l2/libv4l2.c                        | 4 ++--
 utils/v4l2-compliance/v4l2-test-buffers.cpp  | 2 +-
 utils/v4l2-compliance/v4l2-test-controls.cpp | 4 ----
 3 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/lib/libv4l2/libv4l2.c b/lib/libv4l2/libv4l2.c
index 2db25d1..47eadda 100644
--- a/lib/libv4l2/libv4l2.c
+++ b/lib/libv4l2/libv4l2.c
@@ -190,7 +190,7 @@ static int v4l2_map_buffers(int index)
 		buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		buf.memory = V4L2_MEMORY_MMAP;
 		buf.index = i;
-		buf.reserved = buf.reserved2 = 0;
+		buf.reserved = buf.request_fd = 0;
 		result = devices[index].dev_ops->ioctl(
 				devices[index].dev_ops_priv,
 				devices[index].fd, VIDIOC_QUERYBUF, &buf);
@@ -579,7 +579,7 @@ static int v4l2_buffers_mapped(int index)
 			buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 			buf.memory = V4L2_MEMORY_MMAP;
 			buf.index = i;
-			buf.reserved = buf.reserved2 = 0;
+			buf.reserved = buf.request_fd = 0;
 			if (devices[index].dev_ops->ioctl(
 					devices[index].dev_ops_priv,
 					devices[index].fd, VIDIOC_QUERYBUF,
diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp
index 9b0933e..a9e50b4 100644
--- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
+++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
@@ -196,7 +196,7 @@ int buffer::check(unsigned type, unsigned memory, unsigned index,
 	fail_on_test(g_memory() != memory);
 	fail_on_test(g_index() >= VIDEO_MAX_FRAME);
 	fail_on_test(g_index() != index);
-	fail_on_test(buf.reserved2 || buf.reserved);
+	fail_on_test(buf.request_fd || buf.reserved);
 	fail_on_test(timestamp != V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC &&
 		     timestamp != V4L2_BUF_FLAG_TIMESTAMP_COPY);
 	fail_on_test(timestamp_src != V4L2_BUF_FLAG_TSTAMP_SRC_SOE &&
diff --git a/utils/v4l2-compliance/v4l2-test-controls.cpp b/utils/v4l2-compliance/v4l2-test-controls.cpp
index 508daf0..b9a8978 100644
--- a/utils/v4l2-compliance/v4l2-test-controls.cpp
+++ b/utils/v4l2-compliance/v4l2-test-controls.cpp
@@ -589,8 +589,6 @@ int testExtendedControls(struct node *node)
 		return fail("field which changed\n");
 	if (ctrls.count)
 		return fail("field count changed\n");
-	if (check_0(ctrls.reserved, sizeof(ctrls.reserved)))
-		return fail("reserved not zeroed\n");
 
 	memset(&ctrls, 0, sizeof(ctrls));
 	ret = doioctl(node, VIDIOC_TRY_EXT_CTRLS, &ctrls);
@@ -602,8 +600,6 @@ int testExtendedControls(struct node *node)
 		return fail("field which changed\n");
 	if (ctrls.count)
 		return fail("field count changed\n");
-	if (check_0(ctrls.reserved, sizeof(ctrls.reserved)))
-		return fail("reserved not zeroed\n");
 
 	for (iter = node->controls.begin(); iter != node->controls.end(); ++iter) {
 		test_query_ext_ctrl &qctrl = iter->second;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [v4l-utils RFC 3/6] libmediactl: Add open, close and fd to public API
  2018-04-05 10:58 [v4l-utils RFC 0/6] Mediatext test program for request API tests Sakari Ailus
  2018-04-05 10:58 ` [v4l-utils RFC 1/6] Linux kernel header update Sakari Ailus
  2018-04-05 10:58 ` [v4l-utils RFC 2/6] Make v4l-utils compile with request-related changes Sakari Ailus
@ 2018-04-05 10:58 ` Sakari Ailus
  2018-04-05 10:58 ` [v4l-utils RFC 4/6] mediatext: Extract list of V4L2 pixel format strings and 4cc codes Sakari Ailus
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Sakari Ailus @ 2018-04-05 10:58 UTC (permalink / raw)
  To: linux-media; +Cc: tfiga, hverkuil

Add functions to open and close the media device as well as to obtain its
fd.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 utils/media-ctl/libmediactl.c | 9 +++++++--
 utils/media-ctl/mediactl.h    | 4 ++++
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/utils/media-ctl/libmediactl.c b/utils/media-ctl/libmediactl.c
index 1fd6525..e20ab97 100644
--- a/utils/media-ctl/libmediactl.c
+++ b/utils/media-ctl/libmediactl.c
@@ -175,7 +175,7 @@ const struct media_entity_desc *media_entity_get_info(struct media_entity *entit
  * Open/close
  */
 
-static int media_device_open(struct media_device *media)
+int media_device_open(struct media_device *media)
 {
 	int ret;
 
@@ -195,7 +195,12 @@ static int media_device_open(struct media_device *media)
 	return 0;
 }
 
-static void media_device_close(struct media_device *media)
+int media_device_fd(struct media_device *media)
+{
+	return media->fd;
+}
+
+void media_device_close(struct media_device *media)
 {
 	if (media->fd != -1) {
 		close(media->fd);
diff --git a/utils/media-ctl/mediactl.h b/utils/media-ctl/mediactl.h
index af36051..5e325c4 100644
--- a/utils/media-ctl/mediactl.h
+++ b/utils/media-ctl/mediactl.h
@@ -59,6 +59,10 @@ struct media_entity;
  */
 struct media_device *media_device_new(const char *devnode);
 
+int media_device_open(struct media_device *media);
+int media_device_fd(struct media_device *media);
+void media_device_close(struct media_device *media);
+
 /**
  * @brief Create a new emulated media device.
  * @param info - device information.
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [v4l-utils RFC 4/6] mediatext: Extract list of V4L2 pixel format strings and 4cc codes
  2018-04-05 10:58 [v4l-utils RFC 0/6] Mediatext test program for request API tests Sakari Ailus
                   ` (2 preceding siblings ...)
  2018-04-05 10:58 ` [v4l-utils RFC 3/6] libmediactl: Add open, close and fd to public API Sakari Ailus
@ 2018-04-05 10:58 ` Sakari Ailus
  2018-04-05 10:58 ` [v4l-utils RFC 5/6] mediatext: Add library Sakari Ailus
  2018-04-05 10:58 ` [v4l-utils RFC 6/6] mediatext: Add vivid tests Sakari Ailus
  5 siblings, 0 replies; 7+ messages in thread
From: Sakari Ailus @ 2018-04-05 10:58 UTC (permalink / raw)
  To: linux-media; +Cc: tfiga, hverkuil

Extract the list of V4L2 pixel format strings and 4cc codes from
videodev2.h for use in mediatext in order to convert user given format
names to 4cc codes that IOCTLs use.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 utils/media-ctl/Makefile.am | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
index ee7dcc9..8fe653d 100644
--- a/utils/media-ctl/Makefile.am
+++ b/utils/media-ctl/Makefile.am
@@ -12,7 +12,12 @@ media-bus-format-codes.h: ../../include/linux/media-bus-format.h
 	sed -e '/#define MEDIA_BUS_FMT/ ! d; s/.*#define //; /FIXED/ d; s/\t.*//; s/.*/ &,/;' \
 	< $< > $@
 
-BUILT_SOURCES = media-bus-format-names.h media-bus-format-codes.h
+v4l2-pix-formats.h: ../../include/linux/videodev2.h
+	sed -e '/#define V4L2_PIX_FMT_/ ! d; s/.*FMT_//; s/[\t ].*//; s/.*/{ \"&\", V4L2_PIX_FMT_& },/;' \
+	< $< > $@
+
+BUILT_SOURCES = media-bus-format-names.h media-bus-format-codes.h \
+	v4l2-pix-formats.h
 CLEANFILES = $(BUILT_SOURCES)
 
 nodist_libv4l2subdev_la_SOURCES = $(BUILT_SOURCES)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [v4l-utils RFC 5/6] mediatext: Add library
  2018-04-05 10:58 [v4l-utils RFC 0/6] Mediatext test program for request API tests Sakari Ailus
                   ` (3 preceding siblings ...)
  2018-04-05 10:58 ` [v4l-utils RFC 4/6] mediatext: Extract list of V4L2 pixel format strings and 4cc codes Sakari Ailus
@ 2018-04-05 10:58 ` Sakari Ailus
  2018-04-05 10:58 ` [v4l-utils RFC 6/6] mediatext: Add vivid tests Sakari Ailus
  5 siblings, 0 replies; 7+ messages in thread
From: Sakari Ailus @ 2018-04-05 10:58 UTC (permalink / raw)
  To: linux-media; +Cc: tfiga, hverkuil

libmediatext is a helper library for converting configurations (Media
controller links, V4L2 controls and V4L2 sub-device media bus formats and
selections) from text-based form into IOCTLs.

libmediatext depends on libv4l2subdev and libmediactl.

The patch includes a test program, mediatext-test, that can be used to
write tests in interpreted languages such as shell scripts.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Teemu Tuominen <teemu.tuominen@intel.com>
---
 libmediatext.pc.in                 |   10 +
 utils/media-ctl/Makefile.am        |   11 +-
 utils/media-ctl/libmediatext.pc.in |   10 +
 utils/media-ctl/mediatext-test.c   |  127 +++
 utils/media-ctl/mediatext.c        | 2176 ++++++++++++++++++++++++++++++++++++
 utils/media-ctl/mediatext.h        |   33 +
 6 files changed, 2365 insertions(+), 2 deletions(-)
 create mode 100644 libmediatext.pc.in
 create mode 100644 utils/media-ctl/libmediatext.pc.in
 create mode 100644 utils/media-ctl/mediatext-test.c
 create mode 100644 utils/media-ctl/mediatext.c
 create mode 100644 utils/media-ctl/mediatext.h

diff --git a/libmediatext.pc.in b/libmediatext.pc.in
new file mode 100644
index 0000000..6aa6353
--- /dev/null
+++ b/libmediatext.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libmediatext
+Description: Media controller and V4L2 text-based configuration library
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lmediatext
diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
index 8fe653d..ddbc453 100644
--- a/utils/media-ctl/Makefile.am
+++ b/utils/media-ctl/Makefile.am
@@ -1,4 +1,4 @@
-noinst_LTLIBRARIES = libmediactl.la libv4l2subdev.la
+noinst_LTLIBRARIES = libmediactl.la libv4l2subdev.la libmediatext.la
 
 libmediactl_la_SOURCES = libmediactl.c mediactl-priv.h
 libmediactl_la_CFLAGS = -static $(LIBUDEV_CFLAGS)
@@ -26,9 +26,16 @@ libv4l2subdev_la_LIBADD = libmediactl.la
 libv4l2subdev_la_CFLAGS = -static
 libv4l2subdev_la_LDFLAGS = -static
 
+libmediatext_la_SOURCES = mediatext.c
+libmediatext_la_CFLAGS = -static $(LIBUDEV_CFLAGS)
+libmediatext_la_LDFLAGS = -static $(LIBUDEV_LIBS)
+
 mediactl_includedir=$(includedir)/mediactl
 noinst_HEADERS = mediactl.h v4l2subdev.h
 
-bin_PROGRAMS = media-ctl
+bin_PROGRAMS = media-ctl mediatext
 media_ctl_SOURCES = media-ctl.c options.c options.h tools.h
 media_ctl_LDADD = libmediactl.la libv4l2subdev.la
+mediatext_SOURCES = mediatext-test.c
+mediatext_LDFLAGS = $(STATIC_LDFLAGS)
+mediatext_LDADD = libmediatext.la libmediactl.la libv4l2subdev.la
diff --git a/utils/media-ctl/libmediatext.pc.in b/utils/media-ctl/libmediatext.pc.in
new file mode 100644
index 0000000..6aa6353
--- /dev/null
+++ b/utils/media-ctl/libmediatext.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libmediatext
+Description: Media controller and V4L2 text-based configuration library
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lmediatext
diff --git a/utils/media-ctl/mediatext-test.c b/utils/media-ctl/mediatext-test.c
new file mode 100644
index 0000000..77e8dc7
--- /dev/null
+++ b/utils/media-ctl/mediatext-test.c
@@ -0,0 +1,127 @@
+/*
+ * libmediatext test program
+ *
+ * Copyright (C) 2013--2016 Intel Corporation
+ *
+ * Contact: Sakari Ailus <sakari.ailus@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mediactl.h"
+#include "mediatext.h"
+
+static const struct option opts[] = {
+	{ "device", 1, 0, 'd', },
+	{ "coproc", 0, 0, 'c', },
+	{ "fd", 1, 0, 'f', },
+	{ "help", 0, 0, 'h', },
+	{ "verbose", 0, 0, 'v', },
+	{ 0 },
+};
+
+void help(char *myname)
+{
+	fprintf(stderr, "usage: %s <media device> <string>\n\n", myname);
+	fprintf(stderr, "\tstring := [ v4l2-ctrl | v4l2-mbus | link-reset | link-conf]\n\n");
+	fprintf(stderr, "\tv4l2-ctrl := \"entity\" ctrl_type ctrl_id ctrl_value\n");
+	fprintf(stderr, "\tctrl_type := [ int | int64 | bitmask ]\n");
+	fprintf(stderr, "\tctrl_value := [ %%d | %%PRId64 | bitmask_value ]\n");
+	fprintf(stderr, "\tbitmask_value := b<binary_number>\n\n");
+	fprintf(stderr, "\tv4l2-mbus := \n");
+	fprintf(stderr, "\tlink-conf := \"entity\":pad -> \"entity\":pad[link-flags]\n");
+}
+
+int main(int argc, char *argv[])
+{
+	struct media_device *device;
+	struct media_text *mt;
+	bool verbose = false;
+	char *devname = "/dev/media0";
+	int fd = 0;
+	int opt;
+	int rval;
+
+	while ((opt = getopt_long(argc, argv, "cd:f:hv", opts, NULL)) != -1) {
+		switch (opt) {
+		case 'd':
+			devname = optarg;
+			break;
+		case 'c':
+			fprintf(stdout, "%s",
+				"eval_line() {"
+				"	while [ $# -ne 0 ]; do"
+				"		local name=${1%=*};"
+				"		local value=${1#*=};"
+				"		p[$name]=\"$value\";"
+				"		shift;"
+				"	done;"
+				"}\n");
+			fflush(stdout);
+			break;
+		case 'f':
+			fd = atoi(optarg);
+			break;
+		case 'h':
+			help(argv[0]);
+			return EXIT_SUCCESS;
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			fprintf(stderr, "unknown option '%c'\n", opt);
+			return EXIT_FAILURE;
+		}
+	}
+
+	device = media_device_new(devname);
+	if (!device)
+		return EXIT_FAILURE;
+
+	if (verbose)
+		media_debug_set_handler(device, (void (*)(void *, ...))fprintf,
+					stdout);
+
+	rval = media_device_enumerate(device);
+	if (rval)
+		return EXIT_FAILURE;
+
+	mt = mediatext_init(device);
+	if (!mt)
+		return EXIT_FAILURE;
+
+	if (optind < argc) {
+		rval = mediatext_parse(mt, argv[optind]);
+		if (rval) {
+			fprintf(stderr, "bad string %s (%s)\n", argv[2],
+				strerror(-rval));
+			return EXIT_FAILURE;
+		}
+	}
+
+	rval = mediatext_poll(mt, fd);
+
+	mediatext_cleanup(mt);
+
+	media_device_unref(device);
+
+	return EXIT_SUCCESS;
+}
diff --git a/utils/media-ctl/mediatext.c b/utils/media-ctl/mediatext.c
new file mode 100644
index 0000000..b3b26a5
--- /dev/null
+++ b/utils/media-ctl/mediatext.c
@@ -0,0 +1,2176 @@
+/*
+ * Media controller text-based configuration library
+ *
+ * Copyright (C) 2013--2018 Intel Corporation
+ *
+ * Contact: Sakari Ailus <sakari.ailus@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <malloc.h>
+#include <poll.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <linux/types.h>
+
+#include "mediactl.h"
+#include "mediactl-priv.h"
+#include "tools.h"
+#include "v4l2subdev.h"
+
+struct {
+	char *string;
+	uint32_t pixelformat;
+} v4l2_pix_formats[] = {
+#include "v4l2-pix-formats.h"
+};
+
+#define container_of(ptr, type, field) \
+	((type *)((uintptr_t)ptr - (uintptr_t)&(((type *)NULL)->field)))
+
+#define array_length(a) (sizeof(a) / sizeof(*(a)))
+
+struct list {
+	struct list *next;
+	struct list *prev;
+};
+
+#define list_next(list) ((list)->next)
+#define list_first(list) list_next(list)
+#define list_last(list) list_prev(list)
+#define list_prev(list) ((list)->prev)
+
+static void list_init(struct list *list)
+{
+	list->next = list;
+	list->prev = list;
+}
+
+static bool list_empty(struct list *list)
+{
+	return list->next == list->prev;
+}
+
+static void list_add(struct list *list, struct list *item)
+{
+	item->next = list->next;
+	list->next->prev = item;
+	list->next = item;
+	item->prev = list;
+}
+
+static void list_add_tail(struct list *list, struct list *item)
+{
+	list_add(list_last(list), item);
+}
+
+static void list_del(struct list *item)
+{
+	item->prev->next = item->next;
+	item->next->prev = item->prev;
+	item->prev = item;
+	item->next = item;
+}
+
+#define list_for_each(list, iter)			      \
+	for (iter = list_next(list); iter != (list);	      \
+	     iter = list_next(iter))
+
+#define list_for_each_entry(list, entry, type, field)			\
+	for (entry = container_of(list_next(list), type, field);	\
+	     &entry->field != list;					\
+	     entry = container_of(list_next(&entry->field), type, field))
+
+struct name {
+	uint32_t id;
+	char *str;
+	struct list list;
+};
+
+void name_cleanup(struct name *name)
+{
+	free(name->str);
+	list_del(&name->list);
+}
+
+int name_init(struct list *list, struct name *name, uint32_t id, char *str)
+{
+	struct list *iter;
+
+	list_for_each(list, iter) {
+		struct name *n = container_of(iter, struct name, list);
+
+		if (!strcmp(n->str, str))
+			return -EEXIST;
+	}
+
+	name->str = strdup(str);
+	if (!name->str)
+		return -ENOMEM;
+
+	name->id = id;
+
+	list_add_tail(list, &name->list);
+
+	return 0;
+}
+
+struct name *name_find(struct list *list, char *str)
+{
+	struct list *iter;
+
+	list_for_each(list, iter) {
+		struct name *name = container_of(iter, struct name, list);
+
+		if (!strcmp(str, name->str))
+			return name;
+	}
+
+	return NULL;
+}
+
+struct name *name_find_by_id(struct list *list, unsigned int id)
+{
+	struct list *iter;
+
+	list_for_each(list, iter) {
+		struct name *name = container_of(iter, struct name, list);
+
+		if (id == name->id)
+			return name;
+	}
+
+	return NULL;
+}
+
+#define list_to_name(__list) container_of(__list, struct name, list)
+
+#define list_for_each_name(__list, __name) \
+	list_for_each_entry(__list, __name, struct name, list)
+
+struct mt_buf {
+	struct v4l2_buffer vb;
+	struct v4l2_plane planes[VIDEO_MAX_PLANES];
+	void *plane_ptrs[VIDEO_MAX_PLANES];
+	bool dirty;
+};
+
+struct mt_request {
+	struct name name;
+	unsigned int refcount;
+	bool queued;
+};
+
+struct v4l2_queue {
+	struct mt_buf *bufs;
+	unsigned int nbufs;
+	unsigned int queued;
+	uint32_t memory;
+	unsigned int type;
+	bool auto_rw;
+	bool auto_qbuf;
+	char *buf_fname;
+	struct timeval ts;
+	struct v4l2_format fmt;
+	struct v4l2_device *vdev;
+	bool streaming;
+};
+
+#define BUF_TYPES	(V4L2_BUF_TYPE_META_CAPTURE + 1)
+
+struct v4l2_device {
+	struct name name;
+	int fd;
+	dev_t dev;
+	struct v4l2_queue q[BUF_TYPES];
+	struct media_entity *entity;
+};
+
+struct media_text {
+	struct media_device *media;
+	struct list vdev_names;
+	struct list request_names;
+	unsigned int requests_queued;
+	bool verbose;
+	FILE *log;
+	bool quit;
+};
+
+struct media_text *mediatext_init(struct media_device *media)
+{
+	struct media_text *mt;
+
+	mt = calloc(1, sizeof(*mt));
+	if (!mt)
+		return NULL;
+
+	mt->media = media;
+	mt->log = stderr;
+
+	list_init(&mt->request_names);
+	list_init(&mt->vdev_names);
+
+	return mt;
+}
+
+static void v4l2_close(struct media_text *mt, struct v4l2_device *vdev);
+
+void mediatext_cleanup(struct media_text *mt)
+{
+	while (!list_empty(&mt->vdev_names)) {
+		struct name *name = list_to_name(list_first(&mt->vdev_names));
+		struct v4l2_device *vdev =
+			container_of(name, struct v4l2_device, name);
+
+		v4l2_close(mt, vdev);
+	}
+
+	if (mt && mt->log != stderr)
+		fclose(mt->log);
+	free(mt);
+}
+
+#define FLAG_ARGS_NONE		0x0001
+#define FLAG_ARGS_OPTIONAL	0x0002
+#define FLAG_MENU		0x0004
+
+struct parser {
+	char *prefix;
+	int (*parse)(struct media_text *media,
+		     char *string, bool help);
+	unsigned long flags;
+	char *help;
+};
+
+static void show_help(struct media_text *mt, const struct parser *p)
+{
+	while (p->prefix) {
+		fprintf(mt->log, "\t%s\n", p->prefix);
+		p++;
+	}
+}
+
+static int parse(struct media_text *mt, const struct parser *p, char *string,
+		 bool help)
+{
+	if (!string && help) {
+		show_help(mt, p);
+		return 0;
+	}
+
+	while (isspace(*string))
+		string++;
+
+	if (!*string)
+		return 0;
+
+	for (; p->prefix; p++) {
+		size_t len = strlen(p->prefix);
+		bool has_arg;
+		int rval;
+
+		if (strncmp(p->prefix, string, len))
+			continue;
+
+		string += len;
+
+		for (; isspace(*string); string++);
+
+		has_arg = strlen(string);
+
+		if (help && !has_arg) {
+			fprintf(mt->log, "%s\n", p->help);
+			return p->flags & FLAG_MENU ?
+				p->parse(mt, NULL, help) : 0;
+		}
+
+		if (p->flags & FLAG_ARGS_OPTIONAL)
+			return p->parse(mt, has_arg ? string : NULL, help);
+		else if (!(p->flags & FLAG_ARGS_NONE) && !has_arg)
+			return -ENOEXEC;
+		else
+			return p->parse(mt, string, help);
+
+		if (!help || !rval)
+			return rval;
+
+		return 0;
+
+	}
+
+	fprintf(mt->log,
+		"invalid command \"%s\"; use \"help\" for help\n",
+		string);
+
+	return 0;
+}
+
+#define MAX_ARG 32
+
+struct arg {
+	unsigned int n;
+	char *str;
+	struct pair {
+		char *key;
+		char *value;
+	} pair[MAX_ARG];
+};
+
+static int arg_parse(struct media_text *mt, struct arg *a, char *str)
+{
+	char *base;
+	char *end = str + strlen(str) + 1 /* \0 */;
+
+	memset(a, 0, sizeof(*a));
+
+	a->str = str;
+
+	for (base = str; *str && a->n < MAX_ARG && str < end; str++, base = str) {
+		while (isspace(*str))
+			str++;
+
+		a->pair[a->n].key = str;
+
+		for (; *str && *str != '='; str++)
+			if (isspace(*str))
+				*str = 0;
+
+		if (*str != '=') {
+			*str = 0;
+			a->n++;
+			break;
+		}
+
+		*str = 0;
+
+		str++;
+		base = str;
+
+		if (*str != '"') {
+			while (*str && !isspace(*str))
+				str++;
+			a->pair[a->n].value = base;
+			*str = 0;
+			a->n++;
+			continue;
+		}
+
+		/* Handle quoted strings */
+		if (!str[1]) {
+			fprintf(mt->log, "unmatched \" at %s\n", str);
+			return -EINVAL;
+		}
+
+		/* Copy the entire string on top of the quote mark */
+		memmove(str, str + 1, strlen(str));
+
+		while (*str && *str != '"') {
+			if (*str == '\\') {
+				if (str[1] != '"') {
+					fprintf(mt->log, "invalid \\ at %s\n",
+						str);
+					return -EINVAL;
+				} else {
+					memmove(base + 1, base, str - base);
+					base++;
+					*str = '"';
+				}
+			}
+			str++;
+		}
+		if (!*str) {
+			fprintf(mt->log, "unmatched \" at %s\n", str);
+			return -EINVAL;
+		}
+		*str = 0;
+		a->pair[a->n].value = base;
+		a->n++;
+	}
+
+	return 0;
+}
+
+struct pair *arg_pos(struct arg *a, unsigned int pos)
+{
+	if (pos >= a->n)
+		return NULL;
+
+	return &a->pair[pos];
+}
+
+static char *arg(struct arg *a, char *key)
+{
+	unsigned int pos;
+
+	for (pos = 0; pos < a->n; pos++) {
+		if (!strcmp(a->pair[pos].key, key))
+			return a->pair[pos].value;
+	}
+
+	return NULL;
+}
+
+enum param_type {
+	PARAM_TYPE_INT,
+	PARAM_TYPE_U32,
+	PARAM_TYPE_BOOL,
+	PARAM_TYPE_STRING,
+	PARAM_TYPE_V4L2_DEVICE,
+	PARAM_TYPE_MEMORY,
+	PARAM_TYPE_BUF_TYPE,
+	PARAM_TYPE_PIXELFORMAT,
+	PARAM_TYPE_MEDIA_REQ,
+};
+
+struct param {
+	char *key;
+	enum param_type type;
+	void *ptr;
+	bool optional;
+};
+
+static const char *buf_types[] = {
+	"",
+	"VIDEO_CAPTURE",
+	"VIDEO_OUTPUT",
+	"VIDEO_OVERLAY",
+	"VBI_CAPTURE",
+	"VBI_OUTPUT",
+	"SLICED_VBI_CAPTURE",
+	"SLICED_VBI_OUTPUT",
+	"VIDEO_OUTPUT_OVERLAY",
+	"VIDEO_CAPTURE_MPLANE",
+	"VIDEO_OUTPUT_MPLANE",
+	"SDR_CAPTURE",
+	"SDR_OUTPUT",
+	"META_CAPTURE",
+};
+
+static int get_buf_type(struct media_text *mt, char *s)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(buf_types); i++)
+		if (!strcmp(s, buf_types[i]))
+			return i;
+
+	fprintf(mt->log, "invalid buffer type %s\n", s);
+
+	return -EINVAL;
+}
+
+static int get_memory(struct media_text *mt, char *s)
+{
+	if (!strcmp(s, "MMAP"))
+		return V4L2_MEMORY_MMAP;
+	else if (!strcmp(s, "USERPTR"))
+		return V4L2_MEMORY_USERPTR;
+
+	printf("invalid memory %s\n", s);
+	return -EINVAL;
+}
+
+static int get_pixel_format(struct media_text *mt, char *s, uint32_t *pixelformat)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(v4l2_pix_formats); i++) {
+		if (strcmp(s, v4l2_pix_formats[i].string))
+			continue;
+
+		*pixelformat = v4l2_pix_formats[i].pixelformat;
+
+		return 0;
+	}
+
+	fprintf(mt->log, "can't find pixelformat \"%s\"\n", s);
+
+	return -ENOENT;
+}
+
+static struct v4l2_device *v4l2_device_find(struct media_text *mt, int fd)
+{
+	struct name *name;
+
+	list_for_each_name(&mt->vdev_names, name) {
+		struct v4l2_device *vdev =
+			container_of(name, struct v4l2_device, name);
+
+		if (vdev->fd != fd)
+			continue;
+
+		return vdev;
+	}
+
+	return NULL;
+}
+
+static void request_get(struct media_text *mt, struct mt_request *mtr)
+{
+	if (!mtr)
+		return;
+
+	mtr->refcount++;
+}
+
+static int request_close(struct mt_request *mtr)
+{
+	int fd;
+
+	name_cleanup(&mtr->name);
+	fd = mtr->name.id;
+	free(mtr);
+
+	close(fd);
+
+	return 0;
+}
+
+static void request_put(struct media_text *mt, struct mt_request *mtr)
+{
+	if (!mtr)
+		return;
+
+	if (!--mtr->refcount)
+		request_close(mtr);
+}
+
+static struct mt_request *request_find(struct media_text *mt, char *str)
+{
+	struct name *name;
+
+	name = name_find(&mt->request_names, str);
+	if (!name)
+		return NULL;
+
+	return container_of(name, struct mt_request, name);
+}
+
+static struct mt_request *request_find_by_fd(struct media_text *mt, int fd)
+{
+	struct name *name;
+
+	name = name_find_by_id(&mt->request_names, fd);
+
+	if (!name)
+		return NULL;
+
+	return container_of(name, struct mt_request, name);
+}
+
+static int request_poll(struct media_text *mt, int fd, short revents)
+{
+	struct mt_request *mtr;
+
+	mtr = request_find_by_fd(mt, fd);
+	if (!mtr) {
+		fprintf(mt->log, "invalid fd %d\n", fd);
+		return -EINVAL;
+	}
+
+	if (revents & POLLPRI) {
+		char buf[128];
+		int rval;
+
+		mtr->queued = false;
+		strncpy(buf, mtr->name.str, sizeof(buf));
+		request_put(mt, mtr);
+		fprintf(mt->log, "event=request-complete req=%s rval=%d\n",
+			buf, rval);
+		return 0;
+	}
+
+	fprintf(mt->log, "no events on fd %d\n", fd);
+
+	return 0;
+}
+
+static int arg_param(struct media_text *mt, struct arg *a, struct param *p)
+{
+	for (; p->key; p++) {
+		char *s = arg(a, p->key);
+
+		if (!s) {
+			if (p->optional)
+				continue;
+			fprintf(mt->log, "missing mandatory parameter \"%s\"\n",
+				p->key);
+			return -EINVAL;
+		}
+
+		switch (p->type) {
+		case PARAM_TYPE_INT:
+			*(int *)p->ptr = atoi(s);
+			break;
+		case PARAM_TYPE_U32:
+			*(uint32_t *)p->ptr = strtoul(s, NULL, 0);
+			break;
+		case PARAM_TYPE_BOOL:
+			*(bool *)p->ptr = !(strcasecmp(s, "true") && strcmp(s, "1"));
+			break;
+		case PARAM_TYPE_STRING:
+			*(char **)p->ptr = s;
+			break;
+		case PARAM_TYPE_V4L2_DEVICE: {
+			struct name *name = name_find(&mt->vdev_names, s);
+
+			if (name) {
+				*(struct v4l2_device **)p->ptr =
+					container_of(name, struct v4l2_device,
+						     name);
+				break;
+			}
+
+			*(struct v4l2_device **)p->ptr =
+				v4l2_device_find(mt, atoi(s));
+
+			if (!*(struct v4l2_device **)p->ptr) {
+				fprintf(mt->log,
+					"unable to find video device \"%s\"\n",
+					s);
+				return -EINVAL;
+			}
+			break;
+		}
+		case PARAM_TYPE_MEMORY: {
+			int memory = get_memory(mt, s);
+
+			if (memory < 0)
+				return memory;
+
+			*(uint32_t *)p->ptr = memory;
+			break;
+		}
+		case PARAM_TYPE_BUF_TYPE: {
+			int type = get_buf_type(mt, s);
+
+			if (type < 0)
+				return type;
+
+			*(uint32_t *)p->ptr = type;
+			break;
+		}
+		case PARAM_TYPE_PIXELFORMAT: {
+			uint32_t pixelformat;
+			int rval = get_pixel_format(mt, s, &pixelformat);
+
+			if (rval < 0)
+				return rval;
+
+			*(uint32_t *)p->ptr = pixelformat;
+			break;
+		}
+		case PARAM_TYPE_MEDIA_REQ: {
+			struct mt_request *mtr = request_find(mt, s);
+
+			if (!mtr)
+				return -ENOENT;
+
+			*(struct mt_request **)p->ptr = mtr;
+			break;
+		}
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int parse_param(struct media_text *mt, struct param *p, char *s)
+{
+	struct arg a;
+	int rval;
+
+	rval = arg_parse(mt, &a, s);
+	if (rval)
+		return rval;
+
+	return arg_param(mt, &a, p);
+}
+
+struct ctrl_type {
+	uint32_t type;
+	char *str;
+} ctrltypes[] = {
+	{ V4L2_CTRL_TYPE_INTEGER, "int" },
+	{ V4L2_CTRL_TYPE_MENU, "menu" },
+	{ V4L2_CTRL_TYPE_INTEGER_MENU, "intmenu" },
+	{ V4L2_CTRL_TYPE_BITMASK, "bitmask" },
+	{ V4L2_CTRL_TYPE_INTEGER64, "int64" },
+};
+
+static int parse_v4l2_ctrl(struct media_text *mt,
+			   char *string, bool help)
+{
+	struct v4l2_ext_control ctrl = { 0 };
+	struct v4l2_ext_controls ctrls = { .count = 1,
+					   .controls = &ctrl };
+	int64_t val;
+	int rval;
+	struct media_entity *entity;
+	struct ctrl_type *ctype;
+	unsigned int i;
+
+	entity = media_parse_entity(mt->media, string, &string);
+	if (!entity)
+		return -ENOENT;
+
+	for (i = 0; i < ARRAY_SIZE(ctrltypes); i++)
+		if (!strncmp(string, ctrltypes[i].str,
+			     strlen(ctrltypes[i].str)))
+			break;
+
+	if (i == ARRAY_SIZE(ctrltypes))
+		return -ENOENT;
+
+	ctype = &ctrltypes[i];
+
+	string += strlen(ctrltypes[i].str);
+	for (; isspace(*string); string++);
+	rval = sscanf(string, "0x%" PRIx32, &ctrl.id);
+	if (rval <= 0)
+		return -EINVAL;
+
+	for (; !isspace(*string) && *string; string++);
+	for (; isspace(*string); string++);
+
+	ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(ctrl.id);
+
+	switch (ctype->type) {
+	case V4L2_CTRL_TYPE_BITMASK:
+		if (*string++ != 'b')
+			return -EINVAL;
+		while (*string == '1' || *string == '0') {
+			val <<= 1;
+			if (*string == '1')
+				val++;
+			string++;
+		}
+		break;
+	default:
+		rval = sscanf(string, "%" PRId64, &val);
+		break;
+	}
+	if (rval <= 0)
+		return -EINVAL;
+
+	media_dbg(mt->media,
+		  "Setting control 0x%8.8x (type %s), value %" PRId64 "\n",
+		  ctrl.id, ctype->str, val);
+
+	if (ctype->type == V4L2_CTRL_TYPE_INTEGER64)
+		ctrl.value64 = val;
+	else
+		ctrl.value = val;
+
+	rval = v4l2_subdev_open(entity);
+	if (rval < 0)
+		return rval;
+
+	rval = ioctl(entity->fd, VIDIOC_S_EXT_CTRLS, &ctrls);
+	if (ctype->type != V4L2_CTRL_TYPE_INTEGER64) {
+		if (rval != -1) {
+			ctrl.value64 = ctrl.value;
+		} else if (ctype->type != V4L2_CTRL_TYPE_STRING &&
+			   (errno == EINVAL || errno == ENOTTY)) {
+			struct v4l2_control old = { .id = ctrl.id,
+						    .value = val };
+
+			rval = ioctl(entity->fd, VIDIOC_S_CTRL, &old);
+			if (rval != -1)
+				ctrl.value64 = old.value;
+		}
+	}
+	if (rval == -1) {
+		rval = -errno;
+		media_dbg(mt->media,
+			  "Failed setting control 0x8.8x: \"%s\" %d to value %"
+			  PRId64 "\n", ctrl.id, strerror(errno), errno, val);;
+		return rval;
+	}
+
+	if (val != ctrl.value64)
+		media_dbg(mt->media,
+			  "Asking for %" PRId64 ", got %" PRId64 "\n",
+			  val, ctrl.value64);
+
+	return 0;
+}
+
+static int parse_v4l2_subdev_fmt(struct media_text *mt,
+				 char *string, bool help)
+{
+	media_dbg(mt->media, "Media bus format setup: \"%s\"\n", string);
+	return v4l2_subdev_parse_setup_formats(mt->media, string);
+}
+
+static bool is_buf_type_capture(int type)
+{
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+	case V4L2_BUF_TYPE_SDR_CAPTURE:
+	case V4L2_BUF_TYPE_META_CAPTURE:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool is_buf_type_mplane(int type)
+{
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int v4l2_reqbufs_zero(struct media_text *mt, struct v4l2_queue *q)
+{
+	struct v4l2_requestbuffers rb = { .type = q->type,
+					  .count = 0,
+					  .memory = q->memory };
+	unsigned int i;
+	int rval;
+
+	if (q->streaming) {
+		fprintf(mt->log, "still streaming\n");
+		return -EBUSY;
+	}
+
+	for (i = 0; i < q->nbufs; i++) {
+		struct mt_buf *mb = &q->bufs[i];
+		unsigned int j;
+
+		for (j = 0; j < (is_buf_type_mplane(q->type) ?
+				 mb->vb.length : 1); j++) {
+
+			if (!mb->plane_ptrs[j])
+				continue;
+
+			munmap(mb->plane_ptrs[j], is_buf_type_mplane(q->type) ?
+			       mb->planes[j].length : mb->vb.length);
+		}
+	}
+
+	rval = ioctl(q->vdev->fd, VIDIOC_REQBUFS, &rb);
+	if (rval == -1)
+		return -errno;
+
+	free(q->bufs);
+	q->bufs = NULL;
+	q->nbufs = 0;
+
+	return 0;
+}
+
+static int v4l2_querybuf(struct v4l2_queue *q, unsigned int index)
+{
+	struct v4l2_buffer *vb = &q->bufs[index].vb;
+
+	vb->memory = q->memory;
+	vb->type = q->type;
+	vb->index = index;
+	vb->m.planes = q->bufs[index].planes;
+	vb->length = q->fmt.fmt.pix_mp.num_planes;
+
+	return ioctl(q->vdev->fd, VIDIOC_QUERYBUF, vb) == -1 ? -errno : 0;
+}
+
+static int parse_v4l2_reqbufs(struct media_text *mt, char *string, bool help)
+{
+	struct v4l2_requestbuffers rb = { 0 };
+	struct v4l2_device *vdev;
+	struct v4l2_queue *q;
+	struct param p[] = {
+		{ "vdev", PARAM_TYPE_V4L2_DEVICE, &vdev },
+		{ "type", PARAM_TYPE_BUF_TYPE, &rb.type },
+		{ "count", PARAM_TYPE_U32, &rb.count },
+		{ "memory", PARAM_TYPE_MEMORY, &rb.memory },
+		{ 0 },
+	};
+	unsigned int i;
+	int rval;
+
+	rval = parse_param(mt, p, string);
+	if (rval)
+		return rval;
+
+	if (!rb.count)
+		return v4l2_reqbufs_zero(mt, &vdev->q[rb.type]);
+
+	q = &vdev->q[rb.type];
+
+	if (q->nbufs) {
+		fprintf(mt->log, "buffers allocated already\n");
+		return -EINVAL;
+	}
+
+	q->bufs = calloc(rb.count, sizeof(*q->bufs));
+	if (!q->bufs)
+		return -ENOMEM;
+
+	rval = ioctl(vdev->fd, VIDIOC_REQBUFS, &rb);
+	if (rval == -1) {
+		rval = -errno;
+		goto out_release;
+	}
+
+	q->memory = rb.memory;
+	q->nbufs = rb.count;
+
+	for (i = 0; i < rb.count; i++) {
+		struct v4l2_buffer *vb = &q->bufs[i].vb;
+		struct v4l2_plane *planes = q->bufs[i].planes;
+		void **plane_ptrs = q->bufs[i].plane_ptrs;
+		unsigned int j;
+
+		rval = v4l2_querybuf(q, i);
+		if (rval) {
+			v4l2_reqbufs_zero(mt, q);
+			return rval;
+		}
+
+		for (j = 0; j < (is_buf_type_mplane(rb.type) ?
+				 vb->length : 1); j++) {
+			plane_ptrs[j] = mmap(
+				NULL, is_buf_type_mplane(rb.type) ?
+				planes[j].length : vb->length,
+				PROT_READ | PROT_WRITE, MAP_SHARED,
+				vdev->fd, is_buf_type_mplane(rb.type) ?
+				planes[j].m.mem_offset : vb->m.offset);
+
+			if (!plane_ptrs[j]) {
+				v4l2_reqbufs_zero(mt, q);
+				fprintf(mt->log, "failed to mmap %u/%u\n",
+					i, j);
+				return -ENOMEM;
+			}
+		}
+
+		vb->sequence = -1;
+
+	}
+
+	return 0;
+
+out_release:
+
+	return rval;
+}
+
+static int parse_v4l2_set_format(struct media_text *mt, char *string, bool help)
+{
+	struct v4l2_format fmt = { 0 };
+	struct v4l2_device *vdev = NULL;
+	struct arg a;
+	struct param p[] = {
+		{ "vdev", PARAM_TYPE_V4L2_DEVICE, &vdev, true },
+		{ "type", PARAM_TYPE_BUF_TYPE, &fmt.type },
+		{ "width", PARAM_TYPE_U32, &fmt.fmt.pix.width },
+		{ "height", PARAM_TYPE_U32, &fmt.fmt.pix.height },
+		{ "pixelformat", PARAM_TYPE_PIXELFORMAT, &fmt.fmt.pix.pixelformat },
+		{ 0 },
+	};
+	int rval;
+
+	rval = arg_parse(mt, &a, string);
+	if (rval)
+		return rval;
+
+	rval = arg_param(mt, &a, p);
+	if (rval)
+		return rval;
+
+	if (is_buf_type_mplane(fmt.type)) {
+		struct param pm[] = {
+			{ "num_planes", PARAM_TYPE_U32, &fmt.fmt.pix_mp.num_planes },
+			{ 0 },
+		};
+
+		rval = arg_param(mt, &a, pm);
+		if (rval)
+			return rval;
+
+		if (fmt.fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+			return -EINVAL;
+	} else {
+		struct param ps[] = {
+			{ "bytesperline", PARAM_TYPE_U32, &fmt.fmt.pix.bytesperline, true },
+			{ 0 },
+		};
+
+		rval = arg_param(mt, &a, ps);
+		if (rval)
+			return rval;
+	}
+
+	rval = ioctl(vdev->fd, VIDIOC_S_FMT, &fmt);
+	if (rval == -1)
+		return -errno;
+
+	vdev->q[fmt.type].fmt = fmt;
+
+#ifndef v4l2_fourcc_conv
+#define v4l2_fourcc_conv "%c%c%c%c%s"
+#endif
+
+#ifndef v4l2_fourcc_to_conv
+#define v4l2_fourcc_to_conv(fourcc)					\
+	(fourcc) & 0x7f, ((fourcc) >> 8) & 0x7f, ((fourcc) >> 16) & 0x7f, \
+	((fourcc) >> 24) & 0x7f, (fourcc) & (1 << 31) ? "-BE" : ""
+#endif
+
+	if (mt->verbose && !is_buf_type_mplane(fmt.type))
+		fprintf(mt->log, "%s: width %u, height %u, format "
+			v4l2_fourcc_conv ", bytesperline %u, sizeimage %u\n",
+			vdev->name.str, fmt.fmt.pix.width, fmt.fmt.pix.height,
+			v4l2_fourcc_to_conv(fmt.fmt.pix.pixelformat),
+			fmt.fmt.pix.bytesperline, fmt.fmt.pix.sizeimage);
+
+	return 0;
+}
+
+/* Get a buffer with oldest data to write to memory. */
+static struct mt_buf *oldest_seq_mb_data(struct v4l2_queue *q)
+{
+	struct mt_buf *best = NULL;
+	unsigned int i;
+
+	for (i = 0; i < q->nbufs; i++) {
+		struct mt_buf *this = &q->bufs[i];
+
+		if (this->vb.flags & (V4L2_BUF_FLAG_QUEUED |
+				      V4L2_BUF_FLAG_IN_REQUEST))
+			continue;
+
+		if (this->dirty != is_buf_type_capture(q->type))
+			continue;
+
+		if (!best ||
+		    (int)(best->vb.sequence - this->vb.sequence) > 0)
+			best = this;
+	}
+
+	return best;
+}
+
+/* Get a buffer, preferrably without dirty data for capture. */
+static struct mt_buf *oldest_seq_mb_buf(struct v4l2_queue *q)
+{
+	struct mt_buf *best = NULL;
+	unsigned int i;
+
+	for (i = 0; i < q->nbufs; i++) {
+		struct mt_buf *this = &q->bufs[i];
+
+		if (this->vb.flags & (V4L2_BUF_FLAG_QUEUED |
+				      V4L2_BUF_FLAG_IN_REQUEST))
+			continue;
+
+		if (best && this->dirty == is_buf_type_capture(q->type)
+		    && best->dirty != is_buf_type_capture(q->type))
+			continue;
+
+		if (!best ||
+		    (int)(best->vb.sequence - this->vb.sequence) > 0)
+			best = this;
+	}
+
+	return best;
+}
+
+static int do_read_write(struct media_text *mt, struct v4l2_queue *q,
+			 struct mt_buf *mb, char *fname)
+{
+	char __fname[strlen(fname) + 1 /* \0 */ + 20 /* buffer index + plane */];
+	char *pos = strchr(fname, '#');
+	char *ing = is_buf_type_capture(q->type) ? "writing" : "reading";
+	char *tofrom = is_buf_type_capture(q->type) ? "to" : "from";
+	unsigned int plane;
+	int fd;
+	int rval = 0;
+
+	if (!is_buf_type_capture(q->type)) {
+		struct timespec ts;
+
+		clock_gettime(CLOCK_MONOTONIC, &ts);
+		mb->vb.timestamp.tv_sec = ts.tv_sec;
+		mb->vb.timestamp.tv_usec = ts.tv_nsec / 1000;
+	}
+
+	if (!pos && is_buf_type_mplane(q->type))
+		pos = fname + strlen(fname);
+
+	for (plane = 0; plane < (is_buf_type_mplane(q->type)
+				 ? mb->vb.length : 1); plane++) {
+		char *plane_fname = fname;
+
+		if (pos) {
+			snprintf(__fname, sizeof(__fname),
+				 "%.*s%6.6" PRIu32 "-%1" PRIu32 "%s",
+				 (int)(pos - fname), fname,
+				 mb->vb.sequence, plane,
+				 *pos == '#' ? pos + 1 : pos);
+			plane_fname = __fname;
+		}
+
+		if (mt->verbose)
+			fprintf(mt->log,
+				"%s: %s plane %u %s \"%s\", buffer type %s, index %u\n",
+				q->vdev->name.str, ing, plane, tofrom, plane_fname,
+				buf_types[q->type], mb->vb.index);
+
+		if (is_buf_type_capture(q->type))
+			fd = open(plane_fname, O_CREAT | O_WRONLY | O_TRUNC,
+				  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
+				  | S_IROTH | S_IWOTH);
+		else
+			fd = open(plane_fname, O_RDONLY);
+		if (fd == -1) {
+			rval = -errno;
+			fprintf(mt->log, "can't open \"%s\", \"%s\"\n",
+				plane_fname, strerror(errno));
+			return rval;
+		}
+
+		if (is_buf_type_capture(q->type)) {
+			rval = write(fd, mb->plane_ptrs[plane],
+				     is_buf_type_mplane(q->type) ?
+				     mb->planes[plane].length : mb->vb.length);
+		} else {
+			rval = read(fd, mb->plane_ptrs[plane],
+				    is_buf_type_mplane(q->type) ?
+				    mb->planes[plane].length : mb->vb.length);
+			if (is_buf_type_mplane(q->type))
+				mb->planes[plane].bytesused = q->fmt.fmt.pix_mp.plane_fmt[plane].sizeimage;
+			else
+				mb->vb.bytesused = q->fmt.fmt.pix.sizeimage;
+		}
+		if (rval == -1)
+			rval = -errno;
+		else
+			rval = 0;
+		close(fd);
+		if (rval < 0) {
+			fprintf(mt->log, "%s %u bytes failed\n",
+				ing, is_buf_type_mplane(q->type) ?
+				mb->planes[plane].length : mb->vb.length);
+			goto err;
+		}
+	}
+
+	mb->dirty = !is_buf_type_capture(q->type);
+
+err:
+	return rval;
+}
+
+static int __v4l2_prepare_queue_buf(struct media_text *mt, struct v4l2_queue *q,
+				    unsigned int index, struct mt_request *mtr,
+				    bool queue)
+{
+	int ioctlcmd = queue ? VIDIOC_QBUF : VIDIOC_PREPARE_BUF;
+	struct mt_buf *mb = &q->bufs[index];
+	int rval;
+
+	if (mtr) {
+		mb->vb.request_fd = mtr->name.id;
+		mb->vb.flags |= V4L2_BUF_FLAG_REQUEST_FD;
+	} else {
+		mb->vb.flags &= ~V4L2_BUF_FLAG_REQUEST_FD;
+	}
+
+	if (q->auto_rw && !is_buf_type_capture(q->type)) {
+		rval = do_read_write(mt, q, mb, q->buf_fname);
+		if (rval == -1)
+			return -errno;
+	}
+
+	if (mt->verbose)
+		fprintf(mt->log, "%s: %s %s buffer %u request %s\n",
+			q->vdev->name.str,
+			queue ? "queueing" : "preparing",
+			buf_types[q->type], index, mtr ? mtr->name.str : "nul");
+
+	rval = ioctl(q->vdev->fd, ioctlcmd, &mb->vb);
+	if (rval == -1) {
+		rval = errno;
+		fprintf(mt->log, "cannot queue buffer %u, error %d \"%s\"\n",
+			index, rval, strerror(rval));
+		return -rval;
+	}
+
+	request_get(mt, mtr);
+
+	q->queued++;
+
+	return 0;
+}
+
+static int v4l2_prepare_queue_buf(struct media_text *mt, char *string,
+				  bool queue)
+{
+	struct v4l2_device *vdev;
+	struct v4l2_queue *q;
+	uint32_t index = -1, count = 1, type;
+	struct mt_request *mtr = NULL;
+	struct arg a;
+	struct param p[] = {
+		{ "vdev", PARAM_TYPE_V4L2_DEVICE, &vdev },
+		{ "index", PARAM_TYPE_U32, &index, true },
+		{ "count", PARAM_TYPE_U32, &count, true },
+		{ "type", PARAM_TYPE_BUF_TYPE, &type },
+		{ "req", PARAM_TYPE_MEDIA_REQ, &mtr, true },
+		{ 0 },
+	};
+	int rval;
+
+	rval = arg_parse(mt, &a, string);
+	if (rval)
+		return rval;
+
+	rval = arg_param(mt, &a, p);
+	if (rval)
+		return rval;
+
+	q = &vdev->q[type];
+	{
+		struct param p2[] = {
+			{ "auto-qbuf", PARAM_TYPE_BOOL, &q->auto_qbuf, true },
+			{ 0 },
+		};
+
+		rval = arg_param(mt, &a, p2);
+		if (rval)
+			return rval;
+	}
+
+	if (mtr) {
+		if (q->auto_qbuf) {
+			fprintf(mt->log,
+				"auto-qbuf not possible with requests\n");
+			return -EINVAL;
+		}
+	}
+
+	if (index == -1) {
+		struct mt_buf *mb = oldest_seq_mb_buf(q);
+
+		if (!mb) {
+			fprintf(mt->log,
+				"no free buffers available\n");
+			return -EINVAL;
+		}
+
+		index = mb->vb.index;
+	}
+
+	if (index != -1) {
+		if (count != 1) {
+			fprintf(mt->log, "can't set both index and count\n");
+			return -EINVAL;
+		}
+
+		__v4l2_prepare_queue_buf(mt, q, index, mtr, queue);
+
+		return 0;
+	}
+
+	for (index = 0; count && index < q->nbufs;
+	     index++) {
+		if (q->bufs[index].vb.flags & V4L2_BUF_FLAG_QUEUED)
+			continue;
+
+		__v4l2_prepare_queue_buf(mt, q, index, NULL, queue);
+
+		count--;
+	}
+	if (index == q->nbufs && count) {
+		fprintf(mt->log, "no available buffers\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int parse_v4l2_prepare_buf(struct media_text *mt, char *string, bool help)
+{
+	return v4l2_prepare_queue_buf(mt, string, false);
+}
+
+static int parse_v4l2_qbuf(struct media_text *mt, char *string, bool help)
+{
+	return v4l2_prepare_queue_buf(mt, string, true);
+}
+
+static struct mt_buf *mt_buf_seq(struct v4l2_queue *q, uint32_t sequence)
+{
+	unsigned int i;
+
+	for (i = 0; i < q->nbufs; i++) {
+		struct mt_buf *this = &q->bufs[i];
+
+		if (this->vb.flags & (V4L2_BUF_FLAG_QUEUED |
+				      V4L2_BUF_FLAG_IN_REQUEST))
+			continue;
+
+		if (this->dirty != is_buf_type_capture(q->type))
+			continue;
+
+		if (this->vb.sequence == sequence)
+			return this;
+	}
+
+	return NULL;
+}
+
+static int parse_v4l2_read_write(struct media_text *mt, char *string, bool help)
+{
+	struct v4l2_device *vdev;
+	struct v4l2_queue *q;
+	char *fname = NULL;
+	uint32_t sequence = -1, type;
+	struct param p[] = {
+		{ "vdev", PARAM_TYPE_V4L2_DEVICE, &vdev },
+		{ "type", PARAM_TYPE_BUF_TYPE, &type },
+		{ "fname", PARAM_TYPE_STRING, &fname, true },
+		{ "sequence", PARAM_TYPE_U32, &sequence, true },
+		{ 0 },
+	};
+	struct arg a;
+	struct mt_buf *mb;
+	int rval;
+
+	rval = arg_parse(mt, &a, string);
+	if (rval)
+		return rval;
+
+	rval = arg_param(mt, &a, p);
+	if (rval)
+		return rval;
+
+	q = &vdev->q[type];
+
+	{
+		struct param p2[] = {
+			{ "auto", PARAM_TYPE_BOOL, &q->auto_rw, true },
+			{ 0 },
+		};
+		rval = arg_param(mt, &a, p2);
+		if (rval)
+			return rval;
+	}
+
+	if (fname) {
+		free(q->buf_fname);
+		q->buf_fname = strdup(fname);
+		if (!q->buf_fname) {
+			q->auto_rw = false;
+			return -ENOMEM;
+		}
+	} else {
+		fname = q->buf_fname;
+	}
+	if (!fname)
+		return -EINVAL;
+
+	if (q->auto_rw)
+		return 0;
+
+	mb = mt_buf_seq(q, sequence);
+	if (!mb)
+		mb = oldest_seq_mb_data(q);
+	if (!mb)
+		return -ENODATA;
+
+	return do_read_write(mt, q, mb, fname);
+}
+
+static int v4l2_dqbuf(struct media_text *mt, struct v4l2_queue *q)
+{
+	struct v4l2_device *vdev = q->vdev;
+	struct v4l2_plane planes[VIDEO_MAX_PLANES];
+	struct v4l2_buffer vb = {
+		.type = q->type,
+		.memory = q->memory,
+	};
+	int rval;
+
+	if (is_buf_type_mplane(q->type)) {
+		vb.length = VIDEO_MAX_PLANES;
+		vb.m.planes = planes;
+	}
+
+	rval = ioctl(vdev->fd, VIDIOC_DQBUF, &vb);
+	if (rval == -1) {
+		rval = -errno;
+		if (rval != -EAGAIN)
+			fprintf(mt->log, "dqbuf failed, %s\n", strerror(errno));
+		return rval;
+	}
+
+	q->queued--;
+
+	q->bufs[vb.index].vb = vb;
+	q->bufs[vb.index].dirty = is_buf_type_capture(q->type);
+
+	{
+		float fps = vb.timestamp.tv_sec || vb.timestamp.tv_usec ?
+			1000000. / (float)(
+				(vb.timestamp.tv_sec - q->ts.tv_sec) * 1000000 +
+				vb.timestamp.tv_usec - q->ts.tv_usec) : 0.;
+		struct mt_request *mtr = request_find_by_fd(mt, vb.request_fd);
+
+		fprintf(mt->log,
+			"event=dqbuf req=%s entity=\"%s\" vdev=%s type=%s index=%u seq=%u ts=%lu.%6.6lu fps=%.3f\n",
+			mtr ? mtr->name.str : "nul",
+			media_entity_get_info(vdev->entity)->name,
+			vdev->name.str, buf_types[q->type], vb.index, vb.sequence,
+			(unsigned long)vb.timestamp.tv_sec,
+			(unsigned long)vb.timestamp.tv_usec, fps);
+
+		request_put(mt, mtr);
+	}
+
+	q->ts = vb.timestamp;
+
+	if (q->auto_rw && is_buf_type_capture(q->type))
+		do_read_write(mt, q, &q->bufs[vb.index], q->buf_fname);
+
+	if (q->auto_qbuf) {
+		if (q->auto_rw && !is_buf_type_capture(q->type))
+			do_read_write(mt, q, &q->bufs[vb.index], q->buf_fname);
+		rval = ioctl(vdev->fd, VIDIOC_QBUF, &vb);
+		if (rval == -1) {
+			fprintf(mt->log, "event=error error=\"queueing buffer %u failed \"%s\"\"\n",
+				vb.index, strerror(errno));
+			return 0;
+		}
+		q->queued--;
+	}
+
+	return 0;
+}
+
+static int v4l2_poll(struct media_text *mt, int fd, short revents)
+{
+	struct v4l2_device *vdev;
+
+	vdev = v4l2_device_find(mt, fd);
+	if (!vdev) {
+		fprintf(mt->log, "invalid fd %d\n", fd);
+		return -EINVAL;
+	}
+
+	if (revents & (POLLIN | POLLOUT)) {
+		unsigned int i;
+		bool has_buf = false;
+
+		for (i = 0; i < BUF_TYPES; i++)
+			if (vdev->q[i].streaming &&
+			    !v4l2_dqbuf(mt, &vdev->q[i]))
+				has_buf = true;
+
+		if (has_buf)
+			return 0;
+	}
+
+	fprintf(mt->log, "no events on fd %d\n", fd);
+
+	return 0;
+}
+
+static int set_stream(struct media_text *mt, char *string, bool enable)
+{
+	struct v4l2_device *vdev;
+	struct v4l2_queue *q;
+	uint32_t type;
+	struct param p[] = {
+		{ "vdev", PARAM_TYPE_V4L2_DEVICE, &vdev },
+		{ "type", PARAM_TYPE_BUF_TYPE, &type },
+		{ 0 },
+	};
+	int rval;
+
+	rval = parse_param(mt, p, string);
+	if (rval)
+		return rval;
+
+	q = &vdev->q[type];
+
+	if (enable) {
+		q->ts.tv_sec = q->ts.tv_usec = 0;
+		rval = ioctl(vdev->fd, VIDIOC_STREAMON, &type);
+	} else {
+		unsigned int i;
+
+		rval = ioctl(vdev->fd, VIDIOC_STREAMOFF, &type);
+
+		for (i = 0; i < q->nbufs; i++)
+			v4l2_querybuf(q, i);
+
+		q->queued = 0;
+	}
+
+	if (rval)
+		return -errno;
+
+	q->streaming = enable;
+
+	return 0;
+}
+
+static int parse_v4l2_streamon(struct media_text *mt, char *string, bool help)
+{
+	return set_stream(mt, string, true);
+}
+
+static int parse_v4l2_streamoff(struct media_text *mt, char *string, bool help)
+{
+	return set_stream(mt, string, false);
+}
+
+static int parse_v4l2_open(struct media_text *mt, char *string, bool help)
+{
+	struct media_entity *entity;
+	const char *node, *source_fname;
+	struct stat stat;
+	struct name *name;
+	char *s;
+	char *n = NULL;
+	struct param p[] = {
+		{ "entity", PARAM_TYPE_STRING, &s },
+		{ "name", PARAM_TYPE_STRING, &n, true },
+		{ 0 },
+	};
+	struct v4l2_device *vdev = NULL;
+	unsigned int i;
+	int fd;
+	int rval;
+
+	rval = parse_param(mt, p, string);
+	if (rval)
+		return rval;
+
+	entity = media_get_entity_by_name(mt->media, s);
+	if (!entity) {
+		fprintf(mt->log, "can't find entity \"%s\"\n", s);
+		return -ENOENT;
+	}
+
+	node = media_entity_get_devname(entity);
+	if (!node) {
+		fprintf(mt->log, "can't find device node for entity\n");
+		return -ENOENT;
+	}
+
+	source_fname = rindex(node, '/');
+	if (n)
+		source_fname = n;
+	else if (source_fname)
+		source_fname++;
+	else
+		source_fname = node;
+
+	fd = open(node, O_RDWR | O_NONBLOCK);
+	if (fd == -1) {
+		return -errno;
+	}
+
+	rval = fstat(fd, &stat);
+	if (rval == -1) {
+		rval = -errno;
+		goto err_close;
+	}
+
+	list_for_each_name(&mt->vdev_names, name) {
+		struct v4l2_device *__vdev =
+			container_of(name, struct v4l2_device, name);
+
+		if (__vdev->dev == stat.st_rdev) {
+			rval = -EEXIST;
+			goto err_close;
+		}
+	}
+
+	vdev = calloc(1, sizeof(*vdev));
+	if (!vdev) {
+		rval = -ENOMEM;
+		goto err_close;
+	}
+
+	if (n) {
+		rval = name_init(&mt->vdev_names, &vdev->name, fd, n);
+		if (rval)
+			goto err_close;
+	}
+
+	vdev->fd = fd;
+	vdev->entity = entity;
+	vdev->dev = stat.st_rdev;
+
+	for (i = 0; i < BUF_TYPES; i++) {
+		struct v4l2_queue *q = &vdev->q[i];
+
+		q->vdev = vdev;
+		q->type = i;
+
+#define SUFFIX	".bin"
+		q->buf_fname = malloc(strlen(source_fname) + 1 /* \0 */
+				      + 3 /* - * 3 */
+				      + 2 /* [type] */
+				      + 20 /* index and plane */
+				      + strlen(SUFFIX));
+		if (!q->buf_fname)
+			goto err_close;
+
+		sprintf(q->buf_fname, "%s-%s-#" SUFFIX, source_fname, buf_types[i]);
+	}
+
+	fprintf(mt->log, "event=return which=\"v4l open\" dev=\"%s\" name=\"%s\" fd=%d node=%u.%u\n",
+		s, n, fd, major(stat.st_rdev), minor(stat.st_rdev));
+
+	return 0;
+
+err_close:
+	for (i = 0; i < BUF_TYPES; i++) {
+		struct v4l2_queue *q = &vdev->q[i];
+
+		free(q->buf_fname);
+	}
+
+	free(vdev);
+	close(fd);
+
+	return rval;
+}
+
+static void v4l2_close(struct media_text *mt, struct v4l2_device *vdev)
+{
+	unsigned int i;
+
+	for (i = 0; i < BUF_TYPES; i++)
+		v4l2_reqbufs_zero(mt, &vdev->q[i]);
+
+	close(vdev->fd);
+	name_cleanup(&vdev->name);
+	free(vdev);
+}
+
+static int parse_v4l2_close(struct media_text *mt, char *string, bool help)
+{
+	struct v4l2_device *vdev;
+	struct param p[] = {
+		{ "vdev", PARAM_TYPE_V4L2_DEVICE, &vdev },
+		{ 0 },
+	};
+	int rval;
+
+	rval = parse_param(mt, p, string);
+	if (rval)
+		return rval;
+
+	v4l2_close(mt, vdev);
+
+	return 0;
+}
+
+static int parse_verbose(struct media_text *mt, char *string, bool help)
+{
+	mt->verbose = !strcasestr(string, "true") || !strstr(string, "1");
+
+	return 0;
+}
+
+#define HELP_TYPES "type [CAPTURE|CAPTURE_MPLANE]\n"
+
+static const struct parser v4l2_parsers[] = {
+	{ "ctrl", parse_v4l2_ctrl, 0, "set V4L2 control" },
+	{ "subdev-fmt", parse_v4l2_subdev_fmt, 0, "set sub-device format" },
+	{ "reqbufs", parse_v4l2_reqbufs, 0, "request buffers\n\narguments:\nfd\n" HELP_TYPES "count\nmemory [USERPTR|MMAP]" },
+	{ "fmt", parse_v4l2_set_format, 0, "set pixel format\n\narguments:\nfd\n" HELP_TYPES "width\nheight\npixelformat\nbytesperline\n" },
+	{ "qbuf", parse_v4l2_qbuf, 0, "queue a buffer\n\narguments:\nfd\n" HELP_TYPES "index (optional)\ncount (optional)\nauto-qbuf=[true|false] (optional)" },
+	{ "prepare-buf", parse_v4l2_prepare_buf, 0, "prepare a buffer\n\narguments:\nfd\n" HELP_TYPES "index (optional)\ncount (optional)\nauto-qbuf=[true|false] (optional)\nreq" },
+	{ "io", parse_v4l2_read_write, 0, "read or write buffer contents to a file\n\narguments:\nfd\n" HELP_TYPES "fname (# will be replaced by sequence)\nauto=[true|false] (optional)" },
+	{ "streamon", parse_v4l2_streamon, 0, "start streaming\n\narguments:\nfd\n" HELP_TYPES },
+	{ "streamoff", parse_v4l2_streamoff, 0, "stop streaming\n\narguments:\nfd\n" HELP_TYPES },
+	{ "open", parse_v4l2_open, 0, "open a video node\n\narguments:\nentity\nname --- name of the device; vdev for other commands" },
+	{ "close", parse_v4l2_close, 0, "close a video node\n\narguments:\nfile desriptor" },
+	{ 0 }
+};
+
+static int parse_v4l2(struct media_text *mt, char *string, bool help)
+{
+	return parse(mt, v4l2_parsers, string, help);
+}
+
+static int parse_media_link_reset(struct media_text *mt, char *string,
+				  bool help)
+{
+	media_dbg(mt->media, "Resetting links\n");
+	return media_reset_links(mt->media);
+}
+
+static int parse_media_link_setup(struct media_text *mt,
+				  char *string,
+				  bool help)
+{
+	media_dbg(mt->media, "Setting up links: %s\n", string);
+	return media_parse_setup_links(mt->media, string);
+}
+
+static int media_ioctl_req_alloc(struct media_text *mt, struct mt_request *mtr)
+{
+	struct media_request_alloc new = { 0 };
+	int rval;
+
+	rval = media_device_open(mt->media);
+	if (rval < 0)
+		return rval;
+
+	rval = ioctl(media_device_fd(mt->media), MEDIA_IOC_REQUEST_ALLOC,
+		     &new);
+	media_device_close(mt->media);
+	if (rval == -1) {
+		rval = -errno;
+		if (mt->verbose)
+			fprintf(mt->log, "cannot allocate request \"%s\"\n",
+				strerror(-rval));
+		return rval;
+	}
+
+	return new.fd;
+}
+
+static int media_ioctl_req_queue(struct media_text *mt, struct mt_request *mtr)
+{
+	int rval;
+
+	rval = ioctl((int)mtr->name.id, MEDIA_REQUEST_IOC_QUEUE);
+	if (rval == -1) {
+		rval = -errno;
+		if (mt->verbose)
+			fprintf(mt->log,
+				"queueing request %u \"%s\" failed \"%s\"\n",
+				mtr->name.id, mtr->name.str,
+				strerror(-rval));
+		return rval;
+	}
+
+	return 0;
+}
+
+static int parse_media_req_create(struct media_text *mt, char *string,
+				  bool help)
+{
+	char *req_name;
+	struct param p[] = {
+		{ "req", PARAM_TYPE_STRING, &req_name },
+		{ 0 },
+	};
+	struct mt_request *mtr;
+	int fd, rval;
+
+	rval = parse_param(mt, p, string);
+	if (rval)
+		return rval;
+
+	if (name_find(&mt->request_names, req_name))
+		return -EEXIST;
+
+	mtr = calloc(1, sizeof(*mtr));
+	if (!mtr)
+		return -ENOMEM;
+
+	fd = rval = media_ioctl_req_alloc(mt, mtr);
+	if (rval < 0)
+		goto out_free_mtr;
+
+	rval = name_init(&mt->request_names, &mtr->name, fd, req_name);
+	if (rval)
+		goto out_fd_close;
+
+	mtr->refcount = 1;
+
+	return 0;
+
+out_fd_close:
+	close(fd);
+
+out_free_mtr:
+	free(mtr);
+
+	return rval;
+}
+
+static int parse_media_req_list(struct media_text *mt, char *string,
+				bool help)
+{
+	struct name *name;
+
+	list_for_each_name(&mt->request_names, name) {
+		struct mt_request *mr =
+			container_of(name, struct mt_request, name);
+
+		fprintf(mt->log, "request %u, name %s\n",
+			mr->name.id, mr->name.str);
+	}
+
+	return 0;
+}
+
+static int parse_media_req_close(struct media_text *mt, char *string,
+				 bool help)
+{
+	struct mt_request *mtr;
+	struct param p[] = {
+		{ "req", PARAM_TYPE_MEDIA_REQ, &mtr },
+		{ 0 },
+	};
+	int rval;
+
+	rval = parse_param(mt, p, string);
+	if (rval)
+		return rval;
+
+	return request_close(mtr);
+}
+
+static int parse_media_req_queue(struct media_text *mt, char *string,
+				 bool help)
+{
+	struct mt_request *mtr;
+	struct param p[] = {
+		{ "req", PARAM_TYPE_MEDIA_REQ, &mtr },
+		{ 0 },
+	};
+	int rval;
+
+	rval = parse_param(mt, p, string);
+	if (rval)
+		return rval;
+
+	rval = media_ioctl_req_queue(mt, mtr);
+	if (rval)
+		return rval;
+
+	mt->requests_queued++;
+	mtr->queued = true;
+
+	return 0;
+}
+
+static const struct parser media_parsers[] = {
+	{ "link-reset", parse_media_link_reset, FLAG_ARGS_NONE, "reset all links" },
+	{ "link-setup", parse_media_link_setup, 0, "enable or disable a link" },
+	{ "req-create", parse_media_req_create, 0, "create media request\n\nreq=requestname" },
+	{ "req-list", parse_media_req_list, FLAG_ARGS_NONE, "list media requests" },
+	{ "req-close", parse_media_req_close, 0, "close media request" },
+	{ "req-queue", parse_media_req_queue, 0, "queue media request" },
+	{ 0 }
+};
+
+static int parse_media(struct media_text *mt,
+		       char *string, bool help)
+{
+	return parse(mt, media_parsers, string, help);
+}
+
+static int parse_help(struct media_text *mt,
+		      char *string, bool help);
+
+static int file_reopen(struct media_text *mt, FILE **file, char *fname)
+{
+	FILE *log;
+
+	log = fopen(fname, "w");
+	if (!log) {
+		fprintf(mt->log, "can't fopen \"%s\"\n", fname);
+		return -EINVAL;
+	}
+
+	setvbuf(log, NULL, _IONBF, 0);
+
+	if (*file != stderr)
+		fclose(*file);
+	*file = log;
+
+	return 0;
+}
+
+static int parse_log(struct media_text *mt, char *string, bool help)
+{
+	char *fname;
+	struct param p[] = {
+		{ "fname", PARAM_TYPE_STRING, &fname },
+		{ 0 },
+	};
+	int rval;
+
+	rval = parse_param(mt, p, string);
+	if (rval)
+		return rval;
+
+	return file_reopen(mt, &mt->log, fname);
+}
+
+static int parse_quit(struct media_text *mt, char *string, bool help)
+{
+	mt->quit = true;
+
+	return 0;
+}
+
+static const struct parser parsers[] = {
+	{ "v4l", parse_v4l2, FLAG_MENU, "V4L2", },
+	{ "media", parse_media, FLAG_MENU, "Media controller", },
+	{ "help", parse_help, FLAG_ARGS_OPTIONAL, "help!", },
+	{ "log", parse_log, 0, "log errors to a file\n\narguments:\nfname\n", },
+	{ "verbose", parse_verbose, 0, "set verbose flag\n\narguments:\ntrue|false" },
+	{ "quit", parse_quit, FLAG_ARGS_OPTIONAL, "quit\n", },
+	{ 0 }
+};
+
+static int parse_help(struct media_text *mt,
+		      char *string, bool help)
+{
+	if (!string) {
+		fprintf(mt->log, "help topics\n");
+		show_help(mt, parsers);
+		return 0;
+	}
+
+	return parse(mt, parsers, string, true);
+}
+
+int mediatext_parse(struct media_text *mt, char *string)
+{
+	return parse(mt, parsers, string, false);
+}
+
+static int mediatext_read(struct media_text *mt, char *buf, size_t bufsize,
+			  size_t *pos, int fd)
+{
+	size_t len = read(fd, buf + *pos, bufsize - *pos - 1);
+	unsigned int i;
+	bool eof = !len;
+	int rval;
+
+	if (len == -1)
+		return -errno;
+
+	if (eof) {
+		mediatext_parse(mt, buf);
+		*buf = 0;
+		*pos = 0;
+		return 0;
+	}
+
+	buf[*pos + len] = 0;
+
+next:
+	for (i = *pos ? *pos - 1 : 0; i < *pos + len; i++) {
+
+		if (buf[i] == '\\' && i < *pos + len + 1
+		    && buf[i + 1] == '\n') {
+			len -= 2;
+			memmove(buf + i, buf + i + 2, len - i + *pos);
+			i--;
+			continue;
+		}
+		/*
+		 * Split input into lines, and handle the last
+		 * line before eof as well.
+		 */
+		if (buf[i] != '\0' && buf[i] != '\n' && !eof)
+			continue;
+
+		buf[i] = '\0';
+
+		rval = mediatext_parse(mt, buf);
+		if (rval) {
+			unsigned int j;
+
+			for (j = 0; j < i; j++)
+				if (!buf[j])
+					buf[j] = ' ';
+
+			fprintf(mt->log, "event=error error=\"%s\" command=\"%s\"\n",
+				strerror(-rval), buf);
+		}
+
+		len -= i - *pos + 1;
+		*pos = 0;
+		*buf = 0;
+		if (len)
+			memmove(buf, buf + i + 1, len);
+
+		goto next;
+	}
+
+	*pos = i;
+
+	return !eof;
+}
+
+int mediatext_poll(struct media_text *mt, int fd)
+{
+	char buf[4096];
+	size_t buf_pos = 0;
+	unsigned int poll_nfds = 0, poll_v4l2_pos = 0, poll_nfds_max = 0;
+	struct pollfd *fds = NULL;
+	int rval;
+
+	rval = fcntl(fd, F_SETFL, O_NONBLOCK);
+	if (rval == -1) {
+		fprintf(mt->log, "fcntl\n");
+		return -errno;
+	}
+
+	rval = -1;
+
+	do {
+		struct name *name;
+		unsigned int i;
+
+		if (!rval)
+			return 0;
+
+		for (i = 1; i < poll_v4l2_pos; i++) {
+			if (!(fds[i].revents & (POLLIN | POLLOUT)))
+				continue;
+
+			rval = v4l2_poll(mt, fds[i].fd, fds[i].revents);
+			if (rval < 0)
+				goto out_free;
+		}
+
+		for (; i < poll_nfds; i++) {
+			if (!(fds[i].revents & POLLPRI))
+				continue;
+
+			rval = request_poll(mt, fds[i].fd, fds[i].revents);
+			if (rval < 0)
+				goto out_free;
+		}
+
+		if (fds && fds[0].revents & POLLIN) {
+			rval = mediatext_read(mt, buf, sizeof(buf),
+					      &buf_pos, fd);
+			switch (rval) {
+			case 0:
+				errno = 0;
+				/* Fall through */
+			case -1:
+				goto out_free;
+			}
+		}
+
+		/* Get number of file descriptors to poll */
+		poll_nfds = 1;
+
+		list_for_each_name(&mt->vdev_names, name)
+			poll_nfds++;
+
+		list_for_each_name(&mt->request_names, name) {
+			struct mt_request *mtr =
+				container_of(name, struct mt_request, name);
+
+			if (mtr->queued)
+				poll_nfds++;
+		}
+
+		/* Reallocate space required for poll file descriptors */
+		if (poll_nfds > poll_nfds_max) {
+			fds = realloc(fds, poll_nfds * sizeof(*fds));
+			if (!fds) {
+				rval = -ENOMEM;
+				goto out_free;
+			}
+			poll_nfds_max = poll_nfds;
+		}
+
+		/* Fill in poll file descriptors */
+		fds[0].fd = fd;
+		fds[0].events = POLLIN;
+
+		poll_v4l2_pos = 1;
+
+		list_for_each_name(&mt->vdev_names, name) {
+			struct v4l2_device *vdev =
+				container_of(name, struct v4l2_device, name);
+			unsigned int i;
+
+			for (i = 0; i < BUF_TYPES; i++) {
+				struct v4l2_queue *q = &vdev->q[i];
+
+				if (!q->streaming)
+					continue;
+
+				if (!q->queued)
+					continue;
+
+				fds[poll_v4l2_pos].fd = vdev->fd;
+				fds[poll_v4l2_pos].events = POLLIN | POLLOUT;
+				poll_v4l2_pos++;
+
+				break;
+			}
+		}
+
+		poll_nfds = poll_v4l2_pos;
+
+		list_for_each_name(&mt->request_names, name) {
+			struct mt_request *mtr =
+				container_of(name, struct mt_request, name);
+
+			if (!mtr->queued)
+				continue;
+
+			fds[poll_nfds].fd = name->id;
+			fds[poll_nfds].events = POLLPRI;
+			poll_nfds++;
+		}
+
+	} while (!mt->quit && (rval = poll(fds, poll_nfds, -1)) != -1);
+
+out_free:
+	free(fds);
+
+	return rval ? -errno : 0;
+}
diff --git a/utils/media-ctl/mediatext.h b/utils/media-ctl/mediatext.h
new file mode 100644
index 0000000..53167e8
--- /dev/null
+++ b/utils/media-ctl/mediatext.h
@@ -0,0 +1,33 @@
+/*
+ * Media controller text-based configuration library
+ *
+ * Copyright (C) 2013--2016 Intel Corporation
+ *
+ * Contact: Sakari Ailus <sakari.ailus@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MEDIATEXT_H__
+#define __MEDIATEXT_H__
+
+struct media_device;
+struct media_text;
+
+struct media_text *mediatext_init(struct media_device *media);
+void mediatext_cleanup(struct media_text *mt);
+int mediatext_poll(struct media_text *mt, int fd);
+int mediatext_parse(struct media_text *mt, char *string);
+
+#endif /* __MEDIATEXT_H__ */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [v4l-utils RFC 6/6] mediatext: Add vivid tests
  2018-04-05 10:58 [v4l-utils RFC 0/6] Mediatext test program for request API tests Sakari Ailus
                   ` (4 preceding siblings ...)
  2018-04-05 10:58 ` [v4l-utils RFC 5/6] mediatext: Add library Sakari Ailus
@ 2018-04-05 10:58 ` Sakari Ailus
  5 siblings, 0 replies; 7+ messages in thread
From: Sakari Ailus @ 2018-04-05 10:58 UTC (permalink / raw)
  To: linux-media; +Cc: tfiga, hverkuil

Add two scripts for vivid tests, with and without using requests.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 utils/media-ctl/tests/test-vivid-mc.bash | 86 ++++++++++++++++++++++++++++++++
 utils/media-ctl/tests/test-vivid.bash    | 59 ++++++++++++++++++++++
 2 files changed, 145 insertions(+)
 create mode 100755 utils/media-ctl/tests/test-vivid-mc.bash
 create mode 100755 utils/media-ctl/tests/test-vivid.bash

diff --git a/utils/media-ctl/tests/test-vivid-mc.bash b/utils/media-ctl/tests/test-vivid-mc.bash
new file mode 100755
index 0000000..40c2e7d
--- /dev/null
+++ b/utils/media-ctl/tests/test-vivid-mc.bash
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+coproc mediatext -c 2>&1
+
+# read initialisation
+read -ru ${COPROC[0]}; eval $REPLY
+
+cat <<EOF >&${COPROC[1]}
+verbose true
+
+v4l open entity="vim2m" name=vim
+v4l fmt vdev=vim type=VIDEO_OUTPUT width=480 height=320 \
+	pixelformat=RGB565X bytesperline=0 num_planes=1
+v4l reqbufs vdev=vim type=VIDEO_OUTPUT count=3 memory=MMAP
+v4l fmt vdev=vim type=VIDEO_CAPTURE width=480 height=320 \
+	pixelformat=RGB565X bytesperline=0 num_planes=1
+v4l reqbufs vdev=vim type=VIDEO_CAPTURE count=3 memory=MMAP
+
+media req-create req=foo
+media req-create req=foo1
+media req-create req=foo2
+
+v4l io vdev=vim type=VIDEO_OUTPUT fname=/bin/bash
+v4l io vdev=vim type=VIDEO_OUTPUT fname=/bin/systemctl
+v4l io vdev=vim type=VIDEO_OUTPUT fname=/vmlinuz
+
+v4l qbuf vdev=vim type=VIDEO_OUTPUT req=foo
+v4l qbuf vdev=vim type=VIDEO_OUTPUT req=foo1
+v4l qbuf vdev=vim type=VIDEO_CAPTURE req=foo1
+v4l qbuf vdev=vim type=VIDEO_CAPTURE req=foo
+
+media req-queue req=foo
+
+v4l qbuf vdev=vim type=VIDEO_OUTPUT req=foo2
+v4l qbuf vdev=vim type=VIDEO_CAPTURE req=foo2
+
+v4l streamon vdev=vim type=VIDEO_CAPTURE
+v4l streamon vdev=vim type=VIDEO_OUTPUT
+
+media req-queue req=foo2
+media req-queue req=foo1
+
+EOF
+
+queued=3
+finished=0
+
+while IFS= read -ru ${COPROC[0]}; do
+	unset p; declare -A p
+	eval eval_line $REPLY
+	echo $REPLY
+	#echo ${p[event]}
+	case ${p[event]} in
+	dqbuf)
+		#echo seq ${p[seq]}
+		if [ ${p[type]} == VIDEO_CAPTURE ]; then
+			echo v4l io vdev=vim type=VIDEO_CAPTURE \
+				sequence=${p[seq]} >&${COPROC[1]}
+		fi
+	;;
+	request-complete)
+		finished=$(($finished+1));
+		if (($queued < 10)); then
+			queued=$(($queued + 1))
+			cat <<EOF >&${COPROC[1]}
+				media req-create req=${p[req]}
+				v4l io vdev=vim type=VIDEO_OUTPUT fname=/bin/tar
+				v4l qbuf vdev=vim type=VIDEO_OUTPUT req=${p[req]}
+				v4l qbuf vdev=vim type=VIDEO_CAPTURE req=${p[req]}
+				media req-queue req=${p[req]}
+EOF
+		fi
+		echo $queued requests queued, $finished finished
+		if (($finished == 10)); then
+			cat <<EOF >&${COPROC[1]}
+				v4l streamoff vdev=vim type=VIDEO_CAPTURE
+				v4l streamoff vdev=vim type=VIDEO_OUTPUT
+				v4l reqbufs vdev=vim type=VIDEO_CAPTURE count=0 memory=MMAP
+				v4l reqbufs vdev=vim type=VIDEO_OUTPUT count=0 memory=MMAP
+				quit
+EOF
+		exit 0
+		fi
+	;;
+	esac;
+done
diff --git a/utils/media-ctl/tests/test-vivid.bash b/utils/media-ctl/tests/test-vivid.bash
new file mode 100755
index 0000000..3c9b2f4
--- /dev/null
+++ b/utils/media-ctl/tests/test-vivid.bash
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+coproc mediatext -c 2>&1
+
+# read initialisation
+read -ru ${COPROC[0]}; eval $REPLY
+
+cat <<EOF >&${COPROC[1]}
+verbose true
+
+v4l open entity="vim2m" name=vim
+v4l fmt vdev=vim type=VIDEO_OUTPUT width=480 height=320 \
+	pixelformat=RGB565X bytesperline=0 num_planes=1
+v4l reqbufs vdev=vim type=VIDEO_OUTPUT count=3 memory=MMAP
+v4l fmt vdev=vim type=VIDEO_CAPTURE width=480 height=320 \
+	pixelformat=RGB565X bytesperline=0 num_planes=1
+v4l reqbufs vdev=vim type=VIDEO_CAPTURE count=3 memory=MMAP
+
+v4l io vdev=vim type=VIDEO_OUTPUT fname=/bin/bash
+v4l io vdev=vim type=VIDEO_OUTPUT fname=/bin/systemctl
+v4l io vdev=vim type=VIDEO_OUTPUT fname=/vmlinuz
+v4l qbuf vdev=vim type=VIDEO_OUTPUT
+v4l qbuf vdev=vim type=VIDEO_OUTPUT
+v4l qbuf vdev=vim type=VIDEO_CAPTURE
+v4l qbuf vdev=vim type=VIDEO_CAPTURE
+
+v4l streamon vdev=vim type=VIDEO_CAPTURE
+v4l streamon vdev=vim type=VIDEO_OUTPUT
+EOF
+
+while IFS= read -ru ${COPROC[0]} line; do
+	unset p; declare -A p
+	eval eval_line $line
+	echo $line
+	#echo ${p[event]}
+	case ${p[event]} in
+	dqbuf)
+		#echo seq ${p[seq]}
+		if [ ${p[type]} == VIDEO_CAPTURE ]; then
+			echo v4l io vdev=vim type=VIDEO_CAPTURE \
+				sequence=${p[seq]} >&${COPROC[1]}
+			echo v4l io vdev=vim type=VIDEO_OUTPUT \
+				fname=/bin/tar >&${COPROC[1]}
+			echo v4l qbuf vdev=vim type=VIDEO_OUTPUT >&${COPROC[1]}
+			echo v4l qbuf vdev=vim type=VIDEO_CAPTURE >&${COPROC[1]}
+			if ((${p[seq]} == 5)); then
+				echo <<EOF >&${COPROC[1]}
+				v4l streamoff vdev=vim type=VIDEO_CAPTURE
+				v4l streamoff vdev=vim type=VIDEO_OUTPUT
+				v4l reqbufs vdev=vim type=VIDEO_OUTPUT count=0
+				v4l reqbufs vdev=vim type=VIDEO_CAPTURE count=0
+				quit
+EOF
+				exit 0
+			fi
+		fi
+	;;
+	esac;
+done
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-04-05 10:59 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-05 10:58 [v4l-utils RFC 0/6] Mediatext test program for request API tests Sakari Ailus
2018-04-05 10:58 ` [v4l-utils RFC 1/6] Linux kernel header update Sakari Ailus
2018-04-05 10:58 ` [v4l-utils RFC 2/6] Make v4l-utils compile with request-related changes Sakari Ailus
2018-04-05 10:58 ` [v4l-utils RFC 3/6] libmediactl: Add open, close and fd to public API Sakari Ailus
2018-04-05 10:58 ` [v4l-utils RFC 4/6] mediatext: Extract list of V4L2 pixel format strings and 4cc codes Sakari Ailus
2018-04-05 10:58 ` [v4l-utils RFC 5/6] mediatext: Add library Sakari Ailus
2018-04-05 10:58 ` [v4l-utils RFC 6/6] mediatext: Add vivid tests Sakari Ailus

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.