All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/47] ADV7611 support
@ 2014-02-05 16:41 Laurent Pinchart
  2014-02-05 16:41 ` [PATCH 01/47] v4l: of: Support empty port nodes Laurent Pinchart
                   ` (47 more replies)
  0 siblings, 48 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:41 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/47 to 27/47 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.

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 (43):
  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: subdev: 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
  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
  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: Control hot-plug detect 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   |   27 +-
 .../devicetree/bindings/media/i2c/adv7604.txt      |   69 +
 drivers/media/i2c/ad9389b.c                        |   67 +-
 drivers/media/i2c/adv7511.c                        |   69 +-
 drivers/media/i2c/adv7604.c                        | 1465 ++++++++++++++------
 drivers/media/i2c/adv7842.c                        |   10 +-
 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              |   15 +
 drivers/staging/media/davinci_vpfe/vpfe_video.c    |    4 +-
 include/media/adv7604.h                            |  109 +-
 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                     |    8 +-
 24 files changed, 2164 insertions(+), 636 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/i2c/adv7604.txt

-- 
Regards,

Laurent Pinchart


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

* [PATCH 01/47] v4l: of: Support empty port nodes
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
@ 2014-02-05 16:41 ` Laurent Pinchart
  2014-02-05 16:41 ` [PATCH 02/47] v4l: Add UYVY10_2X10 and VYUY10_2X10 media bus pixel codes Laurent Pinchart
                   ` (46 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:41 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] 83+ messages in thread

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

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.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] 83+ messages in thread

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

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.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] 83+ messages in thread

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

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.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] 83+ messages in thread

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

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.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] 83+ messages in thread

* [PATCH 06/47] v4l: Add pad-level DV timings subdev operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (4 preceding siblings ...)
  2014-02-05 16:41 ` [PATCH 05/47] v4l: Add 12-bit YUV 4:2:2 " Laurent Pinchart
@ 2014-02-05 16:41 ` Laurent Pinchart
  2014-02-05 17:13   ` Hans Verkuil
  2014-02-06 17:33   ` Sakari Ailus
  2014-02-05 16:41 ` [PATCH 07/47] ad9389b: Add pad-level DV timings operations Laurent Pinchart
                   ` (41 subsequent siblings)
  47 siblings, 2 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:41 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 | 8 ++++++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index d67210a..2c7355a 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -505,6 +505,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 6ae7bbe..b75970d 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1086,12 +1086,14 @@ struct v4l2_dv_timings {
 
 /** struct v4l2_enum_dv_timings - DV timings enumeration
  * @index:	enumeration index
+ * @pad:	the pad number for which to query capabilities
  * @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;
 };
 
@@ -1129,11 +1131,13 @@ 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
  * @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] 83+ messages in thread

* [PATCH 07/47] ad9389b: Add pad-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (5 preceding siblings ...)
  2014-02-05 16:41 ` [PATCH 06/47] v4l: Add pad-level DV timings subdev operations Laurent Pinchart
@ 2014-02-05 16:41 ` Laurent Pinchart
  2014-02-05 16:41 ` [PATCH 08/47] adv7511: " Laurent Pinchart
                   ` (40 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:41 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>
---
 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] 83+ messages in thread

* [PATCH 08/47] adv7511: Add pad-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (6 preceding siblings ...)
  2014-02-05 16:41 ` [PATCH 07/47] ad9389b: Add pad-level DV timings operations Laurent Pinchart
@ 2014-02-05 16:41 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 09/47] adv7842: " Laurent Pinchart
                   ` (39 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:41 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>
---
 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] 83+ messages in thread

* [PATCH 09/47] adv7842: Add pad-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (7 preceding siblings ...)
  2014-02-05 16:41 ` [PATCH 08/47] adv7511: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 10/47] s5p-tv: hdmi: " Laurent Pinchart
                   ` (38 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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] 83+ messages in thread

* [PATCH 10/47] s5p-tv: hdmi: Add pad-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (8 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 09/47] adv7842: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 11/47] s5p-tv: hdmiphy: " Laurent Pinchart
                   ` (37 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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] 83+ messages in thread

* [PATCH 11/47] s5p-tv: hdmiphy: Add pad-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (9 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 10/47] s5p-tv: hdmi: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 12/47] ths8200: " Laurent Pinchart
                   ` (36 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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] 83+ messages in thread

* [PATCH 12/47] ths8200: Add pad-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (10 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 11/47] s5p-tv: hdmiphy: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 13/47] tvp7002: " Laurent Pinchart
                   ` (35 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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 04139ee..e17e5155 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] 83+ messages in thread

* [PATCH 13/47] tvp7002: Add pad-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (11 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 12/47] ths8200: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 14/47] media: bfin_capture: Switch to pad-level DV operations Laurent Pinchart
                   ` (34 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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] 83+ messages in thread

* [PATCH 14/47] media: bfin_capture: Switch to pad-level DV operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (12 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 13/47] tvp7002: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 15/47] media: davinci: vpif: " Laurent Pinchart
                   ` (33 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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 2819165..5928d1d 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] 83+ messages in thread

* [PATCH 15/47] media: davinci: vpif: Switch to pad-level DV operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (13 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 14/47] media: bfin_capture: Switch to pad-level DV operations Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 16/47] media: staging: davinci: vpfe: " Laurent Pinchart
                   ` (32 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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 735ec47..d0081eb 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 9d115cd..20979c4 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] 83+ messages in thread

* [PATCH 16/47] media: staging: davinci: vpfe: Switch to pad-level DV operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (14 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 15/47] media: davinci: vpif: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 17/47] s5p-tv: mixer: " Laurent Pinchart
                   ` (31 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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] 83+ messages in thread

* [PATCH 17/47] s5p-tv: mixer: Switch to pad-level DV operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (15 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 16/47] media: staging: davinci: vpfe: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 18/47] ad9389b: Remove deprecated video-level DV timings operations Laurent Pinchart
                   ` (30 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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] 83+ messages in thread

* [PATCH 18/47] ad9389b: Remove deprecated video-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (16 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 17/47] s5p-tv: mixer: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 19/47] adv7511: " Laurent Pinchart
                   ` (29 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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/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] 83+ messages in thread

* [PATCH 19/47] adv7511: Remove deprecated video-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (17 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 18/47] ad9389b: Remove deprecated video-level DV timings operations Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 20/47] adv7842: " Laurent Pinchart
                   ` (28 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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/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] 83+ messages in thread

* [PATCH 20/47] adv7842: Remove deprecated video-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (18 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 19/47] adv7511: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 21/47] s5p-tv: hdmi: " Laurent Pinchart
                   ` (27 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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/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] 83+ messages in thread

* [PATCH 21/47] s5p-tv: hdmi: Remove deprecated video-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (19 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 20/47] adv7842: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 22/47] s5p-tv: hdmiphy: Remove deprecated video-level DV timings operation Laurent Pinchart
                   ` (26 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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] 83+ messages in thread

* [PATCH 22/47] s5p-tv: hdmiphy: Remove deprecated video-level DV timings operation
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (20 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 21/47] s5p-tv: hdmi: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 23/47] ths8200: Remove deprecated video-level DV timings operations Laurent Pinchart
                   ` (25 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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] 83+ messages in thread

* [PATCH 23/47] ths8200: Remove deprecated video-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (21 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 22/47] s5p-tv: hdmiphy: Remove deprecated video-level DV timings operation Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 24/47] tvp7002: " Laurent Pinchart
                   ` (24 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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/ths8200.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c
index e17e5155..0f1e952 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] 83+ messages in thread

* [PATCH 24/47] tvp7002: Remove deprecated video-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (22 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 23/47] ths8200: Remove deprecated video-level DV timings operations Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 25/47] v4l: subdev: " Laurent Pinchart
                   ` (23 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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/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] 83+ messages in thread

* [PATCH 25/47] v4l: subdev: Remove deprecated video-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (23 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 24/47] tvp7002: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-06 17:35   ` Sakari Ailus
  2014-02-12 12:48   ` Hans Verkuil
  2014-02-05 16:42 ` [PATCH 26/47] v4l: Improve readability by not wrapping ioctl number #define's Laurent Pinchart
                   ` (22 subsequent siblings)
  47 siblings, 2 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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 2c7355a..ddea899 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -326,12 +326,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] 83+ messages in thread

* [PATCH 26/47] v4l: Improve readability by not wrapping ioctl number #define's
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (24 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 25/47] v4l: subdev: " Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-06 17:34   ` Sakari Ailus
  2014-02-05 16:42 ` [PATCH 27/47] v4l: Add support for DV timings ioctls on subdev nodes Laurent Pinchart
                   ` (21 subsequent siblings)
  47 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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>
---
 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] 83+ messages in thread

* [PATCH 27/47] v4l: Add support for DV timings ioctls on subdev nodes
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (25 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 26/47] v4l: Improve readability by not wrapping ioctl number #define's Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 17:31   ` Hans Verkuil
  2014-02-07 11:07   ` Sakari Ailus
  2014-02-05 16:42 ` [PATCH 28/47] adv7604: Add missing include to linux/types.h Laurent Pinchart
                   ` (20 subsequent siblings)
  47 siblings, 2 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

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   | 27 +++++++++++++++++-----
 drivers/media/v4l2-core/v4l2-subdev.c              | 15 ++++++++++++
 include/uapi/linux/v4l2-subdev.h                   |  5 ++++
 4 files changed, 63 insertions(+), 11 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..baef771 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), application must specify the
+desired pad number in the &v4l2-dv-timings-cap; <structfield>pad</structfield>
+field. Attemps 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..e55df46 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), application must specify the desired pad number
+in the &v4l2-enum-dv-timings; <structfield>pad</structfield> field. Attemps 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,7 +90,14 @@ application.</entry>
 	  </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>
@@ -103,7 +118,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 996c248..0ccf9c8 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -354,6 +354,21 @@ 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:
+		return v4l2_subdev_call(sd, pad, dv_timings_cap, arg);
+
+	case VIDIOC_SUBDEV_ENUM_DV_TIMINGS:
+		return v4l2_subdev_call(sd, pad, enum_dv_timings, arg);
+
+	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] 83+ messages in thread

* [PATCH 28/47] adv7604: Add missing include to linux/types.h
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (26 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 27/47] v4l: Add support for DV timings ioctls on subdev nodes Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 29/47] adv7604: Add support for asynchronous probing Laurent Pinchart
                   ` (19 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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] 83+ messages in thread

* [PATCH 29/47] adv7604: Add support for asynchronous probing
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (27 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 28/47] adv7604: Add missing include to linux/types.h Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 30/47] adv7604: Don't put info string arrays on the stack Laurent Pinchart
                   ` (18 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 71c8570..98ac383 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2337,6 +2337,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:
@@ -2360,6 +2365,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] 83+ messages in thread

* [PATCH 30/47] adv7604: Don't put info string arrays on the stack
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (28 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 29/47] adv7604: Add support for asynchronous probing Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 31/47] adv7604: Add 16-bit read functions for CP and HDMI Laurent Pinchart
                   ` (17 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 98ac383..cfcbb6d 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1886,13 +1886,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",
@@ -1900,12 +1900,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] 83+ messages in thread

* [PATCH 31/47] adv7604: Add 16-bit read functions for CP and HDMI
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (29 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 30/47] adv7604: Don't put info string arrays on the stack Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 32/47] adv7604: Cache register contents when reading multiple bits Laurent Pinchart
                   ` (16 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 cfcbb6d..3d6876d 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] 83+ messages in thread

* [PATCH 32/47] adv7604: Cache register contents when reading multiple bits
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (30 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 31/47] adv7604: Add 16-bit read functions for CP and HDMI Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 33/47] adv7604: Add adv7611 support Laurent Pinchart
                   ` (15 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 3d6876d..2a044d1 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';
@@ -1885,6 +1888,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",
@@ -1914,20 +1919,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] 83+ messages in thread

* [PATCH 33/47] adv7604: Add adv7611 support
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (31 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 32/47] adv7604: Cache register contents when reading multiple bits Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 34/47] adv7604: Remove subdev control handlers Laurent Pinchart
                   ` (14 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 2a044d1..fe71d686 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);
@@ -1734,6 +1874,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;
@@ -1747,7 +1888,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;
@@ -1773,7 +1914,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)
@@ -1799,8 +1940,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];
@@ -1819,10 +1966,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);
 	}
@@ -1885,6 +2032,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);
@@ -1919,7 +2067,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"),
@@ -1929,12 +2077,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",
@@ -2107,6 +2255,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,
@@ -2160,19 +2309,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)
@@ -2211,6 +2372,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)
 {
@@ -2220,6 +2505,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 */
@@ -2234,6 +2520,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;
@@ -2248,18 +2536,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);
@@ -2272,15 +2578,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 =
@@ -2293,7 +2601,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;
 
@@ -2302,27 +2611,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) {
@@ -2383,7 +2699,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] 83+ messages in thread

* [PATCH 34/47] adv7604: Remove subdev control handlers
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (32 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 33/47] adv7604: Add adv7611 support Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 35/47] adv7604: Add sink pads Laurent Pinchart
                   ` (13 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 fe71d686..05e7e1a 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2176,13 +2176,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] 83+ messages in thread

