All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/48] ADV7611 support
@ 2014-03-10 23:15 Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 01/48] v4l: of: Support empty port nodes Laurent Pinchart
                   ` (48 more replies)
  0 siblings, 49 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Lars-Peter Clausen, Kyungmin Park,
	Tomasz Stanislawski, Scott Jiang, Prabhakar Lad

Hello,

This patch set implements support for the ADV7611 in the adv7604 driver. It
also comes up with new features such as output format configuration through
pad format operations, hot-plug detect control through GPIO and DT support.

Patches 06/48 to 24/48 and 39/48 replace the subdev video DV timings query cap
and enum operations with pad-level equivalents. I've split driver changes in
one patch per driver to make review easier, but I can squash them together if
desired.

I believe I've addressed all comments received on v1, except the one related
to op_ch_sel in patch "adv7604: Make output format configurable through pad
format operations" which is still open for discussion.

Patches 02/48 to 05/48 have been acked in v1 already, I will send a pull
request for them separately if a v3 of this series ends up being needed. I'd
like to get patch 01/48 upstream soon as well.

Changes compared to v1:

- Check the edid and pad fields for various ioctls in the subdev core
- Switch to the descriptor-based GPIO API
- Leave enum adv7604_pad in header file
- Keep the hotplug notifier
- Fix compilation breakage when !CONFIG_OF due to directly dereferencing the
  return value of of_match_node()
- Move patch "v4l: subdev: Remove deprecated video-level DV timings
  operations" later in the series to avoid bisection breakages
- Document struct v4l2_enum_dv_timings reserved field as being set to 0 by
  both drivers and application
- Document pad field of struct v4l2_enum_dv_timings and struct
  v4l2_dv_timings_cap as being used for subdev nodes only
- Typo fixes in documentation

Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Tomasz Stanislawski <t.stanislaws@samsung.com>
Cc: Scott Jiang <scott.jiang.linux@gmail.com>
Cc: Prabhakar Lad <prabhakar.csengg@gmail.com>

Lars-Peter Clausen (4):
  adv7604: Add missing include to linux/types.h
  adv7604: Add support for asynchronous probing
  adv7604: Don't put info string arrays on the stack
  adv7604: Add adv7611 support

Laurent Pinchart (44):
  v4l: of: Support empty port nodes
  v4l: Add UYVY10_2X10 and VYUY10_2X10 media bus pixel codes
  v4l: Add UYVY10_1X20 and VYUY10_1X20 media bus pixel codes
  v4l: Add 12-bit YUV 4:2:0 media bus pixel codes
  v4l: Add 12-bit YUV 4:2:2 media bus pixel codes
  v4l: Add pad-level DV timings subdev operations
  ad9389b: Add pad-level DV timings operations
  adv7511: Add pad-level DV timings operations
  adv7842: Add pad-level DV timings operations
  s5p-tv: hdmi: Add pad-level DV timings operations
  s5p-tv: hdmiphy: Add pad-level DV timings operations
  ths8200: Add pad-level DV timings operations
  tvp7002: Add pad-level DV timings operations
  media: bfin_capture: Switch to pad-level DV operations
  media: davinci: vpif: Switch to pad-level DV operations
  media: staging: davinci: vpfe: Switch to pad-level DV operations
  s5p-tv: mixer: Switch to pad-level DV operations
  ad9389b: Remove deprecated video-level DV timings operations
  adv7511: Remove deprecated video-level DV timings operations
  adv7842: Remove deprecated video-level DV timings operations
  s5p-tv: hdmi: Remove deprecated video-level DV timings operations
  s5p-tv: hdmiphy: Remove deprecated video-level DV timings operation
  ths8200: Remove deprecated video-level DV timings operations
  tvp7002: Remove deprecated video-level DV timings operations
  v4l: Improve readability by not wrapping ioctl number #define's
  v4l: Add support for DV timings ioctls on subdev nodes
  v4l: Validate fields in the core code for subdev EDID ioctls
  adv7604: Add 16-bit read functions for CP and HDMI
  adv7604: Cache register contents when reading multiple bits
  adv7604: Remove subdev control handlers
  adv7604: Add sink pads
  adv7604: Make output format configurable through pad format operations
  adv7604: Add pad-level DV timings support
  adv7604: Remove deprecated video-level DV timings operations
  v4l: subdev: Remove deprecated video-level DV timings operations
  adv7604: Inline the to_sd function
  adv7604: Store I2C addresses and clients in arrays
  adv7604: Replace *_and_or() functions with *_clr_set()
  adv7604: Sort headers alphabetically
  adv7604: Support hot-plug detect control through a GPIO
  adv7604: Specify the default input through platform data
  adv7604: Add DT support
  adv7604: Add LLC polarity configuration
  adv7604: Add endpoint properties to DT bindings

 Documentation/DocBook/media/v4l/subdev-formats.xml |  760 +++++++++++
 .../DocBook/media/v4l/vidioc-dv-timings-cap.xml    |   27 +-
 .../DocBook/media/v4l/vidioc-enum-dv-timings.xml   |   30 +-
 .../devicetree/bindings/media/i2c/adv7604.txt      |   69 +
 drivers/media/i2c/ad9389b.c                        |   65 +-
 drivers/media/i2c/adv7511.c                        |   67 +-
 drivers/media/i2c/adv7604.c                        | 1440 ++++++++++++++------
 drivers/media/i2c/adv7842.c                        |   14 +-
 drivers/media/i2c/ths8200.c                        |   10 +
 drivers/media/i2c/tvp7002.c                        |    5 +-
 drivers/media/platform/blackfin/bfin_capture.c     |    4 +-
 drivers/media/platform/davinci/vpif_capture.c      |    4 +-
 drivers/media/platform/davinci/vpif_display.c      |    4 +-
 drivers/media/platform/s5p-tv/hdmi_drv.c           |   14 +-
 drivers/media/platform/s5p-tv/hdmiphy_drv.c        |    9 +-
 drivers/media/platform/s5p-tv/mixer_video.c        |    8 +-
 drivers/media/v4l2-core/v4l2-of.c                  |   52 +-
 drivers/media/v4l2-core/v4l2-subdev.c              |   51 +-
 drivers/staging/media/davinci_vpfe/vpfe_video.c    |    4 +-
 include/media/adv7604.h                            |  113 +-
 include/media/v4l2-subdev.h                        |    8 +-
 include/uapi/linux/v4l2-mediabus.h                 |   14 +-
 include/uapi/linux/v4l2-subdev.h                   |   38 +-
 include/uapi/linux/videodev2.h                     |   10 +-
 24 files changed, 2174 insertions(+), 646 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/adv7604.txt

-- 
Regards,

Laurent Pinchart


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

* [PATCH v2 01/48] v4l: of: Support empty port nodes
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11 12:05   ` Sylwester Nawrocki
  2014-03-10 23:15 ` [PATCH v2 02/48] v4l: Add UYVY10_2X10 and VYUY10_2X10 media bus pixel codes Laurent Pinchart
                   ` (47 subsequent siblings)
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Empty port nodes are allowed but currently unsupported as the
v4l2_of_get_next_endpoint() function assumes that all port nodes have at
least an endpoint. Fix this.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/v4l2-core/v4l2-of.c | 52 +++++++++++++++++++++------------------
 1 file changed, 28 insertions(+), 24 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c
index 42e3e8a..4c07343 100644
--- a/drivers/media/v4l2-core/v4l2-of.c
+++ b/drivers/media/v4l2-core/v4l2-of.c
@@ -166,43 +166,51 @@ struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent,
 					struct device_node *prev)
 {
 	struct device_node *endpoint;
-	struct device_node *port = NULL;
+	struct device_node *port;
 
 	if (!parent)
 		return NULL;
 
+	/*
+	 * Start by locating the port node. If no previous endpoint is specified
+	 * search for the first port node, otherwise get the previous endpoint
+	 * parent port node.
+	 */
 	if (!prev) {
 		struct device_node *node;
-		/*
-		 * It's the first call, we have to find a port subnode
-		 * within this node or within an optional 'ports' node.
-		 */
+
 		node = of_get_child_by_name(parent, "ports");
 		if (node)
 			parent = node;
 
 		port = of_get_child_by_name(parent, "port");
+		of_node_put(node);
 
-		if (port) {
-			/* Found a port, get an endpoint. */
-			endpoint = of_get_next_child(port, NULL);
-			of_node_put(port);
-		} else {
-			endpoint = NULL;
-		}
-
-		if (!endpoint)
-			pr_err("%s(): no endpoint nodes specified for %s\n",
+		if (!port) {
+			pr_err("%s(): no port node found in %s\n",
 			       __func__, parent->full_name);
-		of_node_put(node);
+			return NULL;
+		}
 	} else {
 		port = of_get_parent(prev);
-		if (!port)
+		if (!port) {
 			/* Hm, has someone given us the root node ?... */
 			return NULL;
+		}
 
-		/* Avoid dropping prev node refcount to 0. */
+		/*
+		 * Avoid dropping prev node refcount to 0 when getting the next
+		 * child below.
+		 */
 		of_node_get(prev);
+	}
+
+	while (1) {
+		/*
+		 * Now that we have a port node, get the next endpoint by
+		 * getting the next child. If the previous endpoint is NULL this
+		 * will return the first child.
+		 */
 		endpoint = of_get_next_child(port, prev);
 		if (endpoint) {
 			of_node_put(port);
@@ -210,18 +218,14 @@ struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent,
 		}
 
 		/* No more endpoints under this port, try the next one. */
+		prev = NULL;
+
 		do {
 			port = of_get_next_child(parent, port);
 			if (!port)
 				return NULL;
 		} while (of_node_cmp(port->name, "port"));
-
-		/* Pick up the first endpoint in this port. */
-		endpoint = of_get_next_child(port, NULL);
-		of_node_put(port);
 	}
-
-	return endpoint;
 }
 EXPORT_SYMBOL(v4l2_of_get_next_endpoint);
 
-- 
1.8.3.2


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

* [PATCH v2 02/48] v4l: Add UYVY10_2X10 and VYUY10_2X10 media bus pixel codes
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 01/48] v4l: of: Support empty port nodes Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 03/48] v4l: Add UYVY10_1X20 and VYUY10_1X20 " Laurent Pinchart
                   ` (46 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 Documentation/DocBook/media/v4l/subdev-formats.xml | 128 +++++++++++++++++++++
 include/uapi/linux/v4l2-mediabus.h                 |   4 +-
 2 files changed, 131 insertions(+), 1 deletion(-)

diff --git a/Documentation/DocBook/media/v4l/subdev-formats.xml b/Documentation/DocBook/media/v4l/subdev-formats.xml
index 7331ce1..6fb58de 100644
--- a/Documentation/DocBook/media/v4l/subdev-formats.xml
+++ b/Documentation/DocBook/media/v4l/subdev-formats.xml
@@ -1898,6 +1898,134 @@
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
 	    </row>
+	    <row id="V4L2-MBUS-FMT-UYVY10-2X10">
+	      <entry>V4L2_MBUS_FMT_UYVY10_2X10</entry>
+	      <entry>0x2018</entry>
+	      <entry></entry>
+	      &dash-ent-22;
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-22;
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-22;
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-22;
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-VYUY10-2X10">
+	      <entry>V4L2_MBUS_FMT_VYUY10_2X10</entry>
+	      <entry>0x2019</entry>
+	      <entry></entry>
+	      &dash-ent-22;
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-22;
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-22;
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-22;
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
 	    <row id="V4L2-MBUS-FMT-YUYV10-2X10">
 	      <entry>V4L2_MBUS_FMT_YUYV10_2X10</entry>
 	      <entry>0x200b</entry>
diff --git a/include/uapi/linux/v4l2-mediabus.h b/include/uapi/linux/v4l2-mediabus.h
index b5c3aab..20a99b1 100644
--- a/include/uapi/linux/v4l2-mediabus.h
+++ b/include/uapi/linux/v4l2-mediabus.h
@@ -52,7 +52,7 @@ enum v4l2_mbus_pixelcode {
 	V4L2_MBUS_FMT_RGB888_2X12_LE = 0x100c,
 	V4L2_MBUS_FMT_ARGB8888_1X32 = 0x100d,
 
-	/* YUV (including grey) - next is 0x2018 */
+	/* YUV (including grey) - next is 0x201a */
 	V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
 	V4L2_MBUS_FMT_UV8_1X8 = 0x2015,
 	V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
@@ -64,6 +64,8 @@ enum v4l2_mbus_pixelcode {
 	V4L2_MBUS_FMT_YUYV8_2X8 = 0x2008,
 	V4L2_MBUS_FMT_YVYU8_2X8 = 0x2009,
 	V4L2_MBUS_FMT_Y10_1X10 = 0x200a,
+	V4L2_MBUS_FMT_UYVY10_2X10 = 0x2018,
+	V4L2_MBUS_FMT_VYUY10_2X10 = 0x2019,
 	V4L2_MBUS_FMT_YUYV10_2X10 = 0x200b,
 	V4L2_MBUS_FMT_YVYU10_2X10 = 0x200c,
 	V4L2_MBUS_FMT_Y12_1X12 = 0x2013,
-- 
1.8.3.2


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

* [PATCH v2 03/48] v4l: Add UYVY10_1X20 and VYUY10_1X20 media bus pixel codes
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 01/48] v4l: of: Support empty port nodes Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 02/48] v4l: Add UYVY10_2X10 and VYUY10_2X10 media bus pixel codes Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 04/48] v4l: Add 12-bit YUV 4:2:0 " Laurent Pinchart
                   ` (45 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 Documentation/DocBook/media/v4l/subdev-formats.xml | 104 +++++++++++++++++++++
 include/uapi/linux/v4l2-mediabus.h                 |   4 +-
 2 files changed, 107 insertions(+), 1 deletion(-)

diff --git a/Documentation/DocBook/media/v4l/subdev-formats.xml b/Documentation/DocBook/media/v4l/subdev-formats.xml
index 6fb58de..e3cbbb4 100644
--- a/Documentation/DocBook/media/v4l/subdev-formats.xml
+++ b/Documentation/DocBook/media/v4l/subdev-formats.xml
@@ -2436,6 +2436,110 @@
 	      <entry>v<subscript>1</subscript></entry>
 	      <entry>v<subscript>0</subscript></entry>
 	    </row>
+	    <row id="V4L2-MBUS-FMT-UYVY10-1X20">
+	      <entry>V4L2_MBUS_FMT_UYVY10_1X20</entry>
+	      <entry>0x201a</entry>
+	      <entry></entry>
+	      &dash-ent-12;
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-12;
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-VYUY10-1X20">
+	      <entry>V4L2_MBUS_FMT_VYUY10_1X20</entry>
+	      <entry>0x201b</entry>
+	      <entry></entry>
+	      &dash-ent-12;
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-12;
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
 	    <row id="V4L2-MBUS-FMT-YUYV10-1X20">
 	      <entry>V4L2_MBUS_FMT_YUYV10_1X20</entry>
 	      <entry>0x200d</entry>
diff --git a/include/uapi/linux/v4l2-mediabus.h b/include/uapi/linux/v4l2-mediabus.h
index 20a99b1..43707b2 100644
--- a/include/uapi/linux/v4l2-mediabus.h
+++ b/include/uapi/linux/v4l2-mediabus.h
@@ -52,7 +52,7 @@ enum v4l2_mbus_pixelcode {
 	V4L2_MBUS_FMT_RGB888_2X12_LE = 0x100c,
 	V4L2_MBUS_FMT_ARGB8888_1X32 = 0x100d,
 
-	/* YUV (including grey) - next is 0x201a */
+	/* YUV (including grey) - next is 0x201c */
 	V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
 	V4L2_MBUS_FMT_UV8_1X8 = 0x2015,
 	V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
@@ -74,6 +74,8 @@ enum v4l2_mbus_pixelcode {
 	V4L2_MBUS_FMT_YUYV8_1X16 = 0x2011,
 	V4L2_MBUS_FMT_YVYU8_1X16 = 0x2012,
 	V4L2_MBUS_FMT_YDYUYDYV8_1X16 = 0x2014,
+	V4L2_MBUS_FMT_UYVY10_1X20 = 0x201a,
+	V4L2_MBUS_FMT_VYUY10_1X20 = 0x201b,
 	V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
 	V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
 	V4L2_MBUS_FMT_YUV10_1X30 = 0x2016,
-- 
1.8.3.2


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

* [PATCH v2 04/48] v4l: Add 12-bit YUV 4:2:0 media bus pixel codes
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (2 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 03/48] v4l: Add UYVY10_1X20 and VYUY10_1X20 " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 05/48] v4l: Add 12-bit YUV 4:2:2 " Laurent Pinchart
                   ` (44 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 Documentation/DocBook/media/v4l/subdev-formats.xml | 288 +++++++++++++++++++++
 include/uapi/linux/v4l2-mediabus.h                 |   6 +-
 2 files changed, 293 insertions(+), 1 deletion(-)

diff --git a/Documentation/DocBook/media/v4l/subdev-formats.xml b/Documentation/DocBook/media/v4l/subdev-formats.xml
index e3cbbb4..a0fa7e0 100644
--- a/Documentation/DocBook/media/v4l/subdev-formats.xml
+++ b/Documentation/DocBook/media/v4l/subdev-formats.xml
@@ -2718,6 +2718,294 @@
 	      <entry>v<subscript>1</subscript></entry>
 	      <entry>v<subscript>0</subscript></entry>
 	    </row>
+	    <row id="V4L2-MBUS-FMT-UYVY12-2X12">
+	      <entry>V4L2_MBUS_FMT_UYVY12_2X12</entry>
+	      <entry>0x201c</entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-VYUY12-2X12">
+	      <entry>V4L2_MBUS_FMT_VYUY12_2X12</entry>
+	      <entry>0x201d</entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YUYV12-2X12">
+	      <entry>V4L2_MBUS_FMT_YUYV12_2X12</entry>
+	      <entry>0x201e</entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YVYU12-2X12">
+	      <entry>V4L2_MBUS_FMT_YVYU12_2X12</entry>
+	      <entry>0x201f</entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
 	  </tbody>
 	</tgroup>
       </table>
diff --git a/include/uapi/linux/v4l2-mediabus.h b/include/uapi/linux/v4l2-mediabus.h
index 43707b2..70a732b 100644
--- a/include/uapi/linux/v4l2-mediabus.h
+++ b/include/uapi/linux/v4l2-mediabus.h
@@ -52,7 +52,7 @@ enum v4l2_mbus_pixelcode {
 	V4L2_MBUS_FMT_RGB888_2X12_LE = 0x100c,
 	V4L2_MBUS_FMT_ARGB8888_1X32 = 0x100d,
 
-	/* YUV (including grey) - next is 0x201c */
+	/* YUV (including grey) - next is 0x2020 */
 	V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
 	V4L2_MBUS_FMT_UV8_1X8 = 0x2015,
 	V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
@@ -80,6 +80,10 @@ enum v4l2_mbus_pixelcode {
 	V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
 	V4L2_MBUS_FMT_YUV10_1X30 = 0x2016,
 	V4L2_MBUS_FMT_AYUV8_1X32 = 0x2017,
+	V4L2_MBUS_FMT_UYVY12_2X12 = 0x201c,
+	V4L2_MBUS_FMT_VYUY12_2X12 = 0x201d,
+	V4L2_MBUS_FMT_YUYV12_2X12 = 0x201e,
+	V4L2_MBUS_FMT_YVYU12_2X12 = 0x201f,
 
 	/* Bayer - next is 0x3019 */
 	V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
-- 
1.8.3.2


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

* [PATCH v2 05/48] v4l: Add 12-bit YUV 4:2:2 media bus pixel codes
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (3 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 04/48] v4l: Add 12-bit YUV 4:2:0 " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 06/48] v4l: Add pad-level DV timings subdev operations Laurent Pinchart
                   ` (43 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 Documentation/DocBook/media/v4l/subdev-formats.xml | 240 +++++++++++++++++++++
 include/uapi/linux/v4l2-mediabus.h                 |   6 +-
 2 files changed, 245 insertions(+), 1 deletion(-)

diff --git a/Documentation/DocBook/media/v4l/subdev-formats.xml b/Documentation/DocBook/media/v4l/subdev-formats.xml
index a0fa7e0..b2d5a03 100644
--- a/Documentation/DocBook/media/v4l/subdev-formats.xml
+++ b/Documentation/DocBook/media/v4l/subdev-formats.xml
@@ -3006,6 +3006,246 @@
 	      <entry>u<subscript>1</subscript></entry>
 	      <entry>u<subscript>0</subscript></entry>
 	    </row>
+	    <row id="V4L2-MBUS-FMT-UYVY12-1X24">
+	      <entry>V4L2_MBUS_FMT_UYVY12_1X24</entry>
+	      <entry>0x2020</entry>
+	      <entry></entry>
+	      &dash-ent-8;
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-8;
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-VYUY12-1X24">
+	      <entry>V4L2_MBUS_FMT_VYUY12_1X24</entry>
+	      <entry>0x2021</entry>
+	      <entry></entry>
+	      &dash-ent-8;
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-8;
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YUYV12-1X24">
+	      <entry>V4L2_MBUS_FMT_YUYV12_1X24</entry>
+	      <entry>0x2022</entry>
+	      <entry></entry>
+	      &dash-ent-8;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-8;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YVYU12-1X24">
+	      <entry>V4L2_MBUS_FMT_YVYU12_1X24</entry>
+	      <entry>0x2023</entry>
+	      <entry></entry>
+	      &dash-ent-8;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-8;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
 	  </tbody>
 	</tgroup>
       </table>
diff --git a/include/uapi/linux/v4l2-mediabus.h b/include/uapi/linux/v4l2-mediabus.h
index 70a732b..1445e85 100644
--- a/include/uapi/linux/v4l2-mediabus.h
+++ b/include/uapi/linux/v4l2-mediabus.h
@@ -52,7 +52,7 @@ enum v4l2_mbus_pixelcode {
 	V4L2_MBUS_FMT_RGB888_2X12_LE = 0x100c,
 	V4L2_MBUS_FMT_ARGB8888_1X32 = 0x100d,
 
-	/* YUV (including grey) - next is 0x2020 */
+	/* YUV (including grey) - next is 0x2024 */
 	V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
 	V4L2_MBUS_FMT_UV8_1X8 = 0x2015,
 	V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
@@ -84,6 +84,10 @@ enum v4l2_mbus_pixelcode {
 	V4L2_MBUS_FMT_VYUY12_2X12 = 0x201d,
 	V4L2_MBUS_FMT_YUYV12_2X12 = 0x201e,
 	V4L2_MBUS_FMT_YVYU12_2X12 = 0x201f,
+	V4L2_MBUS_FMT_UYVY12_1X24 = 0x2020,
+	V4L2_MBUS_FMT_VYUY12_1X24 = 0x2021,
+	V4L2_MBUS_FMT_YUYV12_1X24 = 0x2022,
+	V4L2_MBUS_FMT_YVYU12_1X24 = 0x2023,
 
 	/* Bayer - next is 0x3019 */
 	V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
-- 
1.8.3.2


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

* [PATCH v2 06/48] v4l: Add pad-level DV timings subdev operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (4 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 05/48] v4l: Add 12-bit YUV 4:2:2 " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11  7:24   ` Prabhakar Lad
  2014-03-11 10:27   ` Hans Verkuil
  2014-03-10 23:15 ` [PATCH v2 07/48] ad9389b: Add pad-level DV timings operations Laurent Pinchart
                   ` (42 subsequent siblings)
  48 siblings, 2 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 include/media/v4l2-subdev.h    |  4 ++++
 include/uapi/linux/videodev2.h | 10 ++++++++--
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 1752530..2b5ec32 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -509,6 +509,10 @@ struct v4l2_subdev_pad_ops {
 			     struct v4l2_subdev_selection *sel);
 	int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid);
 	int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid);
+	int (*dv_timings_cap)(struct v4l2_subdev *sd,
+			      struct v4l2_dv_timings_cap *cap);
+	int (*enum_dv_timings)(struct v4l2_subdev *sd,
+			       struct v4l2_enum_dv_timings *timings);
 #ifdef CONFIG_MEDIA_CONTROLLER
 	int (*link_validate)(struct v4l2_subdev *sd, struct media_link *link,
 			     struct v4l2_subdev_format *source_fmt,
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 17acba8..72fbbd4 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1103,12 +1103,15 @@ struct v4l2_dv_timings {
 
 /** struct v4l2_enum_dv_timings - DV timings enumeration
  * @index:	enumeration index
+ * @pad:	the pad number for which to enumerate timings (used with
+ *		v4l-subdev nodes only)
  * @reserved:	must be zeroed
  * @timings:	the timings for the given index
  */
 struct v4l2_enum_dv_timings {
 	__u32 index;
-	__u32 reserved[3];
+	__u32 pad;
+	__u32 reserved[2];
 	struct v4l2_dv_timings timings;
 };
 
@@ -1146,11 +1149,14 @@ struct v4l2_bt_timings_cap {
 
 /** struct v4l2_dv_timings_cap - DV timings capabilities
  * @type:	the type of the timings (same as in struct v4l2_dv_timings)
+ * @pad:	the pad number for which to query capabilities (used with
+ *		v4l-subdev nodes only)
  * @bt:		the BT656/1120 timings capabilities
  */
 struct v4l2_dv_timings_cap {
 	__u32 type;
-	__u32 reserved[3];
+	__u32 pad;
+	__u32 reserved[2];
 	union {
 		struct v4l2_bt_timings_cap bt;
 		__u32 raw_data[32];
-- 
1.8.3.2


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

* [PATCH v2 07/48] ad9389b: Add pad-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (5 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 06/48] v4l: Add pad-level DV timings subdev operations Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 08/48] adv7511: " Laurent Pinchart
                   ` (41 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings and dv_timings_cap operations are deprecated.
Implement the pad-level version of those operations to prepare for the
removal of the video version.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/ad9389b.c | 69 ++++++++++++++++++++++++++-------------------
 1 file changed, 40 insertions(+), 29 deletions(-)

diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
index 83225d6..44c037d 100644
--- a/drivers/media/i2c/ad9389b.c
+++ b/drivers/media/i2c/ad9389b.c
@@ -571,35 +571,6 @@ static const struct v4l2_subdev_core_ops ad9389b_core_ops = {
 	.interrupt_service_routine = ad9389b_isr,
 };
 
-/* ------------------------------ PAD OPS ------------------------------ */
-
-static int ad9389b_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
-{
-	struct ad9389b_state *state = get_ad9389b_state(sd);
-
-	if (edid->pad != 0)
-		return -EINVAL;
-	if (edid->blocks == 0 || edid->blocks > 256)
-		return -EINVAL;
-	if (!edid->edid)
-		return -EINVAL;
-	if (!state->edid.segments) {
-		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
-		return -ENODATA;
-	}
-	if (edid->start_block >= state->edid.segments * 2)
-		return -E2BIG;
-	if (edid->blocks + edid->start_block >= state->edid.segments * 2)
-		edid->blocks = state->edid.segments * 2 - edid->start_block;
-	memcpy(edid->edid, &state->edid.data[edid->start_block * 128],
-	       128 * edid->blocks);
-	return 0;
-}
-
-static const struct v4l2_subdev_pad_ops ad9389b_pad_ops = {
-	.get_edid = ad9389b_get_edid,
-};
-
 /* ------------------------------ VIDEO OPS ------------------------------ */
 
 /* Enable/disable ad9389b output */
@@ -678,6 +649,9 @@ static int ad9389b_g_dv_timings(struct v4l2_subdev *sd,
 static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd,
 				   struct v4l2_enum_dv_timings *timings)
 {
+	if (timings->pad != 0)
+		return -EINVAL;
+
 	return v4l2_enum_dv_timings_cap(timings, &ad9389b_timings_cap,
 			NULL, NULL);
 }
@@ -685,6 +659,9 @@ static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd,
 static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd,
 				  struct v4l2_dv_timings_cap *cap)
 {
+	if (cap->pad != 0)
+		return -EINVAL;
+
 	*cap = ad9389b_timings_cap;
 	return 0;
 }
@@ -697,6 +674,40 @@ static const struct v4l2_subdev_video_ops ad9389b_video_ops = {
 	.dv_timings_cap = ad9389b_dv_timings_cap,
 };
 
+/* ------------------------------ PAD OPS ------------------------------ */
+
+static int ad9389b_get_edid(struct v4l2_subdev *sd,
+			    struct v4l2_subdev_edid *edid)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+
+	if (edid->pad != 0)
+		return -EINVAL;
+	if (edid->blocks == 0 || edid->blocks > 256)
+		return -EINVAL;
+	if (!edid->edid)
+		return -EINVAL;
+	if (!state->edid.segments) {
+		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
+		return -ENODATA;
+	}
+	if (edid->start_block >= state->edid.segments * 2)
+		return -E2BIG;
+	if (edid->blocks + edid->start_block >= state->edid.segments * 2)
+		edid->blocks = state->edid.segments * 2 - edid->start_block;
+	memcpy(edid->edid, &state->edid.data[edid->start_block * 128],
+	       128 * edid->blocks);
+	return 0;
+}
+
+static const struct v4l2_subdev_pad_ops ad9389b_pad_ops = {
+	.get_edid = ad9389b_get_edid,
+	.enum_dv_timings = ad9389b_enum_dv_timings,
+	.dv_timings_cap = ad9389b_dv_timings_cap,
+};
+
+/* ------------------------------ AUDIO OPS ------------------------------ */
+
 static int ad9389b_s_audio_stream(struct v4l2_subdev *sd, int enable)
 {
 	v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis"));
-- 
1.8.3.2


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

* [PATCH v2 08/48] adv7511: Add pad-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (6 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 07/48] ad9389b: Add pad-level DV timings operations Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 09/48] adv7842: " Laurent Pinchart
                   ` (40 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings and dv_timings_cap operations are deprecated.
Implement the pad-level version of those operations to prepare for the
removal of the video version.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/adv7511.c | 67 ++++++++++++++++++++++++++-------------------
 1 file changed, 39 insertions(+), 28 deletions(-)

diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index ee61894..f8c75c6 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -597,34 +597,6 @@ static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
 	return 0;
 }
 
-static int adv7511_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
-{
-	struct adv7511_state *state = get_adv7511_state(sd);
-
-	if (edid->pad != 0)
-		return -EINVAL;
-	if ((edid->blocks == 0) || (edid->blocks > 256))
-		return -EINVAL;
-	if (!edid->edid)
-		return -EINVAL;
-	if (!state->edid.segments) {
-		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
-		return -ENODATA;
-	}
-	if (edid->start_block >= state->edid.segments * 2)
-		return -E2BIG;
-	if ((edid->blocks + edid->start_block) >= state->edid.segments * 2)
-		edid->blocks = state->edid.segments * 2 - edid->start_block;
-
-	memcpy(edid->edid, &state->edid.data[edid->start_block * 128],
-			128 * edid->blocks);
-	return 0;
-}
-
-static const struct v4l2_subdev_pad_ops adv7511_pad_ops = {
-	.get_edid = adv7511_get_edid,
-};
-
 static const struct v4l2_subdev_core_ops adv7511_core_ops = {
 	.log_status = adv7511_log_status,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -700,12 +672,18 @@ static int adv7511_g_dv_timings(struct v4l2_subdev *sd,
 static int adv7511_enum_dv_timings(struct v4l2_subdev *sd,
 				   struct v4l2_enum_dv_timings *timings)
 {
+	if (timings->pad != 0)
+		return -EINVAL;
+
 	return v4l2_enum_dv_timings_cap(timings, &adv7511_timings_cap, NULL, NULL);
 }
 
 static int adv7511_dv_timings_cap(struct v4l2_subdev *sd,
 				  struct v4l2_dv_timings_cap *cap)
 {
+	if (cap->pad != 0)
+		return -EINVAL;
+
 	*cap = adv7511_timings_cap;
 	return 0;
 }
@@ -797,6 +775,39 @@ static const struct v4l2_subdev_audio_ops adv7511_audio_ops = {
 	.s_routing = adv7511_s_routing,
 };
 
+/* ---------------------------- PAD OPS ------------------------------------- */
+
+static int adv7511_get_edid(struct v4l2_subdev *sd,
+			    struct v4l2_subdev_edid *edid)
+{
+	struct adv7511_state *state = get_adv7511_state(sd);
+
+	if (edid->pad != 0)
+		return -EINVAL;
+	if ((edid->blocks == 0) || (edid->blocks > 256))
+		return -EINVAL;
+	if (!edid->edid)
+		return -EINVAL;
+	if (!state->edid.segments) {
+		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
+		return -ENODATA;
+	}
+	if (edid->start_block >= state->edid.segments * 2)
+		return -E2BIG;
+	if ((edid->blocks + edid->start_block) >= state->edid.segments * 2)
+		edid->blocks = state->edid.segments * 2 - edid->start_block;
+
+	memcpy(edid->edid, &state->edid.data[edid->start_block * 128],
+			128 * edid->blocks);
+	return 0;
+}
+
+static const struct v4l2_subdev_pad_ops adv7511_pad_ops = {
+	.get_edid = adv7511_get_edid,
+	.enum_dv_timings = adv7511_enum_dv_timings,
+	.dv_timings_cap = adv7511_dv_timings_cap,
+};
+
 /* --------------------- SUBDEV OPS --------------------------------------- */
 
 static const struct v4l2_subdev_ops adv7511_ops = {
-- 
1.8.3.2


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

* [PATCH v2 09/48] adv7842: Add pad-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (7 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 08/48] adv7511: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 10/48] s5p-tv: hdmi: " Laurent Pinchart
                   ` (39 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings and dv_timings_cap operations are deprecated.
Implement the pad-level version of those operations to prepare for the
removal of the video version.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/adv7842.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index e04fe3f..78d21fd 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -1399,6 +1399,9 @@ static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
 static int adv7842_enum_dv_timings(struct v4l2_subdev *sd,
 				   struct v4l2_enum_dv_timings *timings)
 {
+	if (timings->pad != 0)
+		return -EINVAL;
+
 	return v4l2_enum_dv_timings_cap(timings,
 		adv7842_get_dv_timings_cap(sd), adv7842_check_dv_timings, NULL);
 }
@@ -1406,6 +1409,9 @@ static int adv7842_enum_dv_timings(struct v4l2_subdev *sd,
 static int adv7842_dv_timings_cap(struct v4l2_subdev *sd,
 				  struct v4l2_dv_timings_cap *cap)
 {
+	if (cap->pad != 0)
+		return -EINVAL;
+
 	*cap = *adv7842_get_dv_timings_cap(sd);
 	return 0;
 }
@@ -2897,6 +2903,8 @@ static const struct v4l2_subdev_video_ops adv7842_video_ops = {
 static const struct v4l2_subdev_pad_ops adv7842_pad_ops = {
 	.get_edid = adv7842_get_edid,
 	.set_edid = adv7842_set_edid,
+	.enum_dv_timings = adv7842_enum_dv_timings,
+	.dv_timings_cap = adv7842_dv_timings_cap,
 };
 
 static const struct v4l2_subdev_ops adv7842_ops = {
-- 
1.8.3.2


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

* [PATCH v2 10/48] s5p-tv: hdmi: Add pad-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (8 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 09/48] adv7842: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 11/48] s5p-tv: hdmiphy: " Laurent Pinchart
                   ` (38 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Lars-Peter Clausen, Kyungmin Park, Tomasz Stanislawski

The video enum_dv_timings and dv_timings_cap operations are deprecated.
Implement the pad-level version of those operations to prepare for the
removal of the video version.

Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/s5p-tv/hdmi_drv.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c
index 534722c..3db496c 100644
--- a/drivers/media/platform/s5p-tv/hdmi_drv.c
+++ b/drivers/media/platform/s5p-tv/hdmi_drv.c
@@ -674,6 +674,8 @@ static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd,
 static int hdmi_enum_dv_timings(struct v4l2_subdev *sd,
 	struct v4l2_enum_dv_timings *timings)
 {
+	if (timings->pad != 0)
+		return -EINVAL;
 	if (timings->index >= ARRAY_SIZE(hdmi_timings))
 		return -EINVAL;
 	timings->timings = hdmi_timings[timings->index].dv_timings;
@@ -687,6 +689,9 @@ static int hdmi_dv_timings_cap(struct v4l2_subdev *sd,
 {
 	struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
 
+	if (cap->pad != 0)
+		return -EINVAL;
+
 	/* Let the phy fill in the pixelclock range */
 	v4l2_subdev_call(hdev->phy_sd, video, dv_timings_cap, cap);
 	cap->type = V4L2_DV_BT_656_1120;
@@ -713,6 +718,11 @@ static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = {
 	.s_stream = hdmi_s_stream,
 };
 
+static const struct v4l2_subdev_pad_ops hdmi_sd_pad_ops = {
+	.enum_dv_timings = hdmi_enum_dv_timings,
+	.dv_timings_cap = hdmi_dv_timings_cap,
+};
+
 static const struct v4l2_subdev_ops hdmi_sd_ops = {
 	.core = &hdmi_sd_core_ops,
 	.video = &hdmi_sd_video_ops,
-- 
1.8.3.2


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

* [PATCH v2 11/48] s5p-tv: hdmiphy: Add pad-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (9 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 10/48] s5p-tv: hdmi: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 12/48] ths8200: " Laurent Pinchart
                   ` (37 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Lars-Peter Clausen, Kyungmin Park, Tomasz Stanislawski

The video enum_dv_timings operation is deprecated. Implement the
pad-level version of the operation to prepare for the removal of the
video version.

Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/s5p-tv/hdmiphy_drv.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/media/platform/s5p-tv/hdmiphy_drv.c b/drivers/media/platform/s5p-tv/hdmiphy_drv.c
index e19a0af..ff22320 100644
--- a/drivers/media/platform/s5p-tv/hdmiphy_drv.c
+++ b/drivers/media/platform/s5p-tv/hdmiphy_drv.c
@@ -225,6 +225,9 @@ static int hdmiphy_s_dv_timings(struct v4l2_subdev *sd,
 static int hdmiphy_dv_timings_cap(struct v4l2_subdev *sd,
 	struct v4l2_dv_timings_cap *cap)
 {
+	if (cap->pad != 0)
+		return -EINVAL;
+
 	cap->type = V4L2_DV_BT_656_1120;
 	/* The phy only determines the pixelclock, leave the other values
 	 * at 0 to signify that we have no information for them. */
@@ -263,9 +266,14 @@ static const struct v4l2_subdev_video_ops hdmiphy_video_ops = {
 	.s_stream =  hdmiphy_s_stream,
 };
 
+static const struct v4l2_subdev_pad_ops hdmiphy_pad_ops = {
+	.dv_timings_cap = hdmiphy_dv_timings_cap,
+};
+
 static const struct v4l2_subdev_ops hdmiphy_ops = {
 	.core = &hdmiphy_core_ops,
 	.video = &hdmiphy_video_ops,
+	.pad = &hdmiphy_pad_ops,
 };
 
 static int hdmiphy_probe(struct i2c_client *client,
-- 
1.8.3.2


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

* [PATCH v2 12/48] ths8200: Add pad-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (10 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 11/48] s5p-tv: hdmiphy: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11  7:11   ` Prabhakar Lad
  2014-03-10 23:15 ` [PATCH v2 13/48] tvp7002: " Laurent Pinchart
                   ` (36 subsequent siblings)
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings and dv_timings_cap operations are deprecated.
Implement the pad-level version of those operations to prepare for the
removal of the video version.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/ths8200.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c
index f72561e..c4ec8b2 100644
--- a/drivers/media/i2c/ths8200.c
+++ b/drivers/media/i2c/ths8200.c
@@ -410,6 +410,9 @@ static int ths8200_g_dv_timings(struct v4l2_subdev *sd,
 static int ths8200_enum_dv_timings(struct v4l2_subdev *sd,
 				   struct v4l2_enum_dv_timings *timings)
 {
+	if (timings->pad != 0)
+		return -EINVAL;
+
 	return v4l2_enum_dv_timings_cap(timings, &ths8200_timings_cap,
 			NULL, NULL);
 }
@@ -417,6 +420,9 @@ static int ths8200_enum_dv_timings(struct v4l2_subdev *sd,
 static int ths8200_dv_timings_cap(struct v4l2_subdev *sd,
 				  struct v4l2_dv_timings_cap *cap)
 {
+	if (cap->pad != 0)
+		return -EINVAL;
+
 	*cap = ths8200_timings_cap;
 	return 0;
 }
@@ -430,10 +436,16 @@ static const struct v4l2_subdev_video_ops ths8200_video_ops = {
 	.dv_timings_cap = ths8200_dv_timings_cap,
 };
 
+static const struct v4l2_subdev_pad_ops ths8200_pad_ops = {
+	.enum_dv_timings = ths8200_enum_dv_timings,
+	.dv_timings_cap = ths8200_dv_timings_cap,
+};
+
 /* V4L2 top level operation handlers */
 static const struct v4l2_subdev_ops ths8200_ops = {
 	.core  = &ths8200_core_ops,
 	.video = &ths8200_video_ops,
+	.pad = &ths8200_pad_ops,
 };
 
 static int ths8200_probe(struct i2c_client *client,
-- 
1.8.3.2


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

* [PATCH v2 13/48] tvp7002: Add pad-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (11 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 12/48] ths8200: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11  7:12   ` Prabhakar Lad
  2014-03-10 23:15 ` [PATCH v2 14/48] media: bfin_capture: Switch to pad-level DV operations Laurent Pinchart
                   ` (35 subsequent siblings)
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings operation is deprecated. Implement the
pad-level version of the operation to prepare for the removal of the
video version.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/tvp7002.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
index 912e1cc..9f56fd5 100644
--- a/drivers/media/i2c/tvp7002.c
+++ b/drivers/media/i2c/tvp7002.c
@@ -832,6 +832,9 @@ static int tvp7002_log_status(struct v4l2_subdev *sd)
 static int tvp7002_enum_dv_timings(struct v4l2_subdev *sd,
 		struct v4l2_enum_dv_timings *timings)
 {
+	if (timings->pad != 0)
+		return -EINVAL;
+
 	/* Check requested format index is within range */
 	if (timings->index >= NUM_TIMINGS)
 		return -EINVAL;
@@ -937,6 +940,7 @@ static const struct v4l2_subdev_pad_ops tvp7002_pad_ops = {
 	.enum_mbus_code = tvp7002_enum_mbus_code,
 	.get_fmt = tvp7002_get_pad_format,
 	.set_fmt = tvp7002_set_pad_format,
+	.enum_dv_timings = tvp7002_enum_dv_timings,
 };
 
 /* V4L2 top level operation handlers */
-- 
1.8.3.2


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

* [PATCH v2 14/48] media: bfin_capture: Switch to pad-level DV operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (12 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 13/48] tvp7002: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-13  8:59   ` Scott Jiang
  2014-03-10 23:15 ` [PATCH v2 15/48] media: davinci: vpif: " Laurent Pinchart
                   ` (34 subsequent siblings)
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen, Scott Jiang

The video-level enum_dv_timings and dv_timings_cap operations are
deprecated in favor of the pad-level versions. All subdev drivers
implement the pad-level versions, switch to them.

Cc: Scott Jiang <scott.jiang.linux@gmail.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/blackfin/bfin_capture.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
index 200bec9..22fb701 100644
--- a/drivers/media/platform/blackfin/bfin_capture.c
+++ b/drivers/media/platform/blackfin/bfin_capture.c
@@ -648,7 +648,9 @@ static int bcap_enum_dv_timings(struct file *file, void *priv,
 {
 	struct bcap_device *bcap_dev = video_drvdata(file);
 
-	return v4l2_subdev_call(bcap_dev->sd, video,
+	timings->pad = 0;
+
+	return v4l2_subdev_call(bcap_dev->sd, pad,
 			enum_dv_timings, timings);
 }
 
-- 
1.8.3.2


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

* [PATCH v2 15/48] media: davinci: vpif: Switch to pad-level DV operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (13 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 14/48] media: bfin_capture: Switch to pad-level DV operations Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11  7:15   ` Prabhakar Lad
  2014-03-10 23:15 ` [PATCH v2 16/48] media: staging: davinci: vpfe: " Laurent Pinchart
                   ` (33 subsequent siblings)
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen, Prabhakar Lad

The video-level enum_dv_timings and dv_timings_cap operations are
deprecated in favor of the pad-level versions. All subdev drivers
implement the pad-level versions, switch to them.

Cc: Prabhakar Lad <prabhakar.csengg@gmail.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/davinci/vpif_capture.c | 4 +++-
 drivers/media/platform/davinci/vpif_display.c | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index cd6da8b..16a1958 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -1723,7 +1723,9 @@ vpif_enum_dv_timings(struct file *file, void *priv,
 	struct channel_obj *ch = fh->channel;
 	int ret;
 
-	ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
+	timings->pad = 0;
+
+	ret = v4l2_subdev_call(ch->sd, pad, enum_dv_timings, timings);
 	if (ret == -ENOIOCTLCMD || ret == -ENODEV)
 		return -EINVAL;
 	return ret;
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index fd68236..e1edefe 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -1380,7 +1380,9 @@ vpif_enum_dv_timings(struct file *file, void *priv,
 	struct channel_obj *ch = fh->channel;
 	int ret;
 
-	ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
+	timings->pad = 0;
+
+	ret = v4l2_subdev_call(ch->sd, pad, enum_dv_timings, timings);
 	if (ret == -ENOIOCTLCMD || ret == -ENODEV)
 		return -EINVAL;
 	return ret;
-- 
1.8.3.2


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

* [PATCH v2 16/48] media: staging: davinci: vpfe: Switch to pad-level DV operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (14 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 15/48] media: davinci: vpif: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11  7:16   ` Prabhakar Lad
  2014-03-10 23:15 ` [PATCH v2 17/48] s5p-tv: mixer: " Laurent Pinchart
                   ` (32 subsequent siblings)
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen, Prabhakar Lad

The video-level enum_dv_timings and dv_timings_cap operations are
deprecated in favor of the pad-level versions. All subdev drivers
implement the pad-level versions, switch to them.

Cc: Prabhakar Lad <prabhakar.csengg@gmail.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/davinci_vpfe/vpfe_video.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index 1f3b0f9..a1655a8 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -987,8 +987,10 @@ vpfe_enum_dv_timings(struct file *file, void *fh,
 	struct vpfe_device *vpfe_dev = video->vpfe_dev;
 	struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
 
+	timings->pad = 0;
+
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_dv_timings\n");
-	return v4l2_subdev_call(subdev, video, enum_dv_timings, timings);
+	return v4l2_subdev_call(subdev, pad, enum_dv_timings, timings);
 }
 
 /*
-- 
1.8.3.2


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

* [PATCH v2 17/48] s5p-tv: mixer: Switch to pad-level DV operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (15 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 16/48] media: staging: davinci: vpfe: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 18/48] ad9389b: Remove deprecated video-level DV timings operations Laurent Pinchart
                   ` (31 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Lars-Peter Clausen, Kyungmin Park, Tomasz Stanislawski

The video-level enum_dv_timings and dv_timings_cap operations are
deprecated in favor of the pad-level versions. All subdev drivers
implement the pad-level versions, switch to them.

Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/s5p-tv/mixer_video.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
index c5059ba..0d6b928 100644
--- a/drivers/media/platform/s5p-tv/mixer_video.c
+++ b/drivers/media/platform/s5p-tv/mixer_video.c
@@ -509,9 +509,11 @@ static int mxr_enum_dv_timings(struct file *file, void *fh,
 	struct mxr_device *mdev = layer->mdev;
 	int ret;
 
+	timings->pad = 0;
+
 	/* lock protects from changing sd_out */
 	mutex_lock(&mdev->mutex);
-	ret = v4l2_subdev_call(to_outsd(mdev), video, enum_dv_timings, timings);
+	ret = v4l2_subdev_call(to_outsd(mdev), pad, enum_dv_timings, timings);
 	mutex_unlock(&mdev->mutex);
 
 	return ret ? -EINVAL : 0;
@@ -567,9 +569,11 @@ static int mxr_dv_timings_cap(struct file *file, void *fh,
 	struct mxr_device *mdev = layer->mdev;
 	int ret;
 
+	cap->pad = 0;
+
 	/* lock protects from changing sd_out */
 	mutex_lock(&mdev->mutex);
-	ret = v4l2_subdev_call(to_outsd(mdev), video, dv_timings_cap, cap);
+	ret = v4l2_subdev_call(to_outsd(mdev), pad, dv_timings_cap, cap);
 	mutex_unlock(&mdev->mutex);
 
 	return ret ? -EINVAL : 0;
-- 
1.8.3.2


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

* [PATCH v2 18/48] ad9389b: Remove deprecated video-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (16 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 17/48] s5p-tv: mixer: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 19/48] adv7511: " Laurent Pinchart
                   ` (30 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings and dv_timings_cap operations are deprecated
and unused. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/ad9389b.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
index 44c037d..4cdff9e 100644
--- a/drivers/media/i2c/ad9389b.c
+++ b/drivers/media/i2c/ad9389b.c
@@ -670,8 +670,6 @@ static const struct v4l2_subdev_video_ops ad9389b_video_ops = {
 	.s_stream = ad9389b_s_stream,
 	.s_dv_timings = ad9389b_s_dv_timings,
 	.g_dv_timings = ad9389b_g_dv_timings,
-	.enum_dv_timings = ad9389b_enum_dv_timings,
-	.dv_timings_cap = ad9389b_dv_timings_cap,
 };
 
 /* ------------------------------ PAD OPS ------------------------------ */
-- 
1.8.3.2


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

* [PATCH v2 19/48] adv7511: Remove deprecated video-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (17 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 18/48] ad9389b: Remove deprecated video-level DV timings operations Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 20/48] adv7842: " Laurent Pinchart
                   ` (29 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings and dv_timings_cap operations are deprecated
and unused. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/adv7511.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index f8c75c6..de7ddf5 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -692,8 +692,6 @@ static const struct v4l2_subdev_video_ops adv7511_video_ops = {
 	.s_stream = adv7511_s_stream,
 	.s_dv_timings = adv7511_s_dv_timings,
 	.g_dv_timings = adv7511_g_dv_timings,
-	.enum_dv_timings = adv7511_enum_dv_timings,
-	.dv_timings_cap = adv7511_dv_timings_cap,
 };
 
 /* ------------------------------ AUDIO OPS ------------------------------ */
-- 
1.8.3.2


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

* [PATCH v2 20/48] adv7842: Remove deprecated video-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (18 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 19/48] adv7511: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 21/48] s5p-tv: hdmi: " Laurent Pinchart
                   ` (28 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings and dv_timings_cap operations are deprecated
and unused. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/adv7842.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 78d21fd..7fd9325 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -2892,8 +2892,6 @@ static const struct v4l2_subdev_video_ops adv7842_video_ops = {
 	.s_dv_timings = adv7842_s_dv_timings,
 	.g_dv_timings = adv7842_g_dv_timings,
 	.query_dv_timings = adv7842_query_dv_timings,
-	.enum_dv_timings = adv7842_enum_dv_timings,
-	.dv_timings_cap = adv7842_dv_timings_cap,
 	.enum_mbus_fmt = adv7842_enum_mbus_fmt,
 	.g_mbus_fmt = adv7842_g_mbus_fmt,
 	.try_mbus_fmt = adv7842_g_mbus_fmt,
-- 
1.8.3.2


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

* [PATCH v2 21/48] s5p-tv: hdmi: Remove deprecated video-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (19 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 20/48] adv7842: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 22/48] s5p-tv: hdmiphy: Remove deprecated video-level DV timings operation Laurent Pinchart
                   ` (27 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Lars-Peter Clausen, Kyungmin Park, Tomasz Stanislawski

The video enum_dv_timings and dv_timings_cap operations are deprecated
and unused. Remove them.

Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/s5p-tv/hdmi_drv.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c
index 3db496c..754740f 100644
--- a/drivers/media/platform/s5p-tv/hdmi_drv.c
+++ b/drivers/media/platform/s5p-tv/hdmi_drv.c
@@ -693,7 +693,7 @@ static int hdmi_dv_timings_cap(struct v4l2_subdev *sd,
 		return -EINVAL;
 
 	/* Let the phy fill in the pixelclock range */
-	v4l2_subdev_call(hdev->phy_sd, video, dv_timings_cap, cap);
+	v4l2_subdev_call(hdev->phy_sd, pad, dv_timings_cap, cap);
 	cap->type = V4L2_DV_BT_656_1120;
 	cap->bt.min_width = 720;
 	cap->bt.max_width = 1920;
@@ -712,8 +712,6 @@ static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = {
 static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = {
 	.s_dv_timings = hdmi_s_dv_timings,
 	.g_dv_timings = hdmi_g_dv_timings,
-	.enum_dv_timings = hdmi_enum_dv_timings,
-	.dv_timings_cap = hdmi_dv_timings_cap,
 	.g_mbus_fmt = hdmi_g_mbus_fmt,
 	.s_stream = hdmi_s_stream,
 };
-- 
1.8.3.2


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

* [PATCH v2 22/48] s5p-tv: hdmiphy: Remove deprecated video-level DV timings operation
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (20 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 21/48] s5p-tv: hdmi: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 23/48] ths8200: Remove deprecated video-level DV timings operations Laurent Pinchart
                   ` (26 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Lars-Peter Clausen, Kyungmin Park, Tomasz Stanislawski

The video enum_dv_timings operation is deprecated and unused. Remove it.

Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/s5p-tv/hdmiphy_drv.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/media/platform/s5p-tv/hdmiphy_drv.c b/drivers/media/platform/s5p-tv/hdmiphy_drv.c
index ff22320..c2f2e35 100644
--- a/drivers/media/platform/s5p-tv/hdmiphy_drv.c
+++ b/drivers/media/platform/s5p-tv/hdmiphy_drv.c
@@ -262,7 +262,6 @@ static const struct v4l2_subdev_core_ops hdmiphy_core_ops = {
 
 static const struct v4l2_subdev_video_ops hdmiphy_video_ops = {
 	.s_dv_timings = hdmiphy_s_dv_timings,
-	.dv_timings_cap = hdmiphy_dv_timings_cap,
 	.s_stream =  hdmiphy_s_stream,
 };
 
-- 
1.8.3.2


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

* [PATCH v2 23/48] ths8200: Remove deprecated video-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (21 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 22/48] s5p-tv: hdmiphy: Remove deprecated video-level DV timings operation Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11  7:13   ` Prabhakar Lad
  2014-03-10 23:15 ` [PATCH v2 24/48] tvp7002: " Laurent Pinchart
                   ` (25 subsequent siblings)
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings and dv_timings_cap operations are deprecated
and unused. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/ths8200.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c
index c4ec8b2..656d889 100644
--- a/drivers/media/i2c/ths8200.c
+++ b/drivers/media/i2c/ths8200.c
@@ -432,8 +432,6 @@ static const struct v4l2_subdev_video_ops ths8200_video_ops = {
 	.s_stream = ths8200_s_stream,
 	.s_dv_timings = ths8200_s_dv_timings,
 	.g_dv_timings = ths8200_g_dv_timings,
-	.enum_dv_timings = ths8200_enum_dv_timings,
-	.dv_timings_cap = ths8200_dv_timings_cap,
 };
 
 static const struct v4l2_subdev_pad_ops ths8200_pad_ops = {
-- 
1.8.3.2


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

* [PATCH v2 24/48] tvp7002: Remove deprecated video-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (22 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 23/48] ths8200: Remove deprecated video-level DV timings operations Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11  7:12   ` Prabhakar Lad
  2014-03-10 23:15 ` [PATCH v2 25/48] v4l: Improve readability by not wrapping ioctl number #define's Laurent Pinchart
                   ` (24 subsequent siblings)
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings and dv_timings_cap operations are deprecated
and unused. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/tvp7002.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
index 9f56fd5..fa901a9 100644
--- a/drivers/media/i2c/tvp7002.c
+++ b/drivers/media/i2c/tvp7002.c
@@ -926,7 +926,6 @@ static const struct v4l2_subdev_core_ops tvp7002_core_ops = {
 static const struct v4l2_subdev_video_ops tvp7002_video_ops = {
 	.g_dv_timings = tvp7002_g_dv_timings,
 	.s_dv_timings = tvp7002_s_dv_timings,
-	.enum_dv_timings = tvp7002_enum_dv_timings,
 	.query_dv_timings = tvp7002_query_dv_timings,
 	.s_stream = tvp7002_s_stream,
 	.g_mbus_fmt = tvp7002_mbus_fmt,
-- 
1.8.3.2


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

* [PATCH v2 25/48] v4l: Improve readability by not wrapping ioctl number #define's
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (23 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 24/48] tvp7002: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 26/48] v4l: Add support for DV timings ioctls on subdev nodes Laurent Pinchart
                   ` (23 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Wrapping the #define's at a 80 columns boundary just obfuscates the
code. Don't do that.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 include/uapi/linux/v4l2-subdev.h | 33 +++++++++++++--------------------
 1 file changed, 13 insertions(+), 20 deletions(-)

diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index a33c4da..9fe3493 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/include/uapi/linux/v4l2-subdev.h
@@ -156,25 +156,18 @@ struct v4l2_subdev_edid {
 	__u8 __user *edid;
 };
 
-#define VIDIOC_SUBDEV_G_FMT	_IOWR('V',  4, struct v4l2_subdev_format)
-#define VIDIOC_SUBDEV_S_FMT	_IOWR('V',  5, struct v4l2_subdev_format)
-#define VIDIOC_SUBDEV_G_FRAME_INTERVAL \
-			_IOWR('V', 21, struct v4l2_subdev_frame_interval)
-#define VIDIOC_SUBDEV_S_FRAME_INTERVAL \
-			_IOWR('V', 22, struct v4l2_subdev_frame_interval)
-#define VIDIOC_SUBDEV_ENUM_MBUS_CODE \
-			_IOWR('V',  2, struct v4l2_subdev_mbus_code_enum)
-#define VIDIOC_SUBDEV_ENUM_FRAME_SIZE \
-			_IOWR('V', 74, struct v4l2_subdev_frame_size_enum)
-#define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \
-			_IOWR('V', 75, struct v4l2_subdev_frame_interval_enum)
-#define VIDIOC_SUBDEV_G_CROP	_IOWR('V', 59, struct v4l2_subdev_crop)
-#define VIDIOC_SUBDEV_S_CROP	_IOWR('V', 60, struct v4l2_subdev_crop)
-#define VIDIOC_SUBDEV_G_SELECTION \
-	_IOWR('V', 61, struct v4l2_subdev_selection)
-#define VIDIOC_SUBDEV_S_SELECTION \
-	_IOWR('V', 62, struct v4l2_subdev_selection)
-#define VIDIOC_SUBDEV_G_EDID	_IOWR('V', 40, struct v4l2_subdev_edid)
-#define VIDIOC_SUBDEV_S_EDID	_IOWR('V', 41, struct v4l2_subdev_edid)
+#define VIDIOC_SUBDEV_G_FMT			_IOWR('V',  4, struct v4l2_subdev_format)
+#define VIDIOC_SUBDEV_S_FMT			_IOWR('V',  5, struct v4l2_subdev_format)
+#define VIDIOC_SUBDEV_G_FRAME_INTERVAL		_IOWR('V', 21, struct v4l2_subdev_frame_interval)
+#define VIDIOC_SUBDEV_S_FRAME_INTERVAL		_IOWR('V', 22, struct v4l2_subdev_frame_interval)
+#define VIDIOC_SUBDEV_ENUM_MBUS_CODE		_IOWR('V',  2, struct v4l2_subdev_mbus_code_enum)
+#define VIDIOC_SUBDEV_ENUM_FRAME_SIZE		_IOWR('V', 74, struct v4l2_subdev_frame_size_enum)
+#define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL	_IOWR('V', 75, struct v4l2_subdev_frame_interval_enum)
+#define VIDIOC_SUBDEV_G_CROP			_IOWR('V', 59, struct v4l2_subdev_crop)
+#define VIDIOC_SUBDEV_S_CROP			_IOWR('V', 60, struct v4l2_subdev_crop)
+#define VIDIOC_SUBDEV_G_SELECTION		_IOWR('V', 61, struct v4l2_subdev_selection)
+#define VIDIOC_SUBDEV_S_SELECTION		_IOWR('V', 62, struct v4l2_subdev_selection)
+#define VIDIOC_SUBDEV_G_EDID			_IOWR('V', 40, struct v4l2_subdev_edid)
+#define VIDIOC_SUBDEV_S_EDID			_IOWR('V', 41, struct v4l2_subdev_edid)
 
 #endif
-- 
1.8.3.2


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

* [PATCH v2 26/48] v4l: Add support for DV timings ioctls on subdev nodes
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (24 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 25/48] v4l: Improve readability by not wrapping ioctl number #define's Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11 10:38   ` Hans Verkuil
  2014-03-11 15:09   ` [PATCH v3 " Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 27/48] v4l: Validate fields in the core code for subdev EDID ioctls Laurent Pinchart
                   ` (22 subsequent siblings)
  48 siblings, 2 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Validate the pad field in the core code whenever specified.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../DocBook/media/v4l/vidioc-dv-timings-cap.xml    | 27 +++++++++++++++----
 .../DocBook/media/v4l/vidioc-enum-dv-timings.xml   | 30 +++++++++++++++++-----
 drivers/media/v4l2-core/v4l2-subdev.c              | 27 +++++++++++++++++++
 include/uapi/linux/v4l2-subdev.h                   |  5 ++++
 4 files changed, 77 insertions(+), 12 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
index cd7720d..28a8c1e 100644
--- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
@@ -1,11 +1,12 @@
 <refentry id="vidioc-dv-timings-cap">
   <refmeta>
-    <refentrytitle>ioctl VIDIOC_DV_TIMINGS_CAP</refentrytitle>
+    <refentrytitle>ioctl VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</refentrytitle>
     &manvol;
   </refmeta>
 
   <refnamediv>
     <refname>VIDIOC_DV_TIMINGS_CAP</refname>
+    <refname>VIDIOC_SUBDEV_DV_TIMINGS_CAP</refname>
     <refpurpose>The capabilities of the Digital Video receiver/transmitter</refpurpose>
   </refnamediv>
 
@@ -33,7 +34,7 @@
       <varlistentry>
 	<term><parameter>request</parameter></term>
 	<listitem>
-	  <para>VIDIOC_DV_TIMINGS_CAP</para>
+	  <para>VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</para>
 	</listitem>
       </varlistentry>
       <varlistentry>
@@ -54,10 +55,19 @@
       interface and may change in the future.</para>
     </note>
 
-    <para>To query the capabilities of the DV receiver/transmitter applications can call
-this ioctl and the driver will fill in the structure. Note that drivers may return
+    <para>To query the capabilities of the DV receiver/transmitter applications
+can call the <constant>VIDIOC_DV_TIMINGS_CAP</constant> ioctl on a video node
+and the driver will fill in the structure. Note that drivers may return
 different values after switching the video input or output.</para>
 
+    <para>When implemented by the driver DV capabilities of subdevices can be
+queried by calling the <constant>VIDIOC_SUBDEV_DV_TIMINGS_CAP</constant> ioctl
+directly on a subdevice node. The capabilities are specific to inputs (for DV
+receivers) or outputs (for DV transmitters), applications must specify the
+desired pad number in the &v4l2-dv-timings-cap; <structfield>pad</structfield>
+field. Attempts to query capabilities on a pad that doesn't support them will
+return an &EINVAL;.</para>
+
     <table pgwide="1" frame="none" id="v4l2-bt-timings-cap">
       <title>struct <structname>v4l2_bt_timings_cap</structname></title>
       <tgroup cols="3">
@@ -127,7 +137,14 @@ different values after switching the video input or output.</para>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[3]</entry>
+	    <entry><structfield>pad</structfield></entry>
+	    <entry>Pad number as reported by the media controller API. This field
+	    is only used when operating on a subdevice node. When operating on a
+	    video node applications must set this field to zero.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[2]</entry>
 	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
 	  </row>
 	  <row>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
index b3e17c1..b9fdfea 100644
--- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
@@ -1,11 +1,12 @@
 <refentry id="vidioc-enum-dv-timings">
   <refmeta>
-    <refentrytitle>ioctl VIDIOC_ENUM_DV_TIMINGS</refentrytitle>
+    <refentrytitle>ioctl VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refentrytitle>
     &manvol;
   </refmeta>
 
   <refnamediv>
     <refname>VIDIOC_ENUM_DV_TIMINGS</refname>
+    <refname>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refname>
     <refpurpose>Enumerate supported Digital Video timings</refpurpose>
   </refnamediv>
 
@@ -33,7 +34,7 @@
       <varlistentry>
 	<term><parameter>request</parameter></term>
 	<listitem>
-	  <para>VIDIOC_ENUM_DV_TIMINGS</para>
+	  <para>VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</para>
 	</listitem>
       </varlistentry>
       <varlistentry>
@@ -61,14 +62,21 @@ standards or even custom timings that are not in this list.</para>
 
     <para>To query the available timings, applications initialize the
 <structfield>index</structfield> field and zero the reserved array of &v4l2-enum-dv-timings;
-and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl with a pointer to this
-structure. Drivers fill the rest of the structure or return an
+and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl on a video node with a
+pointer to this structure. Drivers fill the rest of the structure or return an
 &EINVAL; when the index is out of bounds. To enumerate all supported DV timings,
 applications shall begin at index zero, incrementing by one until the
 driver returns <errorcode>EINVAL</errorcode>. Note that drivers may enumerate a
 different set of DV timings after switching the video input or
 output.</para>
 
+    <para>When implemented by the driver DV timings of subdevices can be queried
+by calling the <constant>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</constant> ioctl directly
+on a subdevice node. The DV timings are specific to inputs (for DV receivers) or
+outputs (for DV transmitters), applications must specify the desired pad number
+in the &v4l2-enum-dv-timings; <structfield>pad</structfield> field. Attempts to
+enumerate timings on a pad that doesn't support them will return an &EINVAL;.</para>
+
     <table pgwide="1" frame="none" id="v4l2-enum-dv-timings">
       <title>struct <structname>v4l2_enum_dv_timings</structname></title>
       <tgroup cols="3">
@@ -82,8 +90,16 @@ application.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[3]</entry>
-	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
+	    <entry><structfield>pad</structfield></entry>
+	    <entry>Pad number as reported by the media controller API. This field
+	    is only used when operating on a subdevice node. When operating on a
+	    video node applications must set this field to zero.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[2]</entry>
+	    <entry>Reserved for future extensions. Drivers and applications must
+	    set the array to zero.</entry>
 	  </row>
 	  <row>
 	    <entry>&v4l2-dv-timings;</entry>
@@ -103,7 +119,7 @@ application.</entry>
 	<term><errorcode>EINVAL</errorcode></term>
 	<listitem>
 	  <para>The &v4l2-enum-dv-timings; <structfield>index</structfield>
-is out of bounds.</para>
+is out of bounds or the <structfield>pad</structfield> number is invalid.</para>
 	</listitem>
       </varlistentry>
       <varlistentry>
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 60d2550..853fb84 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -354,6 +354,33 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
 	case VIDIOC_SUBDEV_S_EDID:
 		return v4l2_subdev_call(sd, pad, set_edid, arg);
+
+	case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
+		struct v4l2_dv_timings_cap *cap = arg;
+
+		if (cap->pad >= sd->entity.num_pads)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, dv_timings_cap, cap);
+	}
+
+	case VIDIOC_SUBDEV_ENUM_DV_TIMINGS: {
+		struct v4l2_enum_dv_timings *dvt = arg;
+
+		if (dvt->pad >= sd->entity.num_pads)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, enum_dv_timings, dvt);
+	}
+
+	case VIDIOC_SUBDEV_QUERY_DV_TIMINGS:
+		return v4l2_subdev_call(sd, video, query_dv_timings, arg);
+
+	case VIDIOC_SUBDEV_G_DV_TIMINGS:
+		return v4l2_subdev_call(sd, video, g_dv_timings, arg);
+
+	case VIDIOC_SUBDEV_S_DV_TIMINGS:
+		return v4l2_subdev_call(sd, video, s_dv_timings, arg);
 #endif
 	default:
 		return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index 9fe3493..6f5c5de 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/include/uapi/linux/v4l2-subdev.h
@@ -169,5 +169,10 @@ struct v4l2_subdev_edid {
 #define VIDIOC_SUBDEV_S_SELECTION		_IOWR('V', 62, struct v4l2_subdev_selection)
 #define VIDIOC_SUBDEV_G_EDID			_IOWR('V', 40, struct v4l2_subdev_edid)
 #define VIDIOC_SUBDEV_S_EDID			_IOWR('V', 41, struct v4l2_subdev_edid)
+#define VIDIOC_SUBDEV_DV_TIMINGS_CAP		_IOWR('V', 42, struct v4l2_dv_timings_cap)
+#define VIDIOC_SUBDEV_ENUM_DV_TIMINGS		_IOWR('V', 43, struct v4l2_enum_dv_timings)
+#define VIDIOC_SUBDEV_QUERY_DV_TIMINGS		_IOR('V', 44, struct v4l2_dv_timings)
+#define VIDIOC_SUBDEV_G_DV_TIMINGS		_IOWR('V', 45, struct v4l2_dv_timings)
+#define VIDIOC_SUBDEV_S_DV_TIMINGS		_IOWR('V', 46, struct v4l2_dv_timings)
 
 #endif
-- 
1.8.3.2


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

* [PATCH v2 27/48] v4l: Validate fields in the core code for subdev EDID ioctls
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (25 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 26/48] v4l: Add support for DV timings ioctls on subdev nodes Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11  8:57   ` Sakari Ailus
                     ` (2 more replies)
  2014-03-10 23:15 ` [PATCH v2 28/48] adv7604: Add missing include to linux/types.h Laurent Pinchart
                   ` (21 subsequent siblings)
  48 siblings, 3 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The subdev EDID ioctls receive a pad field that must reference an
existing pad and an EDID field that must point to a buffer. Validate
both fields in the core code instead of duplicating validation in all
drivers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/ad9389b.c           |  2 --
 drivers/media/i2c/adv7511.c           |  2 --
 drivers/media/i2c/adv7604.c           |  4 ----
 drivers/media/i2c/adv7842.c           |  4 ----
 drivers/media/v4l2-core/v4l2-subdev.c | 24 ++++++++++++++++++++----
 5 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
index 4cdff9e..5b78828 100644
--- a/drivers/media/i2c/ad9389b.c
+++ b/drivers/media/i2c/ad9389b.c
@@ -683,8 +683,6 @@ static int ad9389b_get_edid(struct v4l2_subdev *sd,
 		return -EINVAL;
 	if (edid->blocks == 0 || edid->blocks > 256)
 		return -EINVAL;
-	if (!edid->edid)
-		return -EINVAL;
 	if (!state->edid.segments) {
 		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
 		return -ENODATA;
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index de7ddf5..ff1c2cd 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -784,8 +784,6 @@ static int adv7511_get_edid(struct v4l2_subdev *sd,
 		return -EINVAL;
 	if ((edid->blocks == 0) || (edid->blocks > 256))
 		return -EINVAL;
-	if (!edid->edid)
-		return -EINVAL;
 	if (!state->edid.segments) {
 		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
 		return -ENODATA;
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 71c8570..de3db42 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1673,8 +1673,6 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 		return -EINVAL;
 	if (edid->start_block == 1)
 		edid->blocks = 1;
-	if (!edid->edid)
-		return -EINVAL;
 
 	if (edid->blocks > state->edid.blocks)
 		edid->blocks = state->edid.blocks;
@@ -1761,8 +1759,6 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 		edid->blocks = 2;
 		return -E2BIG;
 	}
-	if (!edid->edid)
-		return -EINVAL;
 
 	v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n",
 			__func__, edid->pad, state->edid.present);
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 7fd9325..33558c8 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -2035,8 +2035,6 @@ static int adv7842_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 		return -EINVAL;
 	if (edid->start_block == 1)
 		edid->blocks = 1;
-	if (!edid->edid)
-		return -EINVAL;
 
 	switch (edid->pad) {
 	case ADV7842_EDID_PORT_A:
@@ -2071,8 +2069,6 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *e)
 		return -EINVAL;
 	if (e->blocks > 2)
 		return -E2BIG;
-	if (!e->edid)
-		return -EINVAL;
 
 	/* todo, per edid */
 	state->aspect_ratio = v4l2_calc_aspect_ratio(e->edid[0x15],
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 853fb84..9fff1eb 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -349,11 +349,27 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 			sd, pad, set_selection, subdev_fh, sel);
 	}
 
-	case VIDIOC_SUBDEV_G_EDID:
-		return v4l2_subdev_call(sd, pad, get_edid, arg);
+	case VIDIOC_SUBDEV_G_EDID: {
+		struct v4l2_subdev_edid *edid = arg;
 
-	case VIDIOC_SUBDEV_S_EDID:
-		return v4l2_subdev_call(sd, pad, set_edid, arg);
+		if (edid->pad >= sd->entity.num_pads)
+			return -EINVAL;
+		if (edid->edid == NULL)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, get_edid, edid);
+	}
+
+	case VIDIOC_SUBDEV_S_EDID: {
+		struct v4l2_subdev_edid *edid = arg;
+
+		if (edid->pad >= sd->entity.num_pads)
+			return -EINVAL;
+		if (edid->edid == NULL)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, set_edid, edid);
+	}
 
 	case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
 		struct v4l2_dv_timings_cap *cap = arg;
-- 
1.8.3.2


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

* [PATCH v2 28/48] adv7604: Add missing include to linux/types.h
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (26 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 27/48] v4l: Validate fields in the core code for subdev EDID ioctls Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 29/48] adv7604: Add support for asynchronous probing Laurent Pinchart
                   ` (20 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

From: Lars-Peter Clausen <lars@metafoo.de>

The file is using u8 which is defined in linux/types.h.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 include/media/adv7604.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index d262a3a..c6b3937 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -21,6 +21,8 @@
 #ifndef _ADV7604_
 #define _ADV7604_
 
+#include <linux/types.h>
+
 /* Analog input muxing modes (AFE register 0x02, [2:0]) */
 enum adv7604_ain_sel {
 	ADV7604_AIN1_2_3_NC_SYNC_1_2 = 0,
-- 
1.8.3.2


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

* [PATCH v2 29/48] adv7604: Add support for asynchronous probing
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (27 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 28/48] adv7604: Add missing include to linux/types.h Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 30/48] adv7604: Don't put info string arrays on the stack Laurent Pinchart
                   ` (19 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

From: Lars-Peter Clausen <lars@metafoo.de>

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index de3db42..c3a76ac 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2333,6 +2333,11 @@ static int adv7604_probe(struct i2c_client *client,
 		goto err_entity;
 	v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
 			client->addr << 1, client->adapter->name);
+
+	err = v4l2_async_register_subdev(sd);
+	if (err)
+		goto err_entity;
+
 	return 0;
 
 err_entity:
@@ -2356,6 +2361,7 @@ static int adv7604_remove(struct i2c_client *client)
 
 	cancel_delayed_work(&state->delayed_work_enable_hotplug);
 	destroy_workqueue(state->work_queues);
+	v4l2_async_unregister_subdev(sd);
 	v4l2_device_unregister_subdev(sd);
 	media_entity_cleanup(&sd->entity);
 	adv7604_unregister_clients(to_state(sd));
-- 
1.8.3.2


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

* [PATCH v2 30/48] adv7604: Don't put info string arrays on the stack
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (28 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 29/48] adv7604: Add support for asynchronous probing Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 31/48] adv7604: Add 16-bit read functions for CP and HDMI Laurent Pinchart
                   ` (18 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

From: Lars-Peter Clausen <lars@metafoo.de>

We do not want to modify the info string arrays ever, so no need to
waste stack space for them. While we are at it also make them const.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index c3a76ac..81d737c 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1882,13 +1882,13 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
 	struct stdi_readback stdi;
 	u8 reg_io_0x02 = io_read(sd, 0x02);
 
-	char *csc_coeff_sel_rb[16] = {
+	static const char * const csc_coeff_sel_rb[16] = {
 		"bypassed", "YPbPr601 -> RGB", "reserved", "YPbPr709 -> RGB",
 		"reserved", "RGB -> YPbPr601", "reserved", "RGB -> YPbPr709",
 		"reserved", "YPbPr709 -> YPbPr601", "YPbPr601 -> YPbPr709",
 		"reserved", "reserved", "reserved", "reserved", "manual"
 	};
-	char *input_color_space_txt[16] = {
+	static const char * const input_color_space_txt[16] = {
 		"RGB limited range (16-235)", "RGB full range (0-255)",
 		"YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)",
 		"xvYCC Bt.601", "xvYCC Bt.709",
@@ -1896,12 +1896,12 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
 		"invalid", "invalid", "invalid", "invalid", "invalid",
 		"invalid", "invalid", "automatic"
 	};
-	char *rgb_quantization_range_txt[] = {
+	static const char * const rgb_quantization_range_txt[] = {
 		"Automatic",
 		"RGB limited range (16-235)",
 		"RGB full range (0-255)",
 	};
-	char *deep_color_mode_txt[4] = {
+	static const char * const deep_color_mode_txt[4] = {
 		"8-bits per channel",
 		"10-bits per channel",
 		"12-bits per channel",
-- 
1.8.3.2


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

* [PATCH v2 31/48] adv7604: Add 16-bit read functions for CP and HDMI
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (29 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 30/48] adv7604: Don't put info string arrays on the stack Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 32/48] adv7604: Cache register contents when reading multiple bits Laurent Pinchart
                   ` (17 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 48 ++++++++++++++++++++++-----------------------
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 81d737c..75b3dae 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -542,6 +542,11 @@ static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg)
 	return adv_smbus_read_byte_data(state->i2c_hdmi, reg);
 }
 
+static u16 hdmi_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
+{
+	return ((hdmi_read(sd, reg) << 8) | hdmi_read(sd, reg + 1)) & mask;
+}
+
 static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
@@ -575,6 +580,11 @@ static inline int cp_read(struct v4l2_subdev *sd, u8 reg)
 	return adv_smbus_read_byte_data(state->i2c_cp, reg);
 }
 
+static u16 cp_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
+{
+	return ((cp_read(sd, reg) << 8) | cp_read(sd, reg + 1)) & mask;
+}
+
 static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
@@ -1203,8 +1213,8 @@ static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
 	}
 
 	/* read STDI */
-	stdi->bl = ((cp_read(sd, 0xb1) & 0x3f) << 8) | cp_read(sd, 0xb2);
-	stdi->lcf = ((cp_read(sd, 0xb3) & 0x7) << 8) | cp_read(sd, 0xb4);
+	stdi->bl = cp_read16(sd, 0xb1, 0x3fff);
+	stdi->lcf = cp_read16(sd, 0xb3, 0x7ff);
 	stdi->lcvs = cp_read(sd, 0xb3) >> 3;
 	stdi->interlaced = io_read(sd, 0x12) & 0x10;
 
@@ -1315,8 +1325,8 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
 
 		timings->type = V4L2_DV_BT_656_1120;
 
-		bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08);
-		bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a);
+		bt->width = hdmi_read16(sd, 0x07, 0xfff);
+		bt->height = hdmi_read16(sd, 0x09, 0xfff);
 		freq = (hdmi_read(sd, 0x06) * 1000000) +
 			((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000;
 		if (is_hdmi(sd)) {
@@ -1326,29 +1336,19 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
 			freq = freq * 8 / bits_per_channel;
 		}
 		bt->pixelclock = freq;
-		bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 +
-			hdmi_read(sd, 0x21);
-		bt->hsync = (hdmi_read(sd, 0x22) & 0x03) * 256 +
-			hdmi_read(sd, 0x23);
-		bt->hbackporch = (hdmi_read(sd, 0x24) & 0x03) * 256 +
-			hdmi_read(sd, 0x25);
-		bt->vfrontporch = ((hdmi_read(sd, 0x2a) & 0x1f) * 256 +
-			hdmi_read(sd, 0x2b)) / 2;
-		bt->vsync = ((hdmi_read(sd, 0x2e) & 0x1f) * 256 +
-			hdmi_read(sd, 0x2f)) / 2;
-		bt->vbackporch = ((hdmi_read(sd, 0x32) & 0x1f) * 256 +
-			hdmi_read(sd, 0x33)) / 2;
+		bt->hfrontporch = hdmi_read16(sd, 0x20, 0x3ff);
+		bt->hsync = hdmi_read16(sd, 0x22, 0x3ff);
+		bt->hbackporch = hdmi_read16(sd, 0x24, 0x3ff);
+		bt->vfrontporch = hdmi_read16(sd, 0x2a, 0x1fff) / 2;
+		bt->vsync = hdmi_read16(sd, 0x2e, 0x1fff) / 2;
+		bt->vbackporch = hdmi_read16(sd, 0x32, 0x1fff) / 2;
 		bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? V4L2_DV_VSYNC_POS_POL : 0) |
 			((hdmi_read(sd, 0x05) & 0x20) ? V4L2_DV_HSYNC_POS_POL : 0);
 		if (bt->interlaced == V4L2_DV_INTERLACED) {
-			bt->height += (hdmi_read(sd, 0x0b) & 0x0f) * 256 +
-					hdmi_read(sd, 0x0c);
-			bt->il_vfrontporch = ((hdmi_read(sd, 0x2c) & 0x1f) * 256 +
-					hdmi_read(sd, 0x2d)) / 2;
-			bt->il_vsync = ((hdmi_read(sd, 0x30) & 0x1f) * 256 +
-					hdmi_read(sd, 0x31)) / 2;
-			bt->vbackporch = ((hdmi_read(sd, 0x34) & 0x1f) * 256 +
-					hdmi_read(sd, 0x35)) / 2;
+			bt->height += hdmi_read16(sd, 0x0b, 0xfff);
+			bt->il_vfrontporch = hdmi_read16(sd, 0x2c, 0x1fff) / 2;
+			bt->il_vsync = hdmi_read16(sd, 0x30, 0x1fff) / 2;
+			bt->vbackporch = hdmi_read16(sd, 0x34, 0x1fff) / 2;
 		}
 		adv7604_fill_optional_dv_timings_fields(sd, timings);
 	} else {
-- 
1.8.3.2


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

* [PATCH v2 32/48] adv7604: Cache register contents when reading multiple bits
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (30 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 31/48] adv7604: Add 16-bit read functions for CP and HDMI Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 33/48] adv7604: Add adv7611 support Laurent Pinchart
                   ` (16 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

When extracting multiple bits from a single register read the register
once and extract the bits on the read value.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 75b3dae..80534f9 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1207,6 +1207,8 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
 
 static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
 {
+	u8 polarity;
+
 	if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
 		v4l2_dbg(2, debug, sd, "%s: STDI and/or SSPD not locked\n", __func__);
 		return -1;
@@ -1219,11 +1221,12 @@ static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
 	stdi->interlaced = io_read(sd, 0x12) & 0x10;
 
 	/* read SSPD */
-	if ((cp_read(sd, 0xb5) & 0x03) == 0x01) {
-		stdi->hs_pol = ((cp_read(sd, 0xb5) & 0x10) ?
-				((cp_read(sd, 0xb5) & 0x08) ? '+' : '-') : 'x');
-		stdi->vs_pol = ((cp_read(sd, 0xb5) & 0x40) ?
-				((cp_read(sd, 0xb5) & 0x20) ? '+' : '-') : 'x');
+	polarity = cp_read(sd, 0xb5);
+	if ((polarity & 0x03) == 0x01) {
+		stdi->hs_pol = polarity & 0x10
+			     ? (polarity & 0x08 ? '+' : '-') : 'x';
+		stdi->vs_pol = polarity & 0x40
+			     ? (polarity & 0x20 ? '+' : '-') : 'x';
 	} else {
 		stdi->hs_pol = 'x';
 		stdi->vs_pol = 'x';
@@ -1881,6 +1884,8 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
 	struct v4l2_dv_timings timings;
 	struct stdi_readback stdi;
 	u8 reg_io_0x02 = io_read(sd, 0x02);
+	u8 edid_enabled;
+	u8 cable_det;
 
 	static const char * const csc_coeff_sel_rb[16] = {
 		"bypassed", "YPbPr601 -> RGB", "reserved", "YPbPr709 -> RGB",
@@ -1910,20 +1915,22 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
 
 	v4l2_info(sd, "-----Chip status-----\n");
 	v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on");
+	edid_enabled = rep_read(sd, 0x7d);
 	v4l2_info(sd, "EDID enabled port A: %s, B: %s, C: %s, D: %s\n",
-			((rep_read(sd, 0x7d) & 0x01) ? "Yes" : "No"),
-			((rep_read(sd, 0x7d) & 0x02) ? "Yes" : "No"),
-			((rep_read(sd, 0x7d) & 0x04) ? "Yes" : "No"),
-			((rep_read(sd, 0x7d) & 0x08) ? "Yes" : "No"));
+			((edid_enabled & 0x01) ? "Yes" : "No"),
+			((edid_enabled & 0x02) ? "Yes" : "No"),
+			((edid_enabled & 0x04) ? "Yes" : "No"),
+			((edid_enabled & 0x08) ? "Yes" : "No"));
 	v4l2_info(sd, "CEC: %s\n", !!(cec_read(sd, 0x2a) & 0x01) ?
 			"enabled" : "disabled");
 
 	v4l2_info(sd, "-----Signal status-----\n");
+	cable_det = io_read(sd, 0x6f);
 	v4l2_info(sd, "Cable detected (+5V power) port A: %s, B: %s, C: %s, D: %s\n",
-			((io_read(sd, 0x6f) & 0x10) ? "Yes" : "No"),
-			((io_read(sd, 0x6f) & 0x08) ? "Yes" : "No"),
-			((io_read(sd, 0x6f) & 0x04) ? "Yes" : "No"),
-			((io_read(sd, 0x6f) & 0x02) ? "Yes" : "No"));
+			((cable_det & 0x10) ? "Yes" : "No"),
+			((cable_det & 0x08) ? "Yes" : "No"),
+			((cable_det & 0x04) ? "Yes" : "No"),
+			((cable_det & 0x02) ? "Yes" : "No"));
 	v4l2_info(sd, "TMDS signal detected: %s\n",
 			no_signal_tmds(sd) ? "false" : "true");
 	v4l2_info(sd, "TMDS signal locked: %s\n",
-- 
1.8.3.2


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

* [PATCH v2 33/48] adv7604: Add adv7611 support
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (31 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 32/48] adv7604: Cache register contents when reading multiple bits Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 34/48] adv7604: Remove subdev control handlers Laurent Pinchart
                   ` (15 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

From: Lars-Peter Clausen <lars@metafoo.de>

This patch adds support for the Analog Devices ADV7611 HDMI receiver.
The adv7611 is quite similar to the adv7604. It has only one instead of four
HDMI inputs and no analog frontend though. Also some register bits have been
shuffled around, but large parts of their register maps are compatible.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/media/i2c/adv7604.c | 719 +++++++++++++++++++++++++++++++-------------
 include/media/adv7604.h     |  10 +
 2 files changed, 528 insertions(+), 201 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 80534f9..3866970 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -53,6 +53,43 @@ MODULE_LICENSE("GPL");
 /* ADV7604 system clock frequency */
 #define ADV7604_fsc (28636360)
 
+enum adv7604_type {
+	ADV7604,
+	ADV7611,
+};
+
+struct adv7604_reg_seq {
+	unsigned int reg;
+	u8 val;
+};
+
+struct adv7604_chip_info {
+	enum adv7604_type type;
+
+	bool has_afe;
+	unsigned int max_port;
+	unsigned int num_dv_ports;
+
+	unsigned int edid_enable_reg;
+	unsigned int edid_status_reg;
+	unsigned int lcf_reg;
+
+	unsigned int cable_det_mask;
+	unsigned int tdms_lock_mask;
+	unsigned int fmt_change_digital_mask;
+
+	void (*set_termination)(struct v4l2_subdev *sd, bool enable);
+	void (*setup_irqs)(struct v4l2_subdev *sd);
+	unsigned int (*read_hdmi_pixelclock)(struct v4l2_subdev *sd);
+	unsigned int (*read_cable_det)(struct v4l2_subdev *sd);
+
+	/* 0 = AFE, 1 = HDMI */
+	const struct adv7604_reg_seq *recommended_settings[2];
+	unsigned int num_recommended_settings[2];
+
+	unsigned long page_mask;
+};
+
 /*
  **********************************************************************
  *
@@ -61,6 +98,7 @@ MODULE_LICENSE("GPL");
  **********************************************************************
  */
 struct adv7604_state {
+	const struct adv7604_chip_info *info;
 	struct adv7604_platform_data pdata;
 	struct v4l2_subdev sd;
 	struct media_pad pad;
@@ -101,6 +139,11 @@ struct adv7604_state {
 	struct v4l2_ctrl *rgb_quantization_range_ctrl;
 };
 
+static bool adv7604_has_afe(struct adv7604_state *state)
+{
+	return state->info->has_afe;
+}
+
 /* Supported CEA and DMT timings */
 static const struct v4l2_dv_timings adv7604_timings[] = {
 	V4L2_DV_BT_CEA_720X480P59_94,
@@ -611,6 +654,121 @@ static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state->i2c_vdp, reg, val);
 }
 
+enum {
+	ADV7604_PAGE_IO,
+	ADV7604_PAGE_AVLINK,
+	ADV7604_PAGE_CEC,
+	ADV7604_PAGE_INFOFRAME,
+	ADV7604_PAGE_ESDP,
+	ADV7604_PAGE_DPP,
+	ADV7604_PAGE_AFE,
+	ADV7604_PAGE_REP,
+	ADV7604_PAGE_EDID,
+	ADV7604_PAGE_HDMI,
+	ADV7604_PAGE_TEST,
+	ADV7604_PAGE_CP,
+	ADV7604_PAGE_VDP,
+	ADV7604_PAGE_TERM,
+};
+
+#define ADV7604_REG(page, offset)	(((page) << 8) | (offset))
+#define ADV7604_REG_SEQ_TERM		0xffff
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int adv7604_read_reg(struct v4l2_subdev *sd, unsigned int reg)
+{
+	struct adv7604_state *state = to_state(sd);
+	unsigned int page = reg >> 8;
+
+	if (!(BIT(page) & state->info->page_mask))
+		return -EINVAL;
+
+	reg &= 0xff;
+
+	switch (page) {
+	case ADV7604_PAGE_IO:
+		return io_read(sd, reg);
+	case ADV7604_PAGE_AVLINK:
+		return avlink_read(sd, reg);
+	case ADV7604_PAGE_CEC:
+		return cec_read(sd, reg);
+	case ADV7604_PAGE_INFOFRAME:
+		return infoframe_read(sd, reg);
+	case ADV7604_PAGE_ESDP:
+		return esdp_read(sd, reg);
+	case ADV7604_PAGE_DPP:
+		return dpp_read(sd, reg);
+	case ADV7604_PAGE_AFE:
+		return afe_read(sd, reg);
+	case ADV7604_PAGE_REP:
+		return rep_read(sd, reg);
+	case ADV7604_PAGE_EDID:
+		return edid_read(sd, reg);
+	case ADV7604_PAGE_HDMI:
+		return hdmi_read(sd, reg);
+	case ADV7604_PAGE_TEST:
+		return test_read(sd, reg);
+	case ADV7604_PAGE_CP:
+		return cp_read(sd, reg);
+	case ADV7604_PAGE_VDP:
+		return vdp_read(sd, reg);
+	}
+
+	return -EINVAL;
+}
+#endif
+
+static int adv7604_write_reg(struct v4l2_subdev *sd, unsigned int reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+	unsigned int page = reg >> 8;
+
+	if (!(BIT(page) & state->info->page_mask))
+		return -EINVAL;
+
+	reg &= 0xff;
+
+	switch (page) {
+	case ADV7604_PAGE_IO:
+		return io_write(sd, reg, val);
+	case ADV7604_PAGE_AVLINK:
+		return avlink_write(sd, reg, val);
+	case ADV7604_PAGE_CEC:
+		return cec_write(sd, reg, val);
+	case ADV7604_PAGE_INFOFRAME:
+		return infoframe_write(sd, reg, val);
+	case ADV7604_PAGE_ESDP:
+		return esdp_write(sd, reg, val);
+	case ADV7604_PAGE_DPP:
+		return dpp_write(sd, reg, val);
+	case ADV7604_PAGE_AFE:
+		return afe_write(sd, reg, val);
+	case ADV7604_PAGE_REP:
+		return rep_write(sd, reg, val);
+	case ADV7604_PAGE_EDID:
+		return edid_write(sd, reg, val);
+	case ADV7604_PAGE_HDMI:
+		return hdmi_write(sd, reg, val);
+	case ADV7604_PAGE_TEST:
+		return test_write(sd, reg, val);
+	case ADV7604_PAGE_CP:
+		return cp_write(sd, reg, val);
+	case ADV7604_PAGE_VDP:
+		return vdp_write(sd, reg, val);
+	}
+
+	return -EINVAL;
+}
+
+static void adv7604_write_reg_seq(struct v4l2_subdev *sd,
+				  const struct adv7604_reg_seq *reg_seq)
+{
+	unsigned int i;
+
+	for (i = 0; reg_seq[i].reg != ADV7604_REG_SEQ_TERM; i++)
+		adv7604_write_reg(sd, reg_seq[i].reg, reg_seq[i].val);
+}
+
 /* ----------------------------------------------------------------------- */
 
 static inline bool is_analog_input(struct v4l2_subdev *sd)
@@ -654,119 +812,61 @@ static void adv7604_inv_register(struct v4l2_subdev *sd)
 static int adv7604_g_register(struct v4l2_subdev *sd,
 					struct v4l2_dbg_register *reg)
 {
-	reg->size = 1;
-	switch (reg->reg >> 8) {
-	case 0:
-		reg->val = io_read(sd, reg->reg & 0xff);
-		break;
-	case 1:
-		reg->val = avlink_read(sd, reg->reg & 0xff);
-		break;
-	case 2:
-		reg->val = cec_read(sd, reg->reg & 0xff);
-		break;
-	case 3:
-		reg->val = infoframe_read(sd, reg->reg & 0xff);
-		break;
-	case 4:
-		reg->val = esdp_read(sd, reg->reg & 0xff);
-		break;
-	case 5:
-		reg->val = dpp_read(sd, reg->reg & 0xff);
-		break;
-	case 6:
-		reg->val = afe_read(sd, reg->reg & 0xff);
-		break;
-	case 7:
-		reg->val = rep_read(sd, reg->reg & 0xff);
-		break;
-	case 8:
-		reg->val = edid_read(sd, reg->reg & 0xff);
-		break;
-	case 9:
-		reg->val = hdmi_read(sd, reg->reg & 0xff);
-		break;
-	case 0xa:
-		reg->val = test_read(sd, reg->reg & 0xff);
-		break;
-	case 0xb:
-		reg->val = cp_read(sd, reg->reg & 0xff);
-		break;
-	case 0xc:
-		reg->val = vdp_read(sd, reg->reg & 0xff);
-		break;
-	default:
+	int ret;
+
+	ret = adv7604_read_reg(sd, reg->reg);
+	if (ret < 0) {
 		v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
 		adv7604_inv_register(sd);
-		break;
+		return ret;
 	}
+
+	reg->size = 1;
+	reg->val = ret;
+
 	return 0;
 }
 
 static int adv7604_s_register(struct v4l2_subdev *sd,
 					const struct v4l2_dbg_register *reg)
 {
-	u8 val = reg->val & 0xff;
+	int ret;
 
-	switch (reg->reg >> 8) {
-	case 0:
-		io_write(sd, reg->reg & 0xff, val);
-		break;
-	case 1:
-		avlink_write(sd, reg->reg & 0xff, val);
-		break;
-	case 2:
-		cec_write(sd, reg->reg & 0xff, val);
-		break;
-	case 3:
-		infoframe_write(sd, reg->reg & 0xff, val);
-		break;
-	case 4:
-		esdp_write(sd, reg->reg & 0xff, val);
-		break;
-	case 5:
-		dpp_write(sd, reg->reg & 0xff, val);
-		break;
-	case 6:
-		afe_write(sd, reg->reg & 0xff, val);
-		break;
-	case 7:
-		rep_write(sd, reg->reg & 0xff, val);
-		break;
-	case 8:
-		edid_write(sd, reg->reg & 0xff, val);
-		break;
-	case 9:
-		hdmi_write(sd, reg->reg & 0xff, val);
-		break;
-	case 0xa:
-		test_write(sd, reg->reg & 0xff, val);
-		break;
-	case 0xb:
-		cp_write(sd, reg->reg & 0xff, val);
-		break;
-	case 0xc:
-		vdp_write(sd, reg->reg & 0xff, val);
-		break;
-	default:
+	ret = adv7604_write_reg(sd, reg->reg, reg->val);
+	if (ret < 0) {
 		v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
 		adv7604_inv_register(sd);
-		break;
+		return ret;
 	}
+
 	return 0;
 }
 #endif
 
+static unsigned int adv7604_read_cable_det(struct v4l2_subdev *sd)
+{
+	u8 value = io_read(sd, 0x6f);
+
+	return ((value & 0x10) >> 4)
+	     | ((value & 0x08) >> 2)
+	     | ((value & 0x04) << 0)
+	     | ((value & 0x02) << 2);
+}
+
+static unsigned int adv7611_read_cable_det(struct v4l2_subdev *sd)
+{
+	u8 value = io_read(sd, 0x6f);
+
+	return value & 1;
+}
+
 static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
 {
 	struct adv7604_state *state = to_state(sd);
-	u8 reg_io_6f = io_read(sd, 0x6f);
+	const struct adv7604_chip_info *info = state->info;
 
 	return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl,
-			((reg_io_6f & 0x10) >> 4) |
-			((reg_io_6f & 0x08) >> 2) |
-			(reg_io_6f & 0x04) |
-			((reg_io_6f & 0x02) << 2));
+				info->read_cable_det(sd));
 }
 
 static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
@@ -797,9 +897,11 @@ static int configure_predefined_video_timings(struct v4l2_subdev *sd,
 
 	v4l2_dbg(1, debug, sd, "%s", __func__);
 
-	/* reset to default values */
-	io_write(sd, 0x16, 0x43);
-	io_write(sd, 0x17, 0x5a);
+	if (adv7604_has_afe(state)) {
+		/* reset to default values */
+		io_write(sd, 0x16, 0x43);
+		io_write(sd, 0x17, 0x5a);
+	}
 	/* disable embedded syncs for auto graphics mode */
 	cp_write_and_or(sd, 0x81, 0xef, 0x00);
 	cp_write(sd, 0x8f, 0x00);
@@ -1061,6 +1163,8 @@ static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
 		set_rgb_quantization_range(sd);
 		return 0;
 	case V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE:
+		if (!adv7604_has_afe(state))
+			return -EINVAL;
 		/* Set the analog sampling phase. This is needed to find the
 		   best sampling phase for analog video: an application or
 		   driver has to try a number of phases and analyze the picture
@@ -1098,7 +1202,10 @@ static inline bool no_signal_tmds(struct v4l2_subdev *sd)
 
 static inline bool no_lock_tmds(struct v4l2_subdev *sd)
 {
-	return (io_read(sd, 0x6a) & 0xe0) != 0xe0;
+	struct adv7604_state *state = to_state(sd);
+	const struct adv7604_chip_info *info = state->info;
+
+	return (io_read(sd, 0x6a) & info->tdms_lock_mask) != info->tdms_lock_mask;
 }
 
 static inline bool is_hdmi(struct v4l2_subdev *sd)
@@ -1108,6 +1215,15 @@ static inline bool is_hdmi(struct v4l2_subdev *sd)
 
 static inline bool no_lock_sspd(struct v4l2_subdev *sd)
 {
+	struct adv7604_state *state = to_state(sd);
+
+	/*
+	 * Chips without a AFE don't expose registers for the SSPD, so just assume
+	 * that we have a lock.
+	 */
+	if (adv7604_has_afe(state))
+		return false;
+
 	/* TODO channel 2 */
 	return ((cp_read(sd, 0xb5) & 0xd0) != 0xd0);
 }
@@ -1137,6 +1253,11 @@ static inline bool no_signal(struct v4l2_subdev *sd)
 
 static inline bool no_lock_cp(struct v4l2_subdev *sd)
 {
+	struct adv7604_state *state = to_state(sd);
+
+	if (!adv7604_has_afe(state))
+		return false;
+
 	/* CP has detected a non standard number of lines on the incoming
 	   video compared to what it is configured to receive by s_dv_timings */
 	return io_read(sd, 0x12) & 0x01;
@@ -1205,8 +1326,11 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
 	return -1;
 }
 
+
 static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
 {
+	struct adv7604_state *state = to_state(sd);
+	const struct adv7604_chip_info *info = state->info;
 	u8 polarity;
 
 	if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
@@ -1216,20 +1340,26 @@ static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
 
 	/* read STDI */
 	stdi->bl = cp_read16(sd, 0xb1, 0x3fff);
-	stdi->lcf = cp_read16(sd, 0xb3, 0x7ff);
+	stdi->lcf = cp_read16(sd, info->lcf_reg, 0x7ff);
 	stdi->lcvs = cp_read(sd, 0xb3) >> 3;
 	stdi->interlaced = io_read(sd, 0x12) & 0x10;
 
-	/* read SSPD */
-	polarity = cp_read(sd, 0xb5);
-	if ((polarity & 0x03) == 0x01) {
-		stdi->hs_pol = polarity & 0x10
-			     ? (polarity & 0x08 ? '+' : '-') : 'x';
-		stdi->vs_pol = polarity & 0x40
-			     ? (polarity & 0x20 ? '+' : '-') : 'x';
+	if (adv7604_has_afe(state)) {
+		/* read SSPD */
+		polarity = cp_read(sd, 0xb5);
+		if ((polarity & 0x03) == 0x01) {
+			stdi->hs_pol = polarity & 0x10
+				     ? (polarity & 0x08 ? '+' : '-') : 'x';
+			stdi->vs_pol = polarity & 0x40
+				     ? (polarity & 0x20 ? '+' : '-') : 'x';
+		} else {
+			stdi->hs_pol = 'x';
+			stdi->vs_pol = 'x';
+		}
 	} else {
-		stdi->hs_pol = 'x';
-		stdi->vs_pol = 'x';
+		polarity = hdmi_read(sd, 0x05);
+		stdi->hs_pol = polarity & 0x20 ? '+' : '-';
+		stdi->vs_pol = polarity & 0x10 ? '+' : '-';
 	}
 
 	if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
@@ -1297,10 +1427,43 @@ static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
 	}
 }
 
+static unsigned int adv7604_read_hdmi_pixelclock(struct v4l2_subdev *sd)
+{
+	unsigned int freq;
+	int a, b;
+
+	a = hdmi_read(sd, 0x06);
+	b = hdmi_read(sd, 0x3b);
+	if (a < 0 || b < 0)
+		return 0;
+	freq =  a * 1000000 + ((b & 0x30) >> 4) * 250000;
+
+	if (is_hdmi(sd)) {
+		/* adjust for deep color mode */
+		unsigned bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8;
+
+		freq = freq * 8 / bits_per_channel;
+	}
+
+	return freq;
+}
+
+static unsigned int adv7611_read_hdmi_pixelclock(struct v4l2_subdev *sd)
+{
+	int a, b;
+
+	a = hdmi_read(sd, 0x51);
+	b = hdmi_read(sd, 0x52);
+	if (a < 0 || b < 0)
+		return 0;
+	return ((a << 1) | (b >> 7)) * 1000000 + (b & 0x7f) * 1000000 / 128;
+}
+
 static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
 			struct v4l2_dv_timings *timings)
 {
 	struct adv7604_state *state = to_state(sd);
+	const struct adv7604_chip_info *info = state->info;
 	struct v4l2_bt_timings *bt = &timings->bt;
 	struct stdi_readback stdi;
 
@@ -1324,21 +1487,12 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
 		V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
 
 	if (is_digital_input(sd)) {
-		uint32_t freq;
-
 		timings->type = V4L2_DV_BT_656_1120;
 
+		/* FIXME: All masks are incorrect for ADV7611 */
 		bt->width = hdmi_read16(sd, 0x07, 0xfff);
 		bt->height = hdmi_read16(sd, 0x09, 0xfff);
-		freq = (hdmi_read(sd, 0x06) * 1000000) +
-			((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000;
-		if (is_hdmi(sd)) {
-			/* adjust for deep color mode */
-			unsigned bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8;
-
-			freq = freq * 8 / bits_per_channel;
-		}
-		bt->pixelclock = freq;
+		bt->pixelclock = info->read_hdmi_pixelclock(sd);
 		bt->hfrontporch = hdmi_read16(sd, 0x20, 0x3ff);
 		bt->hsync = hdmi_read16(sd, 0x22, 0x3ff);
 		bt->hbackporch = hdmi_read16(sd, 0x24, 0x3ff);
@@ -1444,7 +1598,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
 
 	state->timings = *timings;
 
-	cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10);
+	cp_write_and_or(sd, 0x91, 0xbf, bt->interlaced ? 0x40 : 0x00);
 
 	/* Use prim_mode and vid_std when available */
 	err = configure_predefined_video_timings(sd, timings);
@@ -1471,6 +1625,16 @@ static int adv7604_g_dv_timings(struct v4l2_subdev *sd,
 	return 0;
 }
 
+static void adv7604_set_termination(struct v4l2_subdev *sd, bool enable)
+{
+	hdmi_write(sd, 0x01, enable ? 0x00 : 0x78);
+}
+
+static void adv7611_set_termination(struct v4l2_subdev *sd, bool enable)
+{
+	hdmi_write(sd, 0x83, enable ? 0xfe : 0xff);
+}
+
 static void enable_input(struct v4l2_subdev *sd)
 {
 	struct adv7604_state *state = to_state(sd);
@@ -1479,7 +1643,7 @@ static void enable_input(struct v4l2_subdev *sd)
 		io_write(sd, 0x15, 0xb0);   /* Disable Tristate of Pins (no audio) */
 	} else if (is_digital_input(sd)) {
 		hdmi_write_and_or(sd, 0x00, 0xfc, state->selected_input);
-		hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
+		state->info->set_termination(sd, true);
 		io_write(sd, 0x15, 0xa0);   /* Disable Tristate of Pins */
 		hdmi_write_and_or(sd, 0x1a, 0xef, 0x00); /* Unmute audio */
 	} else {
@@ -1490,67 +1654,36 @@ static void enable_input(struct v4l2_subdev *sd)
 
 static void disable_input(struct v4l2_subdev *sd)
 {
+	struct adv7604_state *state = to_state(sd);
+
 	hdmi_write_and_or(sd, 0x1a, 0xef, 0x10); /* Mute audio */
 	msleep(16); /* 512 samples with >= 32 kHz sample rate [REF_03, c. 7.16.10] */
 	io_write(sd, 0x15, 0xbe);   /* Tristate all outputs from video core */
-	hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */
+	state->info->set_termination(sd, false);
 }
 
 static void select_input(struct v4l2_subdev *sd)
 {
 	struct adv7604_state *state = to_state(sd);
+	const struct adv7604_chip_info *info = state->info;
 
 	if (is_analog_input(sd)) {
-		/* reset ADI recommended settings for HDMI: */
-		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
-		hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */
-		hdmi_write(sd, 0x3d, 0x00); /* DDC bus active pull-up control */
-		hdmi_write(sd, 0x3e, 0x74); /* TMDS PLL optimization */
-		hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */
-		hdmi_write(sd, 0x57, 0x74); /* TMDS PLL optimization */
-		hdmi_write(sd, 0x58, 0x63); /* TMDS PLL optimization */
-		hdmi_write(sd, 0x8d, 0x18); /* equaliser */
-		hdmi_write(sd, 0x8e, 0x34); /* equaliser */
-		hdmi_write(sd, 0x93, 0x88); /* equaliser */
-		hdmi_write(sd, 0x94, 0x2e); /* equaliser */
-		hdmi_write(sd, 0x96, 0x00); /* enable automatic EQ changing */
+		adv7604_write_reg_seq(sd, info->recommended_settings[0]);
 
 		afe_write(sd, 0x00, 0x08); /* power up ADC */
 		afe_write(sd, 0x01, 0x06); /* power up Analog Front End */
 		afe_write(sd, 0xc8, 0x00); /* phase control */
-
-		/* set ADI recommended settings for digitizer */
-		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
-		afe_write(sd, 0x12, 0x7b); /* ADC noise shaping filter controls */
-		afe_write(sd, 0x0c, 0x1f); /* CP core gain controls */
-		cp_write(sd, 0x3e, 0x04); /* CP core pre-gain control */
-		cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */
-		cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */
 	} else if (is_digital_input(sd)) {
 		hdmi_write(sd, 0x00, state->selected_input & 0x03);
 
-		/* set ADI recommended settings for HDMI: */
-		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
-		hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */
-		hdmi_write(sd, 0x3d, 0x10); /* DDC bus active pull-up control */
-		hdmi_write(sd, 0x3e, 0x39); /* TMDS PLL optimization */
-		hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */
-		hdmi_write(sd, 0x57, 0xb6); /* TMDS PLL optimization */
-		hdmi_write(sd, 0x58, 0x03); /* TMDS PLL optimization */
-		hdmi_write(sd, 0x8d, 0x18); /* equaliser */
-		hdmi_write(sd, 0x8e, 0x34); /* equaliser */
-		hdmi_write(sd, 0x93, 0x8b); /* equaliser */
-		hdmi_write(sd, 0x94, 0x2d); /* equaliser */
-		hdmi_write(sd, 0x96, 0x01); /* enable automatic EQ changing */
-
-		afe_write(sd, 0x00, 0xff); /* power down ADC */
-		afe_write(sd, 0x01, 0xfe); /* power down Analog Front End */
-		afe_write(sd, 0xc8, 0x40); /* phase control */
-
-		/* reset ADI recommended settings for digitizer */
-		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
-		afe_write(sd, 0x12, 0xfb); /* ADC noise shaping filter controls */
-		afe_write(sd, 0x0c, 0x0d); /* CP core gain controls */
+		adv7604_write_reg_seq(sd, info->recommended_settings[1]);
+
+		if (adv7604_has_afe(state)) {
+			afe_write(sd, 0x00, 0xff); /* power down ADC */
+			afe_write(sd, 0x01, 0xfe); /* power down Analog Front End */
+			afe_write(sd, 0xc8, 0x40); /* phase control */
+		}
+
 		cp_write(sd, 0x3e, 0x00); /* CP core pre-gain control */
 		cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */
 		cp_write(sd, 0x40, 0x80); /* CP core pre-gain control. Graphics mode */
@@ -1571,6 +1704,9 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
 	if (input == state->selected_input)
 		return 0;
 
+	if (input > state->info->max_port)
+		return -EINVAL;
+
 	state->selected_input = input;
 
 	disable_input(sd);
@@ -1610,6 +1746,8 @@ static int adv7604_g_mbus_fmt(struct v4l2_subdev *sd,
 
 static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
 {
+	struct adv7604_state *state = to_state(sd);
+	const struct adv7604_chip_info *info = state->info;
 	const u8 irq_reg_0x43 = io_read(sd, 0x43);
 	const u8 irq_reg_0x6b = io_read(sd, 0x6b);
 	const u8 irq_reg_0x70 = io_read(sd, 0x70);
@@ -1628,7 +1766,9 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
 
 	/* format change */
 	fmt_change = irq_reg_0x43 & 0x98;
-	fmt_change_digital = is_digital_input(sd) ? (irq_reg_0x6b & 0xc0) : 0;
+	fmt_change_digital = is_digital_input(sd)
+			   ? irq_reg_0x6b & info->fmt_change_digital_mask
+			   : 0;
 
 	if (fmt_change || fmt_change_digital) {
 		v4l2_dbg(1, debug, sd,
@@ -1650,7 +1790,7 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
 	}
 
 	/* tx 5v detect */
-	tx_5v = io_read(sd, 0x70) & 0x1e;
+	tx_5v = io_read(sd, 0x70) & info->cable_det_mask;
 	if (tx_5v) {
 		v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v);
 		io_write(sd, 0x71, tx_5v);
@@ -1732,6 +1872,7 @@ static int get_edid_spa_location(const u8 *edid)
 static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
 {
 	struct adv7604_state *state = to_state(sd);
+	const struct adv7604_chip_info *info = state->info;
 	int spa_loc;
 	int tmp = 0;
 	int err;
@@ -1745,7 +1886,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 		/* Disable hotplug and I2C access to EDID RAM from DDC port */
 		state->edid.present &= ~(1 << edid->pad);
 		v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
-		rep_write_and_or(sd, 0x77, 0xf0, state->edid.present);
+		rep_write_and_or(sd, info->edid_enable_reg, 0xf0, state->edid.present);
 
 		/* Fall back to a 16:9 aspect ratio */
 		state->aspect_ratio.numerator = 16;
@@ -1769,7 +1910,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 	/* Disable hotplug and I2C access to EDID RAM from DDC port */
 	cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
 	v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&tmp);
-	rep_write_and_or(sd, 0x77, 0xf0, 0x00);
+	rep_write_and_or(sd, info->edid_enable_reg, 0xf0, 0x00);
 
 	spa_loc = get_edid_spa_location(edid->edid);
 	if (spa_loc < 0)
@@ -1795,8 +1936,14 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 	default:
 		return -EINVAL;
 	}
-	rep_write(sd, 0x76, spa_loc & 0xff);
-	rep_write_and_or(sd, 0x77, 0xbf, (spa_loc >> 2) & 0x40);
+
+	if (info->type == ADV7604) {
+		rep_write(sd, 0x76, spa_loc & 0xff);
+		rep_write_and_or(sd, 0x77, 0xbf, (spa_loc & 0x100) >> 2);
+	} else {
+		/* FIXME: Where is the SPA location LSB register ? */
+		rep_write_and_or(sd, 0x71, 0xfe, (spa_loc & 0x100) >> 8);
+	}
 
 	edid->edid[spa_loc] = state->spa_port_a[0];
 	edid->edid[spa_loc + 1] = state->spa_port_a[1];
@@ -1815,10 +1962,10 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 
 	/* adv7604 calculates the checksums and enables I2C access to internal
 	   EDID RAM from DDC port. */
-	rep_write_and_or(sd, 0x77, 0xf0, state->edid.present);
+	rep_write_and_or(sd, info->edid_enable_reg, 0xf0, state->edid.present);
 
 	for (i = 0; i < 1000; i++) {
-		if (rep_read(sd, 0x7d) & state->edid.present)
+		if (rep_read(sd, info->edid_status_reg) & state->edid.present)
 			break;
 		mdelay(1);
 	}
@@ -1881,6 +2028,7 @@ static void print_avi_infoframe(struct v4l2_subdev *sd)
 static int adv7604_log_status(struct v4l2_subdev *sd)
 {
 	struct adv7604_state *state = to_state(sd);
+	const struct adv7604_chip_info *info = state->info;
 	struct v4l2_dv_timings timings;
 	struct stdi_readback stdi;
 	u8 reg_io_0x02 = io_read(sd, 0x02);
@@ -1915,7 +2063,7 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
 
 	v4l2_info(sd, "-----Chip status-----\n");
 	v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on");
-	edid_enabled = rep_read(sd, 0x7d);
+	edid_enabled = rep_read(sd, info->edid_status_reg);
 	v4l2_info(sd, "EDID enabled port A: %s, B: %s, C: %s, D: %s\n",
 			((edid_enabled & 0x01) ? "Yes" : "No"),
 			((edid_enabled & 0x02) ? "Yes" : "No"),
@@ -1925,12 +2073,12 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
 			"enabled" : "disabled");
 
 	v4l2_info(sd, "-----Signal status-----\n");
-	cable_det = io_read(sd, 0x6f);
+	cable_det = info->read_cable_det(sd);
 	v4l2_info(sd, "Cable detected (+5V power) port A: %s, B: %s, C: %s, D: %s\n",
-			((cable_det & 0x10) ? "Yes" : "No"),
-			((cable_det & 0x08) ? "Yes" : "No"),
+			((cable_det & 0x01) ? "Yes" : "No"),
+			((cable_det & 0x02) ? "Yes" : "No"),
 			((cable_det & 0x04) ? "Yes" : "No"),
-			((cable_det & 0x02) ? "Yes" : "No"));
+			((cable_det & 0x08) ? "Yes" : "No"));
 	v4l2_info(sd, "TMDS signal detected: %s\n",
 			no_signal_tmds(sd) ? "false" : "true");
 	v4l2_info(sd, "TMDS signal locked: %s\n",
@@ -2103,6 +2251,7 @@ static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color = {
 static int adv7604_core_init(struct v4l2_subdev *sd)
 {
 	struct adv7604_state *state = to_state(sd);
+	const struct adv7604_chip_info *info = state->info;
 	struct adv7604_platform_data *pdata = &state->pdata;
 
 	hdmi_write(sd, 0x48,
@@ -2156,19 +2305,31 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
 	/* TODO from platform data */
 	afe_write(sd, 0xb5, 0x01);  /* Setting MCLK to 256Fs */
 
-	afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
-	io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
+	if (adv7604_has_afe(state)) {
+		afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
+		io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
+	}
 
 	/* interrupts */
-	io_write(sd, 0x40, 0xc2); /* Configure INT1 */
-	io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
+	io_write(sd, 0x40, 0xc0 | pdata->int1_config); /* Configure INT1 */
 	io_write(sd, 0x46, 0x98); /* Enable SSPD, STDI and CP unlocked interrupts */
-	io_write(sd, 0x6e, 0xc1); /* Enable V_LOCKED, DE_REGEN_LCK, HDMI_MODE interrupts */
-	io_write(sd, 0x73, 0x1e); /* Enable CABLE_DET_A_ST (+5v) interrupts */
+	io_write(sd, 0x6e, info->fmt_change_digital_mask); /* Enable V_LOCKED and DE_REGEN_LCK interrupts */
+	io_write(sd, 0x73, info->cable_det_mask); /* Enable cable detection (+5v) interrupts */
+	info->setup_irqs(sd);
 
 	return v4l2_ctrl_handler_setup(sd->ctrl_handler);
 }
 
+static void adv7604_setup_irqs(struct v4l2_subdev *sd)
+{
+	io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
+}
+
+static void adv7611_setup_irqs(struct v4l2_subdev *sd)
+{
+	io_write(sd, 0x41, 0xd0); /* STDI irq for any change, disable INT2 */
+}
+
 static void adv7604_unregister_clients(struct adv7604_state *state)
 {
 	if (state->i2c_avlink)
@@ -2207,6 +2368,130 @@ static struct i2c_client *adv7604_dummy_client(struct v4l2_subdev *sd,
 	return i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1);
 }
 
+static const struct adv7604_reg_seq adv7604_recommended_settings_afe[] = {
+	/* reset ADI recommended settings for HDMI: */
+	/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x3d), 0x00 }, /* DDC bus active pull-up control */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x3e), 0x74 }, /* TMDS PLL optimization */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0x74 }, /* TMDS PLL optimization */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x63 }, /* TMDS PLL optimization */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x93), 0x88 }, /* equaliser */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x94), 0x2e }, /* equaliser */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x96), 0x00 }, /* enable automatic EQ changing */
+
+	/* set ADI recommended settings for digitizer */
+	/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
+	{ ADV7604_REG(ADV7604_PAGE_AFE, 0x12), 0x7b }, /* ADC noise shaping filter controls */
+	{ ADV7604_REG(ADV7604_PAGE_AFE, 0x0c), 0x1f }, /* CP core gain controls */
+	{ ADV7604_REG(ADV7604_PAGE_CP, 0x3e), 0x04 }, /* CP core pre-gain control */
+	{ ADV7604_REG(ADV7604_PAGE_CP, 0xc3), 0x39 }, /* CP coast control. Graphics mode */
+	{ ADV7604_REG(ADV7604_PAGE_CP, 0x40), 0x5c }, /* CP core pre-gain control. Graphics mode */
+
+	{ ADV7604_REG_SEQ_TERM, 0 },
+};
+
+static const struct adv7604_reg_seq adv7604_recommended_settings_hdmi[] = {
+	/* set ADI recommended settings for HDMI: */
+	/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x84 }, /* HDMI filter optimization */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x3d), 0x10 }, /* DDC bus active pull-up control */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x3e), 0x39 }, /* TMDS PLL optimization */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xb6 }, /* TMDS PLL optimization */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x03 }, /* TMDS PLL optimization */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x93), 0x8b }, /* equaliser */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x94), 0x2d }, /* equaliser */
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x96), 0x01 }, /* enable automatic EQ changing */
+
+	/* reset ADI recommended settings for digitizer */
+	/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
+	{ ADV7604_REG(ADV7604_PAGE_AFE, 0x12), 0xfb }, /* ADC noise shaping filter controls */
+	{ ADV7604_REG(ADV7604_PAGE_AFE, 0x0c), 0x0d }, /* CP core gain controls */
+
+	{ ADV7604_REG_SEQ_TERM, 0 },
+};
+
+static const struct adv7604_reg_seq adv7611_recommended_settings_hdmi[] = {
+	{ ADV7604_REG(ADV7604_PAGE_CP, 0x6c), 0x00 },
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x0c },
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x87), 0x70 },
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xda },
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x01 },
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x03), 0x98 },
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x4c), 0x44 },
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x04 },
+	{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x1e },
+
+	{ ADV7604_REG_SEQ_TERM, 0 },
+};
+
+static const struct adv7604_chip_info adv7604_chip_info[] = {
+	[ADV7604] = {
+		.type = ADV7604,
+		.has_afe = true,
+		.max_port = ADV7604_INPUT_VGA_COMP,
+		.num_dv_ports = 4,
+		.edid_enable_reg = 0x77,
+		.edid_status_reg = 0x7d,
+		.lcf_reg = 0xb3,
+		.tdms_lock_mask = 0xe0,
+		.cable_det_mask = 0x1e,
+		.fmt_change_digital_mask = 0xc1,
+		.set_termination = adv7604_set_termination,
+		.setup_irqs = adv7604_setup_irqs,
+		.read_hdmi_pixelclock = adv7604_read_hdmi_pixelclock,
+		.read_cable_det = adv7604_read_cable_det,
+		.recommended_settings = {
+		    [0] = adv7604_recommended_settings_afe,
+		    [1] = adv7604_recommended_settings_hdmi,
+		},
+		.num_recommended_settings = {
+		    [0] = ARRAY_SIZE(adv7604_recommended_settings_afe),
+		    [1] = ARRAY_SIZE(adv7604_recommended_settings_hdmi),
+		},
+		.page_mask = BIT(ADV7604_PAGE_IO) | BIT(ADV7604_PAGE_AVLINK) |
+			BIT(ADV7604_PAGE_CEC) | BIT(ADV7604_PAGE_INFOFRAME) |
+			BIT(ADV7604_PAGE_ESDP) | BIT(ADV7604_PAGE_DPP) |
+			BIT(ADV7604_PAGE_AFE) | BIT(ADV7604_PAGE_REP) |
+			BIT(ADV7604_PAGE_EDID) | BIT(ADV7604_PAGE_HDMI) |
+			BIT(ADV7604_PAGE_TEST) | BIT(ADV7604_PAGE_CP) |
+			BIT(ADV7604_PAGE_VDP),
+	},
+	[ADV7611] = {
+		.type = ADV7611,
+		.has_afe = false,
+		.max_port = ADV7604_INPUT_HDMI_PORT_A,
+		.num_dv_ports = 1,
+		.edid_enable_reg = 0x74,
+		.edid_status_reg = 0x76,
+		.lcf_reg = 0xa3,
+		.tdms_lock_mask = 0x43,
+		.cable_det_mask = 0x01,
+		.fmt_change_digital_mask = 0x03,
+		.set_termination = adv7611_set_termination,
+		.setup_irqs = adv7611_setup_irqs,
+		.read_hdmi_pixelclock = adv7611_read_hdmi_pixelclock,
+		.read_cable_det = adv7611_read_cable_det,
+		.recommended_settings = {
+		    [1] = adv7611_recommended_settings_hdmi,
+		},
+		.num_recommended_settings = {
+		    [1] = ARRAY_SIZE(adv7611_recommended_settings_hdmi),
+		},
+		.page_mask = BIT(ADV7604_PAGE_IO) | BIT(ADV7604_PAGE_CEC) |
+			BIT(ADV7604_PAGE_INFOFRAME) | BIT(ADV7604_PAGE_AFE) |
+			BIT(ADV7604_PAGE_REP) |  BIT(ADV7604_PAGE_EDID) |
+			BIT(ADV7604_PAGE_HDMI) | BIT(ADV7604_PAGE_CP),
+	},
+};
+
 static int adv7604_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
@@ -2216,6 +2501,7 @@ static int adv7604_probe(struct i2c_client *client,
 	struct adv7604_platform_data *pdata = client->dev.platform_data;
 	struct v4l2_ctrl_handler *hdl;
 	struct v4l2_subdev *sd;
+	u16 val;
 	int err;
 
 	/* Check if the adapter supports the needed features */
@@ -2230,6 +2516,8 @@ static int adv7604_probe(struct i2c_client *client,
 		return -ENOMEM;
 	}
 
+	state->info = &adv7604_chip_info[id->driver_data];
+
 	/* initialize variables */
 	state->restart_stdi_once = true;
 	state->selected_input = ~0;
@@ -2244,18 +2532,36 @@ static int adv7604_probe(struct i2c_client *client,
 
 	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &adv7604_ops);
+	snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
+		id->name, i2c_adapter_id(client->adapter),
+		client->addr);
 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
-	/* i2c access to adv7604? */
-	if (adv_smbus_read_byte_data_check(client, 0xfb, false) != 0x68) {
-		v4l2_info(sd, "not an adv7604 on address 0x%x\n",
-				client->addr << 1);
-		return -ENODEV;
+	/*
+	 * Verify that the chip is present. On ADV7604 the RD_INFO register only
+	 * identifies the revision, while on ADV7611 it identifies the model as
+	 * well. Use the HDMI slave address on ADV7604 and RD_INFO on ADV7611.
+	 */
+	if (state->info->type == ADV7604) {
+		val = adv_smbus_read_byte_data_check(client, 0xfb, false);
+		if (val != 0x68) {
+			v4l2_info(sd, "not an adv7604 on address 0x%x\n",
+					client->addr << 1);
+			return -ENODEV;
+		}
+	} else {
+		val = (adv_smbus_read_byte_data_check(client, 0xea, false) << 8)
+		    | (adv_smbus_read_byte_data_check(client, 0xeb, false) << 0);
+		if (val != 0x2051) {
+			v4l2_info(sd, "not an adv7611 on address 0x%x\n",
+					client->addr << 1);
+			return -ENODEV;
+		}
 	}
 
 	/* control handlers */
 	hdl = &state->hdl;
-	v4l2_ctrl_handler_init(hdl, 9);
+	v4l2_ctrl_handler_init(hdl, adv7604_has_afe(state) ? 9 : 8);
 
 	v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
 			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
@@ -2268,15 +2574,17 @@ static int adv7604_probe(struct i2c_client *client,
 
 	/* private controls */
 	state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL,
-			V4L2_CID_DV_RX_POWER_PRESENT, 0, 0x0f, 0, 0);
+			V4L2_CID_DV_RX_POWER_PRESENT, 0,
+			(1 << state->info->num_dv_ports) - 1, 0, 0);
 	state->rgb_quantization_range_ctrl =
 		v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops,
 			V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
 			0, V4L2_DV_RGB_RANGE_AUTO);
 
 	/* custom controls */
-	state->analog_sampling_phase_ctrl =
-		v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL);
+	if (adv7604_has_afe(state))
+		state->analog_sampling_phase_ctrl =
+			v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL);
 	state->free_run_color_manual_ctrl =
 		v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL);
 	state->free_run_color_ctrl =
@@ -2289,7 +2597,8 @@ static int adv7604_probe(struct i2c_client *client,
 	}
 	state->detect_tx_5v_ctrl->is_private = true;
 	state->rgb_quantization_range_ctrl->is_private = true;
-	state->analog_sampling_phase_ctrl->is_private = true;
+	if (adv7604_has_afe(state))
+		state->analog_sampling_phase_ctrl->is_private = true;
 	state->free_run_color_manual_ctrl->is_private = true;
 	state->free_run_color_ctrl->is_private = true;
 
@@ -2298,27 +2607,34 @@ static int adv7604_probe(struct i2c_client *client,
 		goto err_hdl;
 	}
 
-	state->i2c_avlink = adv7604_dummy_client(sd, pdata->i2c_avlink, 0xf3);
 	state->i2c_cec = adv7604_dummy_client(sd, pdata->i2c_cec, 0xf4);
 	state->i2c_infoframe = adv7604_dummy_client(sd, pdata->i2c_infoframe, 0xf5);
-	state->i2c_esdp = adv7604_dummy_client(sd, pdata->i2c_esdp, 0xf6);
-	state->i2c_dpp = adv7604_dummy_client(sd, pdata->i2c_dpp, 0xf7);
 	state->i2c_afe = adv7604_dummy_client(sd, pdata->i2c_afe, 0xf8);
 	state->i2c_repeater = adv7604_dummy_client(sd, pdata->i2c_repeater, 0xf9);
 	state->i2c_edid = adv7604_dummy_client(sd, pdata->i2c_edid, 0xfa);
 	state->i2c_hdmi = adv7604_dummy_client(sd, pdata->i2c_hdmi, 0xfb);
-	state->i2c_test = adv7604_dummy_client(sd, pdata->i2c_test, 0xfc);
 	state->i2c_cp = adv7604_dummy_client(sd, pdata->i2c_cp, 0xfd);
-	state->i2c_vdp = adv7604_dummy_client(sd, pdata->i2c_vdp, 0xfe);
-	if (!state->i2c_avlink || !state->i2c_cec || !state->i2c_infoframe ||
-	    !state->i2c_esdp || !state->i2c_dpp || !state->i2c_afe ||
+	if (!state->i2c_cec || !state->i2c_infoframe || !state->i2c_afe ||
 	    !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi ||
-	    !state->i2c_test || !state->i2c_cp || !state->i2c_vdp) {
+	    !state->i2c_cp) {
 		err = -ENOMEM;
-		v4l2_err(sd, "failed to create all i2c clients\n");
+		v4l2_err(sd, "failed to create digital i2c clients\n");
 		goto err_i2c;
 	}
 
+	if (adv7604_has_afe(state)) {
+		state->i2c_avlink = adv7604_dummy_client(sd, pdata->i2c_avlink, 0xf3);
+		state->i2c_esdp = adv7604_dummy_client(sd, pdata->i2c_esdp, 0xf6);
+		state->i2c_dpp = adv7604_dummy_client(sd, pdata->i2c_dpp, 0xf7);
+		state->i2c_test = adv7604_dummy_client(sd, pdata->i2c_test, 0xfc);
+		state->i2c_vdp = adv7604_dummy_client(sd, pdata->i2c_vdp, 0xfe);
+		if (!state->i2c_avlink || !state->i2c_esdp || !state->i2c_dpp ||
+		    !state->i2c_test || !state->i2c_vdp) {
+			err = -ENOMEM;
+			v4l2_err(sd, "failed to create analog i2c clients\n");
+			goto err_i2c;
+		}
+	}
 	/* work queues */
 	state->work_queues = create_singlethread_workqueue(client->name);
 	if (!state->work_queues) {
@@ -2379,7 +2695,8 @@ static int adv7604_remove(struct i2c_client *client)
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_device_id adv7604_id[] = {
-	{ "adv7604", 0 },
+	{ "adv7604", ADV7604 },
+	{ "adv7611", ADV7611 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adv7604_id);
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index c6b3937..b2500bae 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -86,6 +86,13 @@ enum adv7604_drive_strength {
 	ADV7604_DR_STR_HIGH = 3,
 };
 
+enum adv7604_int1_config {
+	ADV7604_INT1_CONFIG_OPEN_DRAIN,
+	ADV7604_INT1_CONFIG_ACTIVE_LOW,
+	ADV7604_INT1_CONFIG_ACTIVE_HIGH,
+	ADV7604_INT1_CONFIG_DISABLED,
+};
+
 /* Platform dependent definition */
 struct adv7604_platform_data {
 	/* DIS_PWRDNB: 1 if the PWRDNB pin is unused and unconnected */
@@ -103,6 +110,9 @@ struct adv7604_platform_data {
 	/* Select output format */
 	enum adv7604_op_format_sel op_format_sel;
 
+	/* Configuration of the INT1 pin */
+	enum adv7604_int1_config int1_config;
+
 	/* IO register 0x02 */
 	unsigned alt_gamma:1;
 	unsigned op_656_range:1;
-- 
1.8.3.2


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

* [PATCH v2 34/48] adv7604: Remove subdev control handlers
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (32 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 33/48] adv7604: Add adv7611 support Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 35/48] adv7604: Add sink pads Laurent Pinchart
                   ` (14 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Control operations are handled by the control framework and the subdev
control handlers are never called directly. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 3866970..dc7f6e0 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2172,13 +2172,6 @@ static const struct v4l2_ctrl_ops adv7604_ctrl_ops = {
 
 static const struct v4l2_subdev_core_ops adv7604_core_ops = {
 	.log_status = adv7604_log_status,
-	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
-	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
-	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
-	.g_ctrl = v4l2_subdev_g_ctrl,
-	.s_ctrl = v4l2_subdev_s_ctrl,
-	.queryctrl = v4l2_subdev_queryctrl,
-	.querymenu = v4l2_subdev_querymenu,
 	.interrupt_service_routine = adv7604_isr,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register = adv7604_g_register,
-- 
1.8.3.2


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

* [PATCH v2 35/48] adv7604: Add sink pads
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (33 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 34/48] adv7604: Remove subdev control handlers Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 36/48] adv7604: Make output format configurable through pad format operations Laurent Pinchart
                   ` (13 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The ADV7604 has sink pads for its HDMI and analog inputs. Report them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 61 ++++++++++++++++++++++++++-------------------
 include/media/adv7604.h     | 23 ++++++++---------
 2 files changed, 46 insertions(+), 38 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index dc7f6e0..851b350 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -97,13 +97,15 @@ struct adv7604_chip_info {
  *
  **********************************************************************
  */
+
 struct adv7604_state {
 	const struct adv7604_chip_info *info;
 	struct adv7604_platform_data pdata;
 	struct v4l2_subdev sd;
-	struct media_pad pad;
+	struct media_pad pads[ADV7604_PAD_MAX];
+	unsigned int source_pad;
 	struct v4l2_ctrl_handler hdl;
-	enum adv7604_input_port selected_input;
+	enum adv7604_pad selected_input;
 	struct v4l2_dv_timings timings;
 	struct {
 		u8 edid[256];
@@ -775,18 +777,18 @@ static inline bool is_analog_input(struct v4l2_subdev *sd)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return state->selected_input == ADV7604_INPUT_VGA_RGB ||
-	       state->selected_input == ADV7604_INPUT_VGA_COMP;
+	return state->selected_input == ADV7604_PAD_VGA_RGB ||
+	       state->selected_input == ADV7604_PAD_VGA_COMP;
 }
 
 static inline bool is_digital_input(struct v4l2_subdev *sd)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return state->selected_input == ADV7604_INPUT_HDMI_PORT_A ||
-	       state->selected_input == ADV7604_INPUT_HDMI_PORT_B ||
-	       state->selected_input == ADV7604_INPUT_HDMI_PORT_C ||
-	       state->selected_input == ADV7604_INPUT_HDMI_PORT_D;
+	return state->selected_input == ADV7604_PAD_HDMI_PORT_A ||
+	       state->selected_input == ADV7604_PAD_HDMI_PORT_B ||
+	       state->selected_input == ADV7604_PAD_HDMI_PORT_C ||
+	       state->selected_input == ADV7604_PAD_HDMI_PORT_D;
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1066,14 +1068,14 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 
 	switch (state->rgb_quantization_range) {
 	case V4L2_DV_RGB_RANGE_AUTO:
-		if (state->selected_input == ADV7604_INPUT_VGA_RGB) {
+		if (state->selected_input == ADV7604_PAD_VGA_RGB) {
 			/* Receiving analog RGB signal
 			 * Set RGB full range (0-255) */
 			io_write_and_or(sd, 0x02, 0x0f, 0x10);
 			break;
 		}
 
-		if (state->selected_input == ADV7604_INPUT_VGA_COMP) {
+		if (state->selected_input == ADV7604_PAD_VGA_COMP) {
 			/* Receiving analog YPbPr signal
 			 * Set automode */
 			io_write_and_or(sd, 0x02, 0x0f, 0xf0);
@@ -1106,7 +1108,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 		}
 		break;
 	case V4L2_DV_RGB_RANGE_LIMITED:
-		if (state->selected_input == ADV7604_INPUT_VGA_COMP) {
+		if (state->selected_input == ADV7604_PAD_VGA_COMP) {
 			/* YCrCb limited range (16-235) */
 			io_write_and_or(sd, 0x02, 0x0f, 0x20);
 			break;
@@ -1117,7 +1119,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 
 		break;
 	case V4L2_DV_RGB_RANGE_FULL:
-		if (state->selected_input == ADV7604_INPUT_VGA_COMP) {
+		if (state->selected_input == ADV7604_PAD_VGA_COMP) {
 			/* YCrCb full range (0-255) */
 			io_write_and_or(sd, 0x02, 0x0f, 0x60);
 			break;
@@ -1806,7 +1808,7 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 	struct adv7604_state *state = to_state(sd);
 	u8 *data = NULL;
 
-	if (edid->pad > ADV7604_EDID_PORT_D)
+	if (edid->pad > ADV7604_PAD_HDMI_PORT_D)
 		return -EINVAL;
 	if (edid->blocks == 0)
 		return -EINVAL;
@@ -1821,10 +1823,10 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 		edid->blocks = state->edid.blocks;
 
 	switch (edid->pad) {
-	case ADV7604_EDID_PORT_A:
-	case ADV7604_EDID_PORT_B:
-	case ADV7604_EDID_PORT_C:
-	case ADV7604_EDID_PORT_D:
+	case ADV7604_PAD_HDMI_PORT_A:
+	case ADV7604_PAD_HDMI_PORT_B:
+	case ADV7604_PAD_HDMI_PORT_C:
+	case ADV7604_PAD_HDMI_PORT_D:
 		if (state->edid.present & (1 << edid->pad))
 			data = state->edid.edid;
 		break;
@@ -1878,7 +1880,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 	int err;
 	int i;
 
-	if (edid->pad > ADV7604_EDID_PORT_D)
+	if (edid->pad > ADV7604_PAD_HDMI_PORT_D)
 		return -EINVAL;
 	if (edid->start_block != 0)
 		return -EINVAL;
@@ -1917,19 +1919,19 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 		spa_loc = 0xc0; /* Default value [REF_02, p. 116] */
 
 	switch (edid->pad) {
-	case ADV7604_EDID_PORT_A:
+	case ADV7604_PAD_HDMI_PORT_A:
 		state->spa_port_a[0] = edid->edid[spa_loc];
 		state->spa_port_a[1] = edid->edid[spa_loc + 1];
 		break;
-	case ADV7604_EDID_PORT_B:
+	case ADV7604_PAD_HDMI_PORT_B:
 		rep_write(sd, 0x70, edid->edid[spa_loc]);
 		rep_write(sd, 0x71, edid->edid[spa_loc + 1]);
 		break;
-	case ADV7604_EDID_PORT_C:
+	case ADV7604_PAD_HDMI_PORT_C:
 		rep_write(sd, 0x72, edid->edid[spa_loc]);
 		rep_write(sd, 0x73, edid->edid[spa_loc + 1]);
 		break;
-	case ADV7604_EDID_PORT_D:
+	case ADV7604_PAD_HDMI_PORT_D:
 		rep_write(sd, 0x74, edid->edid[spa_loc]);
 		rep_write(sd, 0x75, edid->edid[spa_loc + 1]);
 		break;
@@ -2429,7 +2431,7 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
 	[ADV7604] = {
 		.type = ADV7604,
 		.has_afe = true,
-		.max_port = ADV7604_INPUT_VGA_COMP,
+		.max_port = ADV7604_PAD_VGA_COMP,
 		.num_dv_ports = 4,
 		.edid_enable_reg = 0x77,
 		.edid_status_reg = 0x7d,
@@ -2460,7 +2462,7 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
 	[ADV7611] = {
 		.type = ADV7611,
 		.has_afe = false,
-		.max_port = ADV7604_INPUT_HDMI_PORT_A,
+		.max_port = ADV7604_PAD_HDMI_PORT_A,
 		.num_dv_ports = 1,
 		.edid_enable_reg = 0x74,
 		.edid_status_reg = 0x76,
@@ -2494,6 +2496,7 @@ static int adv7604_probe(struct i2c_client *client,
 	struct adv7604_platform_data *pdata = client->dev.platform_data;
 	struct v4l2_ctrl_handler *hdl;
 	struct v4l2_subdev *sd;
+	unsigned int i;
 	u16 val;
 	int err;
 
@@ -2639,8 +2642,14 @@ static int adv7604_probe(struct i2c_client *client,
 	INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug,
 			adv7604_delayed_work_enable_hotplug);
 
-	state->pad.flags = MEDIA_PAD_FL_SOURCE;
-	err = media_entity_init(&sd->entity, 1, &state->pad, 0);
+	state->source_pad = state->info->num_dv_ports
+			  + (state->info->has_afe ? 2 : 0);
+	for (i = 0; i < state->source_pad; ++i)
+		state->pads[i].flags = MEDIA_PAD_FL_SINK;
+	state->pads[state->source_pad].flags = MEDIA_PAD_FL_SOURCE;
+
+	err = media_entity_init(&sd->entity, state->source_pad + 1,
+				state->pads, 0);
 	if (err)
 		goto err_work_queues;
 
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index b2500bae..6186771 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -155,20 +155,19 @@ struct adv7604_platform_data {
 	u8 i2c_vdp;
 };
 
-enum adv7604_input_port {
-	ADV7604_INPUT_HDMI_PORT_A,
-	ADV7604_INPUT_HDMI_PORT_B,
-	ADV7604_INPUT_HDMI_PORT_C,
-	ADV7604_INPUT_HDMI_PORT_D,
-	ADV7604_INPUT_VGA_RGB,
-	ADV7604_INPUT_VGA_COMP,
+enum adv7604_pad {
+	ADV7604_PAD_HDMI_PORT_A = 0,
+	ADV7604_PAD_HDMI_PORT_B = 1,
+	ADV7604_PAD_HDMI_PORT_C = 2,
+	ADV7604_PAD_HDMI_PORT_D = 3,
+	ADV7604_PAD_VGA_RGB = 4,
+	ADV7604_PAD_VGA_COMP = 5,
+	/* The source pad is either 1 (ADV7611) or 6 (ADV7604) */
+	ADV7604_PAD_SOURCE = 6,
+	ADV7611_PAD_SOURCE = 1,
+	ADV7604_PAD_MAX = 7,
 };
 
-#define ADV7604_EDID_PORT_A 0
-#define ADV7604_EDID_PORT_B 1
-#define ADV7604_EDID_PORT_C 2
-#define ADV7604_EDID_PORT_D 3
-
 #define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE	(V4L2_CID_DV_CLASS_BASE + 0x1000)
 #define V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL	(V4L2_CID_DV_CLASS_BASE + 0x1001)
 #define V4L2_CID_ADV_RX_FREE_RUN_COLOR		(V4L2_CID_DV_CLASS_BASE + 0x1002)
-- 
1.8.3.2


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

* [PATCH v2 36/48] adv7604: Make output format configurable through pad format operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (34 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 35/48] adv7604: Add sink pads Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11 15:10   ` [PATCH v3 " Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 37/48] adv7604: Add pad-level DV timings support Laurent Pinchart
                   ` (12 subsequent siblings)
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Replace the dummy video format operations by pad format operations that
configure the output format.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 243 +++++++++++++++++++++++++++++++++++++++-----
 include/media/adv7604.h     |  47 ++-------
 2 files changed, 225 insertions(+), 65 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 851b350..66b3481 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -53,6 +53,28 @@ MODULE_LICENSE("GPL");
 /* ADV7604 system clock frequency */
 #define ADV7604_fsc (28636360)
 
+#define ADV7604_RGB_OUT					(1 << 1)
+
+#define ADV7604_OP_FORMAT_SEL_8BIT			(0 << 0)
+#define ADV7604_OP_FORMAT_SEL_10BIT			(1 << 0)
+#define ADV7604_OP_FORMAT_SEL_12BIT			(2 << 0)
+
+#define ADV7604_OP_MODE_SEL_SDR_422			(0 << 5)
+#define ADV7604_OP_MODE_SEL_DDR_422			(1 << 5)
+#define ADV7604_OP_MODE_SEL_SDR_444			(2 << 5)
+#define ADV7604_OP_MODE_SEL_DDR_444			(3 << 5)
+#define ADV7604_OP_MODE_SEL_SDR_422_2X			(4 << 5)
+#define ADV7604_OP_MODE_SEL_ADI_CM			(5 << 5)
+
+#define ADV7604_OP_CH_SEL_GBR				(0 << 5)
+#define ADV7604_OP_CH_SEL_GRB				(1 << 5)
+#define ADV7604_OP_CH_SEL_BGR				(2 << 5)
+#define ADV7604_OP_CH_SEL_RGB				(3 << 5)
+#define ADV7604_OP_CH_SEL_BRG				(4 << 5)
+#define ADV7604_OP_CH_SEL_RBG				(5 << 5)
+
+#define ADV7604_OP_SWAP_CB_CR				(1 << 0)
+
 enum adv7604_type {
 	ADV7604,
 	ADV7611,
@@ -63,6 +85,14 @@ struct adv7604_reg_seq {
 	u8 val;
 };
 
+struct adv7604_format_info {
+	enum v4l2_mbus_pixelcode code;
+	u8 op_ch_sel;
+	bool rgb_out;
+	bool swap_cb_cr;
+	u8 op_format_sel;
+};
+
 struct adv7604_chip_info {
 	enum adv7604_type type;
 
@@ -78,6 +108,9 @@ struct adv7604_chip_info {
 	unsigned int tdms_lock_mask;
 	unsigned int fmt_change_digital_mask;
 
+	const struct adv7604_format_info *formats;
+	unsigned int nformats;
+
 	void (*set_termination)(struct v4l2_subdev *sd, bool enable);
 	void (*setup_irqs)(struct v4l2_subdev *sd);
 	unsigned int (*read_hdmi_pixelclock)(struct v4l2_subdev *sd);
@@ -101,12 +134,18 @@ struct adv7604_chip_info {
 struct adv7604_state {
 	const struct adv7604_chip_info *info;
 	struct adv7604_platform_data pdata;
+
 	struct v4l2_subdev sd;
 	struct media_pad pads[ADV7604_PAD_MAX];
 	unsigned int source_pad;
+
 	struct v4l2_ctrl_handler hdl;
+
 	enum adv7604_pad selected_input;
+
 	struct v4l2_dv_timings timings;
+	const struct adv7604_format_info *format;
+
 	struct {
 		u8 edid[256];
 		u32 present;
@@ -771,6 +810,93 @@ static void adv7604_write_reg_seq(struct v4l2_subdev *sd,
 		adv7604_write_reg(sd, reg_seq[i].reg, reg_seq[i].val);
 }
 
+/* -----------------------------------------------------------------------------
+ * Format helpers
+ */
+
+static const struct adv7604_format_info adv7604_formats[] = {
+	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
+	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV10_2X10, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_YVYU10_2X10, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_UYVY10_1X20, ADV7604_OP_CH_SEL_RBG, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_VYUY10_1X20, ADV7604_OP_CH_SEL_RBG, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_YUYV10_1X20, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_YVYU10_1X20, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+};
+
+static const struct adv7604_format_info adv7611_formats[] = {
+	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
+	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+};
+
+static const struct adv7604_format_info *
+adv7604_format_info(struct adv7604_state *state, enum v4l2_mbus_pixelcode code)
+{
+	unsigned int i;
+
+	for (i = 0; i < state->info->nformats; ++i) {
+		if (state->info->formats[i].code == code)
+			return &state->info->formats[i];
+	}
+
+	return NULL;
+}
+
 /* ----------------------------------------------------------------------- */
 
 static inline bool is_analog_input(struct v4l2_subdev *sd)
@@ -1720,29 +1846,95 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
 	return 0;
 }
 
-static int adv7604_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
-			     enum v4l2_mbus_pixelcode *code)
+static int adv7604_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
 {
-	if (index)
+	struct adv7604_state *state = to_state(sd);
+
+	if (code->index >= state->info->nformats)
 		return -EINVAL;
-	/* Good enough for now */
-	*code = V4L2_MBUS_FMT_FIXED;
+
+	code->code = state->info->formats[code->index].code;
+
 	return 0;
 }
 
-static int adv7604_g_mbus_fmt(struct v4l2_subdev *sd,
-		struct v4l2_mbus_framefmt *fmt)
+static void adv7604_fill_format(struct adv7604_state *state,
+				struct v4l2_mbus_framefmt *format)
 {
-	struct adv7604_state *state = to_state(sd);
+	memset(format, 0, sizeof(*format));
 
-	fmt->width = state->timings.bt.width;
-	fmt->height = state->timings.bt.height;
-	fmt->code = V4L2_MBUS_FMT_FIXED;
-	fmt->field = V4L2_FIELD_NONE;
-	if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
-		fmt->colorspace = (state->timings.bt.height <= 576) ?
+	format->width = state->timings.bt.width;
+	format->height = state->timings.bt.height;
+	format->field = V4L2_FIELD_NONE;
+
+	if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861)
+		format->colorspace = (state->timings.bt.height <= 576) ?
 			V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
+}
+
+static void adv7604_setup_format(struct adv7604_state *state)
+{
+	struct v4l2_subdev *sd = &state->sd;
+
+	io_write_and_or(sd, 0x02, 0xfd,
+			state->format->rgb_out ? ADV7604_RGB_OUT : 0);
+	io_write(sd, 0x03, state->format->op_format_sel |
+		 state->pdata.op_format_mode_sel);
+	io_write_and_or(sd, 0x04, 0x1f, state->format->op_ch_sel);
+	io_write_and_or(sd, 0x05, 0xfe,
+			state->format->swap_cb_cr ? ADV7604_OP_SWAP_CB_CR : 0);
+}
+
+static int adv7604_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	if (format->pad != state->source_pad)
+		return -EINVAL;
+
+	adv7604_fill_format(state, &format->format);
+
+	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+		struct v4l2_mbus_framefmt *fmt;
+
+		fmt = v4l2_subdev_get_try_format(fh, format->pad);
+		format->format.code = fmt->code;
+	} else {
+		format->format.code = state->format->code;
 	}
+
+	return 0;
+}
+
+static int adv7604_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct adv7604_state *state = to_state(sd);
+	const struct adv7604_format_info *info;
+
+	if (format->pad != state->source_pad)
+		return -EINVAL;
+
+	info = adv7604_format_info(state, format->format.code);
+	if (info == NULL)
+		info = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
+
+	adv7604_fill_format(state, &format->format);
+	format->format.code = info->code;
+
+	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+		struct v4l2_mbus_framefmt *fmt;
+
+		fmt = v4l2_subdev_get_try_format(fh, format->pad);
+		fmt->code = format->format.code;
+	} else {
+		state->format = info;
+		adv7604_setup_format(state);
+	}
+
 	return 0;
 }
 
@@ -2189,13 +2381,12 @@ static const struct v4l2_subdev_video_ops adv7604_video_ops = {
 	.query_dv_timings = adv7604_query_dv_timings,
 	.enum_dv_timings = adv7604_enum_dv_timings,
 	.dv_timings_cap = adv7604_dv_timings_cap,
-	.enum_mbus_fmt = adv7604_enum_mbus_fmt,
-	.g_mbus_fmt = adv7604_g_mbus_fmt,
-	.try_mbus_fmt = adv7604_g_mbus_fmt,
-	.s_mbus_fmt = adv7604_g_mbus_fmt,
 };
 
 static const struct v4l2_subdev_pad_ops adv7604_pad_ops = {
+	.enum_mbus_code = adv7604_enum_mbus_code,
+	.get_fmt = adv7604_get_format,
+	.set_fmt = adv7604_set_format,
 	.get_edid = adv7604_get_edid,
 	.set_edid = adv7604_set_edid,
 };
@@ -2264,14 +2455,11 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
 	io_write_and_or(sd, 0x02, 0xf0,
 			pdata->alt_gamma << 3 |
 			pdata->op_656_range << 2 |
-			pdata->rgb_out << 1 |
 			pdata->alt_data_sat << 0);
-	io_write(sd, 0x03, pdata->op_format_sel);
-	io_write_and_or(sd, 0x04, 0x1f, pdata->op_ch_sel << 5);
-	io_write_and_or(sd, 0x05, 0xf0, pdata->blank_data << 3 |
-					pdata->insert_av_codes << 2 |
-					pdata->replicate_av_codes << 1 |
-					pdata->invert_cbcr << 0);
+	io_write_and_or(sd, 0x05, 0xf1, pdata->blank_data << 3 |
+			pdata->insert_av_codes << 2 |
+			pdata->replicate_av_codes << 1);
+	adv7604_setup_format(state);
 
 	cp_write(sd, 0x69, 0x30);   /* Enable CP CSC */
 
@@ -2439,6 +2627,8 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
 		.tdms_lock_mask = 0xe0,
 		.cable_det_mask = 0x1e,
 		.fmt_change_digital_mask = 0xc1,
+		.formats = adv7604_formats,
+		.nformats = ARRAY_SIZE(adv7604_formats),
 		.set_termination = adv7604_set_termination,
 		.setup_irqs = adv7604_setup_irqs,
 		.read_hdmi_pixelclock = adv7604_read_hdmi_pixelclock,
@@ -2470,6 +2660,8 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
 		.tdms_lock_mask = 0x43,
 		.cable_det_mask = 0x01,
 		.fmt_change_digital_mask = 0x03,
+		.formats = adv7611_formats,
+		.nformats = ARRAY_SIZE(adv7611_formats),
 		.set_termination = adv7611_set_termination,
 		.setup_irqs = adv7611_setup_irqs,
 		.read_hdmi_pixelclock = adv7611_read_hdmi_pixelclock,
@@ -2525,6 +2717,7 @@ static int adv7604_probe(struct i2c_client *client,
 	}
 	state->pdata = *pdata;
 	state->timings = cea640x480;
+	state->format = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
 
 	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &adv7604_ops);
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index 6186771..f5791bb 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -32,16 +32,6 @@ enum adv7604_ain_sel {
 	ADV7604_AIN9_4_5_6_SYNC_2_1 = 4,
 };
 
-/* Bus rotation and reordering (IO register 0x04, [7:5]) */
-enum adv7604_op_ch_sel {
-	ADV7604_OP_CH_SEL_GBR = 0,
-	ADV7604_OP_CH_SEL_GRB = 1,
-	ADV7604_OP_CH_SEL_BGR = 2,
-	ADV7604_OP_CH_SEL_RGB = 3,
-	ADV7604_OP_CH_SEL_BRG = 4,
-	ADV7604_OP_CH_SEL_RBG = 5,
-};
-
 /* Input Color Space (IO register 0x02, [7:4]) */
 enum adv7604_inp_color_space {
 	ADV7604_INP_COLOR_SPACE_LIM_RGB = 0,
@@ -55,29 +45,11 @@ enum adv7604_inp_color_space {
 	ADV7604_INP_COLOR_SPACE_AUTO = 0xf,
 };
 
-/* Select output format (IO register 0x03, [7:0]) */
-enum adv7604_op_format_sel {
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_8 = 0x00,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_10 = 0x01,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE0 = 0x02,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE1 = 0x06,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE2 = 0x0a,
-	ADV7604_OP_FORMAT_SEL_DDR_422_8 = 0x20,
-	ADV7604_OP_FORMAT_SEL_DDR_422_10 = 0x21,
-	ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE0 = 0x22,
-	ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE1 = 0x23,
-	ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE2 = 0x24,
-	ADV7604_OP_FORMAT_SEL_SDR_444_24 = 0x40,
-	ADV7604_OP_FORMAT_SEL_SDR_444_30 = 0x41,
-	ADV7604_OP_FORMAT_SEL_SDR_444_36_MODE0 = 0x42,
-	ADV7604_OP_FORMAT_SEL_DDR_444_24 = 0x60,
-	ADV7604_OP_FORMAT_SEL_DDR_444_30 = 0x61,
-	ADV7604_OP_FORMAT_SEL_DDR_444_36 = 0x62,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_16 = 0x80,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_20 = 0x81,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE0 = 0x82,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE1 = 0x86,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE2 = 0x8a,
+/* Select output format (IO register 0x03, [4:2]) */
+enum adv7604_op_format_mode_sel {
+	ADV7604_OP_FORMAT_MODE0 = 0x00,
+	ADV7604_OP_FORMAT_MODE1 = 0x04,
+	ADV7604_OP_FORMAT_MODE2 = 0x08,
 };
 
 enum adv7604_drive_strength {
@@ -104,11 +76,8 @@ struct adv7604_platform_data {
 	/* Analog input muxing mode */
 	enum adv7604_ain_sel ain_sel;
 
-	/* Bus rotation and reordering */
-	enum adv7604_op_ch_sel op_ch_sel;
-
-	/* Select output format */
-	enum adv7604_op_format_sel op_format_sel;
+	/* Select output format mode */
+	enum adv7604_op_format_mode_sel op_format_mode_sel;
 
 	/* Configuration of the INT1 pin */
 	enum adv7604_int1_config int1_config;
@@ -116,14 +85,12 @@ struct adv7604_platform_data {
 	/* IO register 0x02 */
 	unsigned alt_gamma:1;
 	unsigned op_656_range:1;
-	unsigned rgb_out:1;
 	unsigned alt_data_sat:1;
 
 	/* IO register 0x05 */
 	unsigned blank_data:1;
 	unsigned insert_av_codes:1;
 	unsigned replicate_av_codes:1;
-	unsigned invert_cbcr:1;
 
 	/* IO register 0x06 */
 	unsigned inv_vs_pol:1;
-- 
1.8.3.2


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

* [PATCH v2 37/48] adv7604: Add pad-level DV timings support
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (35 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 36/48] adv7604: Make output format configurable through pad format operations Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 38/48] adv7604: Remove deprecated video-level DV timings operations Laurent Pinchart
                   ` (11 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 47 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 43 insertions(+), 4 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 66b3481..a96c339 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1514,24 +1514,42 @@ static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
 static int adv7604_enum_dv_timings(struct v4l2_subdev *sd,
 			struct v4l2_enum_dv_timings *timings)
 {
+	struct adv7604_state *state = to_state(sd);
+
 	if (timings->index >= ARRAY_SIZE(adv7604_timings) - 1)
 		return -EINVAL;
+
+	if (timings->pad >= state->source_pad)
+		return -EINVAL;
+
 	memset(timings->reserved, 0, sizeof(timings->reserved));
 	timings->timings = adv7604_timings[timings->index];
 	return 0;
 }
 
-static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
-			struct v4l2_dv_timings_cap *cap)
+static int __adv7604_dv_timings_cap(struct v4l2_subdev *sd,
+			struct v4l2_dv_timings_cap *cap,
+			unsigned int pad)
 {
 	cap->type = V4L2_DV_BT_656_1120;
 	cap->bt.max_width = 1920;
 	cap->bt.max_height = 1200;
 	cap->bt.min_pixelclock = 25000000;
-	if (is_digital_input(sd))
+
+	switch (pad) {
+	case ADV7604_PAD_HDMI_PORT_A:
+	case ADV7604_PAD_HDMI_PORT_B:
+	case ADV7604_PAD_HDMI_PORT_C:
+	case ADV7604_PAD_HDMI_PORT_D:
 		cap->bt.max_pixelclock = 225000000;
-	else
+		break;
+	case ADV7604_PAD_VGA_RGB:
+	case ADV7604_PAD_VGA_COMP:
+	default:
 		cap->bt.max_pixelclock = 170000000;
+		break;
+	}
+
 	cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			 V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT;
 	cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
@@ -1539,6 +1557,25 @@ static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
 	return 0;
 }
 
+static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
+			struct v4l2_dv_timings_cap *cap)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return __adv7604_dv_timings_cap(sd, cap, state->selected_input);
+}
+
+static int adv7604_pad_dv_timings_cap(struct v4l2_subdev *sd,
+			struct v4l2_dv_timings_cap *cap)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	if (cap->pad >= state->source_pad)
+		return -EINVAL;
+
+	return __adv7604_dv_timings_cap(sd, cap, cap->pad);
+}
+
 /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
    if the format is listed in adv7604_timings[] */
 static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
@@ -2389,6 +2426,8 @@ static const struct v4l2_subdev_pad_ops adv7604_pad_ops = {
 	.set_fmt = adv7604_set_format,
 	.get_edid = adv7604_get_edid,
 	.set_edid = adv7604_set_edid,
+	.dv_timings_cap = adv7604_pad_dv_timings_cap,
+	.enum_dv_timings = adv7604_enum_dv_timings,
 };
 
 static const struct v4l2_subdev_ops adv7604_ops = {
-- 
1.8.3.2


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

* [PATCH v2 38/48] adv7604: Remove deprecated video-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (36 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 37/48] adv7604: Add pad-level DV timings support Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 39/48] v4l: subdev: " Laurent Pinchart
                   ` (10 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings and dv_timings_cap operations are deprecated
and unused. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 35 +++++++++--------------------------
 1 file changed, 9 insertions(+), 26 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index a96c339..d4d085c 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1527,16 +1527,20 @@ static int adv7604_enum_dv_timings(struct v4l2_subdev *sd,
 	return 0;
 }
 
-static int __adv7604_dv_timings_cap(struct v4l2_subdev *sd,
-			struct v4l2_dv_timings_cap *cap,
-			unsigned int pad)
+static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
+			struct v4l2_dv_timings_cap *cap)
 {
+	struct adv7604_state *state = to_state(sd);
+
+	if (cap->pad >= state->source_pad)
+		return -EINVAL;
+
 	cap->type = V4L2_DV_BT_656_1120;
 	cap->bt.max_width = 1920;
 	cap->bt.max_height = 1200;
 	cap->bt.min_pixelclock = 25000000;
 
-	switch (pad) {
+	switch (cap->pad) {
 	case ADV7604_PAD_HDMI_PORT_A:
 	case ADV7604_PAD_HDMI_PORT_B:
 	case ADV7604_PAD_HDMI_PORT_C:
@@ -1557,25 +1561,6 @@ static int __adv7604_dv_timings_cap(struct v4l2_subdev *sd,
 	return 0;
 }
 
-static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
-			struct v4l2_dv_timings_cap *cap)
-{
-	struct adv7604_state *state = to_state(sd);
-
-	return __adv7604_dv_timings_cap(sd, cap, state->selected_input);
-}
-
-static int adv7604_pad_dv_timings_cap(struct v4l2_subdev *sd,
-			struct v4l2_dv_timings_cap *cap)
-{
-	struct adv7604_state *state = to_state(sd);
-
-	if (cap->pad >= state->source_pad)
-		return -EINVAL;
-
-	return __adv7604_dv_timings_cap(sd, cap, cap->pad);
-}
-
 /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
    if the format is listed in adv7604_timings[] */
 static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
@@ -2416,8 +2401,6 @@ static const struct v4l2_subdev_video_ops adv7604_video_ops = {
 	.s_dv_timings = adv7604_s_dv_timings,
 	.g_dv_timings = adv7604_g_dv_timings,
 	.query_dv_timings = adv7604_query_dv_timings,
-	.enum_dv_timings = adv7604_enum_dv_timings,
-	.dv_timings_cap = adv7604_dv_timings_cap,
 };
 
 static const struct v4l2_subdev_pad_ops adv7604_pad_ops = {
@@ -2426,7 +2409,7 @@ static const struct v4l2_subdev_pad_ops adv7604_pad_ops = {
 	.set_fmt = adv7604_set_format,
 	.get_edid = adv7604_get_edid,
 	.set_edid = adv7604_set_edid,
-	.dv_timings_cap = adv7604_pad_dv_timings_cap,
+	.dv_timings_cap = adv7604_dv_timings_cap,
 	.enum_dv_timings = adv7604_enum_dv_timings,
 };
 
-- 
1.8.3.2


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

* [PATCH v2 39/48] v4l: subdev: Remove deprecated video-level DV timings operations
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (37 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 38/48] adv7604: Remove deprecated video-level DV timings operations Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11  7:21   ` Prabhakar Lad
  2014-03-10 23:15 ` [PATCH v2 40/48] adv7604: Inline the to_sd function Laurent Pinchart
                   ` (9 subsequent siblings)
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The video enum_dv_timings and dv_timings_cap operations are deprecated
and unused. Remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 include/media/v4l2-subdev.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 2b5ec32..ab2b59d 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -330,12 +330,8 @@ struct v4l2_subdev_video_ops {
 			struct v4l2_dv_timings *timings);
 	int (*g_dv_timings)(struct v4l2_subdev *sd,
 			struct v4l2_dv_timings *timings);
-	int (*enum_dv_timings)(struct v4l2_subdev *sd,
-			struct v4l2_enum_dv_timings *timings);
 	int (*query_dv_timings)(struct v4l2_subdev *sd,
 			struct v4l2_dv_timings *timings);
-	int (*dv_timings_cap)(struct v4l2_subdev *sd,
-			struct v4l2_dv_timings_cap *cap);
 	int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index,
 			     enum v4l2_mbus_pixelcode *code);
 	int (*enum_mbus_fsizes)(struct v4l2_subdev *sd,
-- 
1.8.3.2


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

* [PATCH v2 40/48] adv7604: Inline the to_sd function
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (38 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 39/48] v4l: subdev: " Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 41/48] adv7604: Store I2C addresses and clients in arrays Laurent Pinchart
                   ` (8 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

This one line function is called in a single location. Inline it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index d4d085c..2a3ced2 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -340,11 +340,6 @@ static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
 	return container_of(sd, struct adv7604_state, sd);
 }
 
-static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
-{
-	return &container_of(ctrl->handler, struct adv7604_state, hdl)->sd;
-}
-
 static inline unsigned hblanking(const struct v4l2_bt_timings *t)
 {
 	return V4L2_DV_BT_BLANKING_WIDTH(t);
@@ -1270,7 +1265,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 
 static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct v4l2_subdev *sd =
+		&container_of(ctrl->handler, struct adv7604_state, hdl)->sd;
+
 	struct adv7604_state *state = to_state(sd);
 
 	switch (ctrl->id) {
-- 
1.8.3.2


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

* [PATCH v2 41/48] adv7604: Store I2C addresses and clients in arrays
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (39 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 40/48] adv7604: Inline the to_sd function Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 42/48] adv7604: Replace *_and_or() functions with *_clr_set() Laurent Pinchart
                   ` (7 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

This allows replacing duplicate code blocks by loops over the arrays.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 248 +++++++++++++-------------------------------
 include/media/adv7604.h     |  30 +++---
 2 files changed, 88 insertions(+), 190 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 2a3ced2..f79761e 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -159,18 +159,7 @@ struct adv7604_state {
 	bool restart_stdi_once;
 
 	/* i2c clients */
-	struct i2c_client *i2c_avlink;
-	struct i2c_client *i2c_cec;
-	struct i2c_client *i2c_infoframe;
-	struct i2c_client *i2c_esdp;
-	struct i2c_client *i2c_dpp;
-	struct i2c_client *i2c_afe;
-	struct i2c_client *i2c_repeater;
-	struct i2c_client *i2c_edid;
-	struct i2c_client *i2c_hdmi;
-	struct i2c_client *i2c_test;
-	struct i2c_client *i2c_cp;
-	struct i2c_client *i2c_vdp;
+	struct i2c_client *i2c_clients[ADV7604_PAGE_MAX];
 
 	/* controls */
 	struct v4l2_ctrl *detect_tx_5v_ctrl;
@@ -377,14 +366,18 @@ static s32 adv_smbus_read_byte_data_check(struct i2c_client *client,
 	return -EIO;
 }
 
-static s32 adv_smbus_read_byte_data(struct i2c_client *client, u8 command)
+static s32 adv_smbus_read_byte_data(struct adv7604_state *state,
+				    enum adv7604_page page, u8 command)
 {
-	return adv_smbus_read_byte_data_check(client, command, true);
+	return adv_smbus_read_byte_data_check(state->i2c_clients[page],
+					      command, true);
 }
 
-static s32 adv_smbus_write_byte_data(struct i2c_client *client,
-					u8 command, u8 value)
+static s32 adv_smbus_write_byte_data(struct adv7604_state *state,
+				     enum adv7604_page page, u8 command,
+				     u8 value)
 {
+	struct i2c_client *client = state->i2c_clients[page];
 	union i2c_smbus_data data;
 	int err;
 	int i;
@@ -404,9 +397,11 @@ static s32 adv_smbus_write_byte_data(struct i2c_client *client,
 	return err;
 }
 
-static s32 adv_smbus_write_i2c_block_data(struct i2c_client *client,
-	       u8 command, unsigned length, const u8 *values)
+static s32 adv_smbus_write_i2c_block_data(struct adv7604_state *state,
+					  enum adv7604_page page, u8 command,
+					  unsigned length, const u8 *values)
 {
+	struct i2c_client *client = state->i2c_clients[page];
 	union i2c_smbus_data data;
 
 	if (length > I2C_SMBUS_BLOCK_MAX)
@@ -422,16 +417,16 @@ static s32 adv_smbus_write_i2c_block_data(struct i2c_client *client,
 
 static inline int io_read(struct v4l2_subdev *sd, u8 reg)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(client, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_IO, reg);
 }
 
 static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(client, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_IO, reg, val);
 }
 
 static inline int io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
@@ -443,28 +438,28 @@ static inline int avlink_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_avlink, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_AVLINK, reg);
 }
 
 static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_avlink, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_AVLINK, reg, val);
 }
 
 static inline int cec_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_cec, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_CEC, reg);
 }
 
 static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_cec, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_CEC, reg, val);
 }
 
 static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
@@ -476,70 +471,71 @@ static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_infoframe, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_INFOFRAME, reg);
 }
 
 static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_infoframe, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_INFOFRAME,
+					 reg, val);
 }
 
 static inline int esdp_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_esdp, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_ESDP, reg);
 }
 
 static inline int esdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_esdp, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_ESDP, reg, val);
 }
 
 static inline int dpp_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_dpp, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_DPP, reg);
 }
 
 static inline int dpp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_dpp, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_DPP, reg, val);
 }
 
 static inline int afe_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_afe, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_AFE, reg);
 }
 
 static inline int afe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_afe, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_AFE, reg, val);
 }
 
 static inline int rep_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_repeater, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_REP, reg);
 }
 
 static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_repeater, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_REP, reg, val);
 }
 
 static inline int rep_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
@@ -551,20 +547,20 @@ static inline int edid_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_edid, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_EDID, reg);
 }
 
 static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_edid, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_EDID, reg, val);
 }
 
 static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val)
 {
 	struct adv7604_state *state = to_state(sd);
-	struct i2c_client *client = state->i2c_edid;
+	struct i2c_client *client = state->i2c_clients[ADV7604_PAGE_EDID];
 	u8 msgbuf0[1] = { 0 };
 	u8 msgbuf1[256];
 	struct i2c_msg msg[2] = {
@@ -597,8 +593,8 @@ static inline int edid_write_block(struct v4l2_subdev *sd,
 	v4l2_dbg(2, debug, sd, "%s: write EDID block (%d byte)\n", __func__, len);
 
 	for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX)
-		err = adv_smbus_write_i2c_block_data(state->i2c_edid, i,
-				I2C_SMBUS_BLOCK_MAX, val + i);
+		err = adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_EDID,
+				i, I2C_SMBUS_BLOCK_MAX, val + i);
 	return err;
 }
 
@@ -618,7 +614,7 @@ static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_hdmi, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_HDMI, reg);
 }
 
 static u16 hdmi_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
@@ -630,7 +626,7 @@ static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_hdmi, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_HDMI, reg, val);
 }
 
 static inline int hdmi_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
@@ -642,21 +638,21 @@ static inline int test_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_test, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_TEST, reg);
 }
 
 static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_test, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_TEST, reg, val);
 }
 
 static inline int cp_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_cp, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_CP, reg);
 }
 
 static u16 cp_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
@@ -668,7 +664,7 @@ static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_cp, reg, val);
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_CP, reg, val);
 }
 
 static inline int cp_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
@@ -680,32 +676,15 @@ static inline int vdp_read(struct v4l2_subdev *sd, u8 reg)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_read_byte_data(state->i2c_vdp, reg);
+	return adv_smbus_read_byte_data(state, ADV7604_PAGE_VDP, reg);
 }
 
 static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	return adv_smbus_write_byte_data(state->i2c_vdp, reg, val);
-}
-
-enum {
-	ADV7604_PAGE_IO,
-	ADV7604_PAGE_AVLINK,
-	ADV7604_PAGE_CEC,
-	ADV7604_PAGE_INFOFRAME,
-	ADV7604_PAGE_ESDP,
-	ADV7604_PAGE_DPP,
-	ADV7604_PAGE_AFE,
-	ADV7604_PAGE_REP,
-	ADV7604_PAGE_EDID,
-	ADV7604_PAGE_HDMI,
-	ADV7604_PAGE_TEST,
-	ADV7604_PAGE_CP,
-	ADV7604_PAGE_VDP,
-	ADV7604_PAGE_TERM,
-};
+	return adv_smbus_write_byte_data(state, ADV7604_PAGE_VDP, reg, val);
+}
 
 #define ADV7604_REG(page, offset)	(((page) << 8) | (offset))
 #define ADV7604_REG_SEQ_TERM		0xffff
@@ -721,36 +700,7 @@ static int adv7604_read_reg(struct v4l2_subdev *sd, unsigned int reg)
 
 	reg &= 0xff;
 
-	switch (page) {
-	case ADV7604_PAGE_IO:
-		return io_read(sd, reg);
-	case ADV7604_PAGE_AVLINK:
-		return avlink_read(sd, reg);
-	case ADV7604_PAGE_CEC:
-		return cec_read(sd, reg);
-	case ADV7604_PAGE_INFOFRAME:
-		return infoframe_read(sd, reg);
-	case ADV7604_PAGE_ESDP:
-		return esdp_read(sd, reg);
-	case ADV7604_PAGE_DPP:
-		return dpp_read(sd, reg);
-	case ADV7604_PAGE_AFE:
-		return afe_read(sd, reg);
-	case ADV7604_PAGE_REP:
-		return rep_read(sd, reg);
-	case ADV7604_PAGE_EDID:
-		return edid_read(sd, reg);
-	case ADV7604_PAGE_HDMI:
-		return hdmi_read(sd, reg);
-	case ADV7604_PAGE_TEST:
-		return test_read(sd, reg);
-	case ADV7604_PAGE_CP:
-		return cp_read(sd, reg);
-	case ADV7604_PAGE_VDP:
-		return vdp_read(sd, reg);
-	}
-
-	return -EINVAL;
+	return adv_smbus_read_byte_data(state, page, reg);
 }
 #endif
 
@@ -764,36 +714,7 @@ static int adv7604_write_reg(struct v4l2_subdev *sd, unsigned int reg, u8 val)
 
 	reg &= 0xff;
 
-	switch (page) {
-	case ADV7604_PAGE_IO:
-		return io_write(sd, reg, val);
-	case ADV7604_PAGE_AVLINK:
-		return avlink_write(sd, reg, val);
-	case ADV7604_PAGE_CEC:
-		return cec_write(sd, reg, val);
-	case ADV7604_PAGE_INFOFRAME:
-		return infoframe_write(sd, reg, val);
-	case ADV7604_PAGE_ESDP:
-		return esdp_write(sd, reg, val);
-	case ADV7604_PAGE_DPP:
-		return dpp_write(sd, reg, val);
-	case ADV7604_PAGE_AFE:
-		return afe_write(sd, reg, val);
-	case ADV7604_PAGE_REP:
-		return rep_write(sd, reg, val);
-	case ADV7604_PAGE_EDID:
-		return edid_write(sd, reg, val);
-	case ADV7604_PAGE_HDMI:
-		return hdmi_write(sd, reg, val);
-	case ADV7604_PAGE_TEST:
-		return test_write(sd, reg, val);
-	case ADV7604_PAGE_CP:
-		return cp_write(sd, reg, val);
-	case ADV7604_PAGE_VDP:
-		return vdp_write(sd, reg, val);
-	}
-
-	return -EINVAL;
+	return adv_smbus_write_byte_data(state, page, reg, val);
 }
 
 static void adv7604_write_reg_seq(struct v4l2_subdev *sd,
@@ -1064,7 +985,6 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
 		const struct v4l2_bt_timings *bt)
 {
 	struct adv7604_state *state = to_state(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	u32 width = htotal(bt);
 	u32 height = vtotal(bt);
 	u16 cp_start_sav = bt->hsync + bt->hbackporch - 4;
@@ -1090,7 +1010,8 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
 		/* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
 		/* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
 		/* IO-map reg. 0x16 and 0x17 should be written in sequence */
-		if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll))
+		if (adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_IO,
+						   0x16, 2, pll))
 			v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
 
 		/* active video - horizontal timing */
@@ -1141,7 +1062,8 @@ static void adv7604_set_offset(struct v4l2_subdev *sd, bool auto_offset, u16 off
 	offset_buf[3] = offset_c & 0x0ff;
 
 	/* Registers must be written in this order with no i2c access in between */
-	if (adv_smbus_write_i2c_block_data(state->i2c_cp, 0x77, 4, offset_buf))
+	if (adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_CP,
+					   0x77, 4, offset_buf))
 		v4l2_err(sd, "%s: i2c error writing to CP reg 0x77, 0x78, 0x79, 0x7a\n", __func__);
 }
 
@@ -1170,7 +1092,8 @@ static void adv7604_set_gain(struct v4l2_subdev *sd, bool auto_gain, u16 gain_a,
 	gain_buf[3] = ((gain_c & 0x0ff));
 
 	/* Registers must be written in this order with no i2c access in between */
-	if (adv_smbus_write_i2c_block_data(state->i2c_cp, 0x73, 4, gain_buf))
+	if (adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_CP,
+					   0x73, 4, gain_buf))
 		v4l2_err(sd, "%s: i2c error writing to CP reg 0x73, 0x74, 0x75, 0x76\n", __func__);
 }
 
@@ -2534,30 +2457,12 @@ static void adv7611_setup_irqs(struct v4l2_subdev *sd)
 
 static void adv7604_unregister_clients(struct adv7604_state *state)
 {
-	if (state->i2c_avlink)
-		i2c_unregister_device(state->i2c_avlink);
-	if (state->i2c_cec)
-		i2c_unregister_device(state->i2c_cec);
-	if (state->i2c_infoframe)
-		i2c_unregister_device(state->i2c_infoframe);
-	if (state->i2c_esdp)
-		i2c_unregister_device(state->i2c_esdp);
-	if (state->i2c_dpp)
-		i2c_unregister_device(state->i2c_dpp);
-	if (state->i2c_afe)
-		i2c_unregister_device(state->i2c_afe);
-	if (state->i2c_repeater)
-		i2c_unregister_device(state->i2c_repeater);
-	if (state->i2c_edid)
-		i2c_unregister_device(state->i2c_edid);
-	if (state->i2c_hdmi)
-		i2c_unregister_device(state->i2c_hdmi);
-	if (state->i2c_test)
-		i2c_unregister_device(state->i2c_test);
-	if (state->i2c_cp)
-		i2c_unregister_device(state->i2c_cp);
-	if (state->i2c_vdp)
-		i2c_unregister_device(state->i2c_vdp);
+	unsigned int i;
+
+	for (i = 1; i < ARRAY_SIZE(state->i2c_clients); ++i) {
+		if (state->i2c_clients[i])
+			i2c_unregister_device(state->i2c_clients[i]);
+	}
 }
 
 static struct i2c_client *adv7604_dummy_client(struct v4l2_subdev *sd,
@@ -2724,6 +2629,7 @@ static int adv7604_probe(struct i2c_client *client,
 	}
 
 	state->info = &adv7604_chip_info[id->driver_data];
+	state->i2c_clients[ADV7604_PAGE_IO] = client;
 
 	/* initialize variables */
 	state->restart_stdi_once = true;
@@ -2815,34 +2721,20 @@ static int adv7604_probe(struct i2c_client *client,
 		goto err_hdl;
 	}
 
-	state->i2c_cec = adv7604_dummy_client(sd, pdata->i2c_cec, 0xf4);
-	state->i2c_infoframe = adv7604_dummy_client(sd, pdata->i2c_infoframe, 0xf5);
-	state->i2c_afe = adv7604_dummy_client(sd, pdata->i2c_afe, 0xf8);
-	state->i2c_repeater = adv7604_dummy_client(sd, pdata->i2c_repeater, 0xf9);
-	state->i2c_edid = adv7604_dummy_client(sd, pdata->i2c_edid, 0xfa);
-	state->i2c_hdmi = adv7604_dummy_client(sd, pdata->i2c_hdmi, 0xfb);
-	state->i2c_cp = adv7604_dummy_client(sd, pdata->i2c_cp, 0xfd);
-	if (!state->i2c_cec || !state->i2c_infoframe || !state->i2c_afe ||
-	    !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi ||
-	    !state->i2c_cp) {
-		err = -ENOMEM;
-		v4l2_err(sd, "failed to create digital i2c clients\n");
-		goto err_i2c;
-	}
+	for (i = 1; i < ADV7604_PAGE_MAX; ++i) {
+		if (!(BIT(i) & state->info->page_mask))
+			continue;
 
-	if (adv7604_has_afe(state)) {
-		state->i2c_avlink = adv7604_dummy_client(sd, pdata->i2c_avlink, 0xf3);
-		state->i2c_esdp = adv7604_dummy_client(sd, pdata->i2c_esdp, 0xf6);
-		state->i2c_dpp = adv7604_dummy_client(sd, pdata->i2c_dpp, 0xf7);
-		state->i2c_test = adv7604_dummy_client(sd, pdata->i2c_test, 0xfc);
-		state->i2c_vdp = adv7604_dummy_client(sd, pdata->i2c_vdp, 0xfe);
-		if (!state->i2c_avlink || !state->i2c_esdp || !state->i2c_dpp ||
-		    !state->i2c_test || !state->i2c_vdp) {
+		state->i2c_clients[i] =
+			adv7604_dummy_client(sd, pdata->i2c_addresses[i],
+					     0xf2 + i);
+		if (state->i2c_clients[i] == NULL) {
 			err = -ENOMEM;
-			v4l2_err(sd, "failed to create analog i2c clients\n");
+			v4l2_err(sd, "failed to create i2c client %u\n", i);
 			goto err_i2c;
 		}
 	}
+
 	/* work queues */
 	state->work_queues = create_singlethread_workqueue(client->name);
 	if (!state->work_queues) {
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index f5791bb..a1798d6 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -65,6 +65,23 @@ enum adv7604_int1_config {
 	ADV7604_INT1_CONFIG_DISABLED,
 };
 
+enum adv7604_page {
+	ADV7604_PAGE_IO,
+	ADV7604_PAGE_AVLINK,
+	ADV7604_PAGE_CEC,
+	ADV7604_PAGE_INFOFRAME,
+	ADV7604_PAGE_ESDP,
+	ADV7604_PAGE_DPP,
+	ADV7604_PAGE_AFE,
+	ADV7604_PAGE_REP,
+	ADV7604_PAGE_EDID,
+	ADV7604_PAGE_HDMI,
+	ADV7604_PAGE_TEST,
+	ADV7604_PAGE_CP,
+	ADV7604_PAGE_VDP,
+	ADV7604_PAGE_MAX,
+};
+
 /* Platform dependent definition */
 struct adv7604_platform_data {
 	/* DIS_PWRDNB: 1 if the PWRDNB pin is unused and unconnected */
@@ -108,18 +125,7 @@ struct adv7604_platform_data {
 	unsigned hdmi_free_run_mode;
 
 	/* i2c addresses: 0 == use default */
-	u8 i2c_avlink;
-	u8 i2c_cec;
-	u8 i2c_infoframe;
-	u8 i2c_esdp;
-	u8 i2c_dpp;
-	u8 i2c_afe;
-	u8 i2c_repeater;
-	u8 i2c_edid;
-	u8 i2c_hdmi;
-	u8 i2c_test;
-	u8 i2c_cp;
-	u8 i2c_vdp;
+	u8 i2c_addresses[ADV7604_PAGE_MAX];
 };
 
 enum adv7604_pad {
-- 
1.8.3.2


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

* [PATCH v2 42/48] adv7604: Replace *_and_or() functions with *_clr_set()
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (40 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 41/48] adv7604: Store I2C addresses and clients in arrays Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11 15:10   ` [PATCH v3 " Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 43/48] adv7604: Sort headers alphabetically Laurent Pinchart
                   ` (6 subsequent siblings)
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The *_and_or() functions take an 'and' bitmask to be ANDed with the
register value before ORing it with th 'or' bitmask. As the functions
are used to mask and set bits selectively, this requires the caller to
invert the 'and' bitmask and is thus error prone. Replace those
functions with a *_clr_set() variant that takes a mask of bits to be
cleared instead of a mask of bits to be kept.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 86 ++++++++++++++++++++++-----------------------
 1 file changed, 43 insertions(+), 43 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index f79761e..83ad97e 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -429,9 +429,9 @@ static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_IO, reg, val);
 }
 
-static inline int io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
 {
-	return io_write(sd, reg, (io_read(sd, reg) & mask) | val);
+	return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val);
 }
 
 static inline int avlink_read(struct v4l2_subdev *sd, u8 reg)
@@ -462,9 +462,9 @@ static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_CEC, reg, val);
 }
 
-static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
 {
-	return cec_write(sd, reg, (cec_read(sd, reg) & mask) | val);
+	return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val);
 }
 
 static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
@@ -538,9 +538,9 @@ static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_REP, reg, val);
 }
 
-static inline int rep_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int rep_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
 {
-	return rep_write(sd, reg, (rep_read(sd, reg) & mask) | val);
+	return rep_write(sd, reg, (rep_read(sd, reg) & ~mask) | val);
 }
 
 static inline int edid_read(struct v4l2_subdev *sd, u8 reg)
@@ -629,9 +629,9 @@ static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_HDMI, reg, val);
 }
 
-static inline int hdmi_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
 {
-	return hdmi_write(sd, reg, (hdmi_read(sd, reg) & mask) | val);
+	return hdmi_write(sd, reg, (hdmi_read(sd, reg) & ~mask) | val);
 }
 
 static inline int test_read(struct v4l2_subdev *sd, u8 reg)
@@ -667,9 +667,9 @@ static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_CP, reg, val);
 }
 
-static inline int cp_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int cp_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
 {
-	return cp_write(sd, reg, (cp_read(sd, reg) & mask) | val);
+	return cp_write(sd, reg, (cp_read(sd, reg) & ~mask) | val);
 }
 
 static inline int vdp_read(struct v4l2_subdev *sd, u8 reg)
@@ -947,7 +947,7 @@ static int configure_predefined_video_timings(struct v4l2_subdev *sd,
 		io_write(sd, 0x17, 0x5a);
 	}
 	/* disable embedded syncs for auto graphics mode */
-	cp_write_and_or(sd, 0x81, 0xef, 0x00);
+	cp_write_clr_set(sd, 0x81, 0x10, 0x00);
 	cp_write(sd, 0x8f, 0x00);
 	cp_write(sd, 0x90, 0x00);
 	cp_write(sd, 0xa2, 0x00);
@@ -1005,7 +1005,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
 		io_write(sd, 0x00, 0x07); /* video std */
 		io_write(sd, 0x01, 0x02); /* prim mode */
 		/* enable embedded syncs for auto graphics mode */
-		cp_write_and_or(sd, 0x81, 0xef, 0x10);
+		cp_write_clr_set(sd, 0x81, 0x10, 0x10);
 
 		/* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
 		/* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
@@ -1115,21 +1115,21 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 		if (state->selected_input == ADV7604_PAD_VGA_RGB) {
 			/* Receiving analog RGB signal
 			 * Set RGB full range (0-255) */
-			io_write_and_or(sd, 0x02, 0x0f, 0x10);
+			io_write_clr_set(sd, 0x02, 0xf0, 0x10);
 			break;
 		}
 
 		if (state->selected_input == ADV7604_PAD_VGA_COMP) {
 			/* Receiving analog YPbPr signal
 			 * Set automode */
-			io_write_and_or(sd, 0x02, 0x0f, 0xf0);
+			io_write_clr_set(sd, 0x02, 0xf0, 0xf0);
 			break;
 		}
 
 		if (hdmi_signal) {
 			/* Receiving HDMI signal
 			 * Set automode */
-			io_write_and_or(sd, 0x02, 0x0f, 0xf0);
+			io_write_clr_set(sd, 0x02, 0xf0, 0xf0);
 			break;
 		}
 
@@ -1138,10 +1138,10 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 		 * input format (CE/IT) in automatic mode */
 		if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
 			/* RGB limited range (16-235) */
-			io_write_and_or(sd, 0x02, 0x0f, 0x00);
+			io_write_clr_set(sd, 0x02, 0xf0, 0x00);
 		} else {
 			/* RGB full range (0-255) */
-			io_write_and_or(sd, 0x02, 0x0f, 0x10);
+			io_write_clr_set(sd, 0x02, 0xf0, 0x10);
 
 			if (is_digital_input(sd) && rgb_output) {
 				adv7604_set_offset(sd, false, 0x40, 0x40, 0x40);
@@ -1154,23 +1154,23 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 	case V4L2_DV_RGB_RANGE_LIMITED:
 		if (state->selected_input == ADV7604_PAD_VGA_COMP) {
 			/* YCrCb limited range (16-235) */
-			io_write_and_or(sd, 0x02, 0x0f, 0x20);
+			io_write_clr_set(sd, 0x02, 0xf0, 0x20);
 			break;
 		}
 
 		/* RGB limited range (16-235) */
-		io_write_and_or(sd, 0x02, 0x0f, 0x00);
+		io_write_clr_set(sd, 0x02, 0xf0, 0x00);
 
 		break;
 	case V4L2_DV_RGB_RANGE_FULL:
 		if (state->selected_input == ADV7604_PAD_VGA_COMP) {
 			/* YCrCb full range (0-255) */
-			io_write_and_or(sd, 0x02, 0x0f, 0x60);
+			io_write_clr_set(sd, 0x02, 0xf0, 0x60);
 			break;
 		}
 
 		/* RGB full range (0-255) */
-		io_write_and_or(sd, 0x02, 0x0f, 0x10);
+		io_write_clr_set(sd, 0x02, 0xf0, 0x10);
 
 		if (is_analog_input(sd) || hdmi_signal)
 			break;
@@ -1222,7 +1222,7 @@ static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
 	case V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL:
 		/* Use the default blue color for free running mode,
 		   or supply your own. */
-		cp_write_and_or(sd, 0xbf, ~0x04, (ctrl->val << 2));
+		cp_write_clr_set(sd, 0xbf, 0x04, ctrl->val << 2);
 		return 0;
 	case V4L2_CID_ADV_RX_FREE_RUN_COLOR:
 		cp_write(sd, 0xc0, (ctrl->val & 0xff0000) >> 16);
@@ -1605,11 +1605,11 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
 				v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__);
 				/* TODO restart STDI for Sync Channel 2 */
 				/* enter one-shot mode */
-				cp_write_and_or(sd, 0x86, 0xf9, 0x00);
+				cp_write_clr_set(sd, 0x86, 0x06, 0x00);
 				/* trigger STDI restart */
-				cp_write_and_or(sd, 0x86, 0xf9, 0x04);
+				cp_write_clr_set(sd, 0x86, 0x06, 0x04);
 				/* reset to continuous mode */
-				cp_write_and_or(sd, 0x86, 0xf9, 0x02);
+				cp_write_clr_set(sd, 0x86, 0x06, 0x02);
 				state->restart_stdi_once = false;
 				return -ENOLINK;
 			}
@@ -1668,7 +1668,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
 
 	state->timings = *timings;
 
-	cp_write_and_or(sd, 0x91, 0xbf, bt->interlaced ? 0x40 : 0x00);
+	cp_write_clr_set(sd, 0x91, 0x40, bt->interlaced ? 0x40 : 0x00);
 
 	/* Use prim_mode and vid_std when available */
 	err = configure_predefined_video_timings(sd, timings);
@@ -1712,10 +1712,10 @@ static void enable_input(struct v4l2_subdev *sd)
 	if (is_analog_input(sd)) {
 		io_write(sd, 0x15, 0xb0);   /* Disable Tristate of Pins (no audio) */
 	} else if (is_digital_input(sd)) {
-		hdmi_write_and_or(sd, 0x00, 0xfc, state->selected_input);
+		hdmi_write_clr_set(sd, 0x00, 0x03, state->selected_input);
 		state->info->set_termination(sd, true);
 		io_write(sd, 0x15, 0xa0);   /* Disable Tristate of Pins */
-		hdmi_write_and_or(sd, 0x1a, 0xef, 0x00); /* Unmute audio */
+		hdmi_write_clr_set(sd, 0x1a, 0x10, 0x00); /* Unmute audio */
 	} else {
 		v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
 				__func__, state->selected_input);
@@ -1726,7 +1726,7 @@ static void disable_input(struct v4l2_subdev *sd)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	hdmi_write_and_or(sd, 0x1a, 0xef, 0x10); /* Mute audio */
+	hdmi_write_clr_set(sd, 0x1a, 0x10, 0x10); /* Mute audio */
 	msleep(16); /* 512 samples with >= 32 kHz sample rate [REF_03, c. 7.16.10] */
 	io_write(sd, 0x15, 0xbe);   /* Tristate all outputs from video core */
 	state->info->set_termination(sd, false);
@@ -1820,12 +1820,12 @@ static void adv7604_setup_format(struct adv7604_state *state)
 {
 	struct v4l2_subdev *sd = &state->sd;
 
-	io_write_and_or(sd, 0x02, 0xfd,
+	io_write_clr_set(sd, 0x02, 0x02,
 			state->format->rgb_out ? ADV7604_RGB_OUT : 0);
 	io_write(sd, 0x03, state->format->op_format_sel |
 		 state->pdata.op_format_mode_sel);
-	io_write_and_or(sd, 0x04, 0x1f, state->format->op_ch_sel);
-	io_write_and_or(sd, 0x05, 0xfe,
+	io_write_clr_set(sd, 0x04, 0xe0, state->format->op_ch_sel);
+	io_write_clr_set(sd, 0x05, 0x01,
 			state->format->swap_cb_cr ? ADV7604_OP_SWAP_CB_CR : 0);
 }
 
@@ -2022,7 +2022,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 		/* Disable hotplug and I2C access to EDID RAM from DDC port */
 		state->edid.present &= ~(1 << edid->pad);
 		v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
-		rep_write_and_or(sd, info->edid_enable_reg, 0xf0, state->edid.present);
+		rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
 
 		/* Fall back to a 16:9 aspect ratio */
 		state->aspect_ratio.numerator = 16;
@@ -2046,7 +2046,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 	/* Disable hotplug and I2C access to EDID RAM from DDC port */
 	cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
 	v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&tmp);
-	rep_write_and_or(sd, info->edid_enable_reg, 0xf0, 0x00);
+	rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, 0x00);
 
 	spa_loc = get_edid_spa_location(edid->edid);
 	if (spa_loc < 0)
@@ -2075,10 +2075,10 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 
 	if (info->type == ADV7604) {
 		rep_write(sd, 0x76, spa_loc & 0xff);
-		rep_write_and_or(sd, 0x77, 0xbf, (spa_loc & 0x100) >> 2);
+		rep_write_clr_set(sd, 0x77, 0x40, (spa_loc & 0x100) >> 2);
 	} else {
 		/* FIXME: Where is the SPA location LSB register ? */
-		rep_write_and_or(sd, 0x71, 0xfe, (spa_loc & 0x100) >> 8);
+		rep_write_clr_set(sd, 0x71, 0x01, (spa_loc & 0x100) >> 8);
 	}
 
 	edid->edid[spa_loc] = state->spa_port_a[0];
@@ -2098,7 +2098,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 
 	/* adv7604 calculates the checksums and enables I2C access to internal
 	   EDID RAM from DDC port. */
-	rep_write_and_or(sd, info->edid_enable_reg, 0xf0, state->edid.present);
+	rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
 
 	for (i = 0; i < 1000; i++) {
 		if (rep_read(sd, info->edid_status_reg) & state->edid.present)
@@ -2394,11 +2394,11 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
 	cp_write(sd, 0xcf, 0x01);   /* Power down macrovision */
 
 	/* video format */
-	io_write_and_or(sd, 0x02, 0xf0,
+	io_write_clr_set(sd, 0x02, 0x0f,
 			pdata->alt_gamma << 3 |
 			pdata->op_656_range << 2 |
 			pdata->alt_data_sat << 0);
-	io_write_and_or(sd, 0x05, 0xf1, pdata->blank_data << 3 |
+	io_write_clr_set(sd, 0x05, 0x0e, pdata->blank_data << 3 |
 			pdata->insert_av_codes << 2 |
 			pdata->replicate_av_codes << 1);
 	adv7604_setup_format(state);
@@ -2423,16 +2423,16 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
 				     for digital formats */
 
 	/* HDMI audio */
-	hdmi_write_and_or(sd, 0x15, 0xfc, 0x03); /* Mute on FIFO over-/underflow [REF_01, c. 1.2.18] */
-	hdmi_write_and_or(sd, 0x1a, 0xf1, 0x08); /* Wait 1 s before unmute */
-	hdmi_write_and_or(sd, 0x68, 0xf9, 0x06); /* FIFO reset on over-/underflow [REF_01, c. 1.2.19] */
+	hdmi_write_clr_set(sd, 0x15, 0x03, 0x03); /* Mute on FIFO over-/underflow [REF_01, c. 1.2.18] */
+	hdmi_write_clr_set(sd, 0x1a, 0x0e, 0x08); /* Wait 1 s before unmute */
+	hdmi_write_clr_set(sd, 0x68, 0x06, 0x06); /* FIFO reset on over-/underflow [REF_01, c. 1.2.19] */
 
 	/* TODO from platform data */
 	afe_write(sd, 0xb5, 0x01);  /* Setting MCLK to 256Fs */
 
 	if (adv7604_has_afe(state)) {
 		afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
-		io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
+		io_write_clr_set(sd, 0x30, 1 << 4, pdata->output_bus_lsb_to_msb << 4);
 	}
 
 	/* interrupts */
-- 
1.8.3.2


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

* [PATCH v2 43/48] adv7604: Sort headers alphabetically
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (41 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 42/48] adv7604: Replace *_and_or() functions with *_clr_set() Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 44/48] adv7604: Support hot-plug detect control through a GPIO Laurent Pinchart
                   ` (5 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

This helps locating duplicates and inserting new headers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 83ad97e..0c81c72 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -27,19 +27,19 @@
  * REF_03 - Analog devices, ADV7604, Hardware Manual, Rev. F, August 2010
  */
 
-
+#include <linux/delay.h>
+#include <linux/i2c.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
+#include <linux/v4l2-dv-timings.h>
 #include <linux/videodev2.h>
 #include <linux/workqueue.h>
-#include <linux/v4l2-dv-timings.h>
-#include <media/v4l2-device.h>
+
+#include <media/adv7604.h>
 #include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
 #include <media/v4l2-dv-timings.h>
-#include <media/adv7604.h>
 
 static int debug;
 module_param(debug, int, 0644);
-- 
1.8.3.2


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

* [PATCH v2 44/48] adv7604: Support hot-plug detect control through a GPIO
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (42 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 43/48] adv7604: Sort headers alphabetically Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 45/48] adv7604: Specify the default input through platform data Laurent Pinchart
                   ` (4 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Add support for optional GPIO-controlled HPD pins in addition to the
ADV7604-specific hotplug notifier.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 37 +++++++++++++++++++++++++++++++++----
 1 file changed, 33 insertions(+), 4 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 0c81c72..7f70c6f 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -28,6 +28,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -135,6 +136,8 @@ struct adv7604_state {
 	const struct adv7604_chip_info *info;
 	struct adv7604_platform_data pdata;
 
+	struct gpio_desc *hpd_gpio[4];
+
 	struct v4l2_subdev sd;
 	struct media_pad pads[ADV7604_PAD_MAX];
 	unsigned int source_pad;
@@ -598,6 +601,20 @@ static inline int edid_write_block(struct v4l2_subdev *sd,
 	return err;
 }
 
+static void adv7604_set_hpd(struct adv7604_state *state, unsigned int hpd)
+{
+	unsigned int i;
+
+	for (i = 0; i < state->info->num_dv_ports; ++i) {
+		if (IS_ERR(state->hpd_gpio[i]))
+			continue;
+
+		gpiod_set_value_cansleep(state->hpd_gpio[i], hpd & BIT(i));
+	}
+
+	v4l2_subdev_notify(&state->sd, ADV7604_HOTPLUG, &hpd);
+}
+
 static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
 {
 	struct delayed_work *dwork = to_delayed_work(work);
@@ -607,7 +624,7 @@ static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
 
 	v4l2_dbg(2, debug, sd, "%s: enable hotplug\n", __func__);
 
-	v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
+	adv7604_set_hpd(state, state->edid.present);
 }
 
 static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg)
@@ -2010,7 +2027,6 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 	struct adv7604_state *state = to_state(sd);
 	const struct adv7604_chip_info *info = state->info;
 	int spa_loc;
-	int tmp = 0;
 	int err;
 	int i;
 
@@ -2021,7 +2037,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 	if (edid->blocks == 0) {
 		/* Disable hotplug and I2C access to EDID RAM from DDC port */
 		state->edid.present &= ~(1 << edid->pad);
-		v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
+		adv7604_set_hpd(state, state->edid.present);
 		rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
 
 		/* Fall back to a 16:9 aspect ratio */
@@ -2045,7 +2061,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 
 	/* Disable hotplug and I2C access to EDID RAM from DDC port */
 	cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
-	v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&tmp);
+	adv7604_set_hpd(state, 0);
 	rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, 0x00);
 
 	spa_loc = get_edid_spa_location(edid->edid);
@@ -2641,6 +2657,19 @@ static int adv7604_probe(struct i2c_client *client,
 		return -ENODEV;
 	}
 	state->pdata = *pdata;
+
+	/* Request GPIOs. */
+	for (i = 0; i < state->info->num_dv_ports; ++i) {
+		state->hpd_gpio[i] =
+			devm_gpiod_get_index(&client->dev, "hpd", i);
+		if (IS_ERR(state->hpd_gpio[i]))
+			continue;
+
+		gpiod_set_value_cansleep(state->hpd_gpio[i], 0);
+
+		v4l_info(client, "Handling HPD %u GPIO\n", i);
+	}
+
 	state->timings = cea640x480;
 	state->format = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
 
-- 
1.8.3.2


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

* [PATCH v2 45/48] adv7604: Specify the default input through platform data
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (43 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 44/48] adv7604: Support hot-plug detect control through a GPIO Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-10 23:15 ` [PATCH v2 46/48] adv7604: Add DT support Laurent Pinchart
                   ` (3 subsequent siblings)
  48 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

And set input routing when initializing the device.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 7 +++++++
 include/media/adv7604.h     | 2 ++
 2 files changed, 9 insertions(+)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 7f70c6f..cce140c 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2404,6 +2404,13 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
 
 	disable_input(sd);
 
+	if (pdata->default_input >= 0 &&
+	    pdata->default_input < state->source_pad) {
+		state->selected_input = pdata->default_input;
+		select_input(sd);
+		enable_input(sd);
+	}
+
 	/* power */
 	io_write(sd, 0x0c, 0x42);   /* Power up part and power down VDP */
 	io_write(sd, 0x0b, 0x44);   /* Power down ESDP block */
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index a1798d6..6d69207 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -90,6 +90,8 @@ struct adv7604_platform_data {
 	/* DIS_CABLE_DET_RST: 1 if the 5V pins are unused and unconnected */
 	unsigned disable_cable_det_rst:1;
 
+	int default_input;
+
 	/* Analog input muxing mode */
 	enum adv7604_ain_sel ain_sel;
 
-- 
1.8.3.2


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

* [PATCH v2 46/48] adv7604: Add DT support
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (44 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 45/48] adv7604: Specify the default input through platform data Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-11 15:11   ` [PATCH v3 " Laurent Pinchart
  2014-04-17 10:59   ` [PATCH v2 " Sylwester Nawrocki
  2014-03-10 23:15 ` [PATCH v2 47/48] adv7604: Add LLC polarity configuration Laurent Pinchart
                   ` (2 subsequent siblings)
  48 siblings, 2 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen, devicetree

Parse the device tree node to populate platform data.

Cc: devicetree@vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../devicetree/bindings/media/i2c/adv7604.txt      | 56 +++++++++++++
 drivers/media/i2c/adv7604.c                        | 92 ++++++++++++++++++----
 2 files changed, 134 insertions(+), 14 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/adv7604.txt

diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
new file mode 100644
index 0000000..0845c50
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
@@ -0,0 +1,56 @@
+* Analog Devices ADV7604/11 video decoder with HDMI receiver
+
+The ADV7604 and ADV7611 are multiformat video decoders with an integrated HDMI
+receiver. The ADV7604 has four multiplexed HDMI inputs and one analog input,
+and the ADV7611 has one HDMI input and no analog input.
+
+Required Properties:
+
+  - compatible: Must contain one of the following
+    - "adi,adv7604" for the ADV7604
+    - "adi,adv7611" for the ADV7611
+
+  - reg: I2C slave address
+
+  - hpd-gpios: References to the GPIOs that control the HDMI hot-plug
+    detection pins, one per HDMI input. The active flag indicates the GPIO
+    level that enables hot-plug detection.
+
+Optional Properties:
+
+  - reset-gpios: Reference to the GPIO connected to the device's reset pin.
+
+  - adi,default-input: Index of the input to be configured as default. Valid
+    values are 0..5 for the ADV7604 and 0 for the ADV7611.
+
+  - adi,disable-power-down: Boolean property. When set forces the device to
+    ignore the power-down pin. The property is valid for the ADV7604 only as
+    the ADV7611 has no power-down pin.
+
+  - adi,disable-cable-reset: Boolean property. When set disables the HDMI
+    receiver automatic reset when the HDMI cable is unplugged.
+
+Example:
+
+	hdmi_receiver@4c {
+		compatible = "adi,adv7611";
+		reg = <0x4c>;
+
+		reset-gpios = <&ioexp 0 GPIO_ACTIVE_LOW>;
+		hpd-gpios = <&ioexp 2 GPIO_ACTIVE_HIGH>;
+
+		adi,default-input = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+		};
+		port@1 {
+			reg = <1>;
+			hdmi_in: endpoint {
+				remote-endpoint = <&ccdc_in>;
+			};
+		};
+	};
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index cce140c..de44213 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2626,13 +2626,70 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
 	},
 };
 
+static struct i2c_device_id adv7604_i2c_id[] = {
+	{ "adv7604", (kernel_ulong_t)&adv7604_chip_info[ADV7604] },
+	{ "adv7611", (kernel_ulong_t)&adv7604_chip_info[ADV7611] },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adv7604_i2c_id);
+
+static struct of_device_id adv7604_of_id[] = {
+	{ .compatible = "adi,adv7604", .data = &adv7604_chip_info[ADV7604] },
+	{ .compatible = "adi,adv7611", .data = &adv7604_chip_info[ADV7611] },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, adv7604_of_id);
+
+static int adv7604_parse_dt(struct adv7604_state *state)
+{
+	struct device_node *np;
+	int ret;
+
+	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
+
+	state->pdata.disable_pwrdnb =
+		of_property_read_bool(np, "adi,disable-power-down");
+	state->pdata.disable_cable_det_rst =
+		of_property_read_bool(np, "adi,disable-cable-reset");
+
+	ret = of_property_read_u32(np, "adi,default-input",
+				   &state->pdata.default_input);
+	if (ret < 0)
+		state->pdata.default_input = -1;
+
+	/* Disable the interrupt for now as no DT-based board uses it. */
+	state->pdata.int1_config = ADV7604_INT1_CONFIG_DISABLED;
+
+	/* Use the default I2C addresses. */
+	state->pdata.i2c_addresses[ADV7604_PAGE_AVLINK] = 0x42;
+	state->pdata.i2c_addresses[ADV7604_PAGE_CEC] = 0x40;
+	state->pdata.i2c_addresses[ADV7604_PAGE_INFOFRAME] = 0x3e;
+	state->pdata.i2c_addresses[ADV7604_PAGE_ESDP] = 0x38;
+	state->pdata.i2c_addresses[ADV7604_PAGE_DPP] = 0x3c;
+	state->pdata.i2c_addresses[ADV7604_PAGE_AFE] = 0x26;
+	state->pdata.i2c_addresses[ADV7604_PAGE_REP] = 0x32;
+	state->pdata.i2c_addresses[ADV7604_PAGE_EDID] = 0x36;
+	state->pdata.i2c_addresses[ADV7604_PAGE_HDMI] = 0x34;
+	state->pdata.i2c_addresses[ADV7604_PAGE_TEST] = 0x30;
+	state->pdata.i2c_addresses[ADV7604_PAGE_CP] = 0x22;
+	state->pdata.i2c_addresses[ADV7604_PAGE_VDP] = 0x24;
+
+	/* HACK: Hardcode the remaining platform data fields. */
+	state->pdata.blank_data = 1;
+	state->pdata.op_656_range = 1;
+	state->pdata.alt_data_sat = 1;
+	state->pdata.insert_av_codes = 1;
+	state->pdata.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0;
+
+	return 0;
+}
+
 static int adv7604_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	static const struct v4l2_dv_timings cea640x480 =
 		V4L2_DV_BT_CEA_640X480P59_94;
 	struct adv7604_state *state;
-	struct adv7604_platform_data *pdata = client->dev.platform_data;
 	struct v4l2_ctrl_handler *hdl;
 	struct v4l2_subdev *sd;
 	unsigned int i;
@@ -2651,19 +2708,32 @@ static int adv7604_probe(struct i2c_client *client,
 		return -ENOMEM;
 	}
 
-	state->info = &adv7604_chip_info[id->driver_data];
 	state->i2c_clients[ADV7604_PAGE_IO] = client;
 
 	/* initialize variables */
 	state->restart_stdi_once = true;
 	state->selected_input = ~0;
 
-	/* platform data */
-	if (!pdata) {
+	if (IS_ENABLED(CONFIG_OF) && client->dev.of_node) {
+		const struct of_device_id *oid;
+
+		oid = of_match_node(adv7604_of_id, client->dev.of_node);
+		state->info = oid->data;
+
+		err = adv7604_parse_dt(state);
+		if (err < 0) {
+			v4l_err(client, "DT parsing error\n");
+			return err;
+		}
+	} else if (client->dev.platform_data) {
+		struct adv7604_platform_data *pdata = client->dev.platform_data;
+
+		state->info = (const struct adv7604_chip_info *)id->driver_data;
+		state->pdata = *pdata;
+	} else {
 		v4l_err(client, "No platform data!\n");
 		return -ENODEV;
 	}
-	state->pdata = *pdata;
 
 	/* Request GPIOs. */
 	for (i = 0; i < state->info->num_dv_ports; ++i) {
@@ -2762,7 +2832,7 @@ static int adv7604_probe(struct i2c_client *client,
 			continue;
 
 		state->i2c_clients[i] =
-			adv7604_dummy_client(sd, pdata->i2c_addresses[i],
+			adv7604_dummy_client(sd, state->pdata.i2c_addresses[i],
 					     0xf2 + i);
 		if (state->i2c_clients[i] == NULL) {
 			err = -ENOMEM;
@@ -2836,21 +2906,15 @@ static int adv7604_remove(struct i2c_client *client)
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_device_id adv7604_id[] = {
-	{ "adv7604", ADV7604 },
-	{ "adv7611", ADV7611 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, adv7604_id);
-
 static struct i2c_driver adv7604_driver = {
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "adv7604",
+		.of_match_table = of_match_ptr(adv7604_of_id),
 	},
 	.probe = adv7604_probe,
 	.remove = adv7604_remove,
-	.id_table = adv7604_id,
+	.id_table = adv7604_i2c_id,
 };
 
 module_i2c_driver(adv7604_driver);
-- 
1.8.3.2

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

* [PATCH v2 47/48] adv7604: Add LLC polarity configuration
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (45 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 46/48] adv7604: Add DT support Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-03-18 13:05   ` Hans Verkuil
  2014-04-17 11:29   ` Sylwester Nawrocki
  2014-03-10 23:15 ` [PATCH v2 48/48] adv7604: Add endpoint properties to DT bindings Laurent Pinchart
  2014-03-11 11:58 ` [PATCH v2 00/48] ADV7611 support Hans Verkuil
  48 siblings, 2 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Add an inv_llc_pol field to platform data to control the clock polarity.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 3 ++-
 include/media/adv7604.h     | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index de44213..95cc911 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2429,7 +2429,8 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
 	cp_write(sd, 0x69, 0x30);   /* Enable CP CSC */
 
 	/* VS, HS polarities */
-	io_write(sd, 0x06, 0xa0 | pdata->inv_vs_pol << 2 | pdata->inv_hs_pol << 1);
+	io_write(sd, 0x06, 0xa0 | pdata->inv_vs_pol << 2 |
+		 pdata->inv_hs_pol << 1 | pdata->inv_llc_pol);
 
 	/* Adjust drive strength */
 	io_write(sd, 0x14, 0x40 | pdata->dr_str_data << 4 |
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index 6d69207..7a8462f 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -114,6 +114,7 @@ struct adv7604_platform_data {
 	/* IO register 0x06 */
 	unsigned inv_vs_pol:1;
 	unsigned inv_hs_pol:1;
+	unsigned inv_llc_pol:1;
 
 	/* IO register 0x14 */
 	enum adv7604_drive_strength dr_str_data;
-- 
1.8.3.2


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

* [PATCH v2 48/48] adv7604: Add endpoint properties to DT bindings
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (46 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 47/48] adv7604: Add LLC polarity configuration Laurent Pinchart
@ 2014-03-10 23:15 ` Laurent Pinchart
  2014-04-17 11:17   ` Sylwester Nawrocki
  2014-03-11 11:58 ` [PATCH v2 00/48] ADV7611 support Hans Verkuil
  48 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:15 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Add support for the hsync-active, vsync-active and pclk-sample
properties to the DT bindings and control BT.656 mode implicitly.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../devicetree/bindings/media/i2c/adv7604.txt      | 13 +++++++++
 drivers/media/i2c/adv7604.c                        | 31 ++++++++++++++++++++--
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
index 0845c50..2b62c06 100644
--- a/Documentation/devicetree/bindings/media/i2c/adv7604.txt
+++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
@@ -30,6 +30,19 @@ Optional Properties:
   - adi,disable-cable-reset: Boolean property. When set disables the HDMI
     receiver automatic reset when the HDMI cable is unplugged.
 
+Optional Endpoint Properties:
+
+  The following three properties are defined in video-interfaces.txt and are
+  valid for source endpoints only.
+
+  - hsync-active: Horizontal synchronization polarity. Defaults to active low.
+  - vsync-active: Vertical synchronization polarity. Defaults to active low.
+  - pclk-sample: Pixel clock polarity. Defaults to output on the falling edge.
+
+  If none of hsync-active, vsync-active and pclk-sample is specified the
+  endpoint will use embedded BT.656 synchronization.
+
+
 Example:
 
 	hdmi_receiver@4c {
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 95cc911..2a92099 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -41,6 +41,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-dv-timings.h>
+#include <media/v4l2-of.h>
 
 static int debug;
 module_param(debug, int, 0644);
@@ -2643,11 +2644,39 @@ MODULE_DEVICE_TABLE(of, adv7604_of_id);
 
 static int adv7604_parse_dt(struct adv7604_state *state)
 {
+	struct v4l2_of_endpoint bus_cfg;
+	struct device_node *endpoint;
 	struct device_node *np;
+	unsigned int flags;
 	int ret;
 
 	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
 
+	/* Parse the endpoint. */
+	endpoint = v4l2_of_get_next_endpoint(np, NULL);
+	if (!endpoint)
+		return -EINVAL;
+
+	v4l2_of_parse_endpoint(endpoint, &bus_cfg);
+	of_node_put(endpoint);
+
+	flags = bus_cfg.bus.parallel.flags;
+
+	if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
+		state->pdata.inv_hs_pol = 1;
+
+	if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
+		state->pdata.inv_vs_pol = 1;
+
+	if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
+		state->pdata.inv_llc_pol = 1;
+
+	if (bus_cfg.bus_type == V4L2_MBUS_BT656) {
+		state->pdata.insert_av_codes = 1;
+		state->pdata.op_656_range = 1;
+	}
+
+	/* Parse device-specific properties. */
 	state->pdata.disable_pwrdnb =
 		of_property_read_bool(np, "adi,disable-power-down");
 	state->pdata.disable_cable_det_rst =
@@ -2677,9 +2706,7 @@ static int adv7604_parse_dt(struct adv7604_state *state)
 
 	/* HACK: Hardcode the remaining platform data fields. */
 	state->pdata.blank_data = 1;
-	state->pdata.op_656_range = 1;
 	state->pdata.alt_data_sat = 1;
-	state->pdata.insert_av_codes = 1;
 	state->pdata.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0;
 
 	return 0;
-- 
1.8.3.2


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

* Re: [PATCH v2 12/48] ths8200: Add pad-level DV timings operations
  2014-03-10 23:15 ` [PATCH v2 12/48] ths8200: " Laurent Pinchart
@ 2014-03-11  7:11   ` Prabhakar Lad
  0 siblings, 0 replies; 93+ messages in thread
From: Prabhakar Lad @ 2014-03-11  7:11 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On Tue, Mar 11, 2014 at 4:45 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> The video enum_dv_timings and dv_timings_cap operations are deprecated.
> Implement the pad-level version of those operations to prepare for the
> removal of the video version.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>

Regards,
--Prabhakar lad

> ---
>  drivers/media/i2c/ths8200.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
>
> diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c
> index f72561e..c4ec8b2 100644
> --- a/drivers/media/i2c/ths8200.c
> +++ b/drivers/media/i2c/ths8200.c
> @@ -410,6 +410,9 @@ static int ths8200_g_dv_timings(struct v4l2_subdev *sd,
>  static int ths8200_enum_dv_timings(struct v4l2_subdev *sd,
>                                    struct v4l2_enum_dv_timings *timings)
>  {
> +       if (timings->pad != 0)
> +               return -EINVAL;
> +
>         return v4l2_enum_dv_timings_cap(timings, &ths8200_timings_cap,
>                         NULL, NULL);
>  }
> @@ -417,6 +420,9 @@ static int ths8200_enum_dv_timings(struct v4l2_subdev *sd,
>  static int ths8200_dv_timings_cap(struct v4l2_subdev *sd,
>                                   struct v4l2_dv_timings_cap *cap)
>  {
> +       if (cap->pad != 0)
> +               return -EINVAL;
> +
>         *cap = ths8200_timings_cap;
>         return 0;
>  }
> @@ -430,10 +436,16 @@ static const struct v4l2_subdev_video_ops ths8200_video_ops = {
>         .dv_timings_cap = ths8200_dv_timings_cap,
>  };
>
> +static const struct v4l2_subdev_pad_ops ths8200_pad_ops = {
> +       .enum_dv_timings = ths8200_enum_dv_timings,
> +       .dv_timings_cap = ths8200_dv_timings_cap,
> +};
> +
>  /* V4L2 top level operation handlers */
>  static const struct v4l2_subdev_ops ths8200_ops = {
>         .core  = &ths8200_core_ops,
>         .video = &ths8200_video_ops,
> +       .pad = &ths8200_pad_ops,
>  };
>
>  static int ths8200_probe(struct i2c_client *client,
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 24/48] tvp7002: Remove deprecated video-level DV timings operations
  2014-03-10 23:15 ` [PATCH v2 24/48] tvp7002: " Laurent Pinchart
@ 2014-03-11  7:12   ` Prabhakar Lad
  0 siblings, 0 replies; 93+ messages in thread
From: Prabhakar Lad @ 2014-03-11  7:12 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On Tue, Mar 11, 2014 at 4:45 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> The video enum_dv_timings and dv_timings_cap operations are deprecated
> and unused. Remove them.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>

Regards,
--Prabhakar lad

> ---
>  drivers/media/i2c/tvp7002.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
> index 9f56fd5..fa901a9 100644
> --- a/drivers/media/i2c/tvp7002.c
> +++ b/drivers/media/i2c/tvp7002.c
> @@ -926,7 +926,6 @@ static const struct v4l2_subdev_core_ops tvp7002_core_ops = {
>  static const struct v4l2_subdev_video_ops tvp7002_video_ops = {
>         .g_dv_timings = tvp7002_g_dv_timings,
>         .s_dv_timings = tvp7002_s_dv_timings,
> -       .enum_dv_timings = tvp7002_enum_dv_timings,
>         .query_dv_timings = tvp7002_query_dv_timings,
>         .s_stream = tvp7002_s_stream,
>         .g_mbus_fmt = tvp7002_mbus_fmt,
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 13/48] tvp7002: Add pad-level DV timings operations
  2014-03-10 23:15 ` [PATCH v2 13/48] tvp7002: " Laurent Pinchart
@ 2014-03-11  7:12   ` Prabhakar Lad
  0 siblings, 0 replies; 93+ messages in thread
From: Prabhakar Lad @ 2014-03-11  7:12 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On Tue, Mar 11, 2014 at 4:45 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> The video enum_dv_timings operation is deprecated. Implement the
> pad-level version of the operation to prepare for the removal of the
> video version.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>

Regards,
--Prabhakar lad

> ---
>  drivers/media/i2c/tvp7002.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
> index 912e1cc..9f56fd5 100644
> --- a/drivers/media/i2c/tvp7002.c
> +++ b/drivers/media/i2c/tvp7002.c
> @@ -832,6 +832,9 @@ static int tvp7002_log_status(struct v4l2_subdev *sd)
>  static int tvp7002_enum_dv_timings(struct v4l2_subdev *sd,
>                 struct v4l2_enum_dv_timings *timings)
>  {
> +       if (timings->pad != 0)
> +               return -EINVAL;
> +
>         /* Check requested format index is within range */
>         if (timings->index >= NUM_TIMINGS)
>                 return -EINVAL;
> @@ -937,6 +940,7 @@ static const struct v4l2_subdev_pad_ops tvp7002_pad_ops = {
>         .enum_mbus_code = tvp7002_enum_mbus_code,
>         .get_fmt = tvp7002_get_pad_format,
>         .set_fmt = tvp7002_set_pad_format,
> +       .enum_dv_timings = tvp7002_enum_dv_timings,
>  };
>
>  /* V4L2 top level operation handlers */
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 23/48] ths8200: Remove deprecated video-level DV timings operations
  2014-03-10 23:15 ` [PATCH v2 23/48] ths8200: Remove deprecated video-level DV timings operations Laurent Pinchart
@ 2014-03-11  7:13   ` Prabhakar Lad
  0 siblings, 0 replies; 93+ messages in thread
From: Prabhakar Lad @ 2014-03-11  7:13 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On Tue, Mar 11, 2014 at 4:45 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> The video enum_dv_timings and dv_timings_cap operations are deprecated
> and unused. Remove them.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>

Regards,
--Prabhakar lad

> ---
>  drivers/media/i2c/ths8200.c | 2 --
>  1 file changed, 2 deletions(-)
>
> diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c
> index c4ec8b2..656d889 100644
> --- a/drivers/media/i2c/ths8200.c
> +++ b/drivers/media/i2c/ths8200.c
> @@ -432,8 +432,6 @@ static const struct v4l2_subdev_video_ops ths8200_video_ops = {
>         .s_stream = ths8200_s_stream,
>         .s_dv_timings = ths8200_s_dv_timings,
>         .g_dv_timings = ths8200_g_dv_timings,
> -       .enum_dv_timings = ths8200_enum_dv_timings,
> -       .dv_timings_cap = ths8200_dv_timings_cap,
>  };
>
>  static const struct v4l2_subdev_pad_ops ths8200_pad_ops = {
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 15/48] media: davinci: vpif: Switch to pad-level DV operations
  2014-03-10 23:15 ` [PATCH v2 15/48] media: davinci: vpif: " Laurent Pinchart
@ 2014-03-11  7:15   ` Prabhakar Lad
  0 siblings, 0 replies; 93+ messages in thread
From: Prabhakar Lad @ 2014-03-11  7:15 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Laurent,

Thanks for the patch.

On Tue, Mar 11, 2014 at 4:45 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> The video-level enum_dv_timings and dv_timings_cap operations are
> deprecated in favor of the pad-level versions. All subdev drivers
> implement the pad-level versions, switch to them.
>
> Cc: Prabhakar Lad <prabhakar.csengg@gmail.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>

Regards,
--Prabhakar lad

> ---
>  drivers/media/platform/davinci/vpif_capture.c | 4 +++-
>  drivers/media/platform/davinci/vpif_display.c | 4 +++-
>  2 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
> index cd6da8b..16a1958 100644
> --- a/drivers/media/platform/davinci/vpif_capture.c
> +++ b/drivers/media/platform/davinci/vpif_capture.c
> @@ -1723,7 +1723,9 @@ vpif_enum_dv_timings(struct file *file, void *priv,
>         struct channel_obj *ch = fh->channel;
>         int ret;
>
> -       ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
> +       timings->pad = 0;
> +
> +       ret = v4l2_subdev_call(ch->sd, pad, enum_dv_timings, timings);
>         if (ret == -ENOIOCTLCMD || ret == -ENODEV)
>                 return -EINVAL;
>         return ret;
> diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
> index fd68236..e1edefe 100644
> --- a/drivers/media/platform/davinci/vpif_display.c
> +++ b/drivers/media/platform/davinci/vpif_display.c
> @@ -1380,7 +1380,9 @@ vpif_enum_dv_timings(struct file *file, void *priv,
>         struct channel_obj *ch = fh->channel;
>         int ret;
>
> -       ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
> +       timings->pad = 0;
> +
> +       ret = v4l2_subdev_call(ch->sd, pad, enum_dv_timings, timings);
>         if (ret == -ENOIOCTLCMD || ret == -ENODEV)
>                 return -EINVAL;
>         return ret;
> --
> 1.8.3.2
>

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

* Re: [PATCH v2 16/48] media: staging: davinci: vpfe: Switch to pad-level DV operations
  2014-03-10 23:15 ` [PATCH v2 16/48] media: staging: davinci: vpfe: " Laurent Pinchart
@ 2014-03-11  7:16   ` Prabhakar Lad
  0 siblings, 0 replies; 93+ messages in thread
From: Prabhakar Lad @ 2014-03-11  7:16 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Laurent,

Thanks for the patch.

On Tue, Mar 11, 2014 at 4:45 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> The video-level enum_dv_timings and dv_timings_cap operations are
> deprecated in favor of the pad-level versions. All subdev drivers
> implement the pad-level versions, switch to them.
>
> Cc: Prabhakar Lad <prabhakar.csengg@gmail.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>

Regards,
--Prabhakar lad

> ---
>  drivers/staging/media/davinci_vpfe/vpfe_video.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
> index 1f3b0f9..a1655a8 100644
> --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
> +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
> @@ -987,8 +987,10 @@ vpfe_enum_dv_timings(struct file *file, void *fh,
>         struct vpfe_device *vpfe_dev = video->vpfe_dev;
>         struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
>
> +       timings->pad = 0;
> +
>         v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_dv_timings\n");
> -       return v4l2_subdev_call(subdev, video, enum_dv_timings, timings);
> +       return v4l2_subdev_call(subdev, pad, enum_dv_timings, timings);
>  }
>
>  /*
> --
> 1.8.3.2
>

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

* Re: [PATCH v2 39/48] v4l: subdev: Remove deprecated video-level DV timings operations
  2014-03-10 23:15 ` [PATCH v2 39/48] v4l: subdev: " Laurent Pinchart
@ 2014-03-11  7:21   ` Prabhakar Lad
  0 siblings, 0 replies; 93+ messages in thread
From: Prabhakar Lad @ 2014-03-11  7:21 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On Tue, Mar 11, 2014 at 4:45 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> The video enum_dv_timings and dv_timings_cap operations are deprecated
> and unused. Remove them.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>

Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>

Regards,
--Prabhakar lad

> ---
>  include/media/v4l2-subdev.h | 4 ----
>  1 file changed, 4 deletions(-)
>
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index 2b5ec32..ab2b59d 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -330,12 +330,8 @@ struct v4l2_subdev_video_ops {
>                         struct v4l2_dv_timings *timings);
>         int (*g_dv_timings)(struct v4l2_subdev *sd,
>                         struct v4l2_dv_timings *timings);
> -       int (*enum_dv_timings)(struct v4l2_subdev *sd,
> -                       struct v4l2_enum_dv_timings *timings);
>         int (*query_dv_timings)(struct v4l2_subdev *sd,
>                         struct v4l2_dv_timings *timings);
> -       int (*dv_timings_cap)(struct v4l2_subdev *sd,
> -                       struct v4l2_dv_timings_cap *cap);
>         int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index,
>                              enum v4l2_mbus_pixelcode *code);
>         int (*enum_mbus_fsizes)(struct v4l2_subdev *sd,
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 06/48] v4l: Add pad-level DV timings subdev operations
  2014-03-10 23:15 ` [PATCH v2 06/48] v4l: Add pad-level DV timings subdev operations Laurent Pinchart
@ 2014-03-11  7:24   ` Prabhakar Lad
  2014-03-11 10:27   ` Hans Verkuil
  1 sibling, 0 replies; 93+ messages in thread
From: Prabhakar Lad @ 2014-03-11  7:24 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On Tue, Mar 11, 2014 at 4:45 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>

Regards,
--Prabhakar lad

> ---
>  include/media/v4l2-subdev.h    |  4 ++++
>  include/uapi/linux/videodev2.h | 10 ++++++++--
>  2 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index 1752530..2b5ec32 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -509,6 +509,10 @@ struct v4l2_subdev_pad_ops {
>                              struct v4l2_subdev_selection *sel);
>         int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid);
>         int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid);
> +       int (*dv_timings_cap)(struct v4l2_subdev *sd,
> +                             struct v4l2_dv_timings_cap *cap);
> +       int (*enum_dv_timings)(struct v4l2_subdev *sd,
> +                              struct v4l2_enum_dv_timings *timings);
>  #ifdef CONFIG_MEDIA_CONTROLLER
>         int (*link_validate)(struct v4l2_subdev *sd, struct media_link *link,
>                              struct v4l2_subdev_format *source_fmt,
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 17acba8..72fbbd4 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -1103,12 +1103,15 @@ struct v4l2_dv_timings {
>
>  /** struct v4l2_enum_dv_timings - DV timings enumeration
>   * @index:     enumeration index
> + * @pad:       the pad number for which to enumerate timings (used with
> + *             v4l-subdev nodes only)
>   * @reserved:  must be zeroed
>   * @timings:   the timings for the given index
>   */
>  struct v4l2_enum_dv_timings {
>         __u32 index;
> -       __u32 reserved[3];
> +       __u32 pad;
> +       __u32 reserved[2];
>         struct v4l2_dv_timings timings;
>  };
>
> @@ -1146,11 +1149,14 @@ struct v4l2_bt_timings_cap {
>
>  /** struct v4l2_dv_timings_cap - DV timings capabilities
>   * @type:      the type of the timings (same as in struct v4l2_dv_timings)
> + * @pad:       the pad number for which to query capabilities (used with
> + *             v4l-subdev nodes only)
>   * @bt:                the BT656/1120 timings capabilities
>   */
>  struct v4l2_dv_timings_cap {
>         __u32 type;
> -       __u32 reserved[3];
> +       __u32 pad;
> +       __u32 reserved[2];
>         union {
>                 struct v4l2_bt_timings_cap bt;
>                 __u32 raw_data[32];
> --
> 1.8.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 27/48] v4l: Validate fields in the core code for subdev EDID ioctls
  2014-03-10 23:15 ` [PATCH v2 27/48] v4l: Validate fields in the core code for subdev EDID ioctls Laurent Pinchart
@ 2014-03-11  8:57   ` Sakari Ailus
  2014-03-11 10:45   ` Hans Verkuil
  2014-03-11 15:09   ` [PATCH v3 " Laurent Pinchart
  2 siblings, 0 replies; 93+ messages in thread
From: Sakari Ailus @ 2014-03-11  8:57 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On Tue, Mar 11, 2014 at 12:15:38AM +0100, Laurent Pinchart wrote:
> The subdev EDID ioctls receive a pad field that must reference an
> existing pad and an EDID field that must point to a buffer. Validate
> both fields in the core code instead of duplicating validation in all
> drivers.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>

-- 
Sakari Ailus
e-mail: sakari.ailus@iki.fi	XMPP: sailus@retiisi.org.uk

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

* Re: [PATCH v2 06/48] v4l: Add pad-level DV timings subdev operations
  2014-03-10 23:15 ` [PATCH v2 06/48] v4l: Add pad-level DV timings subdev operations Laurent Pinchart
  2014-03-11  7:24   ` Prabhakar Lad
@ 2014-03-11 10:27   ` Hans Verkuil
  1 sibling, 0 replies; 93+ messages in thread
From: Hans Verkuil @ 2014-03-11 10:27 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

On 03/11/14 00:15, Laurent Pinchart wrote:
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  include/media/v4l2-subdev.h    |  4 ++++
>  include/uapi/linux/videodev2.h | 10 ++++++++--
>  2 files changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index 1752530..2b5ec32 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -509,6 +509,10 @@ struct v4l2_subdev_pad_ops {
>  			     struct v4l2_subdev_selection *sel);
>  	int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid);
>  	int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid);
> +	int (*dv_timings_cap)(struct v4l2_subdev *sd,
> +			      struct v4l2_dv_timings_cap *cap);
> +	int (*enum_dv_timings)(struct v4l2_subdev *sd,
> +			       struct v4l2_enum_dv_timings *timings);
>  #ifdef CONFIG_MEDIA_CONTROLLER
>  	int (*link_validate)(struct v4l2_subdev *sd, struct media_link *link,
>  			     struct v4l2_subdev_format *source_fmt,
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 17acba8..72fbbd4 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -1103,12 +1103,15 @@ struct v4l2_dv_timings {
>  
>  /** struct v4l2_enum_dv_timings - DV timings enumeration
>   * @index:	enumeration index
> + * @pad:	the pad number for which to enumerate timings (used with
> + *		v4l-subdev nodes only)
>   * @reserved:	must be zeroed
>   * @timings:	the timings for the given index
>   */
>  struct v4l2_enum_dv_timings {
>  	__u32 index;
> -	__u32 reserved[3];
> +	__u32 pad;
> +	__u32 reserved[2];
>  	struct v4l2_dv_timings timings;
>  };
>  
> @@ -1146,11 +1149,14 @@ struct v4l2_bt_timings_cap {
>  
>  /** struct v4l2_dv_timings_cap - DV timings capabilities
>   * @type:	the type of the timings (same as in struct v4l2_dv_timings)
> + * @pad:	the pad number for which to query capabilities (used with
> + *		v4l-subdev nodes only)
>   * @bt:		the BT656/1120 timings capabilities
>   */
>  struct v4l2_dv_timings_cap {
>  	__u32 type;
> -	__u32 reserved[3];
> +	__u32 pad;
> +	__u32 reserved[2];
>  	union {
>  		struct v4l2_bt_timings_cap bt;
>  		__u32 raw_data[32];
> 


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

* Re: [PATCH v2 26/48] v4l: Add support for DV timings ioctls on subdev nodes
  2014-03-10 23:15 ` [PATCH v2 26/48] v4l: Add support for DV timings ioctls on subdev nodes Laurent Pinchart
@ 2014-03-11 10:38   ` Hans Verkuil
  2014-03-11 11:02     ` Laurent Pinchart
  2014-03-11 15:09   ` [PATCH v3 " Laurent Pinchart
  1 sibling, 1 reply; 93+ messages in thread
From: Hans Verkuil @ 2014-03-11 10:38 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 03/11/14 00:15, Laurent Pinchart wrote:
> Validate the pad field in the core code whenever specified.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  .../DocBook/media/v4l/vidioc-dv-timings-cap.xml    | 27 +++++++++++++++----
>  .../DocBook/media/v4l/vidioc-enum-dv-timings.xml   | 30 +++++++++++++++++-----
>  drivers/media/v4l2-core/v4l2-subdev.c              | 27 +++++++++++++++++++
>  include/uapi/linux/v4l2-subdev.h                   |  5 ++++
>  4 files changed, 77 insertions(+), 12 deletions(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
> index cd7720d..28a8c1e 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
> @@ -1,11 +1,12 @@
>  <refentry id="vidioc-dv-timings-cap">
>    <refmeta>
> -    <refentrytitle>ioctl VIDIOC_DV_TIMINGS_CAP</refentrytitle>
> +    <refentrytitle>ioctl VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</refentrytitle>
>      &manvol;
>    </refmeta>
>  
>    <refnamediv>
>      <refname>VIDIOC_DV_TIMINGS_CAP</refname>
> +    <refname>VIDIOC_SUBDEV_DV_TIMINGS_CAP</refname>
>      <refpurpose>The capabilities of the Digital Video receiver/transmitter</refpurpose>
>    </refnamediv>
>  
> @@ -33,7 +34,7 @@
>        <varlistentry>
>  	<term><parameter>request</parameter></term>
>  	<listitem>
> -	  <para>VIDIOC_DV_TIMINGS_CAP</para>
> +	  <para>VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</para>
>  	</listitem>
>        </varlistentry>
>        <varlistentry>
> @@ -54,10 +55,19 @@
>        interface and may change in the future.</para>
>      </note>
>  
> -    <para>To query the capabilities of the DV receiver/transmitter applications can call
> -this ioctl and the driver will fill in the structure. Note that drivers may return
> +    <para>To query the capabilities of the DV receiver/transmitter applications
> +can call the <constant>VIDIOC_DV_TIMINGS_CAP</constant> ioctl on a video node
> +and the driver will fill in the structure. Note that drivers may return
>  different values after switching the video input or output.</para>
>  
> +    <para>When implemented by the driver DV capabilities of subdevices can be
> +queried by calling the <constant>VIDIOC_SUBDEV_DV_TIMINGS_CAP</constant> ioctl
> +directly on a subdevice node. The capabilities are specific to inputs (for DV
> +receivers) or outputs (for DV transmitters), applications must specify the
> +desired pad number in the &v4l2-dv-timings-cap; <structfield>pad</structfield>
> +field. Attempts to query capabilities on a pad that doesn't support them will
> +return an &EINVAL;.</para>
> +
>      <table pgwide="1" frame="none" id="v4l2-bt-timings-cap">
>        <title>struct <structname>v4l2_bt_timings_cap</structname></title>
>        <tgroup cols="3">
> @@ -127,7 +137,14 @@ different values after switching the video input or output.</para>
>  	  </row>
>  	  <row>
>  	    <entry>__u32</entry>
> -	    <entry><structfield>reserved</structfield>[3]</entry>
> +	    <entry><structfield>pad</structfield></entry>
> +	    <entry>Pad number as reported by the media controller API. This field
> +	    is only used when operating on a subdevice node. When operating on a
> +	    video node applications must set this field to zero.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>reserved</structfield>[2]</entry>
>  	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
>  	  </row>
>  	  <row>
> diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
> index b3e17c1..b9fdfea 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
> @@ -1,11 +1,12 @@
>  <refentry id="vidioc-enum-dv-timings">
>    <refmeta>
> -    <refentrytitle>ioctl VIDIOC_ENUM_DV_TIMINGS</refentrytitle>
> +    <refentrytitle>ioctl VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refentrytitle>
>      &manvol;
>    </refmeta>
>  
>    <refnamediv>
>      <refname>VIDIOC_ENUM_DV_TIMINGS</refname>
> +    <refname>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refname>
>      <refpurpose>Enumerate supported Digital Video timings</refpurpose>
>    </refnamediv>
>  
> @@ -33,7 +34,7 @@
>        <varlistentry>
>  	<term><parameter>request</parameter></term>
>  	<listitem>
> -	  <para>VIDIOC_ENUM_DV_TIMINGS</para>
> +	  <para>VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</para>
>  	</listitem>
>        </varlistentry>
>        <varlistentry>
> @@ -61,14 +62,21 @@ standards or even custom timings that are not in this list.</para>
>  
>      <para>To query the available timings, applications initialize the
>  <structfield>index</structfield> field and zero the reserved array of &v4l2-enum-dv-timings;
> -and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl with a pointer to this
> -structure. Drivers fill the rest of the structure or return an
> +and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl on a video node with a
> +pointer to this structure. Drivers fill the rest of the structure or return an
>  &EINVAL; when the index is out of bounds. To enumerate all supported DV timings,
>  applications shall begin at index zero, incrementing by one until the
>  driver returns <errorcode>EINVAL</errorcode>. Note that drivers may enumerate a
>  different set of DV timings after switching the video input or
>  output.</para>
>  
> +    <para>When implemented by the driver DV timings of subdevices can be queried
> +by calling the <constant>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</constant> ioctl directly
> +on a subdevice node. The DV timings are specific to inputs (for DV receivers) or
> +outputs (for DV transmitters), applications must specify the desired pad number
> +in the &v4l2-enum-dv-timings; <structfield>pad</structfield> field. Attempts to
> +enumerate timings on a pad that doesn't support them will return an &EINVAL;.</para>
> +
>      <table pgwide="1" frame="none" id="v4l2-enum-dv-timings">
>        <title>struct <structname>v4l2_enum_dv_timings</structname></title>
>        <tgroup cols="3">
> @@ -82,8 +90,16 @@ application.</entry>
>  	  </row>
>  	  <row>
>  	    <entry>__u32</entry>
> -	    <entry><structfield>reserved</structfield>[3]</entry>
> -	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
> +	    <entry><structfield>pad</structfield></entry>
> +	    <entry>Pad number as reported by the media controller API. This field
> +	    is only used when operating on a subdevice node. When operating on a
> +	    video node applications must set this field to zero.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>reserved</structfield>[2]</entry>
> +	    <entry>Reserved for future extensions. Drivers and applications must
> +	    set the array to zero.</entry>
>  	  </row>
>  	  <row>
>  	    <entry>&v4l2-dv-timings;</entry>
> @@ -103,7 +119,7 @@ application.</entry>
>  	<term><errorcode>EINVAL</errorcode></term>
>  	<listitem>
>  	  <para>The &v4l2-enum-dv-timings; <structfield>index</structfield>
> -is out of bounds.</para>
> +is out of bounds or the <structfield>pad</structfield> number is invalid.</para>
>  	</listitem>
>        </varlistentry>
>        <varlistentry>
> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
> index 60d2550..853fb84 100644
> --- a/drivers/media/v4l2-core/v4l2-subdev.c
> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> @@ -354,6 +354,33 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
>  
>  	case VIDIOC_SUBDEV_S_EDID:
>  		return v4l2_subdev_call(sd, pad, set_edid, arg);
> +
> +	case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
> +		struct v4l2_dv_timings_cap *cap = arg;
> +
> +		if (cap->pad >= sd->entity.num_pads)
> +			return -EINVAL;
> +
> +		return v4l2_subdev_call(sd, pad, dv_timings_cap, cap);
> +	}
> +
> +	case VIDIOC_SUBDEV_ENUM_DV_TIMINGS: {
> +		struct v4l2_enum_dv_timings *dvt = arg;
> +
> +		if (dvt->pad >= sd->entity.num_pads)
> +			return -EINVAL;
> +
> +		return v4l2_subdev_call(sd, pad, enum_dv_timings, dvt);
> +	}
> +
> +	case VIDIOC_SUBDEV_QUERY_DV_TIMINGS:
> +		return v4l2_subdev_call(sd, video, query_dv_timings, arg);
> +
> +	case VIDIOC_SUBDEV_G_DV_TIMINGS:
> +		return v4l2_subdev_call(sd, video, g_dv_timings, arg);
> +
> +	case VIDIOC_SUBDEV_S_DV_TIMINGS:
> +		return v4l2_subdev_call(sd, video, s_dv_timings, arg);
>  #endif
>  	default:
>  		return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
> diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
> index 9fe3493..6f5c5de 100644
> --- a/include/uapi/linux/v4l2-subdev.h
> +++ b/include/uapi/linux/v4l2-subdev.h
> @@ -169,5 +169,10 @@ struct v4l2_subdev_edid {
>  #define VIDIOC_SUBDEV_S_SELECTION		_IOWR('V', 62, struct v4l2_subdev_selection)
>  #define VIDIOC_SUBDEV_G_EDID			_IOWR('V', 40, struct v4l2_subdev_edid)
>  #define VIDIOC_SUBDEV_S_EDID			_IOWR('V', 41, struct v4l2_subdev_edid)
> +#define VIDIOC_SUBDEV_DV_TIMINGS_CAP		_IOWR('V', 42, struct v4l2_dv_timings_cap)
> +#define VIDIOC_SUBDEV_ENUM_DV_TIMINGS		_IOWR('V', 43, struct v4l2_enum_dv_timings)
> +#define VIDIOC_SUBDEV_QUERY_DV_TIMINGS		_IOR('V', 44, struct v4l2_dv_timings)
> +#define VIDIOC_SUBDEV_G_DV_TIMINGS		_IOWR('V', 45, struct v4l2_dv_timings)
> +#define VIDIOC_SUBDEV_S_DV_TIMINGS		_IOWR('V', 46, struct v4l2_dv_timings)

Is there a reason for not using the same ioctls numbers as in videodev2.h? The
advantage is that the core compat32 support will automatically work (it doesn't
have to do anything yet, but that might change in the future).

Unless there is a really good reason I would keep them the same, just as we did
with the EDID ioctls.

Regards,

	Hans

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

* Re: [PATCH v2 27/48] v4l: Validate fields in the core code for subdev EDID ioctls
  2014-03-10 23:15 ` [PATCH v2 27/48] v4l: Validate fields in the core code for subdev EDID ioctls Laurent Pinchart
  2014-03-11  8:57   ` Sakari Ailus
@ 2014-03-11 10:45   ` Hans Verkuil
  2014-03-11 10:57     ` Laurent Pinchart
  2014-03-11 15:09   ` [PATCH v3 " Laurent Pinchart
  2 siblings, 1 reply; 93+ messages in thread
From: Hans Verkuil @ 2014-03-11 10:45 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 03/11/14 00:15, Laurent Pinchart wrote:
> The subdev EDID ioctls receive a pad field that must reference an
> existing pad and an EDID field that must point to a buffer. Validate
> both fields in the core code instead of duplicating validation in all
> drivers.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/ad9389b.c           |  2 --
>  drivers/media/i2c/adv7511.c           |  2 --
>  drivers/media/i2c/adv7604.c           |  4 ----
>  drivers/media/i2c/adv7842.c           |  4 ----
>  drivers/media/v4l2-core/v4l2-subdev.c | 24 ++++++++++++++++++++----
>  5 files changed, 20 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
> index 4cdff9e..5b78828 100644
> --- a/drivers/media/i2c/ad9389b.c
> +++ b/drivers/media/i2c/ad9389b.c
> @@ -683,8 +683,6 @@ static int ad9389b_get_edid(struct v4l2_subdev *sd,
>  		return -EINVAL;
>  	if (edid->blocks == 0 || edid->blocks > 256)
>  		return -EINVAL;
> -	if (!edid->edid)
> -		return -EINVAL;
>  	if (!state->edid.segments) {
>  		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
>  		return -ENODATA;
> diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
> index de7ddf5..ff1c2cd 100644
> --- a/drivers/media/i2c/adv7511.c
> +++ b/drivers/media/i2c/adv7511.c
> @@ -784,8 +784,6 @@ static int adv7511_get_edid(struct v4l2_subdev *sd,
>  		return -EINVAL;
>  	if ((edid->blocks == 0) || (edid->blocks > 256))
>  		return -EINVAL;
> -	if (!edid->edid)
> -		return -EINVAL;
>  	if (!state->edid.segments) {
>  		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
>  		return -ENODATA;
> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> index 71c8570..de3db42 100644
> --- a/drivers/media/i2c/adv7604.c
> +++ b/drivers/media/i2c/adv7604.c
> @@ -1673,8 +1673,6 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
>  		return -EINVAL;
>  	if (edid->start_block == 1)
>  		edid->blocks = 1;
> -	if (!edid->edid)
> -		return -EINVAL;
>  
>  	if (edid->blocks > state->edid.blocks)
>  		edid->blocks = state->edid.blocks;
> @@ -1761,8 +1759,6 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
>  		edid->blocks = 2;
>  		return -E2BIG;
>  	}
> -	if (!edid->edid)
> -		return -EINVAL;
>  
>  	v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n",
>  			__func__, edid->pad, state->edid.present);
> diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
> index 7fd9325..33558c8 100644
> --- a/drivers/media/i2c/adv7842.c
> +++ b/drivers/media/i2c/adv7842.c
> @@ -2035,8 +2035,6 @@ static int adv7842_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
>  		return -EINVAL;
>  	if (edid->start_block == 1)
>  		edid->blocks = 1;
> -	if (!edid->edid)
> -		return -EINVAL;
>  
>  	switch (edid->pad) {
>  	case ADV7842_EDID_PORT_A:
> @@ -2071,8 +2069,6 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *e)
>  		return -EINVAL;
>  	if (e->blocks > 2)
>  		return -E2BIG;
> -	if (!e->edid)
> -		return -EINVAL;
>  
>  	/* todo, per edid */
>  	state->aspect_ratio = v4l2_calc_aspect_ratio(e->edid[0x15],
> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
> index 853fb84..9fff1eb 100644
> --- a/drivers/media/v4l2-core/v4l2-subdev.c
> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> @@ -349,11 +349,27 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
>  			sd, pad, set_selection, subdev_fh, sel);
>  	}
>  
> -	case VIDIOC_SUBDEV_G_EDID:
> -		return v4l2_subdev_call(sd, pad, get_edid, arg);
> +	case VIDIOC_SUBDEV_G_EDID: {
> +		struct v4l2_subdev_edid *edid = arg;
>  
> -	case VIDIOC_SUBDEV_S_EDID:
> -		return v4l2_subdev_call(sd, pad, set_edid, arg);
> +		if (edid->pad >= sd->entity.num_pads)
> +			return -EINVAL;
> +		if (edid->edid == NULL)
> +			return -EINVAL;
> +
> +		return v4l2_subdev_call(sd, pad, get_edid, edid);
> +	}
> +
> +	case VIDIOC_SUBDEV_S_EDID: {
> +		struct v4l2_subdev_edid *edid = arg;
> +
> +		if (edid->pad >= sd->entity.num_pads)
> +			return -EINVAL;
> +		if (edid->edid == NULL)
> +			return -EINVAL;

If edid->blocks == 0, then edid->edid may be NULL. So this should
read:

	if (edid->blocks && edid->edid == NULL)

This is true for both G and S_EDID ioctls.

Regards,

	Hans

> +
> +		return v4l2_subdev_call(sd, pad, set_edid, edid);
> +	}
>  
>  	case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
>  		struct v4l2_dv_timings_cap *cap = arg;
> 


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

* Re: [PATCH v2 27/48] v4l: Validate fields in the core code for subdev EDID ioctls
  2014-03-11 10:45   ` Hans Verkuil
@ 2014-03-11 10:57     ` Laurent Pinchart
  2014-03-11 10:59       ` Hans Verkuil
  0 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-11 10:57 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Hans,

On Tuesday 11 March 2014 11:45:09 Hans Verkuil wrote:
> On 03/11/14 00:15, Laurent Pinchart wrote:
> > The subdev EDID ioctls receive a pad field that must reference an
> > existing pad and an EDID field that must point to a buffer. Validate
> > both fields in the core code instead of duplicating validation in all
> > drivers.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  drivers/media/i2c/ad9389b.c           |  2 --
> >  drivers/media/i2c/adv7511.c           |  2 --
> >  drivers/media/i2c/adv7604.c           |  4 ----
> >  drivers/media/i2c/adv7842.c           |  4 ----
> >  drivers/media/v4l2-core/v4l2-subdev.c | 24 ++++++++++++++++++++----
> >  5 files changed, 20 insertions(+), 16 deletions(-)

[snip]

> > diff --git a/drivers/media/v4l2-core/v4l2-subdev.c
> > b/drivers/media/v4l2-core/v4l2-subdev.c index 853fb84..9fff1eb 100644
> > --- a/drivers/media/v4l2-core/v4l2-subdev.c
> > +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> > @@ -349,11 +349,27 @@ static long subdev_do_ioctl(struct file *file,
> > unsigned int cmd, void *arg)> 
> >  			sd, pad, set_selection, subdev_fh, sel);
> >  	}
> > 
> > -	case VIDIOC_SUBDEV_G_EDID:
> > -		return v4l2_subdev_call(sd, pad, get_edid, arg);
> > +	case VIDIOC_SUBDEV_G_EDID: {
> > +		struct v4l2_subdev_edid *edid = arg;
> > 
> > -	case VIDIOC_SUBDEV_S_EDID:
> > -		return v4l2_subdev_call(sd, pad, set_edid, arg);
> > +		if (edid->pad >= sd->entity.num_pads)
> > +			return -EINVAL;
> > +		if (edid->edid == NULL)
> > +			return -EINVAL;
> > +
> > +		return v4l2_subdev_call(sd, pad, get_edid, edid);
> > +	}
> > +
> > +	case VIDIOC_SUBDEV_S_EDID: {
> > +		struct v4l2_subdev_edid *edid = arg;
> > +
> > +		if (edid->pad >= sd->entity.num_pads)
> > +			return -EINVAL;
> > +		if (edid->edid == NULL)
> > +			return -EINVAL;
> 
> If edid->blocks == 0, then edid->edid may be NULL. So this should
> read:
> 
> 	if (edid->blocks && edid->edid == NULL)

OK, I'll fix that.

> This is true for both G and S_EDID ioctls.

What's the point of G_EDID with blocks == 0 ? Testing whether the ioctl is 
supported ?

> > +
> > +		return v4l2_subdev_call(sd, pad, set_edid, edid);
> > +	}
> > 
> >  	case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
> >  		struct v4l2_dv_timings_cap *cap = arg;

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH v2 27/48] v4l: Validate fields in the core code for subdev EDID ioctls
  2014-03-11 10:57     ` Laurent Pinchart
@ 2014-03-11 10:59       ` Hans Verkuil
  0 siblings, 0 replies; 93+ messages in thread
From: Hans Verkuil @ 2014-03-11 10:59 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans Verkuil, linux-media, Hans Verkuil, Lars-Peter Clausen



On 03/11/14 11:57, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Tuesday 11 March 2014 11:45:09 Hans Verkuil wrote:
>> On 03/11/14 00:15, Laurent Pinchart wrote:
>>> The subdev EDID ioctls receive a pad field that must reference an
>>> existing pad and an EDID field that must point to a buffer. Validate
>>> both fields in the core code instead of duplicating validation in all
>>> drivers.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> ---
>>>
>>>  drivers/media/i2c/ad9389b.c           |  2 --
>>>  drivers/media/i2c/adv7511.c           |  2 --
>>>  drivers/media/i2c/adv7604.c           |  4 ----
>>>  drivers/media/i2c/adv7842.c           |  4 ----
>>>  drivers/media/v4l2-core/v4l2-subdev.c | 24 ++++++++++++++++++++----
>>>  5 files changed, 20 insertions(+), 16 deletions(-)
> 
> [snip]
> 
>>> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c
>>> b/drivers/media/v4l2-core/v4l2-subdev.c index 853fb84..9fff1eb 100644
>>> --- a/drivers/media/v4l2-core/v4l2-subdev.c
>>> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
>>> @@ -349,11 +349,27 @@ static long subdev_do_ioctl(struct file *file,
>>> unsigned int cmd, void *arg)> 
>>>  			sd, pad, set_selection, subdev_fh, sel);
>>>  	}
>>>
>>> -	case VIDIOC_SUBDEV_G_EDID:
>>> -		return v4l2_subdev_call(sd, pad, get_edid, arg);
>>> +	case VIDIOC_SUBDEV_G_EDID: {
>>> +		struct v4l2_subdev_edid *edid = arg;
>>>
>>> -	case VIDIOC_SUBDEV_S_EDID:
>>> -		return v4l2_subdev_call(sd, pad, set_edid, arg);
>>> +		if (edid->pad >= sd->entity.num_pads)
>>> +			return -EINVAL;
>>> +		if (edid->edid == NULL)
>>> +			return -EINVAL;
>>> +
>>> +		return v4l2_subdev_call(sd, pad, get_edid, edid);
>>> +	}
>>> +
>>> +	case VIDIOC_SUBDEV_S_EDID: {
>>> +		struct v4l2_subdev_edid *edid = arg;
>>> +
>>> +		if (edid->pad >= sd->entity.num_pads)
>>> +			return -EINVAL;
>>> +		if (edid->edid == NULL)
>>> +			return -EINVAL;
>>
>> If edid->blocks == 0, then edid->edid may be NULL. So this should
>> read:
>>
>> 	if (edid->blocks && edid->edid == NULL)
> 
> OK, I'll fix that.
> 
>> This is true for both G and S_EDID ioctls.
> 
> What's the point of G_EDID with blocks == 0 ? Testing whether the ioctl is 
> supported ?

Now that you mention it, yes, that would be a good use :-)

But I was thinking that you can call it once with blocks == 0, then the
driver will fill in the real number of blocks and you can use that to
size the edid array correctly.

Regards,

	Hans

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

* Re: [PATCH v2 26/48] v4l: Add support for DV timings ioctls on subdev nodes
  2014-03-11 10:38   ` Hans Verkuil
@ 2014-03-11 11:02     ` Laurent Pinchart
  0 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-11 11:02 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Hans,

On Tuesday 11 March 2014 11:38:39 Hans Verkuil wrote:
> On 03/11/14 00:15, Laurent Pinchart wrote:
> > Validate the pad field in the core code whenever specified.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  .../DocBook/media/v4l/vidioc-dv-timings-cap.xml    | 27 +++++++++++++----
> >  .../DocBook/media/v4l/vidioc-enum-dv-timings.xml   | 30 +++++++++++++----
> >  drivers/media/v4l2-core/v4l2-subdev.c              | 27 +++++++++++++++++
> >  include/uapi/linux/v4l2-subdev.h                   |  5 ++++
> >  4 files changed, 77 insertions(+), 12 deletions(-)

[snip]

> > diff --git a/include/uapi/linux/v4l2-subdev.h
> > b/include/uapi/linux/v4l2-subdev.h index 9fe3493..6f5c5de 100644
> > --- a/include/uapi/linux/v4l2-subdev.h
> > +++ b/include/uapi/linux/v4l2-subdev.h
> > @@ -169,5 +169,10 @@ struct v4l2_subdev_edid {
> > 
> >  #define VIDIOC_SUBDEV_S_SELECTION		_IOWR('V', 62, struct
> > v4l2_subdev_selection)
> >  #define VIDIOC_SUBDEV_G_EDID			_IOWR('V', 40, struct
> > v4l2_subdev_edid)
> >  #define VIDIOC_SUBDEV_S_EDID			_IOWR('V', 41, struct
> > v4l2_subdev_edid)
> > +#define VIDIOC_SUBDEV_DV_TIMINGS_CAP		_IOWR('V', 42, struct
> > v4l2_dv_timings_cap)
> > +#define VIDIOC_SUBDEV_ENUM_DV_TIMINGS		_IOWR('V', 43, struct
> > v4l2_enum_dv_timings)
> > +#define VIDIOC_SUBDEV_QUERY_DV_TIMINGS		_IOR('V', 44, struct
> > v4l2_dv_timings)
> > +#define VIDIOC_SUBDEV_G_DV_TIMINGS		_IOWR('V', 45, struct
> > v4l2_dv_timings)
> > +#define VIDIOC_SUBDEV_S_DV_TIMINGS		_IOWR('V', 46, struct
> > v4l2_dv_timings)
>
> Is there a reason for not using the same ioctls numbers as in videodev2.h?
> The advantage is that the core compat32 support will automatically work (it
> doesn't have to do anything yet, but that might change in the future).
> 
> Unless there is a really good reason I would keep them the same, just as we
> did with the EDID ioctls.

I'll fix that.

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH v2 00/48] ADV7611 support
  2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
                   ` (47 preceding siblings ...)
  2014-03-10 23:15 ` [PATCH v2 48/48] adv7604: Add endpoint properties to DT bindings Laurent Pinchart
@ 2014-03-11 11:58 ` Hans Verkuil
  48 siblings, 0 replies; 93+ messages in thread
From: Hans Verkuil @ 2014-03-11 11:58 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Hans Verkuil, Lars-Peter Clausen, Kyungmin Park,
	Tomasz Stanislawski, Scott Jiang, Prabhakar Lad

Hi Laurent,

You can add my:

Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

for patches 28-35, 37-45 and 47.

For patches 46 and 48 (DT related) add my:

Acked-by: Hans Verkuil <hans.verkuil@cisco.com>

For patches 26 and 27 I posted review comments, and patch 36 is removing
support for the op_ch_sel field which I really need on my system. So that
needs to be resolved.

I've tested the whole lot (with an ugly workaround for patch 36) on my
hardware successfully.

Regards,

	Hans

On 03/11/14 00:15, Laurent Pinchart wrote:
> Hello,
> 
> This patch set implements support for the ADV7611 in the adv7604 driver. It
> also comes up with new features such as output format configuration through
> pad format operations, hot-plug detect control through GPIO and DT support.
> 
> Patches 06/48 to 24/48 and 39/48 replace the subdev video DV timings query cap
> and enum operations with pad-level equivalents. I've split driver changes in
> one patch per driver to make review easier, but I can squash them together if
> desired.
> 
> I believe I've addressed all comments received on v1, except the one related
> to op_ch_sel in patch "adv7604: Make output format configurable through pad
> format operations" which is still open for discussion.
> 
> Patches 02/48 to 05/48 have been acked in v1 already, I will send a pull
> request for them separately if a v3 of this series ends up being needed. I'd
> like to get patch 01/48 upstream soon as well.
> 
> Changes compared to v1:
> 
> - Check the edid and pad fields for various ioctls in the subdev core
> - Switch to the descriptor-based GPIO API
> - Leave enum adv7604_pad in header file
> - Keep the hotplug notifier
> - Fix compilation breakage when !CONFIG_OF due to directly dereferencing the
>   return value of of_match_node()
> - Move patch "v4l: subdev: Remove deprecated video-level DV timings
>   operations" later in the series to avoid bisection breakages
> - Document struct v4l2_enum_dv_timings reserved field as being set to 0 by
>   both drivers and application
> - Document pad field of struct v4l2_enum_dv_timings and struct
>   v4l2_dv_timings_cap as being used for subdev nodes only
> - Typo fixes in documentation
> 
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Cc: Scott Jiang <scott.jiang.linux@gmail.com>
> Cc: Prabhakar Lad <prabhakar.csengg@gmail.com>
> 
> Lars-Peter Clausen (4):
>   adv7604: Add missing include to linux/types.h
>   adv7604: Add support for asynchronous probing
>   adv7604: Don't put info string arrays on the stack
>   adv7604: Add adv7611 support
> 
> Laurent Pinchart (44):
>   v4l: of: Support empty port nodes
>   v4l: Add UYVY10_2X10 and VYUY10_2X10 media bus pixel codes
>   v4l: Add UYVY10_1X20 and VYUY10_1X20 media bus pixel codes
>   v4l: Add 12-bit YUV 4:2:0 media bus pixel codes
>   v4l: Add 12-bit YUV 4:2:2 media bus pixel codes
>   v4l: Add pad-level DV timings subdev operations
>   ad9389b: Add pad-level DV timings operations
>   adv7511: Add pad-level DV timings operations
>   adv7842: Add pad-level DV timings operations
>   s5p-tv: hdmi: Add pad-level DV timings operations
>   s5p-tv: hdmiphy: Add pad-level DV timings operations
>   ths8200: Add pad-level DV timings operations
>   tvp7002: Add pad-level DV timings operations
>   media: bfin_capture: Switch to pad-level DV operations
>   media: davinci: vpif: Switch to pad-level DV operations
>   media: staging: davinci: vpfe: Switch to pad-level DV operations
>   s5p-tv: mixer: Switch to pad-level DV operations
>   ad9389b: Remove deprecated video-level DV timings operations
>   adv7511: Remove deprecated video-level DV timings operations
>   adv7842: Remove deprecated video-level DV timings operations
>   s5p-tv: hdmi: Remove deprecated video-level DV timings operations
>   s5p-tv: hdmiphy: Remove deprecated video-level DV timings operation
>   ths8200: Remove deprecated video-level DV timings operations
>   tvp7002: Remove deprecated video-level DV timings operations
>   v4l: Improve readability by not wrapping ioctl number #define's
>   v4l: Add support for DV timings ioctls on subdev nodes
>   v4l: Validate fields in the core code for subdev EDID ioctls
>   adv7604: Add 16-bit read functions for CP and HDMI
>   adv7604: Cache register contents when reading multiple bits
>   adv7604: Remove subdev control handlers
>   adv7604: Add sink pads
>   adv7604: Make output format configurable through pad format operations
>   adv7604: Add pad-level DV timings support
>   adv7604: Remove deprecated video-level DV timings operations
>   v4l: subdev: Remove deprecated video-level DV timings operations
>   adv7604: Inline the to_sd function
>   adv7604: Store I2C addresses and clients in arrays
>   adv7604: Replace *_and_or() functions with *_clr_set()
>   adv7604: Sort headers alphabetically
>   adv7604: Support hot-plug detect control through a GPIO
>   adv7604: Specify the default input through platform data
>   adv7604: Add DT support
>   adv7604: Add LLC polarity configuration
>   adv7604: Add endpoint properties to DT bindings
> 
>  Documentation/DocBook/media/v4l/subdev-formats.xml |  760 +++++++++++
>  .../DocBook/media/v4l/vidioc-dv-timings-cap.xml    |   27 +-
>  .../DocBook/media/v4l/vidioc-enum-dv-timings.xml   |   30 +-
>  .../devicetree/bindings/media/i2c/adv7604.txt      |   69 +
>  drivers/media/i2c/ad9389b.c                        |   65 +-
>  drivers/media/i2c/adv7511.c                        |   67 +-
>  drivers/media/i2c/adv7604.c                        | 1440 ++++++++++++++------
>  drivers/media/i2c/adv7842.c                        |   14 +-
>  drivers/media/i2c/ths8200.c                        |   10 +
>  drivers/media/i2c/tvp7002.c                        |    5 +-
>  drivers/media/platform/blackfin/bfin_capture.c     |    4 +-
>  drivers/media/platform/davinci/vpif_capture.c      |    4 +-
>  drivers/media/platform/davinci/vpif_display.c      |    4 +-
>  drivers/media/platform/s5p-tv/hdmi_drv.c           |   14 +-
>  drivers/media/platform/s5p-tv/hdmiphy_drv.c        |    9 +-
>  drivers/media/platform/s5p-tv/mixer_video.c        |    8 +-
>  drivers/media/v4l2-core/v4l2-of.c                  |   52 +-
>  drivers/media/v4l2-core/v4l2-subdev.c              |   51 +-
>  drivers/staging/media/davinci_vpfe/vpfe_video.c    |    4 +-
>  include/media/adv7604.h                            |  113 +-
>  include/media/v4l2-subdev.h                        |    8 +-
>  include/uapi/linux/v4l2-mediabus.h                 |   14 +-
>  include/uapi/linux/v4l2-subdev.h                   |   38 +-
>  include/uapi/linux/videodev2.h                     |   10 +-
>  24 files changed, 2174 insertions(+), 646 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/media/i2c/adv7604.txt
> 


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

* Re: [PATCH v2 01/48] v4l: of: Support empty port nodes
  2014-03-10 23:15 ` [PATCH v2 01/48] v4l: of: Support empty port nodes Laurent Pinchart
@ 2014-03-11 12:05   ` Sylwester Nawrocki
  0 siblings, 0 replies; 93+ messages in thread
From: Sylwester Nawrocki @ 2014-03-11 12:05 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Hi Laurent,

On 11/03/14 00:15, Laurent Pinchart wrote:
> Empty port nodes are allowed but currently unsupported as the
> v4l2_of_get_next_endpoint() function assumes that all port nodes have at
> least an endpoint. Fix this.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

> ---
>  drivers/media/v4l2-core/v4l2-of.c | 52 +++++++++++++++++++++------------------
>  1 file changed, 28 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c
> index 42e3e8a..4c07343 100644
> --- a/drivers/media/v4l2-core/v4l2-of.c
> +++ b/drivers/media/v4l2-core/v4l2-of.c
> @@ -166,43 +166,51 @@ struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent,
>  					struct device_node *prev)
>  {
>  	struct device_node *endpoint;
> -	struct device_node *port = NULL;
> +	struct device_node *port;
>  
>  	if (!parent)
>  		return NULL;
>  
> +	/*
> +	 * Start by locating the port node. If no previous endpoint is specified
> +	 * search for the first port node, otherwise get the previous endpoint
> +	 * parent port node.
> +	 */
>  	if (!prev) {
>  		struct device_node *node;
> -		/*
> -		 * It's the first call, we have to find a port subnode
> -		 * within this node or within an optional 'ports' node.
> -		 */
> +
>  		node = of_get_child_by_name(parent, "ports");
>  		if (node)
>  			parent = node;
>  
>  		port = of_get_child_by_name(parent, "port");
> +		of_node_put(node);
>  
> -		if (port) {
> -			/* Found a port, get an endpoint. */
> -			endpoint = of_get_next_child(port, NULL);
> -			of_node_put(port);
> -		} else {
> -			endpoint = NULL;
> -		}
> -
> -		if (!endpoint)
> -			pr_err("%s(): no endpoint nodes specified for %s\n",
> +		if (!port) {
> +			pr_err("%s(): no port node found in %s\n",
>  			       __func__, parent->full_name);
> -		of_node_put(node);
> +			return NULL;
> +		}
>  	} else {
>  		port = of_get_parent(prev);
> -		if (!port)
> +		if (!port) {
>  			/* Hm, has someone given us the root node ?... */
>  			return NULL;
> +		}
>  
> -		/* Avoid dropping prev node refcount to 0. */
> +		/*
> +		 * Avoid dropping prev node refcount to 0 when getting the next
> +		 * child below.
> +		 */
>  		of_node_get(prev);
> +	}
> +
> +	while (1) {
> +		/*
> +		 * Now that we have a port node, get the next endpoint by
> +		 * getting the next child. If the previous endpoint is NULL this
> +		 * will return the first child.
> +		 */
>  		endpoint = of_get_next_child(port, prev);
>  		if (endpoint) {
>  			of_node_put(port);
> @@ -210,18 +218,14 @@ struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent,
>  		}
>  
>  		/* No more endpoints under this port, try the next one. */
> +		prev = NULL;
> +
>  		do {
>  			port = of_get_next_child(parent, port);
>  			if (!port)
>  				return NULL;
>  		} while (of_node_cmp(port->name, "port"));
> -
> -		/* Pick up the first endpoint in this port. */
> -		endpoint = of_get_next_child(port, NULL);
> -		of_node_put(port);
>  	}
> -
> -	return endpoint;
>  }
>  EXPORT_SYMBOL(v4l2_of_get_next_endpoint);
>  

-- 
Regards,
Sylwester

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

* [PATCH v3 26/48] v4l: Add support for DV timings ioctls on subdev nodes
  2014-03-10 23:15 ` [PATCH v2 26/48] v4l: Add support for DV timings ioctls on subdev nodes Laurent Pinchart
  2014-03-11 10:38   ` Hans Verkuil
@ 2014-03-11 15:09   ` Laurent Pinchart
  2014-03-11 15:33     ` Hans Verkuil
  1 sibling, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-11 15:09 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Validate the pad field in the core code whenever specified.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../DocBook/media/v4l/vidioc-dv-timings-cap.xml    | 27 +++++++++++++++----
 .../DocBook/media/v4l/vidioc-enum-dv-timings.xml   | 30 +++++++++++++++++-----
 drivers/media/v4l2-core/v4l2-subdev.c              | 27 +++++++++++++++++++
 include/uapi/linux/v4l2-subdev.h                   |  5 ++++
 4 files changed, 77 insertions(+), 12 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
index cd7720d..28a8c1e 100644
--- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
@@ -1,11 +1,12 @@
 <refentry id="vidioc-dv-timings-cap">
   <refmeta>
-    <refentrytitle>ioctl VIDIOC_DV_TIMINGS_CAP</refentrytitle>
+    <refentrytitle>ioctl VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</refentrytitle>
     &manvol;
   </refmeta>
 
   <refnamediv>
     <refname>VIDIOC_DV_TIMINGS_CAP</refname>
+    <refname>VIDIOC_SUBDEV_DV_TIMINGS_CAP</refname>
     <refpurpose>The capabilities of the Digital Video receiver/transmitter</refpurpose>
   </refnamediv>
 
@@ -33,7 +34,7 @@
       <varlistentry>
 	<term><parameter>request</parameter></term>
 	<listitem>
-	  <para>VIDIOC_DV_TIMINGS_CAP</para>
+	  <para>VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</para>
 	</listitem>
       </varlistentry>
       <varlistentry>
@@ -54,10 +55,19 @@
       interface and may change in the future.</para>
     </note>
 
-    <para>To query the capabilities of the DV receiver/transmitter applications can call
-this ioctl and the driver will fill in the structure. Note that drivers may return
+    <para>To query the capabilities of the DV receiver/transmitter applications
+can call the <constant>VIDIOC_DV_TIMINGS_CAP</constant> ioctl on a video node
+and the driver will fill in the structure. Note that drivers may return
 different values after switching the video input or output.</para>
 
+    <para>When implemented by the driver DV capabilities of subdevices can be
+queried by calling the <constant>VIDIOC_SUBDEV_DV_TIMINGS_CAP</constant> ioctl
+directly on a subdevice node. The capabilities are specific to inputs (for DV
+receivers) or outputs (for DV transmitters), applications must specify the
+desired pad number in the &v4l2-dv-timings-cap; <structfield>pad</structfield>
+field. Attempts to query capabilities on a pad that doesn't support them will
+return an &EINVAL;.</para>
+
     <table pgwide="1" frame="none" id="v4l2-bt-timings-cap">
       <title>struct <structname>v4l2_bt_timings_cap</structname></title>
       <tgroup cols="3">
@@ -127,7 +137,14 @@ different values after switching the video input or output.</para>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[3]</entry>
+	    <entry><structfield>pad</structfield></entry>
+	    <entry>Pad number as reported by the media controller API. This field
+	    is only used when operating on a subdevice node. When operating on a
+	    video node applications must set this field to zero.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[2]</entry>
 	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
 	  </row>
 	  <row>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
index b3e17c1..b9fdfea 100644
--- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
@@ -1,11 +1,12 @@
 <refentry id="vidioc-enum-dv-timings">
   <refmeta>
-    <refentrytitle>ioctl VIDIOC_ENUM_DV_TIMINGS</refentrytitle>
+    <refentrytitle>ioctl VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refentrytitle>
     &manvol;
   </refmeta>
 
   <refnamediv>
     <refname>VIDIOC_ENUM_DV_TIMINGS</refname>
+    <refname>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refname>
     <refpurpose>Enumerate supported Digital Video timings</refpurpose>
   </refnamediv>
 
@@ -33,7 +34,7 @@
       <varlistentry>
 	<term><parameter>request</parameter></term>
 	<listitem>
-	  <para>VIDIOC_ENUM_DV_TIMINGS</para>
+	  <para>VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</para>
 	</listitem>
       </varlistentry>
       <varlistentry>
@@ -61,14 +62,21 @@ standards or even custom timings that are not in this list.</para>
 
     <para>To query the available timings, applications initialize the
 <structfield>index</structfield> field and zero the reserved array of &v4l2-enum-dv-timings;
-and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl with a pointer to this
-structure. Drivers fill the rest of the structure or return an
+and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl on a video node with a
+pointer to this structure. Drivers fill the rest of the structure or return an
 &EINVAL; when the index is out of bounds. To enumerate all supported DV timings,
 applications shall begin at index zero, incrementing by one until the
 driver returns <errorcode>EINVAL</errorcode>. Note that drivers may enumerate a
 different set of DV timings after switching the video input or
 output.</para>
 
+    <para>When implemented by the driver DV timings of subdevices can be queried
+by calling the <constant>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</constant> ioctl directly
+on a subdevice node. The DV timings are specific to inputs (for DV receivers) or
+outputs (for DV transmitters), applications must specify the desired pad number
+in the &v4l2-enum-dv-timings; <structfield>pad</structfield> field. Attempts to
+enumerate timings on a pad that doesn't support them will return an &EINVAL;.</para>
+
     <table pgwide="1" frame="none" id="v4l2-enum-dv-timings">
       <title>struct <structname>v4l2_enum_dv_timings</structname></title>
       <tgroup cols="3">
@@ -82,8 +90,16 @@ application.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[3]</entry>
-	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
+	    <entry><structfield>pad</structfield></entry>
+	    <entry>Pad number as reported by the media controller API. This field
+	    is only used when operating on a subdevice node. When operating on a
+	    video node applications must set this field to zero.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[2]</entry>
+	    <entry>Reserved for future extensions. Drivers and applications must
+	    set the array to zero.</entry>
 	  </row>
 	  <row>
 	    <entry>&v4l2-dv-timings;</entry>
@@ -103,7 +119,7 @@ application.</entry>
 	<term><errorcode>EINVAL</errorcode></term>
 	<listitem>
 	  <para>The &v4l2-enum-dv-timings; <structfield>index</structfield>
-is out of bounds.</para>
+is out of bounds or the <structfield>pad</structfield> number is invalid.</para>
 	</listitem>
       </varlistentry>
       <varlistentry>
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 60d2550..853fb84 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -354,6 +354,33 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
 	case VIDIOC_SUBDEV_S_EDID:
 		return v4l2_subdev_call(sd, pad, set_edid, arg);
+
+	case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
+		struct v4l2_dv_timings_cap *cap = arg;
+
+		if (cap->pad >= sd->entity.num_pads)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, dv_timings_cap, cap);
+	}
+
+	case VIDIOC_SUBDEV_ENUM_DV_TIMINGS: {
+		struct v4l2_enum_dv_timings *dvt = arg;
+
+		if (dvt->pad >= sd->entity.num_pads)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, enum_dv_timings, dvt);
+	}
+
+	case VIDIOC_SUBDEV_QUERY_DV_TIMINGS:
+		return v4l2_subdev_call(sd, video, query_dv_timings, arg);
+
+	case VIDIOC_SUBDEV_G_DV_TIMINGS:
+		return v4l2_subdev_call(sd, video, g_dv_timings, arg);
+
+	case VIDIOC_SUBDEV_S_DV_TIMINGS:
+		return v4l2_subdev_call(sd, video, s_dv_timings, arg);
 #endif
 	default:
 		return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index 9fe3493..8dadb16 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/include/uapi/linux/v4l2-subdev.h
@@ -169,5 +169,10 @@ struct v4l2_subdev_edid {
 #define VIDIOC_SUBDEV_S_SELECTION		_IOWR('V', 62, struct v4l2_subdev_selection)
 #define VIDIOC_SUBDEV_G_EDID			_IOWR('V', 40, struct v4l2_subdev_edid)
 #define VIDIOC_SUBDEV_S_EDID			_IOWR('V', 41, struct v4l2_subdev_edid)
+#define VIDIOC_SUBDEV_S_DV_TIMINGS		_IOWR('V', 87, struct v4l2_dv_timings)
+#define VIDIOC_SUBDEV_G_DV_TIMINGS		_IOWR('V', 88, struct v4l2_dv_timings)
+#define VIDIOC_SUBDEV_ENUM_DV_TIMINGS		_IOWR('V', 98, struct v4l2_enum_dv_timings)
+#define VIDIOC_SUBDEV_QUERY_DV_TIMINGS		_IOR('V', 99, struct v4l2_dv_timings)
+#define VIDIOC_SUBDEV_DV_TIMINGS_CAP		_IOWR('V', 100, struct v4l2_dv_timings_cap)
 
 #endif
-- 
1.8.3.2


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

* [PATCH v3 27/48] v4l: Validate fields in the core code for subdev EDID ioctls
  2014-03-10 23:15 ` [PATCH v2 27/48] v4l: Validate fields in the core code for subdev EDID ioctls Laurent Pinchart
  2014-03-11  8:57   ` Sakari Ailus
  2014-03-11 10:45   ` Hans Verkuil
@ 2014-03-11 15:09   ` Laurent Pinchart
  2014-03-11 15:44     ` Hans Verkuil
  2 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-11 15:09 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The subdev EDID ioctls receive a pad field that must reference an
existing pad and an EDID field that must point to a buffer. Validate
both fields in the core code instead of duplicating validation in all
drivers.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/i2c/ad9389b.c           |  2 --
 drivers/media/i2c/adv7511.c           |  2 --
 drivers/media/i2c/adv7604.c           |  4 ----
 drivers/media/i2c/adv7842.c           |  4 ----
 drivers/media/v4l2-core/v4l2-subdev.c | 24 ++++++++++++++++++++----
 5 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
index 4cdff9e..5b78828 100644
--- a/drivers/media/i2c/ad9389b.c
+++ b/drivers/media/i2c/ad9389b.c
@@ -683,8 +683,6 @@ static int ad9389b_get_edid(struct v4l2_subdev *sd,
 		return -EINVAL;
 	if (edid->blocks == 0 || edid->blocks > 256)
 		return -EINVAL;
-	if (!edid->edid)
-		return -EINVAL;
 	if (!state->edid.segments) {
 		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
 		return -ENODATA;
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index de7ddf5..ff1c2cd 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -784,8 +784,6 @@ static int adv7511_get_edid(struct v4l2_subdev *sd,
 		return -EINVAL;
 	if ((edid->blocks == 0) || (edid->blocks > 256))
 		return -EINVAL;
-	if (!edid->edid)
-		return -EINVAL;
 	if (!state->edid.segments) {
 		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
 		return -ENODATA;
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 71c8570..de3db42 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1673,8 +1673,6 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 		return -EINVAL;
 	if (edid->start_block == 1)
 		edid->blocks = 1;
-	if (!edid->edid)
-		return -EINVAL;
 
 	if (edid->blocks > state->edid.blocks)
 		edid->blocks = state->edid.blocks;
@@ -1761,8 +1759,6 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 		edid->blocks = 2;
 		return -E2BIG;
 	}
-	if (!edid->edid)
-		return -EINVAL;
 
 	v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n",
 			__func__, edid->pad, state->edid.present);
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index a319275..3c5a7d9 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -2035,8 +2035,6 @@ static int adv7842_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 		return -EINVAL;
 	if (edid->start_block == 1)
 		edid->blocks = 1;
-	if (!edid->edid)
-		return -EINVAL;
 
 	switch (edid->pad) {
 	case ADV7842_EDID_PORT_A:
@@ -2071,8 +2069,6 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *e)
 		return -EINVAL;
 	if (e->blocks > 2)
 		return -E2BIG;
-	if (!e->edid)
-		return -EINVAL;
 
 	/* todo, per edid */
 	state->aspect_ratio = v4l2_calc_aspect_ratio(e->edid[0x15],
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 853fb84..f6185f9 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -349,11 +349,27 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 			sd, pad, set_selection, subdev_fh, sel);
 	}
 
-	case VIDIOC_SUBDEV_G_EDID:
-		return v4l2_subdev_call(sd, pad, get_edid, arg);
+	case VIDIOC_SUBDEV_G_EDID: {
+		struct v4l2_subdev_edid *edid = arg;
 
-	case VIDIOC_SUBDEV_S_EDID:
-		return v4l2_subdev_call(sd, pad, set_edid, arg);
+		if (edid->pad >= sd->entity.num_pads)
+			return -EINVAL;
+		if (edid->blocks && edid->edid == NULL)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, get_edid, edid);
+	}
+
+	case VIDIOC_SUBDEV_S_EDID: {
+		struct v4l2_subdev_edid *edid = arg;
+
+		if (edid->pad >= sd->entity.num_pads)
+			return -EINVAL;
+		if (edid->blocks && edid->edid == NULL)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, set_edid, edid);
+	}
 
 	case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
 		struct v4l2_dv_timings_cap *cap = arg;
-- 
1.8.3.2


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

* [PATCH v3 36/48] adv7604: Make output format configurable through pad format operations
  2014-03-10 23:15 ` [PATCH v2 36/48] adv7604: Make output format configurable through pad format operations Laurent Pinchart
@ 2014-03-11 15:10   ` Laurent Pinchart
  2014-03-13 21:45     ` Hans Verkuil
  2014-03-18  9:32     ` Hans Verkuil
  0 siblings, 2 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-11 15:10 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Replace the dummy video format operations by pad format operations that
configure the output format.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/i2c/adv7604.c | 280 ++++++++++++++++++++++++++++++++++++++++----
 include/media/adv7604.h     |  56 ++++-----
 2 files changed, 275 insertions(+), 61 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 851b350..5aa7c29 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -53,6 +53,28 @@ MODULE_LICENSE("GPL");
 /* ADV7604 system clock frequency */
 #define ADV7604_fsc (28636360)
 
+#define ADV7604_RGB_OUT					(1 << 1)
+
+#define ADV7604_OP_FORMAT_SEL_8BIT			(0 << 0)
+#define ADV7604_OP_FORMAT_SEL_10BIT			(1 << 0)
+#define ADV7604_OP_FORMAT_SEL_12BIT			(2 << 0)
+
+#define ADV7604_OP_MODE_SEL_SDR_422			(0 << 5)
+#define ADV7604_OP_MODE_SEL_DDR_422			(1 << 5)
+#define ADV7604_OP_MODE_SEL_SDR_444			(2 << 5)
+#define ADV7604_OP_MODE_SEL_DDR_444			(3 << 5)
+#define ADV7604_OP_MODE_SEL_SDR_422_2X			(4 << 5)
+#define ADV7604_OP_MODE_SEL_ADI_CM			(5 << 5)
+
+#define ADV7604_OP_CH_SEL_GBR				(0 << 5)
+#define ADV7604_OP_CH_SEL_GRB				(1 << 5)
+#define ADV7604_OP_CH_SEL_BGR				(2 << 5)
+#define ADV7604_OP_CH_SEL_RGB				(3 << 5)
+#define ADV7604_OP_CH_SEL_BRG				(4 << 5)
+#define ADV7604_OP_CH_SEL_RBG				(5 << 5)
+
+#define ADV7604_OP_SWAP_CB_CR				(1 << 0)
+
 enum adv7604_type {
 	ADV7604,
 	ADV7611,
@@ -63,6 +85,14 @@ struct adv7604_reg_seq {
 	u8 val;
 };
 
+struct adv7604_format_info {
+	enum v4l2_mbus_pixelcode code;
+	u8 op_ch_sel;
+	bool rgb_out;
+	bool swap_cb_cr;
+	u8 op_format_sel;
+};
+
 struct adv7604_chip_info {
 	enum adv7604_type type;
 
@@ -78,6 +108,9 @@ struct adv7604_chip_info {
 	unsigned int tdms_lock_mask;
 	unsigned int fmt_change_digital_mask;
 
+	const struct adv7604_format_info *formats;
+	unsigned int nformats;
+
 	void (*set_termination)(struct v4l2_subdev *sd, bool enable);
 	void (*setup_irqs)(struct v4l2_subdev *sd);
 	unsigned int (*read_hdmi_pixelclock)(struct v4l2_subdev *sd);
@@ -101,12 +134,18 @@ struct adv7604_chip_info {
 struct adv7604_state {
 	const struct adv7604_chip_info *info;
 	struct adv7604_platform_data pdata;
+
 	struct v4l2_subdev sd;
 	struct media_pad pads[ADV7604_PAD_MAX];
 	unsigned int source_pad;
+
 	struct v4l2_ctrl_handler hdl;
+
 	enum adv7604_pad selected_input;
+
 	struct v4l2_dv_timings timings;
+	const struct adv7604_format_info *format;
+
 	struct {
 		u8 edid[256];
 		u32 present;
@@ -771,6 +810,93 @@ static void adv7604_write_reg_seq(struct v4l2_subdev *sd,
 		adv7604_write_reg(sd, reg_seq[i].reg, reg_seq[i].val);
 }
 
+/* -----------------------------------------------------------------------------
+ * Format helpers
+ */
+
+static const struct adv7604_format_info adv7604_formats[] = {
+	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
+	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV10_2X10, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_YVYU10_2X10, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_UYVY10_1X20, ADV7604_OP_CH_SEL_RBG, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_VYUY10_1X20, ADV7604_OP_CH_SEL_RBG, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_YUYV10_1X20, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_YVYU10_1X20, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+};
+
+static const struct adv7604_format_info adv7611_formats[] = {
+	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
+	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
+	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+};
+
+static const struct adv7604_format_info *
+adv7604_format_info(struct adv7604_state *state, enum v4l2_mbus_pixelcode code)
+{
+	unsigned int i;
+
+	for (i = 0; i < state->info->nformats; ++i) {
+		if (state->info->formats[i].code == code)
+			return &state->info->formats[i];
+	}
+
+	return NULL;
+}
+
 /* ----------------------------------------------------------------------- */
 
 static inline bool is_analog_input(struct v4l2_subdev *sd)
@@ -1720,29 +1846,132 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
 	return 0;
 }
 
-static int adv7604_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
-			     enum v4l2_mbus_pixelcode *code)
+static int adv7604_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
 {
-	if (index)
+	struct adv7604_state *state = to_state(sd);
+
+	if (code->index >= state->info->nformats)
 		return -EINVAL;
-	/* Good enough for now */
-	*code = V4L2_MBUS_FMT_FIXED;
+
+	code->code = state->info->formats[code->index].code;
+
 	return 0;
 }
 
-static int adv7604_g_mbus_fmt(struct v4l2_subdev *sd,
-		struct v4l2_mbus_framefmt *fmt)
+static void adv7604_fill_format(struct adv7604_state *state,
+				struct v4l2_mbus_framefmt *format)
 {
-	struct adv7604_state *state = to_state(sd);
+	memset(format, 0, sizeof(*format));
 
-	fmt->width = state->timings.bt.width;
-	fmt->height = state->timings.bt.height;
-	fmt->code = V4L2_MBUS_FMT_FIXED;
-	fmt->field = V4L2_FIELD_NONE;
-	if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
-		fmt->colorspace = (state->timings.bt.height <= 576) ?
+	format->width = state->timings.bt.width;
+	format->height = state->timings.bt.height;
+	format->field = V4L2_FIELD_NONE;
+
+	if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861)
+		format->colorspace = (state->timings.bt.height <= 576) ?
 			V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
+}
+
+/*
+ * Compute the op_ch_sel value required to obtain on the bus the component order
+ * corresponding to the selected format taking into account bus reordering
+ * applied by the board at the output of the device.
+ *
+ * The following table gives the op_ch_value from the format component order
+ * (expressed as op_ch_sel value in column) and the bus reordering (expressed as
+ * adv7604_bus_order value in row).
+ *
+ *           |	GBR(0)	GRB(1)	BGR(2)	RGB(3)	BRG(4)	RBG(5)
+ * ----------+-------------------------------------------------
+ * RGB (NOP) |	GBR	GRB	BGR	RGB	BRG	RBG
+ * GRB (1-2) |	BGR	RGB	GBR	GRB	RBG	BRG
+ * RBG (2-3) |	GRB	GBR	BRG	RBG	BGR	RGB
+ * BGR (1-3) |	RBG	BRG	RGB	BGR	GRB	GBR
+ * BRG (ROR) |	BRG	RBG	GRB	GBR	RGB	BGR
+ * GBR (ROL) |	RGB	BGR	RBG	BRG	GBR	GRB
+ */
+static unsigned int adv7604_op_ch_sel(struct adv7604_state *state)
+{
+#define _SEL(a,b,c,d,e,f)	{ \
+	ADV7604_OP_CH_SEL_##a, ADV7604_OP_CH_SEL_##b, ADV7604_OP_CH_SEL_##c, \
+	ADV7604_OP_CH_SEL_##d, ADV7604_OP_CH_SEL_##e, ADV7604_OP_CH_SEL_##f }
+#define _BUS(x)			[ADV7604_BUS_ORDER_##x]
+
+	static const unsigned int op_ch_sel[6][6] = {
+		_BUS(RGB) /* NOP */ = _SEL(GBR, GRB, BGR, RGB, BRG, RBG),
+		_BUS(GRB) /* 1-2 */ = _SEL(BGR, RGB, GBR, GRB, RBG, BRG),
+		_BUS(RBG) /* 2-3 */ = _SEL(GRB, GBR, BRG, RBG, BGR, RGB),
+		_BUS(BGR) /* 1-3 */ = _SEL(RBG, BRG, RGB, BGR, GRB, GBR),
+		_BUS(BRG) /* ROR */ = _SEL(BRG, RBG, GRB, GBR, RGB, BGR),
+		_BUS(GBR) /* ROL */ = _SEL(RGB, BGR, RBG, BRG, GBR, GRB),
+	};
+
+	return op_ch_sel[state->pdata.bus_order][state->format->op_ch_sel];
+}
+
+static void adv7604_setup_format(struct adv7604_state *state)
+{
+	struct v4l2_subdev *sd = &state->sd;
+
+	io_write_and_or(sd, 0x02, 0xfd,
+			state->format->rgb_out ? ADV7604_RGB_OUT : 0);
+	io_write(sd, 0x03, state->format->op_format_sel |
+		 state->pdata.op_format_mode_sel);
+	io_write_and_or(sd, 0x04, 0x1f, adv7604_op_ch_sel(state));
+	io_write_and_or(sd, 0x05, 0xfe,
+			state->format->swap_cb_cr ? ADV7604_OP_SWAP_CB_CR : 0);
+}
+
+static int adv7604_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	if (format->pad != state->source_pad)
+		return -EINVAL;
+
+	adv7604_fill_format(state, &format->format);
+
+	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+		struct v4l2_mbus_framefmt *fmt;
+
+		fmt = v4l2_subdev_get_try_format(fh, format->pad);
+		format->format.code = fmt->code;
+	} else {
+		format->format.code = state->format->code;
 	}
+
+	return 0;
+}
+
+static int adv7604_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct adv7604_state *state = to_state(sd);
+	const struct adv7604_format_info *info;
+
+	if (format->pad != state->source_pad)
+		return -EINVAL;
+
+	info = adv7604_format_info(state, format->format.code);
+	if (info == NULL)
+		info = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
+
+	adv7604_fill_format(state, &format->format);
+	format->format.code = info->code;
+
+	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+		struct v4l2_mbus_framefmt *fmt;
+
+		fmt = v4l2_subdev_get_try_format(fh, format->pad);
+		fmt->code = format->format.code;
+	} else {
+		state->format = info;
+		adv7604_setup_format(state);
+	}
+
 	return 0;
 }
 
@@ -2189,13 +2418,12 @@ static const struct v4l2_subdev_video_ops adv7604_video_ops = {
 	.query_dv_timings = adv7604_query_dv_timings,
 	.enum_dv_timings = adv7604_enum_dv_timings,
 	.dv_timings_cap = adv7604_dv_timings_cap,
-	.enum_mbus_fmt = adv7604_enum_mbus_fmt,
-	.g_mbus_fmt = adv7604_g_mbus_fmt,
-	.try_mbus_fmt = adv7604_g_mbus_fmt,
-	.s_mbus_fmt = adv7604_g_mbus_fmt,
 };
 
 static const struct v4l2_subdev_pad_ops adv7604_pad_ops = {
+	.enum_mbus_code = adv7604_enum_mbus_code,
+	.get_fmt = adv7604_get_format,
+	.set_fmt = adv7604_set_format,
 	.get_edid = adv7604_get_edid,
 	.set_edid = adv7604_set_edid,
 };
@@ -2264,14 +2492,11 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
 	io_write_and_or(sd, 0x02, 0xf0,
 			pdata->alt_gamma << 3 |
 			pdata->op_656_range << 2 |
-			pdata->rgb_out << 1 |
 			pdata->alt_data_sat << 0);
-	io_write(sd, 0x03, pdata->op_format_sel);
-	io_write_and_or(sd, 0x04, 0x1f, pdata->op_ch_sel << 5);
-	io_write_and_or(sd, 0x05, 0xf0, pdata->blank_data << 3 |
-					pdata->insert_av_codes << 2 |
-					pdata->replicate_av_codes << 1 |
-					pdata->invert_cbcr << 0);
+	io_write_and_or(sd, 0x05, 0xf1, pdata->blank_data << 3 |
+			pdata->insert_av_codes << 2 |
+			pdata->replicate_av_codes << 1);
+	adv7604_setup_format(state);
 
 	cp_write(sd, 0x69, 0x30);   /* Enable CP CSC */
 
@@ -2439,6 +2664,8 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
 		.tdms_lock_mask = 0xe0,
 		.cable_det_mask = 0x1e,
 		.fmt_change_digital_mask = 0xc1,
+		.formats = adv7604_formats,
+		.nformats = ARRAY_SIZE(adv7604_formats),
 		.set_termination = adv7604_set_termination,
 		.setup_irqs = adv7604_setup_irqs,
 		.read_hdmi_pixelclock = adv7604_read_hdmi_pixelclock,
@@ -2470,6 +2697,8 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
 		.tdms_lock_mask = 0x43,
 		.cable_det_mask = 0x01,
 		.fmt_change_digital_mask = 0x03,
+		.formats = adv7611_formats,
+		.nformats = ARRAY_SIZE(adv7611_formats),
 		.set_termination = adv7611_set_termination,
 		.setup_irqs = adv7611_setup_irqs,
 		.read_hdmi_pixelclock = adv7611_read_hdmi_pixelclock,
@@ -2525,6 +2754,7 @@ static int adv7604_probe(struct i2c_client *client,
 	}
 	state->pdata = *pdata;
 	state->timings = cea640x480;
+	state->format = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
 
 	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &adv7604_ops);
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index 6186771..d8b2cb8 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -32,14 +32,18 @@ enum adv7604_ain_sel {
 	ADV7604_AIN9_4_5_6_SYNC_2_1 = 4,
 };
 
-/* Bus rotation and reordering (IO register 0x04, [7:5]) */
-enum adv7604_op_ch_sel {
-	ADV7604_OP_CH_SEL_GBR = 0,
-	ADV7604_OP_CH_SEL_GRB = 1,
-	ADV7604_OP_CH_SEL_BGR = 2,
-	ADV7604_OP_CH_SEL_RGB = 3,
-	ADV7604_OP_CH_SEL_BRG = 4,
-	ADV7604_OP_CH_SEL_RBG = 5,
+/*
+ * Bus rotation and reordering. This is used to specify component reordering on
+ * the board and describes the components order on the bus when the ADV7604
+ * outputs RGB.
+ */
+enum adv7604_bus_order {
+	ADV7604_BUS_ORDER_RGB,		/* No operation	*/
+	ADV7604_BUS_ORDER_GRB,		/* Swap 1-2	*/
+	ADV7604_BUS_ORDER_RBG,		/* Swap 2-3	*/
+	ADV7604_BUS_ORDER_BGR,		/* Swap 1-3	*/
+	ADV7604_BUS_ORDER_BRG,		/* Rotate right	*/
+	ADV7604_BUS_ORDER_GBR,		/* Rotate left	*/
 };
 
 /* Input Color Space (IO register 0x02, [7:4]) */
@@ -55,29 +59,11 @@ enum adv7604_inp_color_space {
 	ADV7604_INP_COLOR_SPACE_AUTO = 0xf,
 };
 
-/* Select output format (IO register 0x03, [7:0]) */
-enum adv7604_op_format_sel {
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_8 = 0x00,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_10 = 0x01,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE0 = 0x02,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE1 = 0x06,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE2 = 0x0a,
-	ADV7604_OP_FORMAT_SEL_DDR_422_8 = 0x20,
-	ADV7604_OP_FORMAT_SEL_DDR_422_10 = 0x21,
-	ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE0 = 0x22,
-	ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE1 = 0x23,
-	ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE2 = 0x24,
-	ADV7604_OP_FORMAT_SEL_SDR_444_24 = 0x40,
-	ADV7604_OP_FORMAT_SEL_SDR_444_30 = 0x41,
-	ADV7604_OP_FORMAT_SEL_SDR_444_36_MODE0 = 0x42,
-	ADV7604_OP_FORMAT_SEL_DDR_444_24 = 0x60,
-	ADV7604_OP_FORMAT_SEL_DDR_444_30 = 0x61,
-	ADV7604_OP_FORMAT_SEL_DDR_444_36 = 0x62,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_16 = 0x80,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_20 = 0x81,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE0 = 0x82,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE1 = 0x86,
-	ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE2 = 0x8a,
+/* Select output format (IO register 0x03, [4:2]) */
+enum adv7604_op_format_mode_sel {
+	ADV7604_OP_FORMAT_MODE0 = 0x00,
+	ADV7604_OP_FORMAT_MODE1 = 0x04,
+	ADV7604_OP_FORMAT_MODE2 = 0x08,
 };
 
 enum adv7604_drive_strength {
@@ -105,10 +91,10 @@ struct adv7604_platform_data {
 	enum adv7604_ain_sel ain_sel;
 
 	/* Bus rotation and reordering */
-	enum adv7604_op_ch_sel op_ch_sel;
+	enum adv7604_bus_order bus_order;
 
-	/* Select output format */
-	enum adv7604_op_format_sel op_format_sel;
+	/* Select output format mode */
+	enum adv7604_op_format_mode_sel op_format_mode_sel;
 
 	/* Configuration of the INT1 pin */
 	enum adv7604_int1_config int1_config;
@@ -116,14 +102,12 @@ struct adv7604_platform_data {
 	/* IO register 0x02 */
 	unsigned alt_gamma:1;
 	unsigned op_656_range:1;
-	unsigned rgb_out:1;
 	unsigned alt_data_sat:1;
 
 	/* IO register 0x05 */
 	unsigned blank_data:1;
 	unsigned insert_av_codes:1;
 	unsigned replicate_av_codes:1;
-	unsigned invert_cbcr:1;
 
 	/* IO register 0x06 */
 	unsigned inv_vs_pol:1;
-- 
1.8.3.2


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

* [PATCH v3 42/48] adv7604: Replace *_and_or() functions with *_clr_set()
  2014-03-10 23:15 ` [PATCH v2 42/48] adv7604: Replace *_and_or() functions with *_clr_set() Laurent Pinchart
@ 2014-03-11 15:10   ` Laurent Pinchart
  0 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-11 15:10 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

The *_and_or() functions take an 'and' bitmask to be ANDed with the
register value before ORing it with th 'or' bitmask. As the functions
are used to mask and set bits selectively, this requires the caller to
invert the 'and' bitmask and is thus error prone. Replace those
functions with a *_clr_set() variant that takes a mask of bits to be
cleared instead of a mask of bits to be kept.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/i2c/adv7604.c | 86 ++++++++++++++++++++++-----------------------
 1 file changed, 43 insertions(+), 43 deletions(-)

Changes since v2:

- Rebased on top of 36/48 v3.

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 4421fea..ed29d02 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -429,9 +429,9 @@ static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_IO, reg, val);
 }
 
-static inline int io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
 {
-	return io_write(sd, reg, (io_read(sd, reg) & mask) | val);
+	return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val);
 }
 
 static inline int avlink_read(struct v4l2_subdev *sd, u8 reg)
@@ -462,9 +462,9 @@ static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_CEC, reg, val);
 }
 
-static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
 {
-	return cec_write(sd, reg, (cec_read(sd, reg) & mask) | val);
+	return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val);
 }
 
 static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
@@ -538,9 +538,9 @@ static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_REP, reg, val);
 }
 
-static inline int rep_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int rep_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
 {
-	return rep_write(sd, reg, (rep_read(sd, reg) & mask) | val);
+	return rep_write(sd, reg, (rep_read(sd, reg) & ~mask) | val);
 }
 
 static inline int edid_read(struct v4l2_subdev *sd, u8 reg)
@@ -629,9 +629,9 @@ static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_HDMI, reg, val);
 }
 
-static inline int hdmi_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
 {
-	return hdmi_write(sd, reg, (hdmi_read(sd, reg) & mask) | val);
+	return hdmi_write(sd, reg, (hdmi_read(sd, reg) & ~mask) | val);
 }
 
 static inline int test_read(struct v4l2_subdev *sd, u8 reg)
@@ -667,9 +667,9 @@ static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 	return adv_smbus_write_byte_data(state, ADV7604_PAGE_CP, reg, val);
 }
 
-static inline int cp_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int cp_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
 {
-	return cp_write(sd, reg, (cp_read(sd, reg) & mask) | val);
+	return cp_write(sd, reg, (cp_read(sd, reg) & ~mask) | val);
 }
 
 static inline int vdp_read(struct v4l2_subdev *sd, u8 reg)
@@ -947,7 +947,7 @@ static int configure_predefined_video_timings(struct v4l2_subdev *sd,
 		io_write(sd, 0x17, 0x5a);
 	}
 	/* disable embedded syncs for auto graphics mode */
-	cp_write_and_or(sd, 0x81, 0xef, 0x00);
+	cp_write_clr_set(sd, 0x81, 0x10, 0x00);
 	cp_write(sd, 0x8f, 0x00);
 	cp_write(sd, 0x90, 0x00);
 	cp_write(sd, 0xa2, 0x00);
@@ -1005,7 +1005,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
 		io_write(sd, 0x00, 0x07); /* video std */
 		io_write(sd, 0x01, 0x02); /* prim mode */
 		/* enable embedded syncs for auto graphics mode */
-		cp_write_and_or(sd, 0x81, 0xef, 0x10);
+		cp_write_clr_set(sd, 0x81, 0x10, 0x10);
 
 		/* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
 		/* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
@@ -1115,21 +1115,21 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 		if (state->selected_input == ADV7604_PAD_VGA_RGB) {
 			/* Receiving analog RGB signal
 			 * Set RGB full range (0-255) */
-			io_write_and_or(sd, 0x02, 0x0f, 0x10);
+			io_write_clr_set(sd, 0x02, 0xf0, 0x10);
 			break;
 		}
 
 		if (state->selected_input == ADV7604_PAD_VGA_COMP) {
 			/* Receiving analog YPbPr signal
 			 * Set automode */
-			io_write_and_or(sd, 0x02, 0x0f, 0xf0);
+			io_write_clr_set(sd, 0x02, 0xf0, 0xf0);
 			break;
 		}
 
 		if (hdmi_signal) {
 			/* Receiving HDMI signal
 			 * Set automode */
-			io_write_and_or(sd, 0x02, 0x0f, 0xf0);
+			io_write_clr_set(sd, 0x02, 0xf0, 0xf0);
 			break;
 		}
 
@@ -1138,10 +1138,10 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 		 * input format (CE/IT) in automatic mode */
 		if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
 			/* RGB limited range (16-235) */
-			io_write_and_or(sd, 0x02, 0x0f, 0x00);
+			io_write_clr_set(sd, 0x02, 0xf0, 0x00);
 		} else {
 			/* RGB full range (0-255) */
-			io_write_and_or(sd, 0x02, 0x0f, 0x10);
+			io_write_clr_set(sd, 0x02, 0xf0, 0x10);
 
 			if (is_digital_input(sd) && rgb_output) {
 				adv7604_set_offset(sd, false, 0x40, 0x40, 0x40);
@@ -1154,23 +1154,23 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 	case V4L2_DV_RGB_RANGE_LIMITED:
 		if (state->selected_input == ADV7604_PAD_VGA_COMP) {
 			/* YCrCb limited range (16-235) */
-			io_write_and_or(sd, 0x02, 0x0f, 0x20);
+			io_write_clr_set(sd, 0x02, 0xf0, 0x20);
 			break;
 		}
 
 		/* RGB limited range (16-235) */
-		io_write_and_or(sd, 0x02, 0x0f, 0x00);
+		io_write_clr_set(sd, 0x02, 0xf0, 0x00);
 
 		break;
 	case V4L2_DV_RGB_RANGE_FULL:
 		if (state->selected_input == ADV7604_PAD_VGA_COMP) {
 			/* YCrCb full range (0-255) */
-			io_write_and_or(sd, 0x02, 0x0f, 0x60);
+			io_write_clr_set(sd, 0x02, 0xf0, 0x60);
 			break;
 		}
 
 		/* RGB full range (0-255) */
-		io_write_and_or(sd, 0x02, 0x0f, 0x10);
+		io_write_clr_set(sd, 0x02, 0xf0, 0x10);
 
 		if (is_analog_input(sd) || hdmi_signal)
 			break;
@@ -1222,7 +1222,7 @@ static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
 	case V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL:
 		/* Use the default blue color for free running mode,
 		   or supply your own. */
-		cp_write_and_or(sd, 0xbf, ~0x04, (ctrl->val << 2));
+		cp_write_clr_set(sd, 0xbf, 0x04, ctrl->val << 2);
 		return 0;
 	case V4L2_CID_ADV_RX_FREE_RUN_COLOR:
 		cp_write(sd, 0xc0, (ctrl->val & 0xff0000) >> 16);
@@ -1605,11 +1605,11 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
 				v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__);
 				/* TODO restart STDI for Sync Channel 2 */
 				/* enter one-shot mode */
-				cp_write_and_or(sd, 0x86, 0xf9, 0x00);
+				cp_write_clr_set(sd, 0x86, 0x06, 0x00);
 				/* trigger STDI restart */
-				cp_write_and_or(sd, 0x86, 0xf9, 0x04);
+				cp_write_clr_set(sd, 0x86, 0x06, 0x04);
 				/* reset to continuous mode */
-				cp_write_and_or(sd, 0x86, 0xf9, 0x02);
+				cp_write_clr_set(sd, 0x86, 0x06, 0x02);
 				state->restart_stdi_once = false;
 				return -ENOLINK;
 			}
@@ -1668,7 +1668,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
 
 	state->timings = *timings;
 
-	cp_write_and_or(sd, 0x91, 0xbf, bt->interlaced ? 0x40 : 0x00);
+	cp_write_clr_set(sd, 0x91, 0x40, bt->interlaced ? 0x40 : 0x00);
 
 	/* Use prim_mode and vid_std when available */
 	err = configure_predefined_video_timings(sd, timings);
@@ -1712,10 +1712,10 @@ static void enable_input(struct v4l2_subdev *sd)
 	if (is_analog_input(sd)) {
 		io_write(sd, 0x15, 0xb0);   /* Disable Tristate of Pins (no audio) */
 	} else if (is_digital_input(sd)) {
-		hdmi_write_and_or(sd, 0x00, 0xfc, state->selected_input);
+		hdmi_write_clr_set(sd, 0x00, 0x03, state->selected_input);
 		state->info->set_termination(sd, true);
 		io_write(sd, 0x15, 0xa0);   /* Disable Tristate of Pins */
-		hdmi_write_and_or(sd, 0x1a, 0xef, 0x00); /* Unmute audio */
+		hdmi_write_clr_set(sd, 0x1a, 0x10, 0x00); /* Unmute audio */
 	} else {
 		v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
 				__func__, state->selected_input);
@@ -1726,7 +1726,7 @@ static void disable_input(struct v4l2_subdev *sd)
 {
 	struct adv7604_state *state = to_state(sd);
 
-	hdmi_write_and_or(sd, 0x1a, 0xef, 0x10); /* Mute audio */
+	hdmi_write_clr_set(sd, 0x1a, 0x10, 0x10); /* Mute audio */
 	msleep(16); /* 512 samples with >= 32 kHz sample rate [REF_03, c. 7.16.10] */
 	io_write(sd, 0x15, 0xbe);   /* Tristate all outputs from video core */
 	state->info->set_termination(sd, false);
@@ -1857,12 +1857,12 @@ static void adv7604_setup_format(struct adv7604_state *state)
 {
 	struct v4l2_subdev *sd = &state->sd;
 
-	io_write_and_or(sd, 0x02, 0xfd,
+	io_write_clr_set(sd, 0x02, 0x02,
 			state->format->rgb_out ? ADV7604_RGB_OUT : 0);
 	io_write(sd, 0x03, state->format->op_format_sel |
 		 state->pdata.op_format_mode_sel);
-	io_write_and_or(sd, 0x04, 0x1f, adv7604_op_ch_sel(state));
-	io_write_and_or(sd, 0x05, 0xfe,
+	io_write_clr_set(sd, 0x04, 0xe0, adv7604_op_ch_sel(state));
+	io_write_clr_set(sd, 0x05, 0x01,
 			state->format->swap_cb_cr ? ADV7604_OP_SWAP_CB_CR : 0);
 }
 
@@ -2059,7 +2059,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 		/* Disable hotplug and I2C access to EDID RAM from DDC port */
 		state->edid.present &= ~(1 << edid->pad);
 		v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
-		rep_write_and_or(sd, info->edid_enable_reg, 0xf0, state->edid.present);
+		rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
 
 		/* Fall back to a 16:9 aspect ratio */
 		state->aspect_ratio.numerator = 16;
@@ -2083,7 +2083,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 	/* Disable hotplug and I2C access to EDID RAM from DDC port */
 	cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
 	v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&tmp);
-	rep_write_and_or(sd, info->edid_enable_reg, 0xf0, 0x00);
+	rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, 0x00);
 
 	spa_loc = get_edid_spa_location(edid->edid);
 	if (spa_loc < 0)
@@ -2112,10 +2112,10 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 
 	if (info->type == ADV7604) {
 		rep_write(sd, 0x76, spa_loc & 0xff);
-		rep_write_and_or(sd, 0x77, 0xbf, (spa_loc & 0x100) >> 2);
+		rep_write_clr_set(sd, 0x77, 0x40, (spa_loc & 0x100) >> 2);
 	} else {
 		/* FIXME: Where is the SPA location LSB register ? */
-		rep_write_and_or(sd, 0x71, 0xfe, (spa_loc & 0x100) >> 8);
+		rep_write_clr_set(sd, 0x71, 0x01, (spa_loc & 0x100) >> 8);
 	}
 
 	edid->edid[spa_loc] = state->spa_port_a[0];
@@ -2135,7 +2135,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
 
 	/* adv7604 calculates the checksums and enables I2C access to internal
 	   EDID RAM from DDC port. */
-	rep_write_and_or(sd, info->edid_enable_reg, 0xf0, state->edid.present);
+	rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
 
 	for (i = 0; i < 1000; i++) {
 		if (rep_read(sd, info->edid_status_reg) & state->edid.present)
@@ -2431,11 +2431,11 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
 	cp_write(sd, 0xcf, 0x01);   /* Power down macrovision */
 
 	/* video format */
-	io_write_and_or(sd, 0x02, 0xf0,
+	io_write_clr_set(sd, 0x02, 0x0f,
 			pdata->alt_gamma << 3 |
 			pdata->op_656_range << 2 |
 			pdata->alt_data_sat << 0);
-	io_write_and_or(sd, 0x05, 0xf1, pdata->blank_data << 3 |
+	io_write_clr_set(sd, 0x05, 0x0e, pdata->blank_data << 3 |
 			pdata->insert_av_codes << 2 |
 			pdata->replicate_av_codes << 1);
 	adv7604_setup_format(state);
@@ -2460,16 +2460,16 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
 				     for digital formats */
 
 	/* HDMI audio */
-	hdmi_write_and_or(sd, 0x15, 0xfc, 0x03); /* Mute on FIFO over-/underflow [REF_01, c. 1.2.18] */
-	hdmi_write_and_or(sd, 0x1a, 0xf1, 0x08); /* Wait 1 s before unmute */
-	hdmi_write_and_or(sd, 0x68, 0xf9, 0x06); /* FIFO reset on over-/underflow [REF_01, c. 1.2.19] */
+	hdmi_write_clr_set(sd, 0x15, 0x03, 0x03); /* Mute on FIFO over-/underflow [REF_01, c. 1.2.18] */
+	hdmi_write_clr_set(sd, 0x1a, 0x0e, 0x08); /* Wait 1 s before unmute */
+	hdmi_write_clr_set(sd, 0x68, 0x06, 0x06); /* FIFO reset on over-/underflow [REF_01, c. 1.2.19] */
 
 	/* TODO from platform data */
 	afe_write(sd, 0xb5, 0x01);  /* Setting MCLK to 256Fs */
 
 	if (adv7604_has_afe(state)) {
 		afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
-		io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
+		io_write_clr_set(sd, 0x30, 1 << 4, pdata->output_bus_lsb_to_msb << 4);
 	}
 
 	/* interrupts */
-- 
1.8.3.2


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

* [PATCH v3 46/48] adv7604: Add DT support
  2014-03-10 23:15 ` [PATCH v2 46/48] adv7604: Add DT support Laurent Pinchart
@ 2014-03-11 15:11   ` Laurent Pinchart
  2014-04-17 10:59   ` [PATCH v2 " Sylwester Nawrocki
  1 sibling, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-11 15:11 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Parse the device tree node to populate platform data.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 .../devicetree/bindings/media/i2c/adv7604.txt      | 56 +++++++++++++
 drivers/media/i2c/adv7604.c                        | 92 ++++++++++++++++++----
 2 files changed, 134 insertions(+), 14 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/adv7604.txt

Changes since v2:

- Rebased on top of 36/48 v3.

diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
new file mode 100644
index 0000000..0845c50
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
@@ -0,0 +1,56 @@
+* Analog Devices ADV7604/11 video decoder with HDMI receiver
+
+The ADV7604 and ADV7611 are multiformat video decoders with an integrated HDMI
+receiver. The ADV7604 has four multiplexed HDMI inputs and one analog input,
+and the ADV7611 has one HDMI input and no analog input.
+
+Required Properties:
+
+  - compatible: Must contain one of the following
+    - "adi,adv7604" for the ADV7604
+    - "adi,adv7611" for the ADV7611
+
+  - reg: I2C slave address
+
+  - hpd-gpios: References to the GPIOs that control the HDMI hot-plug
+    detection pins, one per HDMI input. The active flag indicates the GPIO
+    level that enables hot-plug detection.
+
+Optional Properties:
+
+  - reset-gpios: Reference to the GPIO connected to the device's reset pin.
+
+  - adi,default-input: Index of the input to be configured as default. Valid
+    values are 0..5 for the ADV7604 and 0 for the ADV7611.
+
+  - adi,disable-power-down: Boolean property. When set forces the device to
+    ignore the power-down pin. The property is valid for the ADV7604 only as
+    the ADV7611 has no power-down pin.
+
+  - adi,disable-cable-reset: Boolean property. When set disables the HDMI
+    receiver automatic reset when the HDMI cable is unplugged.
+
+Example:
+
+	hdmi_receiver@4c {
+		compatible = "adi,adv7611";
+		reg = <0x4c>;
+
+		reset-gpios = <&ioexp 0 GPIO_ACTIVE_LOW>;
+		hpd-gpios = <&ioexp 2 GPIO_ACTIVE_HIGH>;
+
+		adi,default-input = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+		};
+		port@1 {
+			reg = <1>;
+			hdmi_in: endpoint {
+				remote-endpoint = <&ccdc_in>;
+			};
+		};
+	};
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index b352b62..5901b78 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2663,13 +2663,70 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
 	},
 };
 
+static struct i2c_device_id adv7604_i2c_id[] = {
+	{ "adv7604", (kernel_ulong_t)&adv7604_chip_info[ADV7604] },
+	{ "adv7611", (kernel_ulong_t)&adv7604_chip_info[ADV7611] },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adv7604_i2c_id);
+
+static struct of_device_id adv7604_of_id[] = {
+	{ .compatible = "adi,adv7604", .data = &adv7604_chip_info[ADV7604] },
+	{ .compatible = "adi,adv7611", .data = &adv7604_chip_info[ADV7611] },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, adv7604_of_id);
+
+static int adv7604_parse_dt(struct adv7604_state *state)
+{
+	struct device_node *np;
+	int ret;
+
+	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
+
+	state->pdata.disable_pwrdnb =
+		of_property_read_bool(np, "adi,disable-power-down");
+	state->pdata.disable_cable_det_rst =
+		of_property_read_bool(np, "adi,disable-cable-reset");
+
+	ret = of_property_read_u32(np, "adi,default-input",
+				   &state->pdata.default_input);
+	if (ret < 0)
+		state->pdata.default_input = -1;
+
+	/* Disable the interrupt for now as no DT-based board uses it. */
+	state->pdata.int1_config = ADV7604_INT1_CONFIG_DISABLED;
+
+	/* Use the default I2C addresses. */
+	state->pdata.i2c_addresses[ADV7604_PAGE_AVLINK] = 0x42;
+	state->pdata.i2c_addresses[ADV7604_PAGE_CEC] = 0x40;
+	state->pdata.i2c_addresses[ADV7604_PAGE_INFOFRAME] = 0x3e;
+	state->pdata.i2c_addresses[ADV7604_PAGE_ESDP] = 0x38;
+	state->pdata.i2c_addresses[ADV7604_PAGE_DPP] = 0x3c;
+	state->pdata.i2c_addresses[ADV7604_PAGE_AFE] = 0x26;
+	state->pdata.i2c_addresses[ADV7604_PAGE_REP] = 0x32;
+	state->pdata.i2c_addresses[ADV7604_PAGE_EDID] = 0x36;
+	state->pdata.i2c_addresses[ADV7604_PAGE_HDMI] = 0x34;
+	state->pdata.i2c_addresses[ADV7604_PAGE_TEST] = 0x30;
+	state->pdata.i2c_addresses[ADV7604_PAGE_CP] = 0x22;
+	state->pdata.i2c_addresses[ADV7604_PAGE_VDP] = 0x24;
+
+	/* HACK: Hardcode the remaining platform data fields. */
+	state->pdata.blank_data = 1;
+	state->pdata.op_656_range = 1;
+	state->pdata.alt_data_sat = 1;
+	state->pdata.insert_av_codes = 1;
+	state->pdata.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0;
+
+	return 0;
+}
+
 static int adv7604_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	static const struct v4l2_dv_timings cea640x480 =
 		V4L2_DV_BT_CEA_640X480P59_94;
 	struct adv7604_state *state;
-	struct adv7604_platform_data *pdata = client->dev.platform_data;
 	struct v4l2_ctrl_handler *hdl;
 	struct v4l2_subdev *sd;
 	unsigned int i;
@@ -2688,19 +2745,32 @@ static int adv7604_probe(struct i2c_client *client,
 		return -ENOMEM;
 	}
 
-	state->info = &adv7604_chip_info[id->driver_data];
 	state->i2c_clients[ADV7604_PAGE_IO] = client;
 
 	/* initialize variables */
 	state->restart_stdi_once = true;
 	state->selected_input = ~0;
 
-	/* platform data */
-	if (!pdata) {
+	if (IS_ENABLED(CONFIG_OF) && client->dev.of_node) {
+		const struct of_device_id *oid;
+
+		oid = of_match_node(adv7604_of_id, client->dev.of_node);
+		state->info = oid->data;
+
+		err = adv7604_parse_dt(state);
+		if (err < 0) {
+			v4l_err(client, "DT parsing error\n");
+			return err;
+		}
+	} else if (client->dev.platform_data) {
+		struct adv7604_platform_data *pdata = client->dev.platform_data;
+
+		state->info = (const struct adv7604_chip_info *)id->driver_data;
+		state->pdata = *pdata;
+	} else {
 		v4l_err(client, "No platform data!\n");
 		return -ENODEV;
 	}
-	state->pdata = *pdata;
 
 	/* Request GPIOs. */
 	for (i = 0; i < state->info->num_dv_ports; ++i) {
@@ -2799,7 +2869,7 @@ static int adv7604_probe(struct i2c_client *client,
 			continue;
 
 		state->i2c_clients[i] =
-			adv7604_dummy_client(sd, pdata->i2c_addresses[i],
+			adv7604_dummy_client(sd, state->pdata.i2c_addresses[i],
 					     0xf2 + i);
 		if (state->i2c_clients[i] == NULL) {
 			err = -ENOMEM;
@@ -2873,21 +2943,15 @@ static int adv7604_remove(struct i2c_client *client)
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_device_id adv7604_id[] = {
-	{ "adv7604", ADV7604 },
-	{ "adv7611", ADV7611 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, adv7604_id);
-
 static struct i2c_driver adv7604_driver = {
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "adv7604",
+		.of_match_table = of_match_ptr(adv7604_of_id),
 	},
 	.probe = adv7604_probe,
 	.remove = adv7604_remove,
-	.id_table = adv7604_id,
+	.id_table = adv7604_i2c_id,
 };
 
 module_i2c_driver(adv7604_driver);
-- 
1.8.3.2


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

* Re: [PATCH v3 26/48] v4l: Add support for DV timings ioctls on subdev nodes
  2014-03-11 15:09   ` [PATCH v3 " Laurent Pinchart
@ 2014-03-11 15:33     ` Hans Verkuil
  0 siblings, 0 replies; 93+ messages in thread
From: Hans Verkuil @ 2014-03-11 15:33 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

On 03/11/2014 04:09 PM, Laurent Pinchart wrote:
> Validate the pad field in the core code whenever specified.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

Regards,

	Hans

> ---
>  .../DocBook/media/v4l/vidioc-dv-timings-cap.xml    | 27 +++++++++++++++----
>  .../DocBook/media/v4l/vidioc-enum-dv-timings.xml   | 30 +++++++++++++++++-----
>  drivers/media/v4l2-core/v4l2-subdev.c              | 27 +++++++++++++++++++
>  include/uapi/linux/v4l2-subdev.h                   |  5 ++++
>  4 files changed, 77 insertions(+), 12 deletions(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
> index cd7720d..28a8c1e 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
> @@ -1,11 +1,12 @@
>  <refentry id="vidioc-dv-timings-cap">
>    <refmeta>
> -    <refentrytitle>ioctl VIDIOC_DV_TIMINGS_CAP</refentrytitle>
> +    <refentrytitle>ioctl VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</refentrytitle>
>      &manvol;
>    </refmeta>
>  
>    <refnamediv>
>      <refname>VIDIOC_DV_TIMINGS_CAP</refname>
> +    <refname>VIDIOC_SUBDEV_DV_TIMINGS_CAP</refname>
>      <refpurpose>The capabilities of the Digital Video receiver/transmitter</refpurpose>
>    </refnamediv>
>  
> @@ -33,7 +34,7 @@
>        <varlistentry>
>  	<term><parameter>request</parameter></term>
>  	<listitem>
> -	  <para>VIDIOC_DV_TIMINGS_CAP</para>
> +	  <para>VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</para>
>  	</listitem>
>        </varlistentry>
>        <varlistentry>
> @@ -54,10 +55,19 @@
>        interface and may change in the future.</para>
>      </note>
>  
> -    <para>To query the capabilities of the DV receiver/transmitter applications can call
> -this ioctl and the driver will fill in the structure. Note that drivers may return
> +    <para>To query the capabilities of the DV receiver/transmitter applications
> +can call the <constant>VIDIOC_DV_TIMINGS_CAP</constant> ioctl on a video node
> +and the driver will fill in the structure. Note that drivers may return
>  different values after switching the video input or output.</para>
>  
> +    <para>When implemented by the driver DV capabilities of subdevices can be
> +queried by calling the <constant>VIDIOC_SUBDEV_DV_TIMINGS_CAP</constant> ioctl
> +directly on a subdevice node. The capabilities are specific to inputs (for DV
> +receivers) or outputs (for DV transmitters), applications must specify the
> +desired pad number in the &v4l2-dv-timings-cap; <structfield>pad</structfield>
> +field. Attempts to query capabilities on a pad that doesn't support them will
> +return an &EINVAL;.</para>
> +
>      <table pgwide="1" frame="none" id="v4l2-bt-timings-cap">
>        <title>struct <structname>v4l2_bt_timings_cap</structname></title>
>        <tgroup cols="3">
> @@ -127,7 +137,14 @@ different values after switching the video input or output.</para>
>  	  </row>
>  	  <row>
>  	    <entry>__u32</entry>
> -	    <entry><structfield>reserved</structfield>[3]</entry>
> +	    <entry><structfield>pad</structfield></entry>
> +	    <entry>Pad number as reported by the media controller API. This field
> +	    is only used when operating on a subdevice node. When operating on a
> +	    video node applications must set this field to zero.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>reserved</structfield>[2]</entry>
>  	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
>  	  </row>
>  	  <row>
> diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
> index b3e17c1..b9fdfea 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
> @@ -1,11 +1,12 @@
>  <refentry id="vidioc-enum-dv-timings">
>    <refmeta>
> -    <refentrytitle>ioctl VIDIOC_ENUM_DV_TIMINGS</refentrytitle>
> +    <refentrytitle>ioctl VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refentrytitle>
>      &manvol;
>    </refmeta>
>  
>    <refnamediv>
>      <refname>VIDIOC_ENUM_DV_TIMINGS</refname>
> +    <refname>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refname>
>      <refpurpose>Enumerate supported Digital Video timings</refpurpose>
>    </refnamediv>
>  
> @@ -33,7 +34,7 @@
>        <varlistentry>
>  	<term><parameter>request</parameter></term>
>  	<listitem>
> -	  <para>VIDIOC_ENUM_DV_TIMINGS</para>
> +	  <para>VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</para>
>  	</listitem>
>        </varlistentry>
>        <varlistentry>
> @@ -61,14 +62,21 @@ standards or even custom timings that are not in this list.</para>
>  
>      <para>To query the available timings, applications initialize the
>  <structfield>index</structfield> field and zero the reserved array of &v4l2-enum-dv-timings;
> -and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl with a pointer to this
> -structure. Drivers fill the rest of the structure or return an
> +and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl on a video node with a
> +pointer to this structure. Drivers fill the rest of the structure or return an
>  &EINVAL; when the index is out of bounds. To enumerate all supported DV timings,
>  applications shall begin at index zero, incrementing by one until the
>  driver returns <errorcode>EINVAL</errorcode>. Note that drivers may enumerate a
>  different set of DV timings after switching the video input or
>  output.</para>
>  
> +    <para>When implemented by the driver DV timings of subdevices can be queried
> +by calling the <constant>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</constant> ioctl directly
> +on a subdevice node. The DV timings are specific to inputs (for DV receivers) or
> +outputs (for DV transmitters), applications must specify the desired pad number
> +in the &v4l2-enum-dv-timings; <structfield>pad</structfield> field. Attempts to
> +enumerate timings on a pad that doesn't support them will return an &EINVAL;.</para>
> +
>      <table pgwide="1" frame="none" id="v4l2-enum-dv-timings">
>        <title>struct <structname>v4l2_enum_dv_timings</structname></title>
>        <tgroup cols="3">
> @@ -82,8 +90,16 @@ application.</entry>
>  	  </row>
>  	  <row>
>  	    <entry>__u32</entry>
> -	    <entry><structfield>reserved</structfield>[3]</entry>
> -	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
> +	    <entry><structfield>pad</structfield></entry>
> +	    <entry>Pad number as reported by the media controller API. This field
> +	    is only used when operating on a subdevice node. When operating on a
> +	    video node applications must set this field to zero.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>reserved</structfield>[2]</entry>
> +	    <entry>Reserved for future extensions. Drivers and applications must
> +	    set the array to zero.</entry>
>  	  </row>
>  	  <row>
>  	    <entry>&v4l2-dv-timings;</entry>
> @@ -103,7 +119,7 @@ application.</entry>
>  	<term><errorcode>EINVAL</errorcode></term>
>  	<listitem>
>  	  <para>The &v4l2-enum-dv-timings; <structfield>index</structfield>
> -is out of bounds.</para>
> +is out of bounds or the <structfield>pad</structfield> number is invalid.</para>
>  	</listitem>
>        </varlistentry>
>        <varlistentry>
> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
> index 60d2550..853fb84 100644
> --- a/drivers/media/v4l2-core/v4l2-subdev.c
> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> @@ -354,6 +354,33 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
>  
>  	case VIDIOC_SUBDEV_S_EDID:
>  		return v4l2_subdev_call(sd, pad, set_edid, arg);
> +
> +	case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
> +		struct v4l2_dv_timings_cap *cap = arg;
> +
> +		if (cap->pad >= sd->entity.num_pads)
> +			return -EINVAL;
> +
> +		return v4l2_subdev_call(sd, pad, dv_timings_cap, cap);
> +	}
> +
> +	case VIDIOC_SUBDEV_ENUM_DV_TIMINGS: {
> +		struct v4l2_enum_dv_timings *dvt = arg;
> +
> +		if (dvt->pad >= sd->entity.num_pads)
> +			return -EINVAL;
> +
> +		return v4l2_subdev_call(sd, pad, enum_dv_timings, dvt);
> +	}
> +
> +	case VIDIOC_SUBDEV_QUERY_DV_TIMINGS:
> +		return v4l2_subdev_call(sd, video, query_dv_timings, arg);
> +
> +	case VIDIOC_SUBDEV_G_DV_TIMINGS:
> +		return v4l2_subdev_call(sd, video, g_dv_timings, arg);
> +
> +	case VIDIOC_SUBDEV_S_DV_TIMINGS:
> +		return v4l2_subdev_call(sd, video, s_dv_timings, arg);
>  #endif
>  	default:
>  		return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
> diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
> index 9fe3493..8dadb16 100644
> --- a/include/uapi/linux/v4l2-subdev.h
> +++ b/include/uapi/linux/v4l2-subdev.h
> @@ -169,5 +169,10 @@ struct v4l2_subdev_edid {
>  #define VIDIOC_SUBDEV_S_SELECTION		_IOWR('V', 62, struct v4l2_subdev_selection)
>  #define VIDIOC_SUBDEV_G_EDID			_IOWR('V', 40, struct v4l2_subdev_edid)
>  #define VIDIOC_SUBDEV_S_EDID			_IOWR('V', 41, struct v4l2_subdev_edid)
> +#define VIDIOC_SUBDEV_S_DV_TIMINGS		_IOWR('V', 87, struct v4l2_dv_timings)
> +#define VIDIOC_SUBDEV_G_DV_TIMINGS		_IOWR('V', 88, struct v4l2_dv_timings)
> +#define VIDIOC_SUBDEV_ENUM_DV_TIMINGS		_IOWR('V', 98, struct v4l2_enum_dv_timings)
> +#define VIDIOC_SUBDEV_QUERY_DV_TIMINGS		_IOR('V', 99, struct v4l2_dv_timings)
> +#define VIDIOC_SUBDEV_DV_TIMINGS_CAP		_IOWR('V', 100, struct v4l2_dv_timings_cap)
>  
>  #endif
> 


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

* Re: [PATCH v3 27/48] v4l: Validate fields in the core code for subdev EDID ioctls
  2014-03-11 15:09   ` [PATCH v3 " Laurent Pinchart
@ 2014-03-11 15:44     ` Hans Verkuil
  2014-03-11 16:08       ` Laurent Pinchart
  0 siblings, 1 reply; 93+ messages in thread
From: Hans Verkuil @ 2014-03-11 15:44 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

On 03/11/2014 04:09 PM, Laurent Pinchart wrote:
> The subdev EDID ioctls receive a pad field that must reference an
> existing pad and an EDID field that must point to a buffer. Validate
> both fields in the core code instead of duplicating validation in all
> drivers.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>

Here is my:

Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

But take note: the adv7604 driver does not handle a get_edid with
edid->blocks == 0 correctly: it should fill in the blocks field with the
real number of blocks and return 0 instead of returning EINVAL.

I also read through the spec again and it does not actually explicitly say
that you can use G_EDID with edid->blocks == 0, but I think it makes a lot
of sense to do that.

All existing drivers that use get_edid all return -EINVAL if blocks == 0,
so this patch does not change anything with that.

I plan on making a patch to clarify the spec and update the drivers, but you
might want to make a patch for adv7604 yourself instead of waiting for me.
I leave that up to you. Anyway, this patch is fine.

Regards,

	Hans

> ---
>  drivers/media/i2c/ad9389b.c           |  2 --
>  drivers/media/i2c/adv7511.c           |  2 --
>  drivers/media/i2c/adv7604.c           |  4 ----
>  drivers/media/i2c/adv7842.c           |  4 ----
>  drivers/media/v4l2-core/v4l2-subdev.c | 24 ++++++++++++++++++++----
>  5 files changed, 20 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
> index 4cdff9e..5b78828 100644
> --- a/drivers/media/i2c/ad9389b.c
> +++ b/drivers/media/i2c/ad9389b.c
> @@ -683,8 +683,6 @@ static int ad9389b_get_edid(struct v4l2_subdev *sd,
>  		return -EINVAL;
>  	if (edid->blocks == 0 || edid->blocks > 256)
>  		return -EINVAL;
> -	if (!edid->edid)
> -		return -EINVAL;
>  	if (!state->edid.segments) {
>  		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
>  		return -ENODATA;
> diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
> index de7ddf5..ff1c2cd 100644
> --- a/drivers/media/i2c/adv7511.c
> +++ b/drivers/media/i2c/adv7511.c
> @@ -784,8 +784,6 @@ static int adv7511_get_edid(struct v4l2_subdev *sd,
>  		return -EINVAL;
>  	if ((edid->blocks == 0) || (edid->blocks > 256))
>  		return -EINVAL;
> -	if (!edid->edid)
> -		return -EINVAL;
>  	if (!state->edid.segments) {
>  		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
>  		return -ENODATA;
> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> index 71c8570..de3db42 100644
> --- a/drivers/media/i2c/adv7604.c
> +++ b/drivers/media/i2c/adv7604.c
> @@ -1673,8 +1673,6 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
>  		return -EINVAL;
>  	if (edid->start_block == 1)
>  		edid->blocks = 1;
> -	if (!edid->edid)
> -		return -EINVAL;
>  
>  	if (edid->blocks > state->edid.blocks)
>  		edid->blocks = state->edid.blocks;
> @@ -1761,8 +1759,6 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
>  		edid->blocks = 2;
>  		return -E2BIG;
>  	}
> -	if (!edid->edid)
> -		return -EINVAL;
>  
>  	v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n",
>  			__func__, edid->pad, state->edid.present);
> diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
> index a319275..3c5a7d9 100644
> --- a/drivers/media/i2c/adv7842.c
> +++ b/drivers/media/i2c/adv7842.c
> @@ -2035,8 +2035,6 @@ static int adv7842_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edi
>  		return -EINVAL;
>  	if (edid->start_block == 1)
>  		edid->blocks = 1;
> -	if (!edid->edid)
> -		return -EINVAL;
>  
>  	switch (edid->pad) {
>  	case ADV7842_EDID_PORT_A:
> @@ -2071,8 +2069,6 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *e)
>  		return -EINVAL;
>  	if (e->blocks > 2)
>  		return -E2BIG;
> -	if (!e->edid)
> -		return -EINVAL;
>  
>  	/* todo, per edid */
>  	state->aspect_ratio = v4l2_calc_aspect_ratio(e->edid[0x15],
> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
> index 853fb84..f6185f9 100644
> --- a/drivers/media/v4l2-core/v4l2-subdev.c
> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> @@ -349,11 +349,27 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
>  			sd, pad, set_selection, subdev_fh, sel);
>  	}
>  
> -	case VIDIOC_SUBDEV_G_EDID:
> -		return v4l2_subdev_call(sd, pad, get_edid, arg);
> +	case VIDIOC_SUBDEV_G_EDID: {
> +		struct v4l2_subdev_edid *edid = arg;
>  
> -	case VIDIOC_SUBDEV_S_EDID:
> -		return v4l2_subdev_call(sd, pad, set_edid, arg);
> +		if (edid->pad >= sd->entity.num_pads)
> +			return -EINVAL;
> +		if (edid->blocks && edid->edid == NULL)
> +			return -EINVAL;
> +
> +		return v4l2_subdev_call(sd, pad, get_edid, edid);
> +	}
> +
> +	case VIDIOC_SUBDEV_S_EDID: {
> +		struct v4l2_subdev_edid *edid = arg;
> +
> +		if (edid->pad >= sd->entity.num_pads)
> +			return -EINVAL;
> +		if (edid->blocks && edid->edid == NULL)
> +			return -EINVAL;
> +
> +		return v4l2_subdev_call(sd, pad, set_edid, edid);
> +	}
>  
>  	case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
>  		struct v4l2_dv_timings_cap *cap = arg;
> 


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

* Re: [PATCH v3 27/48] v4l: Validate fields in the core code for subdev EDID ioctls
  2014-03-11 15:44     ` Hans Verkuil
@ 2014-03-11 16:08       ` Laurent Pinchart
  2014-03-11 16:11         ` Hans Verkuil
  0 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-11 16:08 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Hans,

On Tuesday 11 March 2014 16:44:27 Hans Verkuil wrote:
> On 03/11/2014 04:09 PM, Laurent Pinchart wrote:
> > The subdev EDID ioctls receive a pad field that must reference an
> > existing pad and an EDID field that must point to a buffer. Validate
> > both fields in the core code instead of duplicating validation in all
> > drivers.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> 
> Here is my:
> 
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> 
> But take note: the adv7604 driver does not handle a get_edid with
> edid->blocks == 0 correctly: it should fill in the blocks field with the
> real number of blocks and return 0 instead of returning EINVAL.

Should it also set edid->start_block to 0 ?

> I also read through the spec again and it does not actually explicitly say
> that you can use G_EDID with edid->blocks == 0, but I think it makes a lot
> of sense to do that.
> 
> All existing drivers that use get_edid all return -EINVAL if blocks == 0,
> so this patch does not change anything with that.
> 
> I plan on making a patch to clarify the spec and update the drivers, but you
> might want to make a patch for adv7604 yourself instead of waiting for me.
> I leave that up to you. Anyway, this patch is fine.
> 
> Regards,
> 
> 	Hans
> 
> > ---
> > 
> >  drivers/media/i2c/ad9389b.c           |  2 --
> >  drivers/media/i2c/adv7511.c           |  2 --
> >  drivers/media/i2c/adv7604.c           |  4 ----
> >  drivers/media/i2c/adv7842.c           |  4 ----
> >  drivers/media/v4l2-core/v4l2-subdev.c | 24 ++++++++++++++++++++----
> >  5 files changed, 20 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
> > index 4cdff9e..5b78828 100644
> > --- a/drivers/media/i2c/ad9389b.c
> > +++ b/drivers/media/i2c/ad9389b.c
> > @@ -683,8 +683,6 @@ static int ad9389b_get_edid(struct v4l2_subdev *sd,
> > 
> >  		return -EINVAL;
> >  	
> >  	if (edid->blocks == 0 || edid->blocks > 256)
> >  	
> >  		return -EINVAL;
> > 
> > -	if (!edid->edid)
> > -		return -EINVAL;
> > 
> >  	if (!state->edid.segments) {
> >  	
> >  		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
> >  		return -ENODATA;
> > 
> > diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
> > index de7ddf5..ff1c2cd 100644
> > --- a/drivers/media/i2c/adv7511.c
> > +++ b/drivers/media/i2c/adv7511.c
> > @@ -784,8 +784,6 @@ static int adv7511_get_edid(struct v4l2_subdev *sd,
> > 
> >  		return -EINVAL;
> >  	
> >  	if ((edid->blocks == 0) || (edid->blocks > 256))
> >  	
> >  		return -EINVAL;
> > 
> > -	if (!edid->edid)
> > -		return -EINVAL;
> > 
> >  	if (!state->edid.segments) {
> >  	
> >  		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
> >  		return -ENODATA;
> > 
> > diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> > index 71c8570..de3db42 100644
> > --- a/drivers/media/i2c/adv7604.c
> > +++ b/drivers/media/i2c/adv7604.c
> > @@ -1673,8 +1673,6 @@ static int adv7604_get_edid(struct v4l2_subdev *sd,
> > struct v4l2_subdev_edid *edi> 
> >  		return -EINVAL;
> >  	
> >  	if (edid->start_block == 1)
> >  	
> >  		edid->blocks = 1;
> > 
> > -	if (!edid->edid)
> > -		return -EINVAL;
> > 
> >  	if (edid->blocks > state->edid.blocks)
> >  	
> >  		edid->blocks = state->edid.blocks;
> > 
> > @@ -1761,8 +1759,6 @@ static int adv7604_set_edid(struct v4l2_subdev *sd,
> > struct v4l2_subdev_edid *edi> 
> >  		edid->blocks = 2;
> >  		return -E2BIG;
> >  	
> >  	}
> > 
> > -	if (!edid->edid)
> > -		return -EINVAL;
> > 
> >  	v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 
0x%x\n",
> >  	
> >  			__func__, edid->pad, state->edid.present);
> > 
> > diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
> > index a319275..3c5a7d9 100644
> > --- a/drivers/media/i2c/adv7842.c
> > +++ b/drivers/media/i2c/adv7842.c
> > @@ -2035,8 +2035,6 @@ static int adv7842_get_edid(struct v4l2_subdev *sd,
> > struct v4l2_subdev_edid *edi> 
> >  		return -EINVAL;
> >  	
> >  	if (edid->start_block == 1)
> >  	
> >  		edid->blocks = 1;
> > 
> > -	if (!edid->edid)
> > -		return -EINVAL;
> > 
> >  	switch (edid->pad) {
> > 
> >  	case ADV7842_EDID_PORT_A:
> > @@ -2071,8 +2069,6 @@ static int adv7842_set_edid(struct v4l2_subdev *sd,
> > struct v4l2_subdev_edid *e)> 
> >  		return -EINVAL;
> >  	
> >  	if (e->blocks > 2)
> >  	
> >  		return -E2BIG;
> > 
> > -	if (!e->edid)
> > -		return -EINVAL;
> > 
> >  	/* todo, per edid */
> >  	state->aspect_ratio = v4l2_calc_aspect_ratio(e->edid[0x15],
> > 
> > diff --git a/drivers/media/v4l2-core/v4l2-subdev.c
> > b/drivers/media/v4l2-core/v4l2-subdev.c index 853fb84..f6185f9 100644
> > --- a/drivers/media/v4l2-core/v4l2-subdev.c
> > +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> > @@ -349,11 +349,27 @@ static long subdev_do_ioctl(struct file *file,
> > unsigned int cmd, void *arg)> 
> >  			sd, pad, set_selection, subdev_fh, sel);
> >  	
> >  	}
> > 
> > -	case VIDIOC_SUBDEV_G_EDID:
> > -		return v4l2_subdev_call(sd, pad, get_edid, arg);
> > +	case VIDIOC_SUBDEV_G_EDID: {
> > +		struct v4l2_subdev_edid *edid = arg;
> > 
> > -	case VIDIOC_SUBDEV_S_EDID:
> > -		return v4l2_subdev_call(sd, pad, set_edid, arg);
> > +		if (edid->pad >= sd->entity.num_pads)
> > +			return -EINVAL;
> > +		if (edid->blocks && edid->edid == NULL)
> > +			return -EINVAL;
> > +
> > +		return v4l2_subdev_call(sd, pad, get_edid, edid);
> > +	}
> > +
> > +	case VIDIOC_SUBDEV_S_EDID: {
> > +		struct v4l2_subdev_edid *edid = arg;
> > +
> > +		if (edid->pad >= sd->entity.num_pads)
> > +			return -EINVAL;
> > +		if (edid->blocks && edid->edid == NULL)
> > +			return -EINVAL;
> > +
> > +		return v4l2_subdev_call(sd, pad, set_edid, edid);
> > +	}
> > 
> >  	case VIDIOC_SUBDEV_DV_TIMINGS_CAP: {
> >  	
> >  		struct v4l2_dv_timings_cap *cap = arg;

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH v3 27/48] v4l: Validate fields in the core code for subdev EDID ioctls
  2014-03-11 16:08       ` Laurent Pinchart
@ 2014-03-11 16:11         ` Hans Verkuil
  2014-03-11 16:24           ` Laurent Pinchart
  0 siblings, 1 reply; 93+ messages in thread
From: Hans Verkuil @ 2014-03-11 16:11 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 03/11/2014 05:08 PM, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Tuesday 11 March 2014 16:44:27 Hans Verkuil wrote:
>> On 03/11/2014 04:09 PM, Laurent Pinchart wrote:
>>> The subdev EDID ioctls receive a pad field that must reference an
>>> existing pad and an EDID field that must point to a buffer. Validate
>>> both fields in the core code instead of duplicating validation in all
>>> drivers.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
>>
>> Here is my:
>>
>> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
>>
>> But take note: the adv7604 driver does not handle a get_edid with
>> edid->blocks == 0 correctly: it should fill in the blocks field with the
>> real number of blocks and return 0 instead of returning EINVAL.
> 
> Should it also set edid->start_block to 0 ?

I don't think so. It makes sense to just set blocks to the total number of
available blocks - edid->start_block.

Note that if edid->start_block >= total number of EDID blocks, then -ENODATA
should be returned.

Regards,

	Hans

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

* Re: [PATCH v3 27/48] v4l: Validate fields in the core code for subdev EDID ioctls
  2014-03-11 16:11         ` Hans Verkuil
@ 2014-03-11 16:24           ` Laurent Pinchart
  2014-03-11 16:44             ` Hans Verkuil
  0 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-11 16:24 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Hans,

On Tuesday 11 March 2014 17:11:07 Hans Verkuil wrote:
> On 03/11/2014 05:08 PM, Laurent Pinchart wrote:
> > Hi Hans,
> > 
> > On Tuesday 11 March 2014 16:44:27 Hans Verkuil wrote:
> >> On 03/11/2014 04:09 PM, Laurent Pinchart wrote:
> >>> The subdev EDID ioctls receive a pad field that must reference an
> >>> existing pad and an EDID field that must point to a buffer. Validate
> >>> both fields in the core code instead of duplicating validation in all
> >>> drivers.
> >>> 
> >>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> >> 
> >> Here is my:
> >> 
> >> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> >> 
> >> But take note: the adv7604 driver does not handle a get_edid with
> >> edid->blocks == 0 correctly: it should fill in the blocks field with the
> >> real number of blocks and return 0 instead of returning EINVAL.
> > 
> > Should it also set edid->start_block to 0 ?
> 
> I don't think so. It makes sense to just set blocks to the total number of
> available blocks - edid->start_block.

OK.

> Note that if edid->start_block >= total number of EDID blocks, then -ENODATA
> should be returned.

What if S_EDID hasn't been called yet ? Should the driver set edid->blocks to 
0 and return success ? Or should it return -ENODATA ?

There's quite a few possible combinations, we should probably start by 
clarifying the spec.

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH v3 27/48] v4l: Validate fields in the core code for subdev EDID ioctls
  2014-03-11 16:24           ` Laurent Pinchart
@ 2014-03-11 16:44             ` Hans Verkuil
  0 siblings, 0 replies; 93+ messages in thread
From: Hans Verkuil @ 2014-03-11 16:44 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 03/11/2014 05:24 PM, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Tuesday 11 March 2014 17:11:07 Hans Verkuil wrote:
>> On 03/11/2014 05:08 PM, Laurent Pinchart wrote:
>>> Hi Hans,
>>>
>>> On Tuesday 11 March 2014 16:44:27 Hans Verkuil wrote:
>>>> On 03/11/2014 04:09 PM, Laurent Pinchart wrote:
>>>>> The subdev EDID ioctls receive a pad field that must reference an
>>>>> existing pad and an EDID field that must point to a buffer. Validate
>>>>> both fields in the core code instead of duplicating validation in all
>>>>> drivers.
>>>>>
>>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>>> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
>>>>
>>>> Here is my:
>>>>
>>>> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
>>>>
>>>> But take note: the adv7604 driver does not handle a get_edid with
>>>> edid->blocks == 0 correctly: it should fill in the blocks field with the
>>>> real number of blocks and return 0 instead of returning EINVAL.
>>>
>>> Should it also set edid->start_block to 0 ?
>>
>> I don't think so. It makes sense to just set blocks to the total number of
>> available blocks - edid->start_block.
> 
> OK.
> 
>> Note that if edid->start_block >= total number of EDID blocks, then -ENODATA
>> should be returned.
> 
> What if S_EDID hasn't been called yet ? Should the driver set edid->blocks to 
> 0 and return success ? Or should it return -ENODATA ?

If start_block == 0 and blocks == 0, then return 0. If start_block > 0, then you
attempt to read a block that doesn't exist, so -ENODATA should be returned.
 
> There's quite a few possible combinations, we should probably start by 
> clarifying the spec.
> 

It's easier to code:

	if (tot_blocks == 0) {
		/* Referring to blocks we don't have? Return -ENODATA! */
		if (edid->start_block || edid->blocks)
			return -ENODATA;
		/* We have 0 blocks starting at block 0, so that's perfectly
		   fine! */
		return 0;
	}
	if (edid->start_block >= tot_blocks)
		return -ENODATA;
	if (edid->blocks == 0) {
		edid->blocks = tot_blocks - edid->start_block;
		return 0;
	}
	if (tot_blocks - edid->start_block < edid->blocks)
		edid->blocks = tot_blocks - edid->start_block;
	/* copy edid->blocks from start_block to edid->edid */
	return 0;

Regards,

	Hans

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

* Re: [PATCH v2 14/48] media: bfin_capture: Switch to pad-level DV operations
  2014-03-10 23:15 ` [PATCH v2 14/48] media: bfin_capture: Switch to pad-level DV operations Laurent Pinchart
@ 2014-03-13  8:59   ` Scott Jiang
  0 siblings, 0 replies; 93+ messages in thread
From: Scott Jiang @ 2014-03-13  8:59 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: LMML, Hans Verkuil, Lars-Peter Clausen

2014-03-11 7:15 GMT+08:00 Laurent Pinchart <laurent.pinchart@ideasonboard.com>:
> The video-level enum_dv_timings and dv_timings_cap operations are
> deprecated in favor of the pad-level versions. All subdev drivers
> implement the pad-level versions, switch to them.
>
> Cc: Scott Jiang <scott.jiang.linux@gmail.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  drivers/media/platform/blackfin/bfin_capture.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
> index 200bec9..22fb701 100644
> --- a/drivers/media/platform/blackfin/bfin_capture.c
> +++ b/drivers/media/platform/blackfin/bfin_capture.c
> @@ -648,7 +648,9 @@ static int bcap_enum_dv_timings(struct file *file, void *priv,
>  {
>         struct bcap_device *bcap_dev = video_drvdata(file);
>
> -       return v4l2_subdev_call(bcap_dev->sd, video,
> +       timings->pad = 0;
> +
> +       return v4l2_subdev_call(bcap_dev->sd, pad,
>                         enum_dv_timings, timings);
>  }
>

Acked-by: Scott Jiang <scott.jiang.linux@gmail.com>

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

* Re: [PATCH v3 36/48] adv7604: Make output format configurable through pad format operations
  2014-03-11 15:10   ` [PATCH v3 " Laurent Pinchart
@ 2014-03-13 21:45     ` Hans Verkuil
  2014-03-18  9:32     ` Hans Verkuil
  1 sibling, 0 replies; 93+ messages in thread
From: Hans Verkuil @ 2014-03-13 21:45 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

On 03/11/2014 04:10 PM, Laurent Pinchart wrote:
> Replace the dummy video format operations by pad format operations that
> configure the output format.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

My apologies, I completely forgot to test this today. It's going to be Tuesday,
I'm afraid.

Sorry,

	Hans

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

* Re: [PATCH v3 36/48] adv7604: Make output format configurable through pad format operations
  2014-03-11 15:10   ` [PATCH v3 " Laurent Pinchart
  2014-03-13 21:45     ` Hans Verkuil
@ 2014-03-18  9:32     ` Hans Verkuil
  2014-03-18 13:02       ` Laurent Pinchart
  1 sibling, 1 reply; 93+ messages in thread
From: Hans Verkuil @ 2014-03-18  9:32 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Laurent,

I've tested it and I thought I was going crazy. Everything was fine after
applying this patch, but as soon as I applied the next patch (37/48) the
colors were wrong. But that patch had nothing whatsoever to do with the
bus ordering. You managed to make a small but crucial bug and it was pure
bad luck that it ever worked.

See details below:

On 03/11/14 16:10, Laurent Pinchart wrote:
> Replace the dummy video format operations by pad format operations that
> configure the output format.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/adv7604.c | 280 ++++++++++++++++++++++++++++++++++++++++----
>  include/media/adv7604.h     |  56 ++++-----
>  2 files changed, 275 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> index 851b350..5aa7c29 100644
> --- a/drivers/media/i2c/adv7604.c
> +++ b/drivers/media/i2c/adv7604.c
> @@ -53,6 +53,28 @@ MODULE_LICENSE("GPL");
>  /* ADV7604 system clock frequency */
>  #define ADV7604_fsc (28636360)
>  
> +#define ADV7604_RGB_OUT					(1 << 1)
> +
> +#define ADV7604_OP_FORMAT_SEL_8BIT			(0 << 0)
> +#define ADV7604_OP_FORMAT_SEL_10BIT			(1 << 0)
> +#define ADV7604_OP_FORMAT_SEL_12BIT			(2 << 0)
> +
> +#define ADV7604_OP_MODE_SEL_SDR_422			(0 << 5)
> +#define ADV7604_OP_MODE_SEL_DDR_422			(1 << 5)
> +#define ADV7604_OP_MODE_SEL_SDR_444			(2 << 5)
> +#define ADV7604_OP_MODE_SEL_DDR_444			(3 << 5)
> +#define ADV7604_OP_MODE_SEL_SDR_422_2X			(4 << 5)
> +#define ADV7604_OP_MODE_SEL_ADI_CM			(5 << 5)
> +
> +#define ADV7604_OP_CH_SEL_GBR				(0 << 5)
> +#define ADV7604_OP_CH_SEL_GRB				(1 << 5)
> +#define ADV7604_OP_CH_SEL_BGR				(2 << 5)
> +#define ADV7604_OP_CH_SEL_RGB				(3 << 5)
> +#define ADV7604_OP_CH_SEL_BRG				(4 << 5)
> +#define ADV7604_OP_CH_SEL_RBG				(5 << 5)

Note that these values are shifted 5 bits to the left...

> +
> +#define ADV7604_OP_SWAP_CB_CR				(1 << 0)
> +
>  enum adv7604_type {
>  	ADV7604,
>  	ADV7611,
> @@ -63,6 +85,14 @@ struct adv7604_reg_seq {
>  	u8 val;
>  };
>  
> +struct adv7604_format_info {
> +	enum v4l2_mbus_pixelcode code;
> +	u8 op_ch_sel;
> +	bool rgb_out;
> +	bool swap_cb_cr;
> +	u8 op_format_sel;
> +};
> +
>  struct adv7604_chip_info {
>  	enum adv7604_type type;
>  
> @@ -78,6 +108,9 @@ struct adv7604_chip_info {
>  	unsigned int tdms_lock_mask;
>  	unsigned int fmt_change_digital_mask;
>  
> +	const struct adv7604_format_info *formats;
> +	unsigned int nformats;
> +
>  	void (*set_termination)(struct v4l2_subdev *sd, bool enable);
>  	void (*setup_irqs)(struct v4l2_subdev *sd);
>  	unsigned int (*read_hdmi_pixelclock)(struct v4l2_subdev *sd);
> @@ -101,12 +134,18 @@ struct adv7604_chip_info {
>  struct adv7604_state {
>  	const struct adv7604_chip_info *info;
>  	struct adv7604_platform_data pdata;
> +
>  	struct v4l2_subdev sd;
>  	struct media_pad pads[ADV7604_PAD_MAX];
>  	unsigned int source_pad;
> +
>  	struct v4l2_ctrl_handler hdl;
> +
>  	enum adv7604_pad selected_input;
> +
>  	struct v4l2_dv_timings timings;
> +	const struct adv7604_format_info *format;
> +
>  	struct {
>  		u8 edid[256];
>  		u32 present;
> @@ -771,6 +810,93 @@ static void adv7604_write_reg_seq(struct v4l2_subdev *sd,
>  		adv7604_write_reg(sd, reg_seq[i].reg, reg_seq[i].val);
>  }
>  
> +/* -----------------------------------------------------------------------------
> + * Format helpers
> + */
> +
> +static const struct adv7604_format_info adv7604_formats[] = {
> +	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
> +	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_YUYV10_2X10, ADV7604_OP_CH_SEL_RGB, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
> +	{ V4L2_MBUS_FMT_YVYU10_2X10, ADV7604_OP_CH_SEL_RGB, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
> +	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
> +	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
> +	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_UYVY10_1X20, ADV7604_OP_CH_SEL_RBG, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
> +	{ V4L2_MBUS_FMT_VYUY10_1X20, ADV7604_OP_CH_SEL_RBG, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
> +	{ V4L2_MBUS_FMT_YUYV10_1X20, ADV7604_OP_CH_SEL_RGB, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
> +	{ V4L2_MBUS_FMT_YVYU10_1X20, ADV7604_OP_CH_SEL_RGB, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
> +	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> +	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> +	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> +	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> +};
> +
> +static const struct adv7604_format_info adv7611_formats[] = {
> +	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
> +	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
> +	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
> +	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> +	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> +	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> +	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> +	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> +};
> +
> +static const struct adv7604_format_info *
> +adv7604_format_info(struct adv7604_state *state, enum v4l2_mbus_pixelcode code)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < state->info->nformats; ++i) {
> +		if (state->info->formats[i].code == code)
> +			return &state->info->formats[i];
> +	}
> +
> +	return NULL;
> +}
> +
>  /* ----------------------------------------------------------------------- */
>  
>  static inline bool is_analog_input(struct v4l2_subdev *sd)
> @@ -1720,29 +1846,132 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
>  	return 0;
>  }
>  
> -static int adv7604_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
> -			     enum v4l2_mbus_pixelcode *code)
> +static int adv7604_enum_mbus_code(struct v4l2_subdev *sd,
> +				  struct v4l2_subdev_fh *fh,
> +				  struct v4l2_subdev_mbus_code_enum *code)
>  {
> -	if (index)
> +	struct adv7604_state *state = to_state(sd);
> +
> +	if (code->index >= state->info->nformats)
>  		return -EINVAL;
> -	/* Good enough for now */
> -	*code = V4L2_MBUS_FMT_FIXED;
> +
> +	code->code = state->info->formats[code->index].code;
> +
>  	return 0;
>  }
>  
> -static int adv7604_g_mbus_fmt(struct v4l2_subdev *sd,
> -		struct v4l2_mbus_framefmt *fmt)
> +static void adv7604_fill_format(struct adv7604_state *state,
> +				struct v4l2_mbus_framefmt *format)
>  {
> -	struct adv7604_state *state = to_state(sd);
> +	memset(format, 0, sizeof(*format));
>  
> -	fmt->width = state->timings.bt.width;
> -	fmt->height = state->timings.bt.height;
> -	fmt->code = V4L2_MBUS_FMT_FIXED;
> -	fmt->field = V4L2_FIELD_NONE;
> -	if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
> -		fmt->colorspace = (state->timings.bt.height <= 576) ?
> +	format->width = state->timings.bt.width;
> +	format->height = state->timings.bt.height;
> +	format->field = V4L2_FIELD_NONE;
> +
> +	if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861)
> +		format->colorspace = (state->timings.bt.height <= 576) ?
>  			V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
> +}
> +
> +/*
> + * Compute the op_ch_sel value required to obtain on the bus the component order
> + * corresponding to the selected format taking into account bus reordering
> + * applied by the board at the output of the device.
> + *
> + * The following table gives the op_ch_value from the format component order
> + * (expressed as op_ch_sel value in column) and the bus reordering (expressed as
> + * adv7604_bus_order value in row).
> + *
> + *           |	GBR(0)	GRB(1)	BGR(2)	RGB(3)	BRG(4)	RBG(5)
> + * ----------+-------------------------------------------------
> + * RGB (NOP) |	GBR	GRB	BGR	RGB	BRG	RBG
> + * GRB (1-2) |	BGR	RGB	GBR	GRB	RBG	BRG
> + * RBG (2-3) |	GRB	GBR	BRG	RBG	BGR	RGB
> + * BGR (1-3) |	RBG	BRG	RGB	BGR	GRB	GBR
> + * BRG (ROR) |	BRG	RBG	GRB	GBR	RGB	BGR
> + * GBR (ROL) |	RGB	BGR	RBG	BRG	GBR	GRB
> + */
> +static unsigned int adv7604_op_ch_sel(struct adv7604_state *state)
> +{
> +#define _SEL(a,b,c,d,e,f)	{ \
> +	ADV7604_OP_CH_SEL_##a, ADV7604_OP_CH_SEL_##b, ADV7604_OP_CH_SEL_##c, \
> +	ADV7604_OP_CH_SEL_##d, ADV7604_OP_CH_SEL_##e, ADV7604_OP_CH_SEL_##f }
> +#define _BUS(x)			[ADV7604_BUS_ORDER_##x]
> +
> +	static const unsigned int op_ch_sel[6][6] = {
> +		_BUS(RGB) /* NOP */ = _SEL(GBR, GRB, BGR, RGB, BRG, RBG),
> +		_BUS(GRB) /* 1-2 */ = _SEL(BGR, RGB, GBR, GRB, RBG, BRG),
> +		_BUS(RBG) /* 2-3 */ = _SEL(GRB, GBR, BRG, RBG, BGR, RGB),
> +		_BUS(BGR) /* 1-3 */ = _SEL(RBG, BRG, RGB, BGR, GRB, GBR),
> +		_BUS(BRG) /* ROR */ = _SEL(BRG, RBG, GRB, GBR, RGB, BGR),
> +		_BUS(GBR) /* ROL */ = _SEL(RGB, BGR, RBG, BRG, GBR, GRB),
> +	};
> +
> +	return op_ch_sel[state->pdata.bus_order][state->format->op_ch_sel];

But you don't shift state->format->op_ch_sel back 5 bits to the right, so
you end up with a random memory value. It should be:

	return op_ch_sel[state->pdata.bus_order][state->format->op_ch_sel >> 5];

After correcting this everything worked fine for me.

Regards,

	Hans

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

* Re: [PATCH v3 36/48] adv7604: Make output format configurable through pad format operations
  2014-03-18  9:32     ` Hans Verkuil
@ 2014-03-18 13:02       ` Laurent Pinchart
  2014-03-18 13:09         ` Hans Verkuil
  0 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-18 13:02 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Hans,

On Tuesday 18 March 2014 10:32:32 Hans Verkuil wrote:
> Hi Laurent,
> 
> I've tested it and I thought I was going crazy. Everything was fine after
> applying this patch, but as soon as I applied the next patch (37/48) the
> colors were wrong. But that patch had nothing whatsoever to do with the
> bus ordering. You managed to make a small but crucial bug and it was pure
> bad luck that it ever worked.
> 
> See details below:
> 
> On 03/11/14 16:10, Laurent Pinchart wrote:
> > Replace the dummy video format operations by pad format operations that
> > configure the output format.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  drivers/media/i2c/adv7604.c | 280 +++++++++++++++++++++++++++++++++++----
> >  include/media/adv7604.h     |  56 ++++-----
> >  2 files changed, 275 insertions(+), 61 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> > index 851b350..5aa7c29 100644
> > --- a/drivers/media/i2c/adv7604.c
> > +++ b/drivers/media/i2c/adv7604.c
> > @@ -53,6 +53,28 @@ MODULE_LICENSE("GPL");
> > 
> >  /* ADV7604 system clock frequency */
> >  #define ADV7604_fsc (28636360)
> > 
> > +#define ADV7604_RGB_OUT					(1 << 1)
> > +
> > +#define ADV7604_OP_FORMAT_SEL_8BIT			(0 << 0)
> > +#define ADV7604_OP_FORMAT_SEL_10BIT			(1 << 0)
> > +#define ADV7604_OP_FORMAT_SEL_12BIT			(2 << 0)
> > +
> > +#define ADV7604_OP_MODE_SEL_SDR_422			(0 << 5)
> > +#define ADV7604_OP_MODE_SEL_DDR_422			(1 << 5)
> > +#define ADV7604_OP_MODE_SEL_SDR_444			(2 << 5)
> > +#define ADV7604_OP_MODE_SEL_DDR_444			(3 << 5)
> > +#define ADV7604_OP_MODE_SEL_SDR_422_2X			(4 << 5)
> > +#define ADV7604_OP_MODE_SEL_ADI_CM			(5 << 5)
> > +
> > +#define ADV7604_OP_CH_SEL_GBR				(0 << 5)
> > +#define ADV7604_OP_CH_SEL_GRB				(1 << 5)
> > +#define ADV7604_OP_CH_SEL_BGR				(2 << 5)
> > +#define ADV7604_OP_CH_SEL_RGB				(3 << 5)
> > +#define ADV7604_OP_CH_SEL_BRG				(4 << 5)
> > +#define ADV7604_OP_CH_SEL_RBG				(5 << 5)
> 
> Note that these values are shifted 5 bits to the left...

[snip]

> > +struct adv7604_format_info {
> > +	enum v4l2_mbus_pixelcode code;
> > +	u8 op_ch_sel;
> > +	bool rgb_out;
> > +	bool swap_cb_cr;
> > +	u8 op_format_sel;
> > +};

[snip]

> > +static const struct adv7604_format_info adv7604_formats[] = {
> > +	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_YUYV10_2X10, ADV7604_OP_CH_SEL_RGB, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
> > +	{ V4L2_MBUS_FMT_YVYU10_2X10, ADV7604_OP_CH_SEL_RGB, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
> > +	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
> > +	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
> > +	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_UYVY10_1X20, ADV7604_OP_CH_SEL_RBG, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
> > +	{ V4L2_MBUS_FMT_VYUY10_1X20, ADV7604_OP_CH_SEL_RBG, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
> > +	{ V4L2_MBUS_FMT_YUYV10_1X20, ADV7604_OP_CH_SEL_RGB, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
> > +	{ V4L2_MBUS_FMT_YVYU10_1X20, ADV7604_OP_CH_SEL_RGB, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
> > +	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> > +	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> > +	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> > +	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> > +};
> > +
> > +static const struct adv7604_format_info adv7611_formats[] = {
> > +	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
> > +	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
> > +	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
> > +	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> > +	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> > +	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> > +	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
> > +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
> > +};

[snip]

> > +/*
> > + * Compute the op_ch_sel value required to obtain on the bus the
> > component order
> > + * corresponding to the selected format taking into account bus
> > reordering
> > + * applied by the board at the output of the device.
> > + *
> > + * The following table gives the op_ch_value from the format component
> > order
> > + * (expressed as op_ch_sel value in column) and the bus reordering
> > (expressed as
> > + * adv7604_bus_order value in row).
> > + *
> > + *           |	GBR(0)	GRB(1)	BGR(2)	RGB(3)	BRG(4)	RBG(5)
> > + * ----------+-------------------------------------------------
> > + * RGB (NOP) |	GBR	GRB	BGR	RGB	BRG	RBG
> > + * GRB (1-2) |	BGR	RGB	GBR	GRB	RBG	BRG
> > + * RBG (2-3) |	GRB	GBR	BRG	RBG	BGR	RGB
> > + * BGR (1-3) |	RBG	BRG	RGB	BGR	GRB	GBR
> > + * BRG (ROR) |	BRG	RBG	GRB	GBR	RGB	BGR
> > + * GBR (ROL) |	RGB	BGR	RBG	BRG	GBR	GRB
> > + */
> > +static unsigned int adv7604_op_ch_sel(struct adv7604_state *state)
> > +{
> > +#define _SEL(a,b,c,d,e,f)	{ \
> > +	ADV7604_OP_CH_SEL_##a, ADV7604_OP_CH_SEL_##b, ADV7604_OP_CH_SEL_##c, 
\
> > +	ADV7604_OP_CH_SEL_##d, ADV7604_OP_CH_SEL_##e, ADV7604_OP_CH_SEL_##f }
> > +#define _BUS(x)			[ADV7604_BUS_ORDER_##x]
> > +
> > +	static const unsigned int op_ch_sel[6][6] = {
> > +		_BUS(RGB) /* NOP */ = _SEL(GBR, GRB, BGR, RGB, BRG, RBG),
> > +		_BUS(GRB) /* 1-2 */ = _SEL(BGR, RGB, GBR, GRB, RBG, BRG),
> > +		_BUS(RBG) /* 2-3 */ = _SEL(GRB, GBR, BRG, RBG, BGR, RGB),
> > +		_BUS(BGR) /* 1-3 */ = _SEL(RBG, BRG, RGB, BGR, GRB, GBR),
> > +		_BUS(BRG) /* ROR */ = _SEL(BRG, RBG, GRB, GBR, RGB, BGR),
> > +		_BUS(GBR) /* ROL */ = _SEL(RGB, BGR, RBG, BRG, GBR, GRB),
> > +	};
> > +
> > +	return op_ch_sel[state->pdata.bus_order][state->format->op_ch_sel];
> 
> But you don't shift state->format->op_ch_sel back 5 bits to the right, so
> you end up with a random memory value. It should be:
> 
> 	return op_ch_sel[state->pdata.bus_order][state->format->op_ch_sel >> 5];
> 
> After correcting this everything worked fine for me.

Good catch ! Thank you. I've fixed that and submitted v4.

In addition to this patch, I'm only missing your Acked-by or Reviewed-by tag 
for patch 47/48 ("adv7604: Add LLC polarity configuration"). Could you please 
provide that ? I'll then send a pull request to Mauro for the whole series.

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH v2 47/48] adv7604: Add LLC polarity configuration
  2014-03-10 23:15 ` [PATCH v2 47/48] adv7604: Add LLC polarity configuration Laurent Pinchart
@ 2014-03-18 13:05   ` Hans Verkuil
  2014-04-17 11:29   ` Sylwester Nawrocki
  1 sibling, 0 replies; 93+ messages in thread
From: Hans Verkuil @ 2014-03-18 13:05 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

On 03/11/2014 12:15 AM, Laurent Pinchart wrote:
> Add an inv_llc_pol field to platform data to control the clock polarity.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>

Regards,

	Hans

> ---
>  drivers/media/i2c/adv7604.c | 3 ++-
>  include/media/adv7604.h     | 1 +
>  2 files changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> index de44213..95cc911 100644
> --- a/drivers/media/i2c/adv7604.c
> +++ b/drivers/media/i2c/adv7604.c
> @@ -2429,7 +2429,8 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
>  	cp_write(sd, 0x69, 0x30);   /* Enable CP CSC */
>  
>  	/* VS, HS polarities */
> -	io_write(sd, 0x06, 0xa0 | pdata->inv_vs_pol << 2 | pdata->inv_hs_pol << 1);
> +	io_write(sd, 0x06, 0xa0 | pdata->inv_vs_pol << 2 |
> +		 pdata->inv_hs_pol << 1 | pdata->inv_llc_pol);
>  
>  	/* Adjust drive strength */
>  	io_write(sd, 0x14, 0x40 | pdata->dr_str_data << 4 |
> diff --git a/include/media/adv7604.h b/include/media/adv7604.h
> index 6d69207..7a8462f 100644
> --- a/include/media/adv7604.h
> +++ b/include/media/adv7604.h
> @@ -114,6 +114,7 @@ struct adv7604_platform_data {
>  	/* IO register 0x06 */
>  	unsigned inv_vs_pol:1;
>  	unsigned inv_hs_pol:1;
> +	unsigned inv_llc_pol:1;
>  
>  	/* IO register 0x14 */
>  	enum adv7604_drive_strength dr_str_data;
> 


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

* Re: [PATCH v3 36/48] adv7604: Make output format configurable through pad format operations
  2014-03-18 13:02       ` Laurent Pinchart
@ 2014-03-18 13:09         ` Hans Verkuil
  0 siblings, 0 replies; 93+ messages in thread
From: Hans Verkuil @ 2014-03-18 13:09 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 03/18/2014 02:02 PM, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Tuesday 18 March 2014 10:32:32 Hans Verkuil wrote:
>> Hi Laurent,
>>
>> I've tested it and I thought I was going crazy. Everything was fine after
>> applying this patch, but as soon as I applied the next patch (37/48) the
>> colors were wrong. But that patch had nothing whatsoever to do with the
>> bus ordering. You managed to make a small but crucial bug and it was pure
>> bad luck that it ever worked.
>>
>> See details below:
>>
>> On 03/11/14 16:10, Laurent Pinchart wrote:
>>> Replace the dummy video format operations by pad format operations that
>>> configure the output format.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> ---
>>>
>>>  drivers/media/i2c/adv7604.c | 280 +++++++++++++++++++++++++++++++++++----
>>>  include/media/adv7604.h     |  56 ++++-----
>>>  2 files changed, 275 insertions(+), 61 deletions(-)
>>>
>>> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
>>> index 851b350..5aa7c29 100644
>>> --- a/drivers/media/i2c/adv7604.c
>>> +++ b/drivers/media/i2c/adv7604.c
>>> @@ -53,6 +53,28 @@ MODULE_LICENSE("GPL");
>>>
>>>  /* ADV7604 system clock frequency */
>>>  #define ADV7604_fsc (28636360)
>>>
>>> +#define ADV7604_RGB_OUT					(1 << 1)
>>> +
>>> +#define ADV7604_OP_FORMAT_SEL_8BIT			(0 << 0)
>>> +#define ADV7604_OP_FORMAT_SEL_10BIT			(1 << 0)
>>> +#define ADV7604_OP_FORMAT_SEL_12BIT			(2 << 0)
>>> +
>>> +#define ADV7604_OP_MODE_SEL_SDR_422			(0 << 5)
>>> +#define ADV7604_OP_MODE_SEL_DDR_422			(1 << 5)
>>> +#define ADV7604_OP_MODE_SEL_SDR_444			(2 << 5)
>>> +#define ADV7604_OP_MODE_SEL_DDR_444			(3 << 5)
>>> +#define ADV7604_OP_MODE_SEL_SDR_422_2X			(4 << 5)
>>> +#define ADV7604_OP_MODE_SEL_ADI_CM			(5 << 5)
>>> +
>>> +#define ADV7604_OP_CH_SEL_GBR				(0 << 5)
>>> +#define ADV7604_OP_CH_SEL_GRB				(1 << 5)
>>> +#define ADV7604_OP_CH_SEL_BGR				(2 << 5)
>>> +#define ADV7604_OP_CH_SEL_RGB				(3 << 5)
>>> +#define ADV7604_OP_CH_SEL_BRG				(4 << 5)
>>> +#define ADV7604_OP_CH_SEL_RBG				(5 << 5)
>>
>> Note that these values are shifted 5 bits to the left...
> 
> [snip]
> 
>>> +struct adv7604_format_info {
>>> +	enum v4l2_mbus_pixelcode code;
>>> +	u8 op_ch_sel;
>>> +	bool rgb_out;
>>> +	bool swap_cb_cr;
>>> +	u8 op_format_sel;
>>> +};
> 
> [snip]
> 
>>> +static const struct adv7604_format_info adv7604_formats[] = {
>>> +	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_YUYV10_2X10, ADV7604_OP_CH_SEL_RGB, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
>>> +	{ V4L2_MBUS_FMT_YVYU10_2X10, ADV7604_OP_CH_SEL_RGB, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
>>> +	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_UYVY10_1X20, ADV7604_OP_CH_SEL_RBG, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
>>> +	{ V4L2_MBUS_FMT_VYUY10_1X20, ADV7604_OP_CH_SEL_RBG, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
>>> +	{ V4L2_MBUS_FMT_YUYV10_1X20, ADV7604_OP_CH_SEL_RGB, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
>>> +	{ V4L2_MBUS_FMT_YVYU10_1X20, ADV7604_OP_CH_SEL_RGB, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
>>> +	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +};
>>> +
>>> +static const struct adv7604_format_info adv7611_formats[] = {
>>> +	{ V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +	{ V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +	{ V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
>>> +	{ V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +	{ V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +	{ V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +	{ V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
>>> +	  ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
>>> +};
> 
> [snip]
> 
>>> +/*
>>> + * Compute the op_ch_sel value required to obtain on the bus the
>>> component order
>>> + * corresponding to the selected format taking into account bus
>>> reordering
>>> + * applied by the board at the output of the device.
>>> + *
>>> + * The following table gives the op_ch_value from the format component
>>> order
>>> + * (expressed as op_ch_sel value in column) and the bus reordering
>>> (expressed as
>>> + * adv7604_bus_order value in row).
>>> + *
>>> + *           |	GBR(0)	GRB(1)	BGR(2)	RGB(3)	BRG(4)	RBG(5)
>>> + * ----------+-------------------------------------------------
>>> + * RGB (NOP) |	GBR	GRB	BGR	RGB	BRG	RBG
>>> + * GRB (1-2) |	BGR	RGB	GBR	GRB	RBG	BRG
>>> + * RBG (2-3) |	GRB	GBR	BRG	RBG	BGR	RGB
>>> + * BGR (1-3) |	RBG	BRG	RGB	BGR	GRB	GBR
>>> + * BRG (ROR) |	BRG	RBG	GRB	GBR	RGB	BGR
>>> + * GBR (ROL) |	RGB	BGR	RBG	BRG	GBR	GRB
>>> + */
>>> +static unsigned int adv7604_op_ch_sel(struct adv7604_state *state)
>>> +{
>>> +#define _SEL(a,b,c,d,e,f)	{ \
>>> +	ADV7604_OP_CH_SEL_##a, ADV7604_OP_CH_SEL_##b, ADV7604_OP_CH_SEL_##c, 
> \
>>> +	ADV7604_OP_CH_SEL_##d, ADV7604_OP_CH_SEL_##e, ADV7604_OP_CH_SEL_##f }
>>> +#define _BUS(x)			[ADV7604_BUS_ORDER_##x]
>>> +
>>> +	static const unsigned int op_ch_sel[6][6] = {
>>> +		_BUS(RGB) /* NOP */ = _SEL(GBR, GRB, BGR, RGB, BRG, RBG),
>>> +		_BUS(GRB) /* 1-2 */ = _SEL(BGR, RGB, GBR, GRB, RBG, BRG),
>>> +		_BUS(RBG) /* 2-3 */ = _SEL(GRB, GBR, BRG, RBG, BGR, RGB),
>>> +		_BUS(BGR) /* 1-3 */ = _SEL(RBG, BRG, RGB, BGR, GRB, GBR),
>>> +		_BUS(BRG) /* ROR */ = _SEL(BRG, RBG, GRB, GBR, RGB, BGR),
>>> +		_BUS(GBR) /* ROL */ = _SEL(RGB, BGR, RBG, BRG, GBR, GRB),
>>> +	};
>>> +
>>> +	return op_ch_sel[state->pdata.bus_order][state->format->op_ch_sel];
>>
>> But you don't shift state->format->op_ch_sel back 5 bits to the right, so
>> you end up with a random memory value. It should be:
>>
>> 	return op_ch_sel[state->pdata.bus_order][state->format->op_ch_sel >> 5];
>>
>> After correcting this everything worked fine for me.
> 
> Good catch ! Thank you. I've fixed that and submitted v4.
> 
> In addition to this patch, I'm only missing your Acked-by or Reviewed-by tag 
> for patch 47/48 ("adv7604: Add LLC polarity configuration"). Could you please 
> provide that ?

Done.

> I'll then send a pull request to Mauro for the whole series.

I'll test v4 of this patch tomorrow (ping me if you haven't seen anything from me
by 11 am!). If all is well, then I'll reply with my reviewed-by and tested-by
tags.

Regards,

	Hans

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

* Re: [PATCH v2 46/48] adv7604: Add DT support
  2014-03-10 23:15 ` [PATCH v2 46/48] adv7604: Add DT support Laurent Pinchart
  2014-03-11 15:11   ` [PATCH v3 " Laurent Pinchart
@ 2014-04-17 10:59   ` Sylwester Nawrocki
  2014-04-17 12:36     ` Laurent Pinchart
  1 sibling, 1 reply; 93+ messages in thread
From: Sylwester Nawrocki @ 2014-04-17 10:59 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Hans Verkuil, Lars-Peter Clausen, devicetree

Hi Laurent.

On 11/03/14 00:15, Laurent Pinchart wrote:
> Parse the device tree node to populate platform data.
> 
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  .../devicetree/bindings/media/i2c/adv7604.txt      | 56 +++++++++++++
>  drivers/media/i2c/adv7604.c                        | 92 ++++++++++++++++++----
>  2 files changed, 134 insertions(+), 14 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/media/i2c/adv7604.txt
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> new file mode 100644
> index 0000000..0845c50
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> @@ -0,0 +1,56 @@
> +* Analog Devices ADV7604/11 video decoder with HDMI receiver
> +
> +The ADV7604 and ADV7611 are multiformat video decoders with an integrated HDMI
> +receiver. The ADV7604 has four multiplexed HDMI inputs and one analog input,
> +and the ADV7611 has one HDMI input and no analog input.
> +
> +Required Properties:
> +
> +  - compatible: Must contain one of the following
> +    - "adi,adv7604" for the ADV7604
> +    - "adi,adv7611" for the ADV7611
> +
> +  - reg: I2C slave address
> +
> +  - hpd-gpios: References to the GPIOs that control the HDMI hot-plug
> +    detection pins, one per HDMI input. The active flag indicates the GPIO
> +    level that enables hot-plug detection.
> +
> +Optional Properties:
> +
> +  - reset-gpios: Reference to the GPIO connected to the device's reset pin.
> +
> +  - adi,default-input: Index of the input to be configured as default. Valid
> +    values are 0..5 for the ADV7604 and 0 for the ADV7611.

I have some doubts about this property. Firstly, it seems it is not needed for
ADV7611 since it is always 0 for that device ?
Why can't we hard code in the driver some default input ?
And which inputs it refers to ? HDMI inputs A..D + analog ? If we keep this 
property I think exact mapping of numbers to inputs should be included 
in description of this property.	

> +  - adi,disable-power-down: Boolean property. When set forces the device to
> +    ignore the power-down pin. The property is valid for the ADV7604 only as
> +    the ADV7611 has no power-down pin.

Does it refer to the !PWRDWN pin ? If so I would replace "power-down" with
PWRDWN, so it is clear what we're talking about when someone looks only
at the datasheet.

> +  - adi,disable-cable-reset: Boolean property. When set disables the HDMI
> +    receiver automatic reset when the HDMI cable is unplugged.

Couldn't this be configured from user space with some default assumed
in the driver ?

> +Example:
> +
> +	hdmi_receiver@4c {
> +		compatible = "adi,adv7611";
> +		reg = <0x4c>;
> +
> +		reset-gpios = <&ioexp 0 GPIO_ACTIVE_LOW>;
> +		hpd-gpios = <&ioexp 2 GPIO_ACTIVE_HIGH>;
> +
> +		adi,default-input = <0>;
> +
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		port@0 {
> +			reg = <0>;
> +		};
> +		port@1 {
> +			reg = <1>;
> +			hdmi_in: endpoint {
> +				remote-endpoint = <&ccdc_in>;
> +			};
> +		};
> +	};
> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> index cce140c..de44213 100644
> --- a/drivers/media/i2c/adv7604.c
> +++ b/drivers/media/i2c/adv7604.c
> @@ -2626,13 +2626,70 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
>  	},
>  };
>  
> +static struct i2c_device_id adv7604_i2c_id[] = {
> +	{ "adv7604", (kernel_ulong_t)&adv7604_chip_info[ADV7604] },
> +	{ "adv7611", (kernel_ulong_t)&adv7604_chip_info[ADV7611] },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, adv7604_i2c_id);
> +
> +static struct of_device_id adv7604_of_id[] = {
> +	{ .compatible = "adi,adv7604", .data = &adv7604_chip_info[ADV7604] },
> +	{ .compatible = "adi,adv7611", .data = &adv7604_chip_info[ADV7611] },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, adv7604_of_id);
> +
> +static int adv7604_parse_dt(struct adv7604_state *state)
> +{
> +	struct device_node *np;
> +	int ret;
> +
> +	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
> +
> +	state->pdata.disable_pwrdnb =
> +		of_property_read_bool(np, "adi,disable-power-down");
> +	state->pdata.disable_cable_det_rst =
> +		of_property_read_bool(np, "adi,disable-cable-reset");
> +
> +	ret = of_property_read_u32(np, "adi,default-input",
> +				   &state->pdata.default_input);
> +	if (ret < 0)
> +		state->pdata.default_input = -1;
> +
> +	/* Disable the interrupt for now as no DT-based board uses it. */
> +	state->pdata.int1_config = ADV7604_INT1_CONFIG_DISABLED;
> +
> +	/* Use the default I2C addresses. */
> +	state->pdata.i2c_addresses[ADV7604_PAGE_AVLINK] = 0x42;
> +	state->pdata.i2c_addresses[ADV7604_PAGE_CEC] = 0x40;
> +	state->pdata.i2c_addresses[ADV7604_PAGE_INFOFRAME] = 0x3e;
> +	state->pdata.i2c_addresses[ADV7604_PAGE_ESDP] = 0x38;
> +	state->pdata.i2c_addresses[ADV7604_PAGE_DPP] = 0x3c;
> +	state->pdata.i2c_addresses[ADV7604_PAGE_AFE] = 0x26;
> +	state->pdata.i2c_addresses[ADV7604_PAGE_REP] = 0x32;
> +	state->pdata.i2c_addresses[ADV7604_PAGE_EDID] = 0x36;
> +	state->pdata.i2c_addresses[ADV7604_PAGE_HDMI] = 0x34;
> +	state->pdata.i2c_addresses[ADV7604_PAGE_TEST] = 0x30;
> +	state->pdata.i2c_addresses[ADV7604_PAGE_CP] = 0x22;
> +	state->pdata.i2c_addresses[ADV7604_PAGE_VDP] = 0x24;
> +
> +	/* HACK: Hardcode the remaining platform data fields. */
> +	state->pdata.blank_data = 1;
> +	state->pdata.op_656_range = 1;
> +	state->pdata.alt_data_sat = 1;
> +	state->pdata.insert_av_codes = 1;
> +	state->pdata.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0;
> +
> +	return 0;
> +}
> +
>  static int adv7604_probe(struct i2c_client *client,
>  			 const struct i2c_device_id *id)
>  {
>  	static const struct v4l2_dv_timings cea640x480 =
>  		V4L2_DV_BT_CEA_640X480P59_94;
>  	struct adv7604_state *state;
> -	struct adv7604_platform_data *pdata = client->dev.platform_data;
>  	struct v4l2_ctrl_handler *hdl;
>  	struct v4l2_subdev *sd;
>  	unsigned int i;
> @@ -2651,19 +2708,32 @@ static int adv7604_probe(struct i2c_client *client,
>  		return -ENOMEM;
>  	}
>  
> -	state->info = &adv7604_chip_info[id->driver_data];
>  	state->i2c_clients[ADV7604_PAGE_IO] = client;
>  
>  	/* initialize variables */
>  	state->restart_stdi_once = true;
>  	state->selected_input = ~0;
>  
> -	/* platform data */
> -	if (!pdata) {
> +	if (IS_ENABLED(CONFIG_OF) && client->dev.of_node) {
> +		const struct of_device_id *oid;
> +
> +		oid = of_match_node(adv7604_of_id, client->dev.of_node);
> +		state->info = oid->data;
> +
> +		err = adv7604_parse_dt(state);
> +		if (err < 0) {
> +			v4l_err(client, "DT parsing error\n");
> +			return err;
> +		}
> +	} else if (client->dev.platform_data) {
> +		struct adv7604_platform_data *pdata = client->dev.platform_data;
> +
> +		state->info = (const struct adv7604_chip_info *)id->driver_data;
> +		state->pdata = *pdata;
> +	} else {
>  		v4l_err(client, "No platform data!\n");
>  		return -ENODEV;
>  	}
> -	state->pdata = *pdata;
>  
>  	/* Request GPIOs. */
>  	for (i = 0; i < state->info->num_dv_ports; ++i) {
> @@ -2762,7 +2832,7 @@ static int adv7604_probe(struct i2c_client *client,
>  			continue;
>  
>  		state->i2c_clients[i] =
> -			adv7604_dummy_client(sd, pdata->i2c_addresses[i],
> +			adv7604_dummy_client(sd, state->pdata.i2c_addresses[i],
>  					     0xf2 + i);
>  		if (state->i2c_clients[i] == NULL) {
>  			err = -ENOMEM;
> @@ -2836,21 +2906,15 @@ static int adv7604_remove(struct i2c_client *client)
>  
>  /* ----------------------------------------------------------------------- */
>  
> -static struct i2c_device_id adv7604_id[] = {
> -	{ "adv7604", ADV7604 },
> -	{ "adv7611", ADV7611 },
> -	{ }
> -};
> -MODULE_DEVICE_TABLE(i2c, adv7604_id);
> -
>  static struct i2c_driver adv7604_driver = {
>  	.driver = {
>  		.owner = THIS_MODULE,
>  		.name = "adv7604",
> +		.of_match_table = of_match_ptr(adv7604_of_id),

of_match_ptr() isn't necessary here.

>  	},
>  	.probe = adv7604_probe,
>  	.remove = adv7604_remove,
> -	.id_table = adv7604_id,
> +	.id_table = adv7604_i2c_id,
>  };
>  
>  module_i2c_driver(adv7604_driver);

--
Regards,
Sylwester

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

* Re: [PATCH v2 48/48] adv7604: Add endpoint properties to DT bindings
  2014-03-10 23:15 ` [PATCH v2 48/48] adv7604: Add endpoint properties to DT bindings Laurent Pinchart
@ 2014-04-17 11:17   ` Sylwester Nawrocki
  2014-04-17 12:45     ` Laurent Pinchart
  0 siblings, 1 reply; 93+ messages in thread
From: Sylwester Nawrocki @ 2014-04-17 11:17 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Hi Laurent,

On 11/03/14 00:15, Laurent Pinchart wrote:
> Add support for the hsync-active, vsync-active and pclk-sample
> properties to the DT bindings and control BT.656 mode implicitly.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  .../devicetree/bindings/media/i2c/adv7604.txt      | 13 +++++++++
>  drivers/media/i2c/adv7604.c                        | 31 ++++++++++++++++++++--
>  2 files changed, 42 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> index 0845c50..2b62c06 100644
> --- a/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> +++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> @@ -30,6 +30,19 @@ Optional Properties:
>    - adi,disable-cable-reset: Boolean property. When set disables the HDMI
>      receiver automatic reset when the HDMI cable is unplugged.
>  
> +Optional Endpoint Properties:
> +
> +  The following three properties are defined in video-interfaces.txt and are
> +  valid for source endpoints only.
> +
> +  - hsync-active: Horizontal synchronization polarity. Defaults to active low.
> +  - vsync-active: Vertical synchronization polarity. Defaults to active low.
> +  - pclk-sample: Pixel clock polarity. Defaults to output on the falling edge.
> +
> +  If none of hsync-active, vsync-active and pclk-sample is specified the
> +  endpoint will use embedded BT.656 synchronization.
> +
> +
>  Example:
>  
>  	hdmi_receiver@4c {
> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> index 95cc911..2a92099 100644
> --- a/drivers/media/i2c/adv7604.c
> +++ b/drivers/media/i2c/adv7604.c
> @@ -41,6 +41,7 @@
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-dv-timings.h>
> +#include <media/v4l2-of.h>
>  
>  static int debug;
>  module_param(debug, int, 0644);
> @@ -2643,11 +2644,39 @@ MODULE_DEVICE_TABLE(of, adv7604_of_id);
>  
>  static int adv7604_parse_dt(struct adv7604_state *state)
>  {
> +	struct v4l2_of_endpoint bus_cfg;
> +	struct device_node *endpoint;
>  	struct device_node *np;
> +	unsigned int flags;
>  	int ret;
>  
>  	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
>  
> +	/* Parse the endpoint. */
> +	endpoint = v4l2_of_get_next_endpoint(np, NULL);
> +	if (!endpoint)
> +		return -EINVAL;

Perhaps we should document this binding requires at least one endpoint
node ? I guess there is no point in not having any endpoint node ?

> +	v4l2_of_parse_endpoint(endpoint, &bus_cfg);
> +	of_node_put(endpoint);
> +
> +	flags = bus_cfg.bus.parallel.flags;
> +
> +	if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
> +		state->pdata.inv_hs_pol = 1;
> +
> +	if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
> +		state->pdata.inv_vs_pol = 1;
> +
> +	if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
> +		state->pdata.inv_llc_pol = 1;
> +
> +	if (bus_cfg.bus_type == V4L2_MBUS_BT656) {
> +		state->pdata.insert_av_codes = 1;
> +		state->pdata.op_656_range = 1;
> +	}
> +
> +	/* Parse device-specific properties. */
>  	state->pdata.disable_pwrdnb =
>  		of_property_read_bool(np, "adi,disable-power-down");
>  	state->pdata.disable_cable_det_rst =
> @@ -2677,9 +2706,7 @@ static int adv7604_parse_dt(struct adv7604_state *state)
>  
>  	/* HACK: Hardcode the remaining platform data fields. */
>  	state->pdata.blank_data = 1;
> -	state->pdata.op_656_range = 1;
>  	state->pdata.alt_data_sat = 1;
> -	state->pdata.insert_av_codes = 1;
>  	state->pdata.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0;
>  
>  	return 0;

--
Regards,
Sylwester

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

* Re: [PATCH v2 47/48] adv7604: Add LLC polarity configuration
  2014-03-10 23:15 ` [PATCH v2 47/48] adv7604: Add LLC polarity configuration Laurent Pinchart
  2014-03-18 13:05   ` Hans Verkuil
@ 2014-04-17 11:29   ` Sylwester Nawrocki
  1 sibling, 0 replies; 93+ messages in thread
From: Sylwester Nawrocki @ 2014-04-17 11:29 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 11/03/14 00:15, Laurent Pinchart wrote:
> Add an inv_llc_pol field to platform data to control the clock polarity.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

> ---
>  drivers/media/i2c/adv7604.c | 3 ++-
>  include/media/adv7604.h     | 1 +
>  2 files changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> index de44213..95cc911 100644
> --- a/drivers/media/i2c/adv7604.c
> +++ b/drivers/media/i2c/adv7604.c
> @@ -2429,7 +2429,8 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
>  	cp_write(sd, 0x69, 0x30);   /* Enable CP CSC */
>  
>  	/* VS, HS polarities */
> -	io_write(sd, 0x06, 0xa0 | pdata->inv_vs_pol << 2 | pdata->inv_hs_pol << 1);
> +	io_write(sd, 0x06, 0xa0 | pdata->inv_vs_pol << 2 |
> +		 pdata->inv_hs_pol << 1 | pdata->inv_llc_pol);
>  
>  	/* Adjust drive strength */
>  	io_write(sd, 0x14, 0x40 | pdata->dr_str_data << 4 |
> diff --git a/include/media/adv7604.h b/include/media/adv7604.h
> index 6d69207..7a8462f 100644
> --- a/include/media/adv7604.h
> +++ b/include/media/adv7604.h
> @@ -114,6 +114,7 @@ struct adv7604_platform_data {
>  	/* IO register 0x06 */
>  	unsigned inv_vs_pol:1;
>  	unsigned inv_hs_pol:1;
> +	unsigned inv_llc_pol:1;
>  
>  	/* IO register 0x14 */
>  	enum adv7604_drive_strength dr_str_data;
> 

-- 
Regards,
Sylwester

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

* Re: [PATCH v2 46/48] adv7604: Add DT support
  2014-04-17 10:59   ` [PATCH v2 " Sylwester Nawrocki
@ 2014-04-17 12:36     ` Laurent Pinchart
  2014-04-17 13:08       ` Laurent Pinchart
  0 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-04-17 12:36 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-media, Hans Verkuil, Lars-Peter Clausen, devicetree

Hi Sylwester,

Thank you for the review.

On Thursday 17 April 2014 12:59:22 Sylwester Nawrocki wrote:
> On 11/03/14 00:15, Laurent Pinchart wrote:
> > Parse the device tree node to populate platform data.
> > 
> > Cc: devicetree@vger.kernel.org
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  .../devicetree/bindings/media/i2c/adv7604.txt      | 56 +++++++++++++
> >  drivers/media/i2c/adv7604.c                        | 92 +++++++++++++----
> >  2 files changed, 134 insertions(+), 14 deletions(-)
> >  create mode 100644
> >  Documentation/devicetree/bindings/media/i2c/adv7604.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> > b/Documentation/devicetree/bindings/media/i2c/adv7604.txt new file mode
> > 100644
> > index 0000000..0845c50
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> > @@ -0,0 +1,56 @@
> > +* Analog Devices ADV7604/11 video decoder with HDMI receiver
> > +
> > +The ADV7604 and ADV7611 are multiformat video decoders with an integrated
> > HDMI +receiver. The ADV7604 has four multiplexed HDMI inputs and one
> > analog input, +and the ADV7611 has one HDMI input and no analog input.
> > +
> > +Required Properties:
> > +
> > +  - compatible: Must contain one of the following
> > +    - "adi,adv7604" for the ADV7604
> > +    - "adi,adv7611" for the ADV7611
> > +
> > +  - reg: I2C slave address
> > +
> > +  - hpd-gpios: References to the GPIOs that control the HDMI hot-plug
> > +    detection pins, one per HDMI input. The active flag indicates the
> > GPIO
> > +    level that enables hot-plug detection.
> > +
> > +Optional Properties:
> > +
> > +  - reset-gpios: Reference to the GPIO connected to the device's reset
> > pin. +
> > +  - adi,default-input: Index of the input to be configured as default.
> > Valid
> > +    values are 0..5 for the ADV7604 and 0 for the ADV7611.
> 
> I have some doubts about this property. Firstly, it seems it is not needed
> for ADV7611 since it is always 0 for that device ?
> Why can't we hard code in the driver some default input ?

I've thought about hardcoding a default input in the driver as well, but Hans 
wasn't really keen on the idea. Hans, could you please comment on this ?

> And which inputs it refers to ? HDMI inputs A..D + analog ? If we keep this
> property I think exact mapping of numbers to inputs should be included
> in description of this property.
> 
> > +  - adi,disable-power-down: Boolean property. When set forces the device
> > to
> > +    ignore the power-down pin. The property is valid for the ADV7604 only
> > as
> > +    the ADV7611 has no power-down pin.
> 
> Does it refer to the !PWRDWN pin ? If so I would replace "power-down" with
> PWRDWN, so it is clear what we're talking about when someone looks only
> at the datasheet.
>
> > +  - adi,disable-cable-reset: Boolean property. When set disables the HDMI
> > +    receiver automatic reset when the HDMI cable is unplugged.
> 
> Couldn't this be configured from user space with some default assumed in the
> driver ?

Good question. I'm not sure what the exact use case for this is.

Let's be careful not to introduce unneeded properties, I'll drop those two 
properties for now, we can implement support for the features later when 
needed.

> > +Example:
> > +
> > +	hdmi_receiver@4c {
> > +		compatible = "adi,adv7611";
> > +		reg = <0x4c>;
> > +
> > +		reset-gpios = <&ioexp 0 GPIO_ACTIVE_LOW>;
> > +		hpd-gpios = <&ioexp 2 GPIO_ACTIVE_HIGH>;
> > +
> > +		adi,default-input = <0>;
> > +
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +
> > +		port@0 {
> > +			reg = <0>;
> > +		};
> > +		port@1 {
> > +			reg = <1>;
> > +			hdmi_in: endpoint {
> > +				remote-endpoint = <&ccdc_in>;
> > +			};
> > +		};
> > +	};
> > diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> > index cce140c..de44213 100644
> > --- a/drivers/media/i2c/adv7604.c
> > +++ b/drivers/media/i2c/adv7604.c

[snip]

> > @@ -2836,21 +2906,15 @@ static int adv7604_remove(struct i2c_client
> > *client)> 
> >  /* ------------------------------------------------------------------- */
> > -static struct i2c_device_id adv7604_id[] = {
> > -	{ "adv7604", ADV7604 },
> > -	{ "adv7611", ADV7611 },
> > -	{ }
> > -};
> > -MODULE_DEVICE_TABLE(i2c, adv7604_id);
> > -
> >  static struct i2c_driver adv7604_driver = {
> >  	.driver = {
> >  		.owner = THIS_MODULE,
> >  		.name = "adv7604",
> > +		.of_match_table = of_match_ptr(adv7604_of_id),
> 
> of_match_ptr() isn't necessary here.

Thanks, will fix in v3.

> >  	},
> >  	.probe = adv7604_probe,
> >  	.remove = adv7604_remove,
> > -	.id_table = adv7604_id,
> > +	.id_table = adv7604_i2c_id,
> >  };
> >  
> >  module_i2c_driver(adv7604_driver);

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v2 48/48] adv7604: Add endpoint properties to DT bindings
  2014-04-17 11:17   ` Sylwester Nawrocki
@ 2014-04-17 12:45     ` Laurent Pinchart
  2014-04-17 13:00       ` Ben Dooks
  0 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-04-17 12:45 UTC (permalink / raw)
  To: Sylwester Nawrocki; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Sylwester,

On Thursday 17 April 2014 13:17:41 Sylwester Nawrocki wrote:
> On 11/03/14 00:15, Laurent Pinchart wrote:
> > Add support for the hsync-active, vsync-active and pclk-sample
> > properties to the DT bindings and control BT.656 mode implicitly.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  .../devicetree/bindings/media/i2c/adv7604.txt      | 13 +++++++++
> >  drivers/media/i2c/adv7604.c                        | 31
> >  ++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> > b/Documentation/devicetree/bindings/media/i2c/adv7604.txt index
> > 0845c50..2b62c06 100644
> > --- a/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> > +++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> > 
> > @@ -30,6 +30,19 @@ Optional Properties:
> >    - adi,disable-cable-reset: Boolean property. When set disables the HDMI
> >    
> >      receiver automatic reset when the HDMI cable is unplugged.
> > 
> > +Optional Endpoint Properties:
> > +
> > +  The following three properties are defined in video-interfaces.txt and
> > are +  valid for source endpoints only.
> > +
> > +  - hsync-active: Horizontal synchronization polarity. Defaults to active
> > low. +  - vsync-active: Vertical synchronization polarity. Defaults to
> > active low. +  - pclk-sample: Pixel clock polarity. Defaults to output on
> > the falling edge. +
> > +  If none of hsync-active, vsync-active and pclk-sample is specified the
> > +  endpoint will use embedded BT.656 synchronization.
> > +
> > +
> > 
> >  Example:
> >  	hdmi_receiver@4c {
> > 
> > diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> > index 95cc911..2a92099 100644
> > --- a/drivers/media/i2c/adv7604.c
> > +++ b/drivers/media/i2c/adv7604.c
> > @@ -41,6 +41,7 @@
> > 
> >  #include <media/v4l2-ctrls.h>
> >  #include <media/v4l2-device.h>
> >  #include <media/v4l2-dv-timings.h>
> > 
> > +#include <media/v4l2-of.h>
> > 
> >  static int debug;
> >  module_param(debug, int, 0644);
> > 
> > @@ -2643,11 +2644,39 @@ MODULE_DEVICE_TABLE(of, adv7604_of_id);
> > 
> >  static int adv7604_parse_dt(struct adv7604_state *state)
> >  {
> > 
> > +	struct v4l2_of_endpoint bus_cfg;
> > +	struct device_node *endpoint;
> > 
> >  	struct device_node *np;
> > 
> > +	unsigned int flags;
> > 
> >  	int ret;
> >  	
> >  	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
> > 
> > +	/* Parse the endpoint. */
> > +	endpoint = v4l2_of_get_next_endpoint(np, NULL);
> > +	if (!endpoint)
> > +		return -EINVAL;
> 
> Perhaps we should document this binding requires at least one endpoint
> node ? I guess there is no point in not having any endpoint node ?

I think that's pretty much implied, otherwise the device will not be connected 
to anything and will be unusable. I will document ports node usage though, 
that's currently missing in the DT bindings documentation.

> > +	v4l2_of_parse_endpoint(endpoint, &bus_cfg);
> > +	of_node_put(endpoint);
> > +
> > +	flags = bus_cfg.bus.parallel.flags;
> > +
> > +	if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
> > +		state->pdata.inv_hs_pol = 1;
> > +
> > +	if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
> > +		state->pdata.inv_vs_pol = 1;
> > +
> > +	if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
> > +		state->pdata.inv_llc_pol = 1;
> > +
> > +	if (bus_cfg.bus_type == V4L2_MBUS_BT656) {
> > +		state->pdata.insert_av_codes = 1;
> > +		state->pdata.op_656_range = 1;
> > +	}
> > +
> > +	/* Parse device-specific properties. */
> > 
> >  	state->pdata.disable_pwrdnb =
> >  	
> >  		of_property_read_bool(np, "adi,disable-power-down");
> >  	
> >  	state->pdata.disable_cable_det_rst =
> > 
> > @@ -2677,9 +2706,7 @@ static int adv7604_parse_dt(struct adv7604_state
> > *state)> 
> >  	/* HACK: Hardcode the remaining platform data fields. */
> >  	state->pdata.blank_data = 1;
> > 
> > -	state->pdata.op_656_range = 1;
> > 
> >  	state->pdata.alt_data_sat = 1;
> > 
> > -	state->pdata.insert_av_codes = 1;
> > 
> >  	state->pdata.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0;
> >  	
> >  	return 0;

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH v2 48/48] adv7604: Add endpoint properties to DT bindings
  2014-04-17 12:45     ` Laurent Pinchart
@ 2014-04-17 13:00       ` Ben Dooks
  2014-04-17 13:04         ` Laurent Pinchart
  0 siblings, 1 reply; 93+ messages in thread
From: Ben Dooks @ 2014-04-17 13:00 UTC (permalink / raw)
  To: Laurent Pinchart, Sylwester Nawrocki
  Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 17/04/14 13:45, Laurent Pinchart wrote:
> Hi Sylwester,
>
> On Thursday 17 April 2014 13:17:41 Sylwester Nawrocki wrote:
>> On 11/03/14 00:15, Laurent Pinchart wrote:
>>> Add support for the hsync-active, vsync-active and pclk-sample
>>> properties to the DT bindings and control BT.656 mode implicitly.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>> ---
>>>
>>>   .../devicetree/bindings/media/i2c/adv7604.txt      | 13 +++++++++
>>>   drivers/media/i2c/adv7604.c                        | 31
>>>   ++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt
>>> b/Documentation/devicetree/bindings/media/i2c/adv7604.txt index
>>> 0845c50..2b62c06 100644
>>> --- a/Documentation/devicetree/bindings/media/i2c/adv7604.txt
>>> +++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
>>>
>>> @@ -30,6 +30,19 @@ Optional Properties:
>>>     - adi,disable-cable-reset: Boolean property. When set disables the HDMI
>>>
>>>       receiver automatic reset when the HDMI cable is unplugged.
>>>
>>> +Optional Endpoint Properties:
>>> +
>>> +  The following three properties are defined in video-interfaces.txt and
>>> are +  valid for source endpoints only.
>>> +
>>> +  - hsync-active: Horizontal synchronization polarity. Defaults to active
>>> low. +  - vsync-active: Vertical synchronization polarity. Defaults to
>>> active low. +  - pclk-sample: Pixel clock polarity. Defaults to output on
>>> the falling edge. +
>>> +  If none of hsync-active, vsync-active and pclk-sample is specified the
>>> +  endpoint will use embedded BT.656 synchronization.
>>> +
>>> +
>>>
>>>   Example:
>>>   	hdmi_receiver@4c {
>>>
>>> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
>>> index 95cc911..2a92099 100644
>>> --- a/drivers/media/i2c/adv7604.c
>>> +++ b/drivers/media/i2c/adv7604.c
>>> @@ -41,6 +41,7 @@
>>>
>>>   #include <media/v4l2-ctrls.h>
>>>   #include <media/v4l2-device.h>
>>>   #include <media/v4l2-dv-timings.h>
>>>
>>> +#include <media/v4l2-of.h>
>>>
>>>   static int debug;
>>>   module_param(debug, int, 0644);
>>>
>>> @@ -2643,11 +2644,39 @@ MODULE_DEVICE_TABLE(of, adv7604_of_id);
>>>
>>>   static int adv7604_parse_dt(struct adv7604_state *state)
>>>   {
>>>
>>> +	struct v4l2_of_endpoint bus_cfg;
>>> +	struct device_node *endpoint;
>>>
>>>   	struct device_node *np;
>>>
>>> +	unsigned int flags;
>>>
>>>   	int ret;
>>>   	
>>>   	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
>>>
>>> +	/* Parse the endpoint. */
>>> +	endpoint = v4l2_of_get_next_endpoint(np, NULL);
>>> +	if (!endpoint)
>>> +		return -EINVAL;
>>
>> Perhaps we should document this binding requires at least one endpoint
>> node ? I guess there is no point in not having any endpoint node ?
>
> I think that's pretty much implied, otherwise the device will not be connected
> to anything and will be unusable. I will document ports node usage though,
> that's currently missing in the DT bindings documentation.

Doesn't the v4l2 helper code have standard parsing for the
endpoint sync configurations?


-- 
Ben Dooks				http://www.codethink.co.uk/
Senior Engineer				Codethink - Providing Genius

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

* Re: [PATCH v2 48/48] adv7604: Add endpoint properties to DT bindings
  2014-04-17 13:00       ` Ben Dooks
@ 2014-04-17 13:04         ` Laurent Pinchart
  0 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-04-17 13:04 UTC (permalink / raw)
  To: Ben Dooks
  Cc: Sylwester Nawrocki, linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Ben,

On Thursday 17 April 2014 14:00:15 Ben Dooks wrote:
> On 17/04/14 13:45, Laurent Pinchart wrote:
> > Hi Sylwester,
> > 
> > On Thursday 17 April 2014 13:17:41 Sylwester Nawrocki wrote:
> >> On 11/03/14 00:15, Laurent Pinchart wrote:
> >>> Add support for the hsync-active, vsync-active and pclk-sample
> >>> properties to the DT bindings and control BT.656 mode implicitly.
> >>> 
> >>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>> ---
> >>> 
> >>>   .../devicetree/bindings/media/i2c/adv7604.txt      | 13 +++++++++
> >>>   drivers/media/i2c/adv7604.c                        | 31
> >>>   ++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2
> >>>   deletions(-)
> >>> 
> >>> diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> >>> b/Documentation/devicetree/bindings/media/i2c/adv7604.txt index
> >>> 0845c50..2b62c06 100644
> >>> --- a/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> >>> +++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> >>> 
> >>> @@ -30,6 +30,19 @@ Optional Properties:
> >>>     - adi,disable-cable-reset: Boolean property. When set disables the
> >>>     HDMI
> >>>     
> >>>       receiver automatic reset when the HDMI cable is unplugged.
> >>> 
> >>> +Optional Endpoint Properties:
> >>> +
> >>> +  The following three properties are defined in video-interfaces.txt
> >>> and
> >>> are +  valid for source endpoints only.
> >>> +
> >>> +  - hsync-active: Horizontal synchronization polarity. Defaults to
> >>> active
> >>> low. +  - vsync-active: Vertical synchronization polarity. Defaults to
> >>> active low. +  - pclk-sample: Pixel clock polarity. Defaults to output
> >>> on
> >>> the falling edge. +
> >>> +  If none of hsync-active, vsync-active and pclk-sample is specified
> >>> the
> >>> +  endpoint will use embedded BT.656 synchronization.
> >>> +
> >>> +
> >>> 
> >>>   Example:
> >>>   	hdmi_receiver@4c {
> >>> 
> >>> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> >>> index 95cc911..2a92099 100644
> >>> --- a/drivers/media/i2c/adv7604.c
> >>> +++ b/drivers/media/i2c/adv7604.c
> >>> @@ -41,6 +41,7 @@
> >>>  #include <media/v4l2-ctrls.h>
> >>>  #include <media/v4l2-device.h>
> >>>  #include <media/v4l2-dv-timings.h>
> >>> +#include <media/v4l2-of.h>
> >>> 
> >>>  static int debug;
> >>>  module_param(debug, int, 0644);
> >>> @@ -2643,11 +2644,39 @@ MODULE_DEVICE_TABLE(of, adv7604_of_id);
> >>> 
> >>>   static int adv7604_parse_dt(struct adv7604_state *state)
> >>>   {
> >>> +	struct v4l2_of_endpoint bus_cfg;
> >>> +	struct device_node *endpoint;
> >>>   	struct device_node *np;
> >>> +	unsigned int flags;
> >>>   	int ret;
> >>>   	
> >>>   	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
> >>> 
> >>> +	/* Parse the endpoint. */
> >>> +	endpoint = v4l2_of_get_next_endpoint(np, NULL);
> >>> +	if (!endpoint)
> >>> +		return -EINVAL;
> >> 
> >> Perhaps we should document this binding requires at least one endpoint
> >> node ? I guess there is no point in not having any endpoint node ?
> > 
> > I think that's pretty much implied, otherwise the device will not be
> > connected to anything and will be unusable. I will document ports node
> > usage though, that's currently missing in the DT bindings documentation.
> 
> Doesn't the v4l2 helper code have standard parsing for the
> endpoint sync configurations?

Yes it does, in the v4l2_of_parse_endpoint() function which the driver uses.

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH v2 46/48] adv7604: Add DT support
  2014-04-17 12:36     ` Laurent Pinchart
@ 2014-04-17 13:08       ` Laurent Pinchart
  2014-04-17 13:41         ` Sylwester Nawrocki
  0 siblings, 1 reply; 93+ messages in thread
From: Laurent Pinchart @ 2014-04-17 13:08 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-media, Hans Verkuil, Lars-Peter Clausen, devicetree

Hi Sylwester,

On Thursday 17 April 2014 14:36:32 Laurent Pinchart wrote:
> On Thursday 17 April 2014 12:59:22 Sylwester Nawrocki wrote:
> > On 11/03/14 00:15, Laurent Pinchart wrote:
> > > Parse the device tree node to populate platform data.
> > > 
> > > Cc: devicetree@vger.kernel.org
> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > > ---
> > > 
> > >  .../devicetree/bindings/media/i2c/adv7604.txt      | 56 +++++++++++++
> > >  drivers/media/i2c/adv7604.c                        | 92
> > >  +++++++++++++----
> > >  2 files changed, 134 insertions(+), 14 deletions(-)
> > >  create mode 100644
> > >  Documentation/devicetree/bindings/media/i2c/adv7604.txt
> > > 
> > > diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> > > b/Documentation/devicetree/bindings/media/i2c/adv7604.txt new file mode
> > > 100644
> > > index 0000000..0845c50
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
> > > @@ -0,0 +1,56 @@
> > > +* Analog Devices ADV7604/11 video decoder with HDMI receiver
> > > +
> > > +The ADV7604 and ADV7611 are multiformat video decoders with an
> > > integrated
> > > HDMI +receiver. The ADV7604 has four multiplexed HDMI inputs and one
> > > analog input, +and the ADV7611 has one HDMI input and no analog input.
> > > +
> > > +Required Properties:
> > > +
> > > +  - compatible: Must contain one of the following
> > > +    - "adi,adv7604" for the ADV7604
> > > +    - "adi,adv7611" for the ADV7611
> > > +
> > > +  - reg: I2C slave address
> > > +
> > > +  - hpd-gpios: References to the GPIOs that control the HDMI hot-plug
> > > +    detection pins, one per HDMI input. The active flag indicates the
> > > GPIO
> > > +    level that enables hot-plug detection.
> > > +
> > > +Optional Properties:
> > > +
> > > +  - reset-gpios: Reference to the GPIO connected to the device's reset
> > > pin. +
> > > +  - adi,default-input: Index of the input to be configured as default.
> > > Valid
> > > +    values are 0..5 for the ADV7604 and 0 for the ADV7611.
> > 
> > I have some doubts about this property. Firstly, it seems it is not needed
> > for ADV7611 since it is always 0 for that device ?
> > Why can't we hard code in the driver some default input ?
> 
> I've thought about hardcoding a default input in the driver as well, but
> Hans wasn't really keen on the idea. Hans, could you please comment on this
> ?
> > And which inputs it refers to ? HDMI inputs A..D + analog ? If we keep
> > this
> > property I think exact mapping of numbers to inputs should be included
> > in description of this property.
> > 
> > > +  - adi,disable-power-down: Boolean property. When set forces the
> > > device
> > > to
> > > +    ignore the power-down pin. The property is valid for the ADV7604
> > > only
> > > as
> > > +    the ADV7611 has no power-down pin.
> > 
> > Does it refer to the !PWRDWN pin ? If so I would replace "power-down" with
> > PWRDWN, so it is clear what we're talking about when someone looks only
> > at the datasheet.
> > 
> > > +  - adi,disable-cable-reset: Boolean property. When set disables the
> > > HDMI
> > > +    receiver automatic reset when the HDMI cable is unplugged.
> > 
> > Couldn't this be configured from user space with some default assumed in
> > the driver ?
> 
> Good question. I'm not sure what the exact use case for this is.
> 
> Let's be careful not to introduce unneeded properties, I'll drop those two
> properties for now, we can implement support for the features later when
> needed.
> 
> > > +Example:
> > > +
> > > +	hdmi_receiver@4c {
> > > +		compatible = "adi,adv7611";
> > > +		reg = <0x4c>;
> > > +
> > > +		reset-gpios = <&ioexp 0 GPIO_ACTIVE_LOW>;
> > > +		hpd-gpios = <&ioexp 2 GPIO_ACTIVE_HIGH>;
> > > +
> > > +		adi,default-input = <0>;
> > > +
> > > +		#address-cells = <1>;
> > > +		#size-cells = <0>;
> > > +
> > > +		port@0 {
> > > +			reg = <0>;
> > > +		};
> > > +		port@1 {
> > > +			reg = <1>;
> > > +			hdmi_in: endpoint {
> > > +				remote-endpoint = <&ccdc_in>;
> > > +			};
> > > +		};
> > > +	};
> > > diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> > > index cce140c..de44213 100644
> > > --- a/drivers/media/i2c/adv7604.c
> > > +++ b/drivers/media/i2c/adv7604.c
> 
> [snip]
> 
> > > @@ -2836,21 +2906,15 @@ static int adv7604_remove(struct i2c_client
> > > *client)>
> > > 
> > >  /* -------------------------------------------------------------------
> > >  */
> > > 
> > > -static struct i2c_device_id adv7604_id[] = {
> > > -	{ "adv7604", ADV7604 },
> > > -	{ "adv7611", ADV7611 },
> > > -	{ }
> > > -};
> > > -MODULE_DEVICE_TABLE(i2c, adv7604_id);
> > > -
> > > 
> > >  static struct i2c_driver adv7604_driver = {
> > >  
> > >  	.driver = {
> > >  	
> > >  		.owner = THIS_MODULE,
> > >  		.name = "adv7604",
> > > 
> > > +		.of_match_table = of_match_ptr(adv7604_of_id),
> > 
> > of_match_ptr() isn't necessary here.
> 
> Thanks, will fix in v3.

On second thought, as the driver has non-DT users, keeping of_match_ptr() and 
marking the table as __maybe_unused will optimize the table out if neither 
CONFIG_OF nor CONFIG_MODULE is set. I'd thus prefer keeping of_match_ptr().

> > >  	},
> > >  	.probe = adv7604_probe,
> > >  	.remove = adv7604_remove,
> > > 
> > > -	.id_table = adv7604_id,
> > > +	.id_table = adv7604_i2c_id,
> > > 
> > >  };
> > >  
> > >  module_i2c_driver(adv7604_driver);

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v2 46/48] adv7604: Add DT support
  2014-04-17 13:08       ` Laurent Pinchart
@ 2014-04-17 13:41         ` Sylwester Nawrocki
  0 siblings, 0 replies; 93+ messages in thread
From: Sylwester Nawrocki @ 2014-04-17 13:41 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Hans Verkuil, Lars-Peter Clausen, devicetree

On 17/04/14 15:08, Laurent Pinchart wrote:
>>>>  static struct i2c_driver adv7604_driver = {
>>>> > > >  
>>>> > > >  	.driver = {
>>>> > > >  	
>>>> > > >  		.owner = THIS_MODULE,
>>>> > > >  		.name = "adv7604",
>>>> > > > 
>>>> > > > +		.of_match_table = of_match_ptr(adv7604_of_id),
>>> > > 
>>> > > of_match_ptr() isn't necessary here.
>> > 
>> > Thanks, will fix in v3.
>
> On second thought, as the driver has non-DT users, keeping of_match_ptr() and 
> marking the table as __maybe_unused will optimize the table out if neither 
> CONFIG_OF nor CONFIG_MODULE is set. I'd thus prefer keeping of_match_ptr().

Yes, itsounds like a good idea to me. This way we avoid unpleasant #ifdefs
and do not increase size of the module for non-dt users.

--
Regards,
Sylwester

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

* [PATCH v2 00/48] ADV7611 support
@ 2014-03-10 23:14 Laurent Pinchart
  0 siblings, 0 replies; 93+ messages in thread
From: Laurent Pinchart @ 2014-03-10 23:14 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Hello,

This patch set implements support for the ADV7611 in the adv7604 driver. It
also comes up with new features such as output format configuration through
pad format operations, hot-plug detect control through GPIO and DT support.

Patches 06/48 to 24/48 and 39/48 replace the subdev video DV timings query cap
and enum operations with pad-level equivalents. I've split driver changes in
one patch per driver to make review easier, but I can squash them together if
desired.

I believe I've addressed all comments received on v1, except the one related
to op_ch_sel in patch "adv7604: Make output format configurable through pad
format operations" which is still open for discussion.

Patches 02/48 to 05/48 have been acked in v1 already, I will send a pull
request for them separately if a v3 of this series ends up being needed. I'd
like to get patch 01/48 upstream soon as well.

Changes compared to v1:

- Check the edid and pad fields for various ioctls in the subdev core
- Switch to the descriptor-based GPIO API
- Leave enum adv7604_pad in header file
- Keep the hotplug notifier
- Fix compilation breakage when !CONFIG_OF due to directly dereferencing the
  return value of of_match_node()
- Move patch "v4l: subdev: Remove deprecated video-level DV timings
  operations" later in the series to avoid bisection breakages
- Document struct v4l2_enum_dv_timings reserved field as being set to 0 by
  both drivers and application
- Document pad field of struct v4l2_enum_dv_timings and struct
  v4l2_dv_timings_cap as being used for subdev nodes only
- Typo fixes in documentation

Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Tomasz Stanislawski <t.stanislaws@samsung.com>
Cc: Scott Jiang <scott.jiang.linux@gmail.com>
Cc: Prabhakar Lad <prabhakar.csengg@gmail.com>

Lars-Peter Clausen (4):
  adv7604: Add missing include to linux/types.h
  adv7604: Add support for asynchronous probing
  adv7604: Don't put info string arrays on the stack
  adv7604: Add adv7611 support

Laurent Pinchart (44):
  v4l: of: Support empty port nodes
  v4l: Add UYVY10_2X10 and VYUY10_2X10 media bus pixel codes
  v4l: Add UYVY10_1X20 and VYUY10_1X20 media bus pixel codes
  v4l: Add 12-bit YUV 4:2:0 media bus pixel codes
  v4l: Add 12-bit YUV 4:2:2 media bus pixel codes
  v4l: Add pad-level DV timings subdev operations
  ad9389b: Add pad-level DV timings operations
  adv7511: Add pad-level DV timings operations
  adv7842: Add pad-level DV timings operations
  s5p-tv: hdmi: Add pad-level DV timings operations
  s5p-tv: hdmiphy: Add pad-level DV timings operations
  ths8200: Add pad-level DV timings operations
  tvp7002: Add pad-level DV timings operations
  media: bfin_capture: Switch to pad-level DV operations
  media: davinci: vpif: Switch to pad-level DV operations
  media: staging: davinci: vpfe: Switch to pad-level DV operations
  s5p-tv: mixer: Switch to pad-level DV operations
  ad9389b: Remove deprecated video-level DV timings operations
  adv7511: Remove deprecated video-level DV timings operations
  adv7842: Remove deprecated video-level DV timings operations
  s5p-tv: hdmi: Remove deprecated video-level DV timings operations
  s5p-tv: hdmiphy: Remove deprecated video-level DV timings operation
  ths8200: Remove deprecated video-level DV timings operations
  tvp7002: Remove deprecated video-level DV timings operations
  v4l: Improve readability by not wrapping ioctl number #define's
  v4l: Add support for DV timings ioctls on subdev nodes
  v4l: Validate fields in the core code for subdev EDID ioctls
  adv7604: Add 16-bit read functions for CP and HDMI
  adv7604: Cache register contents when reading multiple bits
  adv7604: Remove subdev control handlers
  adv7604: Add sink pads
  adv7604: Make output format configurable through pad format operations
  adv7604: Add pad-level DV timings support
  adv7604: Remove deprecated video-level DV timings operations
  v4l: subdev: Remove deprecated video-level DV timings operations
  adv7604: Inline the to_sd function
  adv7604: Store I2C addresses and clients in arrays
  adv7604: Replace *_and_or() functions with *_clr_set()
  adv7604: Sort headers alphabetically
  adv7604: Support hot-plug detect control through a GPIO
  adv7604: Specify the default input through platform data
  adv7604: Add DT support
  adv7604: Add LLC polarity configuration
  adv7604: Add endpoint properties to DT bindings

 Documentation/DocBook/media/v4l/subdev-formats.xml |  760 +++++++++++
 .../DocBook/media/v4l/vidioc-dv-timings-cap.xml    |   27 +-
 .../DocBook/media/v4l/vidioc-enum-dv-timings.xml   |   30 +-
 .../devicetree/bindings/media/i2c/adv7604.txt      |   69 +
 drivers/media/i2c/ad9389b.c                        |   65 +-
 drivers/media/i2c/adv7511.c                        |   67 +-
 drivers/media/i2c/adv7604.c                        | 1440 ++++++++++++++------
 drivers/media/i2c/adv7842.c                        |   14 +-
 drivers/media/i2c/ths8200.c                        |   10 +
 drivers/media/i2c/tvp7002.c                        |    5 +-
 drivers/media/platform/blackfin/bfin_capture.c     |    4 +-
 drivers/media/platform/davinci/vpif_capture.c      |    4 +-
 drivers/media/platform/davinci/vpif_display.c      |    4 +-
 drivers/media/platform/s5p-tv/hdmi_drv.c           |   14 +-
 drivers/media/platform/s5p-tv/hdmiphy_drv.c        |    9 +-
 drivers/media/platform/s5p-tv/mixer_video.c        |    8 +-
 drivers/media/v4l2-core/v4l2-of.c                  |   52 +-
 drivers/media/v4l2-core/v4l2-subdev.c              |   51 +-
 drivers/staging/media/davinci_vpfe/vpfe_video.c    |    4 +-
 include/media/adv7604.h                            |  113 +-
 include/media/v4l2-subdev.h                        |    8 +-
 include/uapi/linux/v4l2-mediabus.h                 |   14 +-
 include/uapi/linux/v4l2-subdev.h                   |   38 +-
 include/uapi/linux/videodev2.h                     |   10 +-
 24 files changed, 2174 insertions(+), 646 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/adv7604.txt

-- 
Regards,

Laurent Pinchart


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

end of thread, other threads:[~2014-04-17 13:41 UTC | newest]

Thread overview: 93+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-10 23:15 [PATCH v2 00/48] ADV7611 support Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 01/48] v4l: of: Support empty port nodes Laurent Pinchart
2014-03-11 12:05   ` Sylwester Nawrocki
2014-03-10 23:15 ` [PATCH v2 02/48] v4l: Add UYVY10_2X10 and VYUY10_2X10 media bus pixel codes Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 03/48] v4l: Add UYVY10_1X20 and VYUY10_1X20 " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 04/48] v4l: Add 12-bit YUV 4:2:0 " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 05/48] v4l: Add 12-bit YUV 4:2:2 " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 06/48] v4l: Add pad-level DV timings subdev operations Laurent Pinchart
2014-03-11  7:24   ` Prabhakar Lad
2014-03-11 10:27   ` Hans Verkuil
2014-03-10 23:15 ` [PATCH v2 07/48] ad9389b: Add pad-level DV timings operations Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 08/48] adv7511: " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 09/48] adv7842: " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 10/48] s5p-tv: hdmi: " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 11/48] s5p-tv: hdmiphy: " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 12/48] ths8200: " Laurent Pinchart
2014-03-11  7:11   ` Prabhakar Lad
2014-03-10 23:15 ` [PATCH v2 13/48] tvp7002: " Laurent Pinchart
2014-03-11  7:12   ` Prabhakar Lad
2014-03-10 23:15 ` [PATCH v2 14/48] media: bfin_capture: Switch to pad-level DV operations Laurent Pinchart
2014-03-13  8:59   ` Scott Jiang
2014-03-10 23:15 ` [PATCH v2 15/48] media: davinci: vpif: " Laurent Pinchart
2014-03-11  7:15   ` Prabhakar Lad
2014-03-10 23:15 ` [PATCH v2 16/48] media: staging: davinci: vpfe: " Laurent Pinchart
2014-03-11  7:16   ` Prabhakar Lad
2014-03-10 23:15 ` [PATCH v2 17/48] s5p-tv: mixer: " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 18/48] ad9389b: Remove deprecated video-level DV timings operations Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 19/48] adv7511: " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 20/48] adv7842: " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 21/48] s5p-tv: hdmi: " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 22/48] s5p-tv: hdmiphy: Remove deprecated video-level DV timings operation Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 23/48] ths8200: Remove deprecated video-level DV timings operations Laurent Pinchart
2014-03-11  7:13   ` Prabhakar Lad
2014-03-10 23:15 ` [PATCH v2 24/48] tvp7002: " Laurent Pinchart
2014-03-11  7:12   ` Prabhakar Lad
2014-03-10 23:15 ` [PATCH v2 25/48] v4l: Improve readability by not wrapping ioctl number #define's Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 26/48] v4l: Add support for DV timings ioctls on subdev nodes Laurent Pinchart
2014-03-11 10:38   ` Hans Verkuil
2014-03-11 11:02     ` Laurent Pinchart
2014-03-11 15:09   ` [PATCH v3 " Laurent Pinchart
2014-03-11 15:33     ` Hans Verkuil
2014-03-10 23:15 ` [PATCH v2 27/48] v4l: Validate fields in the core code for subdev EDID ioctls Laurent Pinchart
2014-03-11  8:57   ` Sakari Ailus
2014-03-11 10:45   ` Hans Verkuil
2014-03-11 10:57     ` Laurent Pinchart
2014-03-11 10:59       ` Hans Verkuil
2014-03-11 15:09   ` [PATCH v3 " Laurent Pinchart
2014-03-11 15:44     ` Hans Verkuil
2014-03-11 16:08       ` Laurent Pinchart
2014-03-11 16:11         ` Hans Verkuil
2014-03-11 16:24           ` Laurent Pinchart
2014-03-11 16:44             ` Hans Verkuil
2014-03-10 23:15 ` [PATCH v2 28/48] adv7604: Add missing include to linux/types.h Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 29/48] adv7604: Add support for asynchronous probing Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 30/48] adv7604: Don't put info string arrays on the stack Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 31/48] adv7604: Add 16-bit read functions for CP and HDMI Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 32/48] adv7604: Cache register contents when reading multiple bits Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 33/48] adv7604: Add adv7611 support Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 34/48] adv7604: Remove subdev control handlers Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 35/48] adv7604: Add sink pads Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 36/48] adv7604: Make output format configurable through pad format operations Laurent Pinchart
2014-03-11 15:10   ` [PATCH v3 " Laurent Pinchart
2014-03-13 21:45     ` Hans Verkuil
2014-03-18  9:32     ` Hans Verkuil
2014-03-18 13:02       ` Laurent Pinchart
2014-03-18 13:09         ` Hans Verkuil
2014-03-10 23:15 ` [PATCH v2 37/48] adv7604: Add pad-level DV timings support Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 38/48] adv7604: Remove deprecated video-level DV timings operations Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 39/48] v4l: subdev: " Laurent Pinchart
2014-03-11  7:21   ` Prabhakar Lad
2014-03-10 23:15 ` [PATCH v2 40/48] adv7604: Inline the to_sd function Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 41/48] adv7604: Store I2C addresses and clients in arrays Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 42/48] adv7604: Replace *_and_or() functions with *_clr_set() Laurent Pinchart
2014-03-11 15:10   ` [PATCH v3 " Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 43/48] adv7604: Sort headers alphabetically Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 44/48] adv7604: Support hot-plug detect control through a GPIO Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 45/48] adv7604: Specify the default input through platform data Laurent Pinchart
2014-03-10 23:15 ` [PATCH v2 46/48] adv7604: Add DT support Laurent Pinchart
2014-03-11 15:11   ` [PATCH v3 " Laurent Pinchart
2014-04-17 10:59   ` [PATCH v2 " Sylwester Nawrocki
2014-04-17 12:36     ` Laurent Pinchart
2014-04-17 13:08       ` Laurent Pinchart
2014-04-17 13:41         ` Sylwester Nawrocki
2014-03-10 23:15 ` [PATCH v2 47/48] adv7604: Add LLC polarity configuration Laurent Pinchart
2014-03-18 13:05   ` Hans Verkuil
2014-04-17 11:29   ` Sylwester Nawrocki
2014-03-10 23:15 ` [PATCH v2 48/48] adv7604: Add endpoint properties to DT bindings Laurent Pinchart
2014-04-17 11:17   ` Sylwester Nawrocki
2014-04-17 12:45     ` Laurent Pinchart
2014-04-17 13:00       ` Ben Dooks
2014-04-17 13:04         ` Laurent Pinchart
2014-03-11 11:58 ` [PATCH v2 00/48] ADV7611 support Hans Verkuil
  -- strict thread matches above, loose matches on Subject: below --
2014-03-10 23:14 Laurent Pinchart

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.