* [PATCH 35/47] adv7604: Add sink pads
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (33 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 34/47] adv7604: Remove subdev control handlers Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-11 10:19   ` Hans Verkuil
  2014-02-05 16:42 ` [PATCH 36/47] adv7604: Make output format configurable through pad format operations Laurent Pinchart
                   ` (12 subsequent siblings)
  47 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 | 71 ++++++++++++++++++++++++++++-----------------
 include/media/adv7604.h     | 14 ---------
 2 files changed, 45 insertions(+), 40 deletions(-)

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 05e7e1a..da32ce9 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -97,13 +97,25 @@ struct adv7604_chip_info {
  *
  **********************************************************************
  */
+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_MAX = 7,
+};
+
 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 +787,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 +1078,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 +1118,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 +1129,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 +1818,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;
@@ -1823,10 +1835,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;
@@ -1880,7 +1892,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;
@@ -1921,19 +1933,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;
@@ -2433,7 +2445,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,
@@ -2464,7 +2476,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,
@@ -2498,6 +2510,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;
 
@@ -2643,8 +2656,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..22811d3 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -155,20 +155,6 @@ 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,
-};
-
-#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] 83+ messages in thread

* [PATCH 36/47] adv7604: Make output format configurable through pad format operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (34 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 35/47] adv7604: Add sink pads Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-12 15:01   ` Hans Verkuil
  2014-02-05 16:42 ` [PATCH 37/47] adv7604: Add pad-level DV timings support Laurent Pinchart
                   ` (11 subsequent siblings)
  47 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 da32ce9..181372a 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);
@@ -111,12 +144,18 @@ enum adv7604_pad {
 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;
@@ -781,6 +820,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)
@@ -1730,29 +1856,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;
 }
 
@@ -2203,13 +2395,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,
 };
@@ -2278,14 +2469,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 */
 
@@ -2453,6 +2641,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,
@@ -2484,6 +2674,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,
@@ -2539,6 +2731,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 22811d3..2cc8e16 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] 83+ messages in thread

* [PATCH 37/47] adv7604: Add pad-level DV timings support
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (35 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 36/47] adv7604: Make output format configurable through pad format operations Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 38/47] adv7604: Remove deprecated video-level DV timings operations Laurent Pinchart
                   ` (10 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 181372a..0925fe8 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1524,24 +1524,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 |
@@ -1549,6 +1567,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,
@@ -2403,6 +2440,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] 83+ messages in thread

* [PATCH 38/47] adv7604: Remove deprecated video-level DV timings operations
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (36 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 37/47] adv7604: Add pad-level DV timings support Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 39/47] adv7604: Inline the to_sd function Laurent Pinchart
                   ` (9 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 0925fe8..4815063 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1537,16 +1537,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:
@@ -1567,25 +1571,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,
@@ -2430,8 +2415,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 = {
@@ -2440,7 +2423,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] 83+ messages in thread

* [PATCH 39/47] adv7604: Inline the to_sd function
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (37 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 38/47] adv7604: Remove deprecated video-level DV timings operations Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 40/47] adv7604: Store I2C addresses and clients in arrays Laurent Pinchart
                   ` (8 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 4815063..be75fa5 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -350,11 +350,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);
@@ -1280,7 +1275,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] 83+ messages in thread

* [PATCH 40/47] adv7604: Store I2C addresses and clients in arrays
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (38 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 39/47] adv7604: Inline the to_sd function Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 41/47] adv7604: Replace *_and_or() functions with *_clr_set() Laurent Pinchart
                   ` (7 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 be75fa5..2733584 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -169,18 +169,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;
@@ -387,14 +376,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;
@@ -414,9 +407,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)
@@ -432,16 +427,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)
@@ -453,28 +448,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)
@@ -486,70 +481,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)
@@ -561,20 +557,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] = {
@@ -607,8 +603,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;
 }
 
@@ -628,7 +624,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)
@@ -640,7 +636,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)
@@ -652,21 +648,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)
@@ -678,7 +674,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)
@@ -690,32 +686,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
@@ -731,36 +710,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
 
@@ -774,36 +724,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,
@@ -1074,7 +995,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;
@@ -1100,7 +1020,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 */
@@ -1151,7 +1072,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__);
 }
 
@@ -1180,7 +1102,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__);
 }
 
@@ -2548,30 +2471,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,
@@ -2738,6 +2643,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;
@@ -2829,34 +2735,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 2cc8e16..4da678c 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];
 };
 
 #define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE	(V4L2_CID_DV_CLASS_BASE + 0x1000)
-- 
1.8.3.2


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

* [PATCH 41/47] adv7604: Replace *_and_or() functions with *_clr_set()
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (39 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 40/47] adv7604: Store I2C addresses and clients in arrays Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 42/47] adv7604: Sort headers alphabetically Laurent Pinchart
                   ` (6 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 2733584..c34cfd6 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -439,9 +439,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)
@@ -472,9 +472,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)
@@ -548,9 +548,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)
@@ -639,9 +639,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)
@@ -677,9 +677,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)
@@ -957,7 +957,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);
@@ -1015,7 +1015,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 */
@@ -1125,21 +1125,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;
 		}
 
@@ -1148,10 +1148,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);
@@ -1164,23 +1164,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;
@@ -1232,7 +1232,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);
@@ -1615,11 +1615,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;
 			}
@@ -1678,7 +1678,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);
@@ -1722,10 +1722,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);
@@ -1736,7 +1736,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);
@@ -1830,12 +1830,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);
 }
 
@@ -2034,7 +2034,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;
@@ -2060,7 +2060,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)
@@ -2089,10 +2089,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];
@@ -2112,7 +2112,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)
@@ -2408,11 +2408,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);
@@ -2437,16 +2437,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] 83+ messages in thread

* [PATCH 42/47] adv7604: Sort headers alphabetically
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (40 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 41/47] adv7604: Replace *_and_or() functions with *_clr_set() Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO Laurent Pinchart
                   ` (5 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 c34cfd6..369cb1e 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] 83+ messages in thread

* [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (41 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 42/47] adv7604: Sort headers alphabetically Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-06 13:10   ` Lars-Peter Clausen
  2014-02-11 10:09   ` Hans Verkuil
  2014-02-05 16:42 ` [PATCH 44/47] adv7604: Specify the default input through platform data Laurent Pinchart
                   ` (4 subsequent siblings)
  47 siblings, 2 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 UTC (permalink / raw)
  To: linux-media; +Cc: Hans Verkuil, Lars-Peter Clausen

Replace the ADV7604-specific hotplug notifier with a GPIO to control the
HPD pin directly instead of going through the bridge driver.

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

diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 369cb1e..2f38071 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -28,6 +28,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -608,6 +609,23 @@ 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) {
+		unsigned int enable = hpd & BIT(i);
+
+		if (IS_ERR_VALUE(state->pdata.hpd_gpio[i]))
+			continue;
+
+		if (state->pdata.hpd_gpio_low[i])
+			enable = !enable;
+
+		gpio_set_value_cansleep(state->pdata.hpd_gpio[i], enable);
+	}
+}
+
 static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
 {
 	struct delayed_work *dwork = to_delayed_work(work);
@@ -617,7 +635,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)
@@ -2022,7 +2040,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;
 
@@ -2033,7 +2050,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 */
@@ -2059,7 +2076,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);
@@ -2655,6 +2672,28 @@ 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) {
+		char name[5];
+
+		if (IS_ERR_VALUE(state->pdata.hpd_gpio[i]))
+			continue;
+
+		sprintf(name, "hpd%u", i);
+		err = devm_gpio_request_one(&client->dev,
+					    state->pdata.hpd_gpio[i],
+					    state->pdata.hpd_gpio_low[i] ?
+					    GPIOF_OUT_INIT_HIGH :
+					    GPIOF_OUT_INIT_LOW,
+					    name);
+		if (err < 0) {
+			v4l_err(client, "Failed to request HPD %u GPIO (%u)\n",
+				i, state->pdata.hpd_gpio[i]);
+			return err;
+		}
+	}
+
 	state->timings = cea640x480;
 	state->format = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
 
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index 4da678c..dddb0cb 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -90,6 +90,10 @@ struct adv7604_platform_data {
 	/* DIS_CABLE_DET_RST: 1 if the 5V pins are unused and unconnected */
 	unsigned disable_cable_det_rst:1;
 
+	/* Hot-Plug Detect control GPIOs */
+	int hpd_gpio[4];
+	bool hpd_gpio_low[4];
+
 	/* Analog input muxing mode */
 	enum adv7604_ain_sel ain_sel;
 
@@ -133,7 +137,6 @@ struct adv7604_platform_data {
 #define V4L2_CID_ADV_RX_FREE_RUN_COLOR		(V4L2_CID_DV_CLASS_BASE + 0x1002)
 
 /* notify events */
-#define ADV7604_HOTPLUG		1
 #define ADV7604_FMT_CHANGE	2
 
 #endif
-- 
1.8.3.2


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

* [PATCH 44/47] adv7604: Specify the default input through platform data
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (42 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 45/47] adv7604: Add DT support Laurent Pinchart
                   ` (3 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 2f38071..e586c1c 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2419,6 +2419,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 dddb0cb..0cad7a7 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -94,6 +94,8 @@ struct adv7604_platform_data {
 	int hpd_gpio[4];
 	bool hpd_gpio_low[4];
 
+	int default_input;
+
 	/* Analog input muxing mode */
 	enum adv7604_ain_sel ain_sel;
 
-- 
1.8.3.2


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

* [PATCH 45/47] adv7604: Add DT support
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (43 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 44/47] adv7604: Specify the default input through platform data Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-11  9:23   ` Hans Verkuil
  2014-02-05 16:42 ` [PATCH 46/47] adv7604: Add LLC polarity configuration Laurent Pinchart
                   ` (2 subsequent siblings)
  47 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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                        | 101 ++++++++++++++++++---
 2 files changed, 143 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 e586c1c..cd8a2dc 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -32,6 +32,7 @@
 #include <linux/i2c.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/v4l2-dv-timings.h>
 #include <linux/videodev2.h>
@@ -2641,13 +2642,83 @@ 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;
+	unsigned int i;
+	int ret;
+
+	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
+	state->info = of_match_node(adv7604_of_id, np)->data;
+
+	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;
+
+	for (i = 0; i < state->info->num_dv_ports; ++i) {
+		enum of_gpio_flags flags;
+
+		state->pdata.hpd_gpio[i] =
+			of_get_named_gpio_flags(np, "hpd-gpios", i, &flags);
+		if (IS_ERR_VALUE(state->pdata.hpd_gpio[i]))
+			continue;
+
+		state->pdata.hpd_gpio_low[i] = flags == OF_GPIO_ACTIVE_LOW;
+	}
+
+	/* 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;
@@ -2666,19 +2737,27 @@ 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 (client->dev.of_node) {
+		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) {
@@ -2786,7 +2865,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;
@@ -2860,21 +2939,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] 83+ messages in thread

* [PATCH 46/47] adv7604: Add LLC polarity configuration
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (44 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 45/47] adv7604: Add DT support Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 16:42 ` [PATCH 47/47] adv7604: Add endpoint properties to DT bindings Laurent Pinchart
  2014-02-05 17:12 ` [PATCH 00/47] ADV7611 support Hans Verkuil
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 cd8a2dc..064e57e 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2445,7 +2445,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 0cad7a7..7c8b4e9 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -118,6 +118,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] 83+ messages in thread

* [PATCH 47/47] adv7604: Add endpoint properties to DT bindings
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (45 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 46/47] adv7604: Add LLC polarity configuration Laurent Pinchart
@ 2014-02-05 16:42 ` Laurent Pinchart
  2014-02-05 17:12 ` [PATCH 00/47] ADV7611 support Hans Verkuil
  47 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-05 16:42 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 064e57e..c5bc8bf 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -42,6 +42,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);
@@ -2659,13 +2660,41 @@ 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;
 	unsigned int i;
 	int ret;
 
 	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
 	state->info = of_match_node(adv7604_of_id, np)->data;
 
+	/* 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 =
@@ -2706,9 +2735,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] 83+ messages in thread

* Re: [PATCH 00/47] ADV7611 support
  2014-02-05 16:41 [PATCH 00/47] ADV7611 support Laurent Pinchart
                   ` (46 preceding siblings ...)
  2014-02-05 16:42 ` [PATCH 47/47] adv7604: Add endpoint properties to DT bindings Laurent Pinchart
@ 2014-02-05 17:12 ` Hans Verkuil
  47 siblings, 0 replies; 83+ messages in thread
From: Hans Verkuil @ 2014-02-05 17:12 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Hans Verkuil, Lars-Peter Clausen, Kyungmin Park,
	Tomasz Stanislawski, Scott Jiang, Prabhakar Lad

Hi Laurent!

On 02/05/2014 05:41 PM, 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/47 to 27/47 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.

For patches 2-5 and 7-26:

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

I have some upcoming comments for patches 6 and 27 and I don't feel qualified
enough to judge patch 1 (unless you ask explicitly).

I will look at the remaining adv7604 patches later. I need to test those on
our hardware, so this will probably going to be next week before I get to them.

Nothing jumped out at me when I quickly read through them, but I didn't
look all that closely.

Regards,

	Hans


> 
> 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 (43):
>   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: subdev: 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
>   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
>   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: Control hot-plug detect 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   |   27 +-
>  .../devicetree/bindings/media/i2c/adv7604.txt      |   69 +
>  drivers/media/i2c/ad9389b.c                        |   67 +-
>  drivers/media/i2c/adv7511.c                        |   69 +-
>  drivers/media/i2c/adv7604.c                        | 1465 ++++++++++++++------
>  drivers/media/i2c/adv7842.c                        |   10 +-
>  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              |   15 +
>  drivers/staging/media/davinci_vpfe/vpfe_video.c    |    4 +-
>  include/media/adv7604.h                            |  109 +-
>  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                     |    8 +-
>  24 files changed, 2164 insertions(+), 636 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/media/i2c/adv7604.txt
> 


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

* Re: [PATCH 06/47] v4l: Add pad-level DV timings subdev operations
  2014-02-05 16:41 ` [PATCH 06/47] v4l: Add pad-level DV timings subdev operations Laurent Pinchart
@ 2014-02-05 17:13   ` Hans Verkuil
  2014-02-06 17:33   ` Sakari Ailus
  1 sibling, 0 replies; 83+ messages in thread
From: Hans Verkuil @ 2014-02-05 17:13 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 02/05/2014 05:41 PM, Laurent Pinchart wrote:
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  include/media/v4l2-subdev.h    | 4 ++++
>  include/uapi/linux/videodev2.h | 8 ++++++--
>  2 files changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index d67210a..2c7355a 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -505,6 +505,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 6ae7bbe..b75970d 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -1086,12 +1086,14 @@ struct v4l2_dv_timings {
>  
>  /** struct v4l2_enum_dv_timings - DV timings enumeration
>   * @index:	enumeration index
> + * @pad:	the pad number for which to query capabilities

Add something like: "pad is only used with v4l-subdev nodes."

>   * @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;
>  };
>  
> @@ -1129,11 +1131,13 @@ 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

Ditto.

>   * @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];
> 

See also my comments for patch 27.

Regards,

	Hans

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

* Re: [PATCH 27/47] v4l: Add support for DV timings ioctls on subdev nodes
  2014-02-05 16:42 ` [PATCH 27/47] v4l: Add support for DV timings ioctls on subdev nodes Laurent Pinchart
@ 2014-02-05 17:31   ` Hans Verkuil
  2014-02-07  1:21     ` Laurent Pinchart
  2014-02-07 11:07   ` Sakari Ailus
  1 sibling, 1 reply; 83+ messages in thread
From: Hans Verkuil @ 2014-02-05 17:31 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Laurent,

Some comments:

On 02/05/2014 05:42 PM, Laurent Pinchart wrote:
> 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   | 27 +++++++++++++++++-----
>  drivers/media/v4l2-core/v4l2-subdev.c              | 15 ++++++++++++
>  include/uapi/linux/v4l2-subdev.h                   |  5 ++++
>  4 files changed, 63 insertions(+), 11 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..baef771 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), application must specify the

s/application/the application/

> +desired pad number in the &v4l2-dv-timings-cap; <structfield>pad</structfield>
> +field. Attemps to query capabilities on a pad that doesn't support them will

s/Attemps/Attempts/

> +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>

Currently the spec says that the driver will zero the reserved array. No mention
is made of the application having to zero it. This means that drivers cannot rely
on what is in the pad field since apps can leave it uninitialized.

If we keep that behavior, then the text has to change as follows:

s/applications must set this field to zero/this field is ignored/

However, should be keep that behavior? This ioctl is still marked as experimental,
so perhaps we should change the spec to require that reserved should be zeroed by
applications as well. I'm not certain, to be honest.

> +	  </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..e55df46 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), application must specify the desired pad number

s/application/the application/

> +in the &v4l2-enum-dv-timings; <structfield>pad</structfield> field. Attemps to

s/Attemps/Attempts/

> +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,7 +90,14 @@ application.</entry>
>  	  </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>

This needs to change to:

"Drivers and applications must set the array to zero."

The description section for this ioctl clearly states that applications must zero the array,
so this field description is not correct.

>  	  </row>
>  	  <row>
> @@ -103,7 +118,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 996c248..0ccf9c8 100644
> --- a/drivers/media/v4l2-core/v4l2-subdev.c
> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> @@ -354,6 +354,21 @@ 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:
> +		return v4l2_subdev_call(sd, pad, dv_timings_cap, arg);
> +
> +	case VIDIOC_SUBDEV_ENUM_DV_TIMINGS:
> +		return v4l2_subdev_call(sd, pad, enum_dv_timings, arg);
> +
> +	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
> 

Regards,

	Hans

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

* Re: [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO
  2014-02-05 16:42 ` [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO Laurent Pinchart
@ 2014-02-06 13:10   ` Lars-Peter Clausen
  2014-02-10 15:00     ` Laurent Pinchart
  2014-02-11 10:09   ` Hans Verkuil
  1 sibling, 1 reply; 83+ messages in thread
From: Lars-Peter Clausen @ 2014-02-06 13:10 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil

On 02/05/2014 05:42 PM, Laurent Pinchart wrote:
> Replace the ADV7604-specific hotplug notifier with a GPIO to control the
> HPD pin directly instead of going through the bridge driver.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

This should probably use the new GPIO descriptor API[1]. It will make things 
a bit simpler as it allows to move the active low handling to the gpio 
subsystem. The other thing is that it makes integration with devicetree nicer.

- Lars

[1] 
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/gpio/consumer.h



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

* Re: [PATCH 06/47] v4l: Add pad-level DV timings subdev operations
  2014-02-05 16:41 ` [PATCH 06/47] v4l: Add pad-level DV timings subdev operations Laurent Pinchart
  2014-02-05 17:13   ` Hans Verkuil
@ 2014-02-06 17:33   ` Sakari Ailus
  2014-02-07  0:50     ` Laurent Pinchart
  1 sibling, 1 reply; 83+ messages in thread
From: Sakari Ailus @ 2014-02-06 17:33 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Laurent,

On Wed, Feb 05, 2014 at 05:41:57PM +0100, Laurent Pinchart wrote:
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  include/media/v4l2-subdev.h    | 4 ++++
>  include/uapi/linux/videodev2.h | 8 ++++++--
>  2 files changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index d67210a..2c7355a 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -505,6 +505,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);

Do you think there would be use for these in the user space API? The
argument structs are defined in the user space header. The driver does also
export a sub-device node.

-- 
Kind regards,

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

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

* Re: [PATCH 26/47] v4l: Improve readability by not wrapping ioctl number #define's
  2014-02-05 16:42 ` [PATCH 26/47] v4l: Improve readability by not wrapping ioctl number #define's Laurent Pinchart
@ 2014-02-06 17:34   ` Sakari Ailus
  0 siblings, 0 replies; 83+ messages in thread
From: Sakari Ailus @ 2014-02-06 17:34 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On Wed, Feb 05, 2014 at 05:42:17PM +0100, Laurent Pinchart wrote:
> 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>

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] 83+ messages in thread

* Re: [PATCH 25/47] v4l: subdev: Remove deprecated video-level DV timings operations
  2014-02-05 16:42 ` [PATCH 25/47] v4l: subdev: " Laurent Pinchart
@ 2014-02-06 17:35   ` Sakari Ailus
  2014-02-12 12:48   ` Hans Verkuil
  1 sibling, 0 replies; 83+ messages in thread
From: Sakari Ailus @ 2014-02-06 17:35 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On Wed, Feb 05, 2014 at 05:42:16PM +0100, Laurent Pinchart 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>

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] 83+ messages in thread

* Re: [PATCH 06/47] v4l: Add pad-level DV timings subdev operations
  2014-02-06 17:33   ` Sakari Ailus
@ 2014-02-07  0:50     ` Laurent Pinchart
  0 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-07  0:50 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Sakari,

Thank you for the review.

On Thursday 06 February 2014 19:33:23 Sakari Ailus wrote:
> Hi Laurent,
> 
> On Wed, Feb 05, 2014 at 05:41:57PM +0100, Laurent Pinchart wrote:
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  include/media/v4l2-subdev.h    | 4 ++++
> >  include/uapi/linux/videodev2.h | 8 ++++++--
> >  2 files changed, 10 insertions(+), 2 deletions(-)
> > 
> > diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> > index d67210a..2c7355a 100644
> > --- a/include/media/v4l2-subdev.h
> > +++ b/include/media/v4l2-subdev.h
> > @@ -505,6 +505,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);
> 
> Do you think there would be use for these in the user space API? The
> argument structs are defined in the user space header. The driver does also
> export a sub-device node.

Please have a look at

[PATCH 27/47] v4l: Add support for DV timings ioctls on subdev nodes

:-)

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 27/47] v4l: Add support for DV timings ioctls on subdev nodes
  2014-02-05 17:31   ` Hans Verkuil
@ 2014-02-07  1:21     ` Laurent Pinchart
  0 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-07  1:21 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Hans,

Thank you for the comments.

On Wednesday 05 February 2014 18:31:14 Hans Verkuil wrote:
> On 02/05/2014 05:42 PM, Laurent Pinchart wrote:
> > 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   | 27 ++++++++++++++---
> >  drivers/media/v4l2-core/v4l2-subdev.c              | 15 ++++++++++++
> >  include/uapi/linux/v4l2-subdev.h                   |  5 ++++
> >  4 files changed, 63 insertions(+), 11 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..baef771 100644
> > --- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
> > +++ b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml

[snip]

> > @@ -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), application must specify
> > the
>
> s/application/the application/

I've replaced "application" with "applications" to be consistent with the 
first paragraph, but I can change both if desired.

> > +desired pad number in the &v4l2-dv-timings-cap;
> > <structfield>pad</structfield> +field. Attemps to query capabilities on a
> > pad that doesn't support them will
>
> s/Attemps/Attempts/
> 
> > +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>
> 
> Currently the spec says that the driver will zero the reserved array. No
> mention is made of the application having to zero it. This means that
> drivers cannot rely on what is in the pad field since apps can leave it
> uninitialized.
> 
> If we keep that behavior, then the text has to change as follows:
> 
> s/applications must set this field to zero/this field is ignored/
> 
> However, should be keep that behavior? This ioctl is still marked as
> experimental, so perhaps we should change the spec to require that reserved
> should be zeroed by applications as well. I'm not certain, to be honest.

I would vote for changing the spec and forcing applications to zero the array. 
This won't cause any regression on subdev nodes (as the ioctl is new there) or 
video nodes (where the pad number is ignored) for now. The only risk is 
applications written before the spec modification that might break later when 
the reserved field is used for a different purpose. That's very unlikely.

> 
> > +	  </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..e55df46 100644
> > --- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
> > +++ b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml

[snip]

> > @@ -82,7 +90,14 @@ application.</entry>
> >  	  </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>
>
> This needs to change to:
> 
> "Drivers and applications must set the array to zero."
> 
> The description section for this ioctl clearly states that applications must
> zero the array, so this field description is not correct.

OK, I'll fix that.
 
> >  	  </row>
> >  	  <row>

[snip]

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 27/47] v4l: Add support for DV timings ioctls on subdev nodes
  2014-02-05 16:42 ` [PATCH 27/47] v4l: Add support for DV timings ioctls on subdev nodes Laurent Pinchart
  2014-02-05 17:31   ` Hans Verkuil
@ 2014-02-07 11:07   ` Sakari Ailus
  2014-02-10 12:53     ` Laurent Pinchart
  1 sibling, 1 reply; 83+ messages in thread
From: Sakari Ailus @ 2014-02-07 11:07 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Laurent,

Thanks for the patch.

On Wed, Feb 05, 2014 at 05:42:18PM +0100, Laurent Pinchart wrote:
...
> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
> index 996c248..0ccf9c8 100644
> --- a/drivers/media/v4l2-core/v4l2-subdev.c
> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> @@ -354,6 +354,21 @@ 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:
> +		return v4l2_subdev_call(sd, pad, dv_timings_cap, arg);
> +
> +	case VIDIOC_SUBDEV_ENUM_DV_TIMINGS:
> +		return v4l2_subdev_call(sd, pad, enum_dv_timings, arg);
> +
> +	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);

Please validate the fields of the argument structs above you can. The pad
field at least can be validated.

-- 
Kind regards,

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

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

* Re: [PATCH 27/47] v4l: Add support for DV timings ioctls on subdev nodes
  2014-02-07 11:07   ` Sakari Ailus
@ 2014-02-10 12:53     ` Laurent Pinchart
  0 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-10 12:53 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Sakari,

On Friday 07 February 2014 13:07:40 Sakari Ailus wrote:
> Hi Laurent,
> 
> Thanks for the patch.
> 
> On Wed, Feb 05, 2014 at 05:42:18PM +0100, Laurent Pinchart wrote:
> ...
> 
> > diff --git a/drivers/media/v4l2-core/v4l2-subdev.c
> > b/drivers/media/v4l2-core/v4l2-subdev.c index 996c248..0ccf9c8 100644
> > --- a/drivers/media/v4l2-core/v4l2-subdev.c
> > +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> > @@ -354,6 +354,21 @@ 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:
> > +		return v4l2_subdev_call(sd, pad, dv_timings_cap, arg);
> > +
> > +	case VIDIOC_SUBDEV_ENUM_DV_TIMINGS:
> > +		return v4l2_subdev_call(sd, pad, enum_dv_timings, arg);
> > +
> > +	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);
> 
> Please validate the fields of the argument structs above you can. The pad
> field at least can be validated.

I wonder how I've missed that :-) I'll fix this, and add pad validation for 
the [GS]_EDID ioctls while I'm at it.

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO
  2014-02-06 13:10   ` Lars-Peter Clausen
@ 2014-02-10 15:00     ` Laurent Pinchart
  0 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-10 15:00 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: linux-media, Hans Verkuil

Hi Lars,

On Thursday 06 February 2014 14:10:05 Lars-Peter Clausen wrote:
> On 02/05/2014 05:42 PM, Laurent Pinchart wrote:
> > Replace the ADV7604-specific hotplug notifier with a GPIO to control the
> > HPD pin directly instead of going through the bridge driver.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
> This should probably use the new GPIO descriptor API[1]. It will make things
> a bit simpler as it allows to move the active low handling to the gpio
> subsystem. The other thing is that it makes integration with devicetree
> nicer.

Agreed. I'll fix that for the next version.

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 45/47] adv7604: Add DT support
  2014-02-05 16:42 ` [PATCH 45/47] adv7604: Add DT support Laurent Pinchart
@ 2014-02-11  9:23   ` Hans Verkuil
  2014-02-11 12:08     ` Laurent Pinchart
  0 siblings, 1 reply; 83+ messages in thread
From: Hans Verkuil @ 2014-02-11  9:23 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, Hans Verkuil, Lars-Peter Clausen, devicetree

On 02/05/14 17:42, 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                        | 101 ++++++++++++++++++---
>  2 files changed, 143 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 e586c1c..cd8a2dc 100644
> --- a/drivers/media/i2c/adv7604.c
> +++ b/drivers/media/i2c/adv7604.c
> @@ -32,6 +32,7 @@
>  #include <linux/i2c.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
> +#include <linux/of_gpio.h>
>  #include <linux/slab.h>
>  #include <linux/v4l2-dv-timings.h>
>  #include <linux/videodev2.h>
> @@ -2641,13 +2642,83 @@ 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)

Put this under #ifdef CONFIG_OF. It fails to compile if CONFIG_OF is not set
(as it is in my case since this driver is used with a PCIe card).

Regards,

	Hans

> +{
> +	struct device_node *np;
> +	unsigned int i;
> +	int ret;
> +
> +	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
> +	state->info = of_match_node(adv7604_of_id, np)->data;
> +
> +	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;
> +
> +	for (i = 0; i < state->info->num_dv_ports; ++i) {
> +		enum of_gpio_flags flags;
> +
> +		state->pdata.hpd_gpio[i] =
> +			of_get_named_gpio_flags(np, "hpd-gpios", i, &flags);
> +		if (IS_ERR_VALUE(state->pdata.hpd_gpio[i]))
> +			continue;
> +
> +		state->pdata.hpd_gpio_low[i] = flags == OF_GPIO_ACTIVE_LOW;
> +	}
> +
> +	/* 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;
> @@ -2666,19 +2737,27 @@ 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 (client->dev.of_node) {
> +		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) {
> @@ -2786,7 +2865,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;
> @@ -2860,21 +2939,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);
> 

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

* Re: [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO
  2014-02-05 16:42 ` [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO Laurent Pinchart
  2014-02-06 13:10   ` Lars-Peter Clausen
@ 2014-02-11 10:09   ` Hans Verkuil
  2014-02-11 12:03     ` Laurent Pinchart
  1 sibling, 1 reply; 83+ messages in thread
From: Hans Verkuil @ 2014-02-11 10:09 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 02/05/14 17:42, Laurent Pinchart wrote:
> Replace the ADV7604-specific hotplug notifier with a GPIO to control the
> HPD pin directly instead of going through the bridge driver.

Hmm, that's not going to work for me. I don't have a GPIO pin here, instead
it is a bit in a register that I have to set.

> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/i2c/adv7604.c | 47 +++++++++++++++++++++++++++++++++++++++++----
>  include/media/adv7604.h     |  5 ++++-
>  2 files changed, 47 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> index 369cb1e..2f38071 100644
> --- a/drivers/media/i2c/adv7604.c
> +++ b/drivers/media/i2c/adv7604.c
> @@ -28,6 +28,7 @@
>   */
>  
>  #include <linux/delay.h>
> +#include <linux/gpio.h>
>  #include <linux/i2c.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
> @@ -608,6 +609,23 @@ 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) {
> +		unsigned int enable = hpd & BIT(i);
> +
> +		if (IS_ERR_VALUE(state->pdata.hpd_gpio[i]))

IS_ERR_VALUE: that's normally used for pointers, not integers. I would
much prefer something simple like 'bool hpd_use_gpio[4]'.

Regards,

	Hans

> +			continue;
> +
> +		if (state->pdata.hpd_gpio_low[i])
> +			enable = !enable;
> +
> +		gpio_set_value_cansleep(state->pdata.hpd_gpio[i], enable);
> +	}
> +}
> +
>  static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
>  {
>  	struct delayed_work *dwork = to_delayed_work(work);
> @@ -617,7 +635,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)
> @@ -2022,7 +2040,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;
>  
> @@ -2033,7 +2050,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 */
> @@ -2059,7 +2076,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);
> @@ -2655,6 +2672,28 @@ 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) {
> +		char name[5];
> +
> +		if (IS_ERR_VALUE(state->pdata.hpd_gpio[i]))
> +			continue;
> +
> +		sprintf(name, "hpd%u", i);
> +		err = devm_gpio_request_one(&client->dev,
> +					    state->pdata.hpd_gpio[i],
> +					    state->pdata.hpd_gpio_low[i] ?
> +					    GPIOF_OUT_INIT_HIGH :
> +					    GPIOF_OUT_INIT_LOW,
> +					    name);
> +		if (err < 0) {
> +			v4l_err(client, "Failed to request HPD %u GPIO (%u)\n",
> +				i, state->pdata.hpd_gpio[i]);
> +			return err;
> +		}
> +	}
> +
>  	state->timings = cea640x480;
>  	state->format = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
>  
> diff --git a/include/media/adv7604.h b/include/media/adv7604.h
> index 4da678c..dddb0cb 100644
> --- a/include/media/adv7604.h
> +++ b/include/media/adv7604.h
> @@ -90,6 +90,10 @@ struct adv7604_platform_data {
>  	/* DIS_CABLE_DET_RST: 1 if the 5V pins are unused and unconnected */
>  	unsigned disable_cable_det_rst:1;
>  
> +	/* Hot-Plug Detect control GPIOs */
> +	int hpd_gpio[4];
> +	bool hpd_gpio_low[4];
> +
>  	/* Analog input muxing mode */
>  	enum adv7604_ain_sel ain_sel;
>  
> @@ -133,7 +137,6 @@ struct adv7604_platform_data {
>  #define V4L2_CID_ADV_RX_FREE_RUN_COLOR		(V4L2_CID_DV_CLASS_BASE + 0x1002)
>  
>  /* notify events */
> -#define ADV7604_HOTPLUG		1
>  #define ADV7604_FMT_CHANGE	2
>  
>  #endif
> 


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

* Re: [PATCH 35/47] adv7604: Add sink pads
  2014-02-05 16:42 ` [PATCH 35/47] adv7604: Add sink pads Laurent Pinchart
@ 2014-02-11 10:19   ` Hans Verkuil
  2014-02-11 12:00     ` Laurent Pinchart
  0 siblings, 1 reply; 83+ messages in thread
From: Hans Verkuil @ 2014-02-11 10:19 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 02/05/14 17:42, Laurent Pinchart wrote:
> 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 | 71 ++++++++++++++++++++++++++++-----------------
>  include/media/adv7604.h     | 14 ---------
>  2 files changed, 45 insertions(+), 40 deletions(-)
> 
> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> index 05e7e1a..da32ce9 100644
> --- a/drivers/media/i2c/adv7604.c
> +++ b/drivers/media/i2c/adv7604.c
> @@ -97,13 +97,25 @@ struct adv7604_chip_info {
>   *
>   **********************************************************************
>   */
> +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) */

How about making this explicit:

	ADV7604_PAD_SOURCE = 6,
	ADV7611_PAD_SOURCE = 1,

> +	ADV7604_PAD_MAX = 7,
> +};

Wouldn't it make more sense to have this in the header? I would really
like to use the symbolic names for these pads in my bridge driver.

Regards,

	Hans

> +
>  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 +787,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 +1078,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 +1118,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 +1129,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 +1818,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;
> @@ -1823,10 +1835,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;
> @@ -1880,7 +1892,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;
> @@ -1921,19 +1933,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;
> @@ -2433,7 +2445,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,
> @@ -2464,7 +2476,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,
> @@ -2498,6 +2510,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;
>  
> @@ -2643,8 +2656,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..22811d3 100644
> --- a/include/media/adv7604.h
> +++ b/include/media/adv7604.h
> @@ -155,20 +155,6 @@ 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,
> -};
> -
> -#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)
> 


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

* Re: [PATCH 35/47] adv7604: Add sink pads
  2014-02-11 10:19   ` Hans Verkuil
@ 2014-02-11 12:00     ` Laurent Pinchart
  2014-02-11 12:07       ` Hans Verkuil
  0 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-11 12:00 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Hans,

On Tuesday 11 February 2014 11:19:32 Hans Verkuil wrote:
> On 02/05/14 17:42, Laurent Pinchart wrote:
> > 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 | 71 +++++++++++++++++++++++++---------------
> >  include/media/adv7604.h     | 14 ---------
> >  2 files changed, 45 insertions(+), 40 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> > index 05e7e1a..da32ce9 100644
> > --- a/drivers/media/i2c/adv7604.c
> > +++ b/drivers/media/i2c/adv7604.c
> > @@ -97,13 +97,25 @@ struct adv7604_chip_info {
> > 
> >   **********************************************************************
> >   */
> > 
> > +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) */
> 
> How about making this explicit:
> 
> 	ADV7604_PAD_SOURCE = 6,
> 	ADV7611_PAD_SOURCE = 1,

I can do that, but those two constants won't be used in the driver as they 
computed dynamically.

> > +	ADV7604_PAD_MAX = 7,
> > +};
> 
> Wouldn't it make more sense to have this in the header? I would really
> like to use the symbolic names for these pads in my bridge driver.

That would add a dependency on the adv7604 driver to the bridge driver, isn't 
the whole point of subdevs to avoid such dependencies ?

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO
  2014-02-11 10:09   ` Hans Verkuil
@ 2014-02-11 12:03     ` Laurent Pinchart
  2014-02-13  9:47       ` Hans Verkuil
  0 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-11 12:03 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Hans,

On Tuesday 11 February 2014 11:09:31 Hans Verkuil wrote:
> On 02/05/14 17:42, Laurent Pinchart wrote:
> > Replace the ADV7604-specific hotplug notifier with a GPIO to control the
> > HPD pin directly instead of going through the bridge driver.
> 
> Hmm, that's not going to work for me. I don't have a GPIO pin here, instead
> it is a bit in a register that I have to set.

But that bit controls a GPIO, doesn't it ? In that case it should be exposed 
as a GPIO controller.

> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  drivers/media/i2c/adv7604.c | 47 ++++++++++++++++++++++++++++++++++++----
> >  include/media/adv7604.h     |  5 ++++-
> >  2 files changed, 47 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> > index 369cb1e..2f38071 100644
> > --- a/drivers/media/i2c/adv7604.c
> > +++ b/drivers/media/i2c/adv7604.c
> > @@ -28,6 +28,7 @@
> >   */
> >  
> >  #include <linux/delay.h>
> > +#include <linux/gpio.h>
> >  #include <linux/i2c.h>
> >  #include <linux/kernel.h>
> >  #include <linux/module.h>
> > @@ -608,6 +609,23 @@ 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) {
> > +		unsigned int enable = hpd & BIT(i);
> > +
> > +		if (IS_ERR_VALUE(state->pdata.hpd_gpio[i]))
> 
> IS_ERR_VALUE: that's normally used for pointers, not integers. I would
> much prefer something simple like 'bool hpd_use_gpio[4]'.

I've reworked this to use the gpiod_* API, I'll post v2 when the whole set 
will be reviewed.

> > +			continue;
> > +
> > +		if (state->pdata.hpd_gpio_low[i])
> > +			enable = !enable;
> > +
> > +		gpio_set_value_cansleep(state->pdata.hpd_gpio[i], enable);
> > +	}
> > +}
> > +
> > 
> >  static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
> >  {
> >  	struct delayed_work *dwork = to_delayed_work(work);
> > @@ -617,7 +635,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)
> > @@ -2022,7 +2040,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;
> > 
> > @@ -2033,7 +2050,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 */
> > @@ -2059,7 +2076,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);
> > @@ -2655,6 +2672,28 @@ 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) {
> > +		char name[5];
> > +
> > +		if (IS_ERR_VALUE(state->pdata.hpd_gpio[i]))
> > +			continue;
> > +
> > +		sprintf(name, "hpd%u", i);
> > +		err = devm_gpio_request_one(&client->dev,
> > +					    state->pdata.hpd_gpio[i],
> > +					    state->pdata.hpd_gpio_low[i] ?
> > +					    GPIOF_OUT_INIT_HIGH :
> > +					    GPIOF_OUT_INIT_LOW,
> > +					    name);
> > +		if (err < 0) {
> > +			v4l_err(client, "Failed to request HPD %u GPIO (%u)\n",
> > +				i, state->pdata.hpd_gpio[i]);
> > +			return err;
> > +		}
> > +	}
> > +
> > 
> >  	state->timings = cea640x480;
> >  	state->format = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
> > diff --git a/include/media/adv7604.h b/include/media/adv7604.h
> > index 4da678c..dddb0cb 100644
> > --- a/include/media/adv7604.h
> > +++ b/include/media/adv7604.h
> > @@ -90,6 +90,10 @@ struct adv7604_platform_data {
> >  	/* DIS_CABLE_DET_RST: 1 if the 5V pins are unused and unconnected */
> >  	unsigned disable_cable_det_rst:1;
> > 
> > +	/* Hot-Plug Detect control GPIOs */
> > +	int hpd_gpio[4];
> > +	bool hpd_gpio_low[4];
> > +
> >  	/* Analog input muxing mode */
> >  	enum adv7604_ain_sel ain_sel;
> > 
> > @@ -133,7 +137,6 @@ struct adv7604_platform_data {
> > 
> >  #define V4L2_CID_ADV_RX_FREE_RUN_COLOR		(V4L2_CID_DV_CLASS_BASE + 
0x1002)
> >  
> >  /* notify events */
> > -#define ADV7604_HOTPLUG		1
> >  #define ADV7604_FMT_CHANGE	2
> >  
> >  #endif

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 35/47] adv7604: Add sink pads
  2014-02-11 12:00     ` Laurent Pinchart
@ 2014-02-11 12:07       ` Hans Verkuil
  2014-02-11 12:23         ` Laurent Pinchart
  0 siblings, 1 reply; 83+ messages in thread
From: Hans Verkuil @ 2014-02-11 12:07 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Hans Verkuil, linux-media, Lars-Peter Clausen



On 02/11/14 13:00, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Tuesday 11 February 2014 11:19:32 Hans Verkuil wrote:
>> On 02/05/14 17:42, Laurent Pinchart wrote:
>>> 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 | 71 +++++++++++++++++++++++++---------------
>>>  include/media/adv7604.h     | 14 ---------
>>>  2 files changed, 45 insertions(+), 40 deletions(-)
>>>
>>> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
>>> index 05e7e1a..da32ce9 100644
>>> --- a/drivers/media/i2c/adv7604.c
>>> +++ b/drivers/media/i2c/adv7604.c
>>> @@ -97,13 +97,25 @@ struct adv7604_chip_info {
>>>
>>>   **********************************************************************
>>>   */
>>>
>>> +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) */
>>
>> How about making this explicit:
>>
>> 	ADV7604_PAD_SOURCE = 6,
>> 	ADV7611_PAD_SOURCE = 1,
> 
> I can do that, but those two constants won't be used in the driver as they 
> computed dynamically.
> 
>>> +	ADV7604_PAD_MAX = 7,
>>> +};
>>
>> Wouldn't it make more sense to have this in the header? I would really
>> like to use the symbolic names for these pads in my bridge driver.
> 
> That would add a dependency on the adv7604 driver to the bridge driver, isn't 
> the whole point of subdevs to avoid such dependencies ?

The bridge driver has to know about the adv7604, not the other way around.

E.g. in my bridge driver I have to match v4l2 inputs to pads, both for
S_EDID and for s_routing, so it needs to know which pad number to use.

Also, for calling set_fmt, BTW. There I need to specify the source pad,
which is also why I would like to have a symbolic name for it as suggested
above.

Regards,

	Hans

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

* Re: [PATCH 45/47] adv7604: Add DT support
  2014-02-11  9:23   ` Hans Verkuil
@ 2014-02-11 12:08     ` Laurent Pinchart
  2014-02-11 12:14       ` Hans Verkuil
  0 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-11 12:08 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen, devicetree

Hi Hans,

On Tuesday 11 February 2014 10:23:03 Hans Verkuil wrote:
> On 02/05/14 17:42, 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                        | 101 ++++++++++++++--
> >  2 files changed, 143 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 e586c1c..cd8a2dc 100644
> > --- a/drivers/media/i2c/adv7604.c
> > +++ b/drivers/media/i2c/adv7604.c
> > @@ -32,6 +32,7 @@
> > 
> >  #include <linux/i2c.h>
> >  #include <linux/kernel.h>
> >  #include <linux/module.h>
> > 
> > +#include <linux/of_gpio.h>
> > 
> >  #include <linux/slab.h>
> >  #include <linux/v4l2-dv-timings.h>
> >  #include <linux/videodev2.h>
> > 
> > @@ -2641,13 +2642,83 @@ 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)
> 
> Put this under #ifdef CONFIG_OF.

#ifdef CONFIG_OF has been discouraged. I'll add an IS_ENABLED(CONFIG_OF) to 
condition the call of adv7604_parse_dt() and let the compiler optimize the 
function out, but I've been recommended to fix compilation errors instead of 
using conditional compilation.

> It fails to compile if CONFIG_OF is not set (as it is in my case since this
> driver is used with a PCIe card).

What's the compilation failure ?

> > +{
> > +	struct device_node *np;
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
> > +	state->info = of_match_node(adv7604_of_id, np)->data;
> > +
> > +	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;
> > +
> > +	for (i = 0; i < state->info->num_dv_ports; ++i) {
> > +		enum of_gpio_flags flags;
> > +
> > +		state->pdata.hpd_gpio[i] =
> > +			of_get_named_gpio_flags(np, "hpd-gpios", i, &flags);
> > +		if (IS_ERR_VALUE(state->pdata.hpd_gpio[i]))
> > +			continue;
> > +
> > +		state->pdata.hpd_gpio_low[i] = flags == OF_GPIO_ACTIVE_LOW;
> > +	}
> > +
> > +	/* 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;
> > +}

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 45/47] adv7604: Add DT support
  2014-02-11 12:08     ` Laurent Pinchart
@ 2014-02-11 12:14       ` Hans Verkuil
  2014-02-11 12:21         ` Lars-Peter Clausen
  0 siblings, 1 reply; 83+ messages in thread
From: Hans Verkuil @ 2014-02-11 12:14 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans Verkuil, linux-media, Hans Verkuil, Lars-Peter Clausen, devicetree



On 02/11/14 13:08, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Tuesday 11 February 2014 10:23:03 Hans Verkuil wrote:
>> On 02/05/14 17:42, 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                        | 101 ++++++++++++++--
>>>  2 files changed, 143 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 e586c1c..cd8a2dc 100644
>>> --- a/drivers/media/i2c/adv7604.c
>>> +++ b/drivers/media/i2c/adv7604.c
>>> @@ -32,6 +32,7 @@
>>>
>>>  #include <linux/i2c.h>
>>>  #include <linux/kernel.h>
>>>  #include <linux/module.h>
>>>
>>> +#include <linux/of_gpio.h>
>>>
>>>  #include <linux/slab.h>
>>>  #include <linux/v4l2-dv-timings.h>
>>>  #include <linux/videodev2.h>
>>>
>>> @@ -2641,13 +2642,83 @@ 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)
>>
>> Put this under #ifdef CONFIG_OF.
> 
> #ifdef CONFIG_OF has been discouraged. I'll add an IS_ENABLED(CONFIG_OF) to 
> condition the call of adv7604_parse_dt() and let the compiler optimize the 
> function out, but I've been recommended to fix compilation errors instead of 
> using conditional compilation.
> 
>> It fails to compile if CONFIG_OF is not set (as it is in my case since this
>> driver is used with a PCIe card).
> 
> What's the compilation failure ?

drivers/media/i2c/adv7604.c: In function ‘adv7604_parse_dt’:
drivers/media/i2c/adv7604.c:2671:48: warning: dereferencing ‘void *’ pointer [enabled by default]
  state->info = of_match_node(adv7604_of_id, np)->data;
                                                ^
drivers/media/i2c/adv7604.c:2671:48: error: request for member ‘data’ in something not a structure or union
make[3]: *** [drivers/media/i2c/adv7604.o] Error 1

> 
>>> +{
>>> +	struct device_node *np;
>>> +	unsigned int i;
>>> +	int ret;
>>> +
>>> +	np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
>>> +	state->info = of_match_node(adv7604_of_id, np)->data;
>>> +
>>> +	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;
>>> +
>>> +	for (i = 0; i < state->info->num_dv_ports; ++i) {
>>> +		enum of_gpio_flags flags;
>>> +
>>> +		state->pdata.hpd_gpio[i] =
>>> +			of_get_named_gpio_flags(np, "hpd-gpios", i, &flags);
>>> +		if (IS_ERR_VALUE(state->pdata.hpd_gpio[i]))
>>> +			continue;
>>> +
>>> +		state->pdata.hpd_gpio_low[i] = flags == OF_GPIO_ACTIVE_LOW;
>>> +	}
>>> +
>>> +	/* 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;
>>> +}
> 

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

* Re: [PATCH 45/47] adv7604: Add DT support
  2014-02-11 12:14       ` Hans Verkuil
@ 2014-02-11 12:21         ` Lars-Peter Clausen
  2014-02-11 12:30           ` Laurent Pinchart
  0 siblings, 1 reply; 83+ messages in thread
From: Lars-Peter Clausen @ 2014-02-11 12:21 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: Laurent Pinchart, Hans Verkuil, linux-media, Hans Verkuil, devicetree

On 02/11/2014 01:14 PM, Hans Verkuil wrote:
>
>
> On 02/11/14 13:08, Laurent Pinchart wrote:
>> Hi Hans,
>>
>> On Tuesday 11 February 2014 10:23:03 Hans Verkuil wrote:
>>> On 02/05/14 17:42, 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                        | 101 ++++++++++++++--
>>>>   2 files changed, 143 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 e586c1c..cd8a2dc 100644
>>>> --- a/drivers/media/i2c/adv7604.c
>>>> +++ b/drivers/media/i2c/adv7604.c
>>>> @@ -32,6 +32,7 @@
>>>>
>>>>   #include <linux/i2c.h>
>>>>   #include <linux/kernel.h>
>>>>   #include <linux/module.h>
>>>>
>>>> +#include <linux/of_gpio.h>
>>>>
>>>>   #include <linux/slab.h>
>>>>   #include <linux/v4l2-dv-timings.h>
>>>>   #include <linux/videodev2.h>
>>>>
>>>> @@ -2641,13 +2642,83 @@ 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)
>>>
>>> Put this under #ifdef CONFIG_OF.
>>
>> #ifdef CONFIG_OF has been discouraged. I'll add an IS_ENABLED(CONFIG_OF) to
>> condition the call of adv7604_parse_dt() and let the compiler optimize the
>> function out, but I've been recommended to fix compilation errors instead of
>> using conditional compilation.
>>
>>> It fails to compile if CONFIG_OF is not set (as it is in my case since this
>>> driver is used with a PCIe card).
>>
>> What's the compilation failure ?
>
> drivers/media/i2c/adv7604.c: In function ‘adv7604_parse_dt’:
> drivers/media/i2c/adv7604.c:2671:48: warning: dereferencing ‘void *’ pointer [enabled by default]
>    state->info = of_match_node(adv7604_of_id, np)->data;
>                                                  ^
> drivers/media/i2c/adv7604.c:2671:48: error: request for member ‘data’ in something not a structure or union
> make[3]: *** [drivers/media/i2c/adv7604.o] Error 1

That looks like a bug in the stubbed out version of of_match_node(). It 
should be a inline function with a return type, rather than a macro.

- Lars

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

* Re: [PATCH 35/47] adv7604: Add sink pads
  2014-02-11 12:07       ` Hans Verkuil
@ 2014-02-11 12:23         ` Laurent Pinchart
  2014-02-11 12:24           ` Hans Verkuil
  0 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-11 12:23 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Hans Verkuil, linux-media, Lars-Peter Clausen

Hi Hans,

On Tuesday 11 February 2014 13:07:51 Hans Verkuil wrote:
> On 02/11/14 13:00, Laurent Pinchart wrote:
> > On Tuesday 11 February 2014 11:19:32 Hans Verkuil wrote:
> >> On 02/05/14 17:42, Laurent Pinchart wrote:
> >>> 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 | 71 ++++++++++++++++++++++++--------------
> >>>  include/media/adv7604.h     | 14 ---------
> >>>  2 files changed, 45 insertions(+), 40 deletions(-)
> >>> 
> >>> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> >>> index 05e7e1a..da32ce9 100644
> >>> --- a/drivers/media/i2c/adv7604.c
> >>> +++ b/drivers/media/i2c/adv7604.c
> >>> @@ -97,13 +97,25 @@ struct adv7604_chip_info {
> >>> 
> >>>   **********************************************************************
> >>>   */
> >>> 
> >>> +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) */
> >> 
> >> How about making this explicit:
> >> 	ADV7604_PAD_SOURCE = 6,
> >> 	ADV7611_PAD_SOURCE = 1,
> > 
> > I can do that, but those two constants won't be used in the driver as they
> > computed dynamically.
> > 
> >>> +	ADV7604_PAD_MAX = 7,
> >>> +};
> >> 
> >> Wouldn't it make more sense to have this in the header? I would really
> >> like to use the symbolic names for these pads in my bridge driver.
> > 
> > That would add a dependency on the adv7604 driver to the bridge driver,
> > isn't the whole point of subdevs to avoid such dependencies ?
> 
> The bridge driver has to know about the adv7604, not the other way around.
> 
> E.g. in my bridge driver I have to match v4l2 inputs to pads, both for
> S_EDID and for s_routing, so it needs to know which pad number to use.

Is that information that you want to pass to the bridge driver through 
platform data, or do you want to hardcode it in the bridge driver itself ? In 
the latter case the bridge driver would become specific to the adv7604. It 
might be fine in your case if your bridge is specific to your board anyway 
(FPGAs come to mind), but it lacks genericity.

> Also, for calling set_fmt, BTW. There I need to specify the source pad,
> which is also why I would like to have a symbolic name for it as suggested
> above.

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 35/47] adv7604: Add sink pads
  2014-02-11 12:23         ` Laurent Pinchart
@ 2014-02-11 12:24           ` Hans Verkuil
  2014-02-11 12:32             ` Laurent Pinchart
  0 siblings, 1 reply; 83+ messages in thread
From: Hans Verkuil @ 2014-02-11 12:24 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Hans Verkuil, linux-media, Lars-Peter Clausen

On 02/11/14 13:23, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Tuesday 11 February 2014 13:07:51 Hans Verkuil wrote:
>> On 02/11/14 13:00, Laurent Pinchart wrote:
>>> On Tuesday 11 February 2014 11:19:32 Hans Verkuil wrote:
>>>> On 02/05/14 17:42, Laurent Pinchart wrote:
>>>>> 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 | 71 ++++++++++++++++++++++++--------------
>>>>>  include/media/adv7604.h     | 14 ---------
>>>>>  2 files changed, 45 insertions(+), 40 deletions(-)
>>>>>
>>>>> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
>>>>> index 05e7e1a..da32ce9 100644
>>>>> --- a/drivers/media/i2c/adv7604.c
>>>>> +++ b/drivers/media/i2c/adv7604.c
>>>>> @@ -97,13 +97,25 @@ struct adv7604_chip_info {
>>>>>
>>>>>   **********************************************************************
>>>>>   */
>>>>>
>>>>> +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) */
>>>>
>>>> How about making this explicit:
>>>> 	ADV7604_PAD_SOURCE = 6,
>>>> 	ADV7611_PAD_SOURCE = 1,
>>>
>>> I can do that, but those two constants won't be used in the driver as they
>>> computed dynamically.
>>>
>>>>> +	ADV7604_PAD_MAX = 7,
>>>>> +};
>>>>
>>>> Wouldn't it make more sense to have this in the header? I would really
>>>> like to use the symbolic names for these pads in my bridge driver.
>>>
>>> That would add a dependency on the adv7604 driver to the bridge driver,
>>> isn't the whole point of subdevs to avoid such dependencies ?
>>
>> The bridge driver has to know about the adv7604, not the other way around.
>>
>> E.g. in my bridge driver I have to match v4l2 inputs to pads, both for
>> S_EDID and for s_routing, so it needs to know which pad number to use.
> 
> Is that information that you want to pass to the bridge driver through 
> platform data, or do you want to hardcode it in the bridge driver itself ? In 
> the latter case the bridge driver would become specific to the adv7604. It 
> might be fine in your case if your bridge is specific to your board anyway 
> (FPGAs come to mind), but it lacks genericity.

Hardcoded. It's just like any PCI driver: the PCI ID determines what the
board is and based on that you set everything up. And if there are multiple
variations of the board you use card structures to define such things.

The only place where you can put that information is in the bridge driver.

Regards,

	Hans

> 
>> Also, for calling set_fmt, BTW. There I need to specify the source pad,
>> which is also why I would like to have a symbolic name for it as suggested
>> above.
> 


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

* Re: [PATCH 45/47] adv7604: Add DT support
  2014-02-11 12:21         ` Lars-Peter Clausen
@ 2014-02-11 12:30           ` Laurent Pinchart
  0 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-11 12:30 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Hans Verkuil, Hans Verkuil, linux-media, Hans Verkuil, devicetree

Hi Lars,

On Tuesday 11 February 2014 13:21:56 Lars-Peter Clausen wrote:
> On 02/11/2014 01:14 PM, Hans Verkuil wrote:
> > On 02/11/14 13:08, Laurent Pinchart wrote:
> >> On Tuesday 11 February 2014 10:23:03 Hans Verkuil wrote:
> >>> On 02/05/14 17:42, 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                        | 101 ++++++++++--
> >>>>   2 files changed, 143 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 e586c1c..cd8a2dc 100644
> >>>> --- a/drivers/media/i2c/adv7604.c
> >>>> +++ b/drivers/media/i2c/adv7604.c
> >>>> @@ -32,6 +32,7 @@
> >>>> 
> >>>>   #include <linux/i2c.h>
> >>>>   #include <linux/kernel.h>
> >>>>   #include <linux/module.h>
> >>>> 
> >>>> +#include <linux/of_gpio.h>
> >>>> 
> >>>>   #include <linux/slab.h>
> >>>>   #include <linux/v4l2-dv-timings.h>
> >>>>   #include <linux/videodev2.h>
> >>>> 
> >>>> @@ -2641,13 +2642,83 @@ 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)
> >>> 
> >>> Put this under #ifdef CONFIG_OF.
> >> 
> >> #ifdef CONFIG_OF has been discouraged. I'll add an IS_ENABLED(CONFIG_OF)
> >> to condition the call of adv7604_parse_dt() and let the compiler optimize
> >> the function out, but I've been recommended to fix compilation errors
> >> instead of using conditional compilation.
> >> 
> >>> It fails to compile if CONFIG_OF is not set (as it is in my case since
> >>> this driver is used with a PCIe card).
> >> 
> >> What's the compilation failure ?
> > 
> > drivers/media/i2c/adv7604.c: In function ‘adv7604_parse_dt’:
> > drivers/media/i2c/adv7604.c:2671:48: warning: dereferencing ‘void *’
> > pointer [enabled by default]> 
> >    state->info = of_match_node(adv7604_of_id, np)->data;
> > 
> > drivers/media/i2c/adv7604.c:2671:48: error: request for member ‘data’ in
> > something not a structure or union make[3]: ***
> > [drivers/media/i2c/adv7604.o] Error 1
> 
> That looks like a bug in the stubbed out version of of_match_node(). It
> should be a inline function with a return type, rather than a macro.

Indeed, I'll cook a patch up.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 35/47] adv7604: Add sink pads
  2014-02-11 12:24           ` Hans Verkuil
@ 2014-02-11 12:32             ` Laurent Pinchart
  2014-02-11 12:33               ` Hans Verkuil
  0 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-11 12:32 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Hans Verkuil, linux-media, Lars-Peter Clausen

Hi Hans,

On Tuesday 11 February 2014 13:24:03 Hans Verkuil wrote:
> On 02/11/14 13:23, Laurent Pinchart wrote:
> > On Tuesday 11 February 2014 13:07:51 Hans Verkuil wrote:
> >> On 02/11/14 13:00, Laurent Pinchart wrote:
> >>> On Tuesday 11 February 2014 11:19:32 Hans Verkuil wrote:
> >>>> On 02/05/14 17:42, Laurent Pinchart wrote:
> >>>>> 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 | 71  ++++++++++++++++++++++-------------
> >>>>>  include/media/adv7604.h     | 14 ---------
> >>>>>  2 files changed, 45 insertions(+), 40 deletions(-)
> >>>>> 
> >>>>> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
> >>>>> index 05e7e1a..da32ce9 100644
> >>>>> --- a/drivers/media/i2c/adv7604.c
> >>>>> +++ b/drivers/media/i2c/adv7604.c
> >>>>> @@ -97,13 +97,25 @@ struct adv7604_chip_info {
> >>>>> 
> >>>>>   ********************************************************************
> >>>>>   */
> >>>>> 
> >>>>> +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) */
> >>>> 
> >>>> How about making this explicit:
> >>>> 	ADV7604_PAD_SOURCE = 6,
> >>>> 	ADV7611_PAD_SOURCE = 1,
> >>> 
> >>> I can do that, but those two constants won't be used in the driver as
> >>> they
> >>> computed dynamically.
> >>> 
> >>>>> +	ADV7604_PAD_MAX = 7,
> >>>>> +};
> >>>> 
> >>>> Wouldn't it make more sense to have this in the header? I would really
> >>>> like to use the symbolic names for these pads in my bridge driver.
> >>> 
> >>> That would add a dependency on the adv7604 driver to the bridge driver,
> >>> isn't the whole point of subdevs to avoid such dependencies ?
> >> 
> >> The bridge driver has to know about the adv7604, not the other way
> >> around.
> >> 
> >> E.g. in my bridge driver I have to match v4l2 inputs to pads, both for
> >> S_EDID and for s_routing, so it needs to know which pad number to use.
> > 
> > Is that information that you want to pass to the bridge driver through
> > platform data, or do you want to hardcode it in the bridge driver itself ?
> > In the latter case the bridge driver would become specific to the
> > adv7604. It might be fine in your case if your bridge is specific to your
> > board anyway (FPGAs come to mind), but it lacks genericity.
> 
> Hardcoded. It's just like any PCI driver: the PCI ID determines what the
> board is and based on that you set everything up. And if there are multiple
> variations of the board you use card structures to define such things.
> 
> The only place where you can put that information is in the bridge driver.

Or in DT I suppose ;-) It could be argued that the bridge driver could/should 
discover pad numbers somehow dynamically, but there's no harm in moving the 
enum to the header, so I'll do that.

> >> Also, for calling set_fmt, BTW. There I need to specify the source pad,
> >> which is also why I would like to have a symbolic name for it as
> >> suggested
> >> above.

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 35/47] adv7604: Add sink pads
  2014-02-11 12:32             ` Laurent Pinchart
@ 2014-02-11 12:33               ` Hans Verkuil
  0 siblings, 0 replies; 83+ messages in thread
From: Hans Verkuil @ 2014-02-11 12:33 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Hans Verkuil, linux-media, Lars-Peter Clausen

On 02/11/14 13:32, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Tuesday 11 February 2014 13:24:03 Hans Verkuil wrote:
>> On 02/11/14 13:23, Laurent Pinchart wrote:
>>> On Tuesday 11 February 2014 13:07:51 Hans Verkuil wrote:
>>>> On 02/11/14 13:00, Laurent Pinchart wrote:
>>>>> On Tuesday 11 February 2014 11:19:32 Hans Verkuil wrote:
>>>>>> On 02/05/14 17:42, Laurent Pinchart wrote:
>>>>>>> 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 | 71  ++++++++++++++++++++++-------------
>>>>>>>  include/media/adv7604.h     | 14 ---------
>>>>>>>  2 files changed, 45 insertions(+), 40 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
>>>>>>> index 05e7e1a..da32ce9 100644
>>>>>>> --- a/drivers/media/i2c/adv7604.c
>>>>>>> +++ b/drivers/media/i2c/adv7604.c
>>>>>>> @@ -97,13 +97,25 @@ struct adv7604_chip_info {
>>>>>>>
>>>>>>>   ********************************************************************
>>>>>>>   */
>>>>>>>
>>>>>>> +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) */
>>>>>>
>>>>>> How about making this explicit:
>>>>>> 	ADV7604_PAD_SOURCE = 6,
>>>>>> 	ADV7611_PAD_SOURCE = 1,
>>>>>
>>>>> I can do that, but those two constants won't be used in the driver as
>>>>> they
>>>>> computed dynamically.
>>>>>
>>>>>>> +	ADV7604_PAD_MAX = 7,
>>>>>>> +};
>>>>>>
>>>>>> Wouldn't it make more sense to have this in the header? I would really
>>>>>> like to use the symbolic names for these pads in my bridge driver.
>>>>>
>>>>> That would add a dependency on the adv7604 driver to the bridge driver,
>>>>> isn't the whole point of subdevs to avoid such dependencies ?
>>>>
>>>> The bridge driver has to know about the adv7604, not the other way
>>>> around.
>>>>
>>>> E.g. in my bridge driver I have to match v4l2 inputs to pads, both for
>>>> S_EDID and for s_routing, so it needs to know which pad number to use.
>>>
>>> Is that information that you want to pass to the bridge driver through
>>> platform data, or do you want to hardcode it in the bridge driver itself ?
>>> In the latter case the bridge driver would become specific to the
>>> adv7604. It might be fine in your case if your bridge is specific to your
>>> board anyway (FPGAs come to mind), but it lacks genericity.
>>
>> Hardcoded. It's just like any PCI driver: the PCI ID determines what the
>> board is and based on that you set everything up. And if there are multiple
>> variations of the board you use card structures to define such things.
>>
>> The only place where you can put that information is in the bridge driver.
> 
> Or in DT I suppose ;-)

Well, there is no DT. So there's that.

> It could be argued that the bridge driver could/should 
> discover pad numbers somehow dynamically, but there's no harm in moving the 
> enum to the header, so I'll do that.

Thanks. 

	Hans

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

* Re: [PATCH 25/47] v4l: subdev: Remove deprecated video-level DV timings operations
  2014-02-05 16:42 ` [PATCH 25/47] v4l: subdev: " Laurent Pinchart
  2014-02-06 17:35   ` Sakari Ailus
@ 2014-02-12 12:48   ` Hans Verkuil
  1 sibling, 0 replies; 83+ messages in thread
From: Hans Verkuil @ 2014-02-12 12:48 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 02/05/14 17:42, Laurent Pinchart wrote:
> The video enum_dv_timings and dv_timings_cap operations are deprecated
> and unused. Remove them.

FYI: after this the adv7604 fails to compile since it is still using the
video ops. You should move the patches that convert the adv7604 before
this patch.

Regards,

	Hans

> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.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 2c7355a..ddea899 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -326,12 +326,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,
> 


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

* Re: [PATCH 36/47] adv7604: Make output format configurable through pad format operations
  2014-02-05 16:42 ` [PATCH 36/47] adv7604: Make output format configurable through pad format operations Laurent Pinchart
@ 2014-02-12 15:01   ` Hans Verkuil
  2014-03-10 22:43     ` Laurent Pinchart
  0 siblings, 1 reply; 83+ messages in thread
From: Hans Verkuil @ 2014-02-12 15:01 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 02/05/14 17:42, 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 | 243 +++++++++++++++++++++++++++++++++++++++-----
>  include/media/adv7604.h     |  47 ++-------
>  2 files changed, 225 insertions(+), 65 deletions(-)
> 

<snip>

> diff --git a/include/media/adv7604.h b/include/media/adv7604.h
> index 22811d3..2cc8e16 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;

I would keep this as part of the platform_data. This is typically used if things
are wired up in a non-standard way and so is specific to the hardware. It is not
something that will change from format to format.

Other than this it all looks quite nice! Much more flexible than before.

Regards,

	Hans

> -
> -	/* 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;
> 


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

* Re: [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO
  2014-02-11 12:03     ` Laurent Pinchart
@ 2014-02-13  9:47       ` Hans Verkuil
  2014-02-13 10:10         ` Lars-Peter Clausen
  2014-02-13 14:33         ` Laurent Pinchart
  0 siblings, 2 replies; 83+ messages in thread
From: Hans Verkuil @ 2014-02-13  9:47 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 02/11/14 13:03, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Tuesday 11 February 2014 11:09:31 Hans Verkuil wrote:
>> On 02/05/14 17:42, Laurent Pinchart wrote:
>>> Replace the ADV7604-specific hotplug notifier with a GPIO to control the
>>> HPD pin directly instead of going through the bridge driver.
>>
>> Hmm, that's not going to work for me. I don't have a GPIO pin here, instead
>> it is a bit in a register that I have to set.
> 
> But that bit controls a GPIO, doesn't it ? In that case it should be exposed 
> as a GPIO controller.

I feel unhappy about losing this notifier for two reasons: first adding a GPIO
controller just to toggle a bit adds 40 lines to my driver, and that doesn't
sit well with me. It's basically completely unnecessary overhead.

The second reason is that in some cases you want to do something in addition
to just toggling the hotplug pin. In particular for CEC support this could be
quite useful.

In fact, if the adv7604 supports the ARC feature (Audio Return Channel), then
this is really needed because in that case the hotplug toggling would have
to be done via CEC CDC commands. However, while this webpage claims that the
ARC is supported, I can't find any other information about that.

http://www.analog.com/en/audiovideo-products/analoghdmidvi-interfaces/adv7604/products/product.html

Lars-Peter, do you know anything about ARC support in the adv7604?

Regards,

	Hans

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

* Re: [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO
  2014-02-13  9:47       ` Hans Verkuil
@ 2014-02-13 10:10         ` Lars-Peter Clausen
  2014-02-13 14:33         ` Laurent Pinchart
  1 sibling, 0 replies; 83+ messages in thread
From: Lars-Peter Clausen @ 2014-02-13 10:10 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Laurent Pinchart, linux-media, Hans Verkuil

On 02/13/2014 10:47 AM, Hans Verkuil wrote:
> On 02/11/14 13:03, Laurent Pinchart wrote:
>> Hi Hans,
>>
>> On Tuesday 11 February 2014 11:09:31 Hans Verkuil wrote:
>>> On 02/05/14 17:42, Laurent Pinchart wrote:
>>>> Replace the ADV7604-specific hotplug notifier with a GPIO to control the
>>>> HPD pin directly instead of going through the bridge driver.
>>>
>>> Hmm, that's not going to work for me. I don't have a GPIO pin here, instead
>>> it is a bit in a register that I have to set.
>>
>> But that bit controls a GPIO, doesn't it ? In that case it should be exposed
>> as a GPIO controller.
>
> I feel unhappy about losing this notifier for two reasons: first adding a GPIO
> controller just to toggle a bit adds 40 lines to my driver, and that doesn't
> sit well with me. It's basically completely unnecessary overhead.
>

I don't think it's a problem to just keep the hotplug event for now. It is 
not a block for other features, so we can just leave it in.

> The second reason is that in some cases you want to do something in addition
> to just toggling the hotplug pin. In particular for CEC support this could be
> quite useful.
>
> In fact, if the adv7604 supports the ARC feature (Audio Return Channel), then
> this is really needed because in that case the hotplug toggling would have
> to be done via CEC CDC commands. However, while this webpage claims that the
> ARC is supported, I can't find any other information about that.
>
> http://www.analog.com/en/audiovideo-products/analoghdmidvi-interfaces/adv7604/products/product.html
>
> Lars-Peter, do you know anything about ARC support in the adv7604?

No, I think that might be a mistake on the website, but I'll check with 
somebody who knows more about this than me.

- Lars


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

* Re: [PATCH 43/47] adv7604: Control hot-plug detect through a GPIO
  2014-02-13  9:47       ` Hans Verkuil
  2014-02-13 10:10         ` Lars-Peter Clausen
@ 2014-02-13 14:33         ` Laurent Pinchart
  1 sibling, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2014-02-13 14:33 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Hans,

On Thursday 13 February 2014 10:47:44 Hans Verkuil wrote:
> On 02/11/14 13:03, Laurent Pinchart wrote:
> > On Tuesday 11 February 2014 11:09:31 Hans Verkuil wrote:
> >> On 02/05/14 17:42, Laurent Pinchart wrote:
> >>> Replace the ADV7604-specific hotplug notifier with a GPIO to control the
> >>> HPD pin directly instead of going through the bridge driver.
> >> 
> >> Hmm, that's not going to work for me. I don't have a GPIO pin here,
> >> instead it is a bit in a register that I have to set.
> > 
> > But that bit controls a GPIO, doesn't it ? In that case it should be
> > exposed as a GPIO controller.
> 
> I feel unhappy about losing this notifier for two reasons: first adding a
> GPIO controller just to toggle a bit adds 40 lines to my driver, and that
> doesn't sit well with me. It's basically completely unnecessary overhead.
> 
> The second reason is that in some cases you want to do something in addition
> to just toggling the hotplug pin. In particular for CEC support this could
> be quite useful.

As discuss over IRC, I'll keep the HPD notification and add optional GPIO 
support in v2.

> In fact, if the adv7604 supports the ARC feature (Audio Return Channel),
> then this is really needed because in that case the hotplug toggling would
> have to be done via CEC CDC commands. However, while this webpage claims
> that the ARC is supported, I can't find any other information about that.
> 
> http://www.analog.com/en/audiovideo-products/analoghdmidvi-interfaces/adv760
> 4/products/product.html
> 
> Lars-Peter, do you know anything about ARC support in the adv7604?

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 36/47] adv7604: Make output format configurable through pad format operations
  2014-02-12 15:01   ` Hans Verkuil
@ 2014-03-10 22:43     ` Laurent Pinchart
  2014-03-11  9:05       ` Hans Verkuil
  0 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2014-03-10 22:43 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Hans,

On Wednesday 12 February 2014 16:01:17 Hans Verkuil wrote:
> On 02/05/14 17:42, 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 | 243 ++++++++++++++++++++++++++++++++++-----
> >  include/media/adv7604.h     |  47 ++-------
> >  2 files changed, 225 insertions(+), 65 deletions(-)
> 
> <snip>
> 
> > diff --git a/include/media/adv7604.h b/include/media/adv7604.h
> > index 22811d3..2cc8e16 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;
> 
> I would keep this as part of the platform_data. This is typically used if
> things are wired up in a non-standard way and so is specific to the
> hardware. It is not something that will change from format to format.

Right, some level of configuration is needed to account for non-standard 
wiring. However I'm not sure where that should be handled.

With exotic wiring the format at the receiver will be different than the 
format output by the ADV7604. From a pure ADV7604 point of view, the output 
format doesn't depend on the wiring. I wonder whether this shouldn't be a link 
property instead of being a subdev property. There's of course the question of 
where to store that link property if it's not part of either subdev.

Even if we decide that the wiring is a property of the source subdev, I don't 
think we should duplicate bus reordering code in all subdev drivers. This 
should thus be handled by the v4l2 core (either directly or as helper 
functions).

> Other than this it all looks quite nice! Much more flexible than before.
>
> > -
> > -	/* 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;

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 36/47] adv7604: Make output format configurable through pad format operations
  2014-03-10 22:43     ` Laurent Pinchart
@ 2014-03-11  9:05       ` Hans Verkuil
  2014-03-11 11:16         ` Laurent Pinchart
  0 siblings, 1 reply; 83+ messages in thread
From: Hans Verkuil @ 2014-03-11  9:05 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

On 03/10/14 23:43, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Wednesday 12 February 2014 16:01:17 Hans Verkuil wrote:
>> On 02/05/14 17:42, 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 | 243 ++++++++++++++++++++++++++++++++++-----
>>>  include/media/adv7604.h     |  47 ++-------
>>>  2 files changed, 225 insertions(+), 65 deletions(-)
>>
>> <snip>
>>
>>> diff --git a/include/media/adv7604.h b/include/media/adv7604.h
>>> index 22811d3..2cc8e16 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;
>>
>> I would keep this as part of the platform_data. This is typically used if
>> things are wired up in a non-standard way and so is specific to the
>> hardware. It is not something that will change from format to format.
> 
> Right, some level of configuration is needed to account for non-standard 
> wiring. However I'm not sure where that should be handled.
> 
> With exotic wiring the format at the receiver will be different than the 
> format output by the ADV7604. From a pure ADV7604 point of view, the output 
> format doesn't depend on the wiring. I wonder whether this shouldn't be a link 
> property instead of being a subdev property. There's of course the question of 
> where to store that link property if it's not part of either subdev.
> 
> Even if we decide that the wiring is a property of the source subdev, I don't 
> think we should duplicate bus reordering code in all subdev drivers. This 
> should thus be handled by the v4l2 core (either directly or as helper 
> functions).

There are two reasons why you might want to use op_ch_sel: one is to
implement weird formats like RBG. Something like that would have to be
controlled through mbus and pixel fourcc codes and not by hardcoding this
register.

The other is to compensate for a wiring problem: we have a card where two
channels were accidentally swapped. You can either redo the board or just
set this register. In this case this register is IMHO a property of this
subdev. It needs to know about it, because if it ever needs to output RBG
in the future then it needs to compensate for reordering for wiring
issues.

So you set this field if you have to compensate for wiring errors, making
this part of the DT/platform_data. You do not set this field when you
want to support special formats, that is done in the driver itself through
fourcc codes (or could be done as this isn't implemented at the moment).

Regards,

	Hans

> 
>> Other than this it all looks quite nice! Much more flexible than before.
>>
>>> -
>>> -	/* 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;
> 


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

* Re: [PATCH 36/47] adv7604: Make output format configurable through pad format operations
  2014-03-11  9:05       ` Hans Verkuil
@ 2014-03-11 11:16         ` Laurent Pinchart
  2014-03-11 11:29           ` Hans Verkuil
  0 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2014-03-11 11:16 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Hans,

On Tuesday 11 March 2014 10:05:00 Hans Verkuil wrote:
> On 03/10/14 23:43, Laurent Pinchart wrote:
> > On Wednesday 12 February 2014 16:01:17 Hans Verkuil wrote:
> >> On 02/05/14 17:42, 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 | 243 ++++++++++++++++++++++++++++++++-----
> >>>  include/media/adv7604.h     |  47 ++-------
> >>>  2 files changed, 225 insertions(+), 65 deletions(-)
> >> 
> >> <snip>
> >> 
> >>> diff --git a/include/media/adv7604.h b/include/media/adv7604.h
> >>> index 22811d3..2cc8e16 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 {

[snip]

> >>> @@ -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;
> >> 
> >> I would keep this as part of the platform_data. This is typically used if
> >> things are wired up in a non-standard way and so is specific to the
> >> hardware. It is not something that will change from format to format.
> > 
> > Right, some level of configuration is needed to account for non-standard
> > wiring. However I'm not sure where that should be handled.
> > 
> > With exotic wiring the format at the receiver will be different than the
> > format output by the ADV7604. From a pure ADV7604 point of view, the
> > output format doesn't depend on the wiring. I wonder whether this
> > shouldn't be a link property instead of being a subdev property. There's
> > of course the question of where to store that link property if it's not
> > part of either subdev.
> > 
> > Even if we decide that the wiring is a property of the source subdev, I
> > don't think we should duplicate bus reordering code in all subdev
> > drivers. This should thus be handled by the v4l2 core (either directly or
> > as helper functions).
> 
> There are two reasons why you might want to use op_ch_sel: one is to
> implement weird formats like RBG. Something like that would have to be
> controlled through mbus and pixel fourcc codes and not by hardcoding this
> register.

Agreed. This patch only adds a subset of the possible output formats. More 
formats can be added later as needed.

> The other is to compensate for a wiring problem: we have a card where two
> channels were accidentally swapped. You can either redo the board or just
> set this register. In this case this register is IMHO a property of this
> subdev. It needs to know about it, because if it ever needs to output RBG
> in the future then it needs to compensate for reordering for wiring
> issues.
> 
> So you set this field if you have to compensate for wiring errors, making
> this part of the DT/platform_data. You do not set this field when you
> want to support special formats, that is done in the driver itself through
> fourcc codes (or could be done as this isn't implemented at the moment).

I agree with the use case, but I'm not sure whether that's the best way to 
support it. Let's say the system is design for RGB, but the G and B channels 
have been swapped by mistake on the board. To make it work, the ADV7604 would 
need to output RBG, and the bridge would receive RGB. Data reordering would 
thus happen on the link.

There's two ways to expose this to userspace. One of them would be to make the 
real formats visible to applications. We would need to extend the link API to 
show that reordering occurs. Userspace would need to explicitly configure the 
adv7604 driver with RBG at its source pad and the bridge driver with RGB at 
its sink pad. This has the advantage of correctly modeling the hardware, and 
not pushing workarounds for board-level issues to individual drivers.

Another solution would be to hide the wiring problem from userspace and handle 
it inside the adv7604 driver. Note that, depending on the hardware 
configuration, it could be the bridge driver that need to implement 
reordering. Userspace would configure both ends of the link to RGB and 
wouldn't be aware of the problem.  This has the advantage of hiding the 
problem in the kernel. However, it would require implementing the same 
workaround in potentially many drivers.

If we decide to go for the second solution I would like to make it a bit more 
generic than just keeping the op_ch_sel field in platform data. I think we 
should instead have a generic representation of the reordering in platform 
data, and implement a V4L2 core function that would translate the format on 
the link to the format required at the device. For instance, still assuming G 
and B are swapped, userspace would configure the ADV7604 output to 
V4L2_MBUS_FMT_RGB888_1X24, the adv7604 driver would pass 
V4L2_MBUS_FMT_RGB888_1X24 along with the reordering information to a V4L2 core 
function which would return V4L2_MBUS_FMT_RBG888_1X24, and the driver would 
then configure the device to output RBG instead of RGB.

This leaves three open questions :

- Should the workaround be visible to userspace ?
- If not, how should reordering be expressed in platform data (and DT) ?
- Does this need to be part of this patch set or can it be implemented later ?

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 36/47] adv7604: Make output format configurable through pad format operations
  2014-03-11 11:16         ` Laurent Pinchart
@ 2014-03-11 11:29           ` Hans Verkuil
  0 siblings, 0 replies; 83+ messages in thread
From: Hans Verkuil @ 2014-03-11 11:29 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans Verkuil, linux-media, Hans Verkuil, Lars-Peter Clausen

Hi Laurent,

On 03/11/14 12:16, Laurent Pinchart wrote:
> Hi Hans,
> 
> On Tuesday 11 March 2014 10:05:00 Hans Verkuil wrote:
>> On 03/10/14 23:43, Laurent Pinchart wrote:
>>> On Wednesday 12 February 2014 16:01:17 Hans Verkuil wrote:
>>>> On 02/05/14 17:42, 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 | 243 ++++++++++++++++++++++++++++++++-----
>>>>>  include/media/adv7604.h     |  47 ++-------
>>>>>  2 files changed, 225 insertions(+), 65 deletions(-)
>>>>
>>>> <snip>
>>>>
>>>>> diff --git a/include/media/adv7604.h b/include/media/adv7604.h
>>>>> index 22811d3..2cc8e16 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 {
> 
> [snip]
> 
>>>>> @@ -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;
>>>>
>>>> I would keep this as part of the platform_data. This is typically used if
>>>> things are wired up in a non-standard way and so is specific to the
>>>> hardware. It is not something that will change from format to format.
>>>
>>> Right, some level of configuration is needed to account for non-standard
>>> wiring. However I'm not sure where that should be handled.
>>>
>>> With exotic wiring the format at the receiver will be different than the
>>> format output by the ADV7604. From a pure ADV7604 point of view, the
>>> output format doesn't depend on the wiring. I wonder whether this
>>> shouldn't be a link property instead of being a subdev property. There's
>>> of course the question of where to store that link property if it's not
>>> part of either subdev.
>>>
>>> Even if we decide that the wiring is a property of the source subdev, I
>>> don't think we should duplicate bus reordering code in all subdev
>>> drivers. This should thus be handled by the v4l2 core (either directly or
>>> as helper functions).
>>
>> There are two reasons why you might want to use op_ch_sel: one is to
>> implement weird formats like RBG. Something like that would have to be
>> controlled through mbus and pixel fourcc codes and not by hardcoding this
>> register.
> 
> Agreed. This patch only adds a subset of the possible output formats. More 
> formats can be added later as needed.
> 
>> The other is to compensate for a wiring problem: we have a card where two
>> channels were accidentally swapped. You can either redo the board or just
>> set this register. In this case this register is IMHO a property of this
>> subdev. It needs to know about it, because if it ever needs to output RBG
>> in the future then it needs to compensate for reordering for wiring
>> issues.
>>
>> So you set this field if you have to compensate for wiring errors, making
>> this part of the DT/platform_data. You do not set this field when you
>> want to support special formats, that is done in the driver itself through
>> fourcc codes (or could be done as this isn't implemented at the moment).
> 
> I agree with the use case, but I'm not sure whether that's the best way to 
> support it. Let's say the system is design for RGB, but the G and B channels 
> have been swapped by mistake on the board. To make it work, the ADV7604 would 
> need to output RBG, and the bridge would receive RGB. Data reordering would 
> thus happen on the link.
> 
> There's two ways to expose this to userspace. One of them would be to make the 
> real formats visible to applications. We would need to extend the link API to 
> show that reordering occurs. Userspace would need to explicitly configure the 
> adv7604 driver with RBG at its source pad and the bridge driver with RGB at 
> its sink pad. This has the advantage of correctly modeling the hardware, and 
> not pushing workarounds for board-level issues to individual drivers.
> 
> Another solution would be to hide the wiring problem from userspace and handle 
> it inside the adv7604 driver. Note that, depending on the hardware 
> configuration, it could be the bridge driver that need to implement 
> reordering. Userspace would configure both ends of the link to RGB and 
> wouldn't be aware of the problem.  This has the advantage of hiding the 
> problem in the kernel. However, it would require implementing the same 
> workaround in potentially many drivers.
> 
> If we decide to go for the second solution I would like to make it a bit more 
> generic than just keeping the op_ch_sel field in platform data. I think we 
> should instead have a generic representation of the reordering in platform 
> data, and implement a V4L2 core function that would translate the format on 
> the link to the format required at the device. For instance, still assuming G 
> and B are swapped, userspace would configure the ADV7604 output to 
> V4L2_MBUS_FMT_RGB888_1X24, the adv7604 driver would pass 
> V4L2_MBUS_FMT_RGB888_1X24 along with the reordering information to a V4L2 core 
> function which would return V4L2_MBUS_FMT_RBG888_1X24, and the driver would 
> then configure the device to output RBG instead of RGB.
> 
> This leaves three open questions :
> 
> - Should the workaround be visible to userspace ?

Absolutely not. Userspace really, really does not want to care about this.
It would also lead to a crazy proliferation of different fourccs, one for
each 'reordering' combination of channels.

> - If not, how should reordering be expressed in platform data (and DT) ?

It could be a more generic reordering define (i.e. less ADV specific).
Proposals are welcome.

> - Does this need to be part of this patch set or can it be implemented later ?

Yes. I need it :-)

But it doesn't have to be in the DT, keeping it as platform_data for now is
perfectly fine with me, nor do I mind changing it in the future.

Regards,

	Hans

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

end of thread, other threads:[~2014-03-11 11:29 UTC | newest]

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

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.