All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/5] Add MIPI rx DPI support
@ 2021-03-19  6:31 ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:31 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: Neil Armstrong, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Dan Carpenter, David Airlie, Daniel Vetter, Boris Brezillon,
	Sam Ravnborg, Hsin-Yi Wang, Torsten Duwe, Vasily Khoruzhick,
	Marek Szyprowski, Sheng Pan, Bernie Liang, Zhen Li, dri-devel,
	linux-kernel, devel

Hi all, this patch series implement MIPI rx DPI feature. Please help to review.

This is the v6 version, any mistakes, please let me know,
I'll fix it in the next series.

Change history:
v6: Fix kernel robot compile warning

v5: Fix Rob Herring, Hsin-Yi, Robert Foss comments
 - Rebase code on the branch 'drm-misc-next', refer video-interfaces.yaml
 - Seprate HDCP function to a new patch
 - Fix driver not correctly get 'bus-type' 'data-lanes'
 - Add audio HDMI codec function support

v4: Fix Rob Herring comment
 - Rebase code on the branch 'drm-misc-next'
 - Change 'analogix,hdcp-support' type to boolean

v3: Fix Rob Herring, Dan Carpenter, Nicolas comment
 - Split the patch, fix not correct return data
 - Fix several coding format
 - Split DP tx swing register setting to two property
 - Add HDCP support vender flag
 - remove 'analogix,swing-setting' and 'analogix,mipi-dpi-in' property

v2: Fix Rob Herring comment
 - Fix yamllint warnings/errors in analogix,anx7625.yaml
 - Fix kernel robot compile warning

v1: initial MIPI rx DPI feature support


Xin Ji (5):
  dt-bindings:drm/bridge:anx7625:add vendor define flags
  drm/bridge: anx7625: fix not correct return value
  drm/bridge: anx7625: add MIPI DPI input feature support
  drm/bridge: anx7625: add HDCP support
  drm/bridge: anx7625: add HDMI audio function

 .../display/bridge/analogix,anx7625.yaml      |  58 +-
 drivers/gpu/drm/bridge/analogix/anx7625.c     | 603 ++++++++++++++++--
 drivers/gpu/drm/bridge/analogix/anx7625.h     |  59 +-
 3 files changed, 667 insertions(+), 53 deletions(-)

-- 
2.25.1


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

* [PATCH v6 0/5] Add MIPI rx DPI support
@ 2021-03-19  6:31 ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:31 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: devel, Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, linux-kernel, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe,
	Laurent Pinchart, Daniel Vetter, Hsin-Yi Wang, Sam Ravnborg,
	Dan Carpenter, Marek Szyprowski

Hi all, this patch series implement MIPI rx DPI feature. Please help to review.

This is the v6 version, any mistakes, please let me know,
I'll fix it in the next series.

Change history:
v6: Fix kernel robot compile warning

v5: Fix Rob Herring, Hsin-Yi, Robert Foss comments
 - Rebase code on the branch 'drm-misc-next', refer video-interfaces.yaml
 - Seprate HDCP function to a new patch
 - Fix driver not correctly get 'bus-type' 'data-lanes'
 - Add audio HDMI codec function support

v4: Fix Rob Herring comment
 - Rebase code on the branch 'drm-misc-next'
 - Change 'analogix,hdcp-support' type to boolean

v3: Fix Rob Herring, Dan Carpenter, Nicolas comment
 - Split the patch, fix not correct return data
 - Fix several coding format
 - Split DP tx swing register setting to two property
 - Add HDCP support vender flag
 - remove 'analogix,swing-setting' and 'analogix,mipi-dpi-in' property

v2: Fix Rob Herring comment
 - Fix yamllint warnings/errors in analogix,anx7625.yaml
 - Fix kernel robot compile warning

v1: initial MIPI rx DPI feature support


Xin Ji (5):
  dt-bindings:drm/bridge:anx7625:add vendor define flags
  drm/bridge: anx7625: fix not correct return value
  drm/bridge: anx7625: add MIPI DPI input feature support
  drm/bridge: anx7625: add HDCP support
  drm/bridge: anx7625: add HDMI audio function

 .../display/bridge/analogix,anx7625.yaml      |  58 +-
 drivers/gpu/drm/bridge/analogix/anx7625.c     | 603 ++++++++++++++++--
 drivers/gpu/drm/bridge/analogix/anx7625.h     |  59 +-
 3 files changed, 667 insertions(+), 53 deletions(-)

-- 
2.25.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* [PATCH v6 0/5] Add MIPI rx DPI support
@ 2021-03-19  6:31 ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:31 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: devel, Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, linux-kernel, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe,
	Laurent Pinchart, Hsin-Yi Wang, Sam Ravnborg, Dan Carpenter,
	Marek Szyprowski

Hi all, this patch series implement MIPI rx DPI feature. Please help to review.

This is the v6 version, any mistakes, please let me know,
I'll fix it in the next series.

Change history:
v6: Fix kernel robot compile warning

v5: Fix Rob Herring, Hsin-Yi, Robert Foss comments
 - Rebase code on the branch 'drm-misc-next', refer video-interfaces.yaml
 - Seprate HDCP function to a new patch
 - Fix driver not correctly get 'bus-type' 'data-lanes'
 - Add audio HDMI codec function support

v4: Fix Rob Herring comment
 - Rebase code on the branch 'drm-misc-next'
 - Change 'analogix,hdcp-support' type to boolean

v3: Fix Rob Herring, Dan Carpenter, Nicolas comment
 - Split the patch, fix not correct return data
 - Fix several coding format
 - Split DP tx swing register setting to two property
 - Add HDCP support vender flag
 - remove 'analogix,swing-setting' and 'analogix,mipi-dpi-in' property

v2: Fix Rob Herring comment
 - Fix yamllint warnings/errors in analogix,anx7625.yaml
 - Fix kernel robot compile warning

v1: initial MIPI rx DPI feature support


Xin Ji (5):
  dt-bindings:drm/bridge:anx7625:add vendor define flags
  drm/bridge: anx7625: fix not correct return value
  drm/bridge: anx7625: add MIPI DPI input feature support
  drm/bridge: anx7625: add HDCP support
  drm/bridge: anx7625: add HDMI audio function

 .../display/bridge/analogix,anx7625.yaml      |  58 +-
 drivers/gpu/drm/bridge/analogix/anx7625.c     | 603 ++++++++++++++++--
 drivers/gpu/drm/bridge/analogix/anx7625.h     |  59 +-
 3 files changed, 667 insertions(+), 53 deletions(-)

-- 
2.25.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v6 1/5] dt-bindings:drm/bridge:anx7625:add vendor define flags
  2021-03-19  6:31 ` Xin Ji
@ 2021-03-19  6:32   ` Xin Ji
  -1 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:32 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Nicolas Boichat, Hsin-Yi Wang
  Cc: Daniel Vetter, Sam Ravnborg, Laurent Pinchart, Maxime Ripard,
	Mark Brown, Ricardo Cañuelo, dri-devel, devicetree,
	Bernie Liang, Sheng Pan, Zhen Li, linux-kernel

Add 'bus-type' and 'data-lanes' define for port0. Define DP tx lane0,
lane1 swing register array define, and audio enable flag.

Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 .../display/bridge/analogix,anx7625.yaml      | 58 ++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
index c789784efe30..3f54d5876982 100644
--- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
@@ -34,6 +34,26 @@ properties:
     description: used for reset chip control, RESET_N pin B7.
     maxItems: 1
 
+  analogix,lane0-swing:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    minItems: 1
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane0 PHY, please don't
+      add this property, or contact vendor.
+
+  analogix,lane1-swing:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    minItems: 1
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane1 PHY, please don't
+      add this property, or contact vendor.
+
+  analogix,audio-enable:
+    type: boolean
+    description: let the driver enable audio HDMI codec function or not.
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
@@ -41,13 +61,43 @@ properties:
       port@0:
         $ref: /schemas/graph.yaml#/properties/port
         description:
-          Video port for MIPI DSI input.
+          MIPI DSI/DPI input.
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            type: object
+            additionalProperties: false
+
+            properties:
+              remote-endpoint: true
+              bus-type: true
+              data-lanes: true
+
+            required:
+              - remote-endpoint
+
+        required:
+          - endpoint
+
 
       port@1:
         $ref: /schemas/graph.yaml#/properties/port
         description:
           Video port for panel or connector.
 
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            type: object
+            additionalProperties: false
+
+            properties:
+              remote-endpoint: true
+
+            required:
+              - remote-endpoint
+
     required:
       - port@0
       - port@1
@@ -73,6 +123,10 @@ examples:
             enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
             reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
 
+            analogix,audio-enable;
+            analogix,lane0-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
+            analogix,lane1-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
+
             ports {
                 #address-cells = <1>;
                 #size-cells = <0>;
@@ -81,6 +135,8 @@ examples:
                     reg = <0>;
                     anx7625_in: endpoint {
                         remote-endpoint = <&mipi_dsi>;
+                        bus-type = <5>;
+                        data-lanes = <0 1 2 3>;
                     };
                 };
 
-- 
2.25.1


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

* [PATCH v6 1/5] dt-bindings:drm/bridge:anx7625:add vendor define flags
@ 2021-03-19  6:32   ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:32 UTC (permalink / raw)
  To: Rob Herring, David Airlie, Nicolas Boichat, Hsin-Yi Wang
  Cc: devicetree, Laurent Pinchart, Sam Ravnborg, linux-kernel,
	Mark Brown, dri-devel, Zhen Li, Ricardo Cañuelo,
	Bernie Liang, Sheng Pan

Add 'bus-type' and 'data-lanes' define for port0. Define DP tx lane0,
lane1 swing register array define, and audio enable flag.

Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 .../display/bridge/analogix,anx7625.yaml      | 58 ++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
index c789784efe30..3f54d5876982 100644
--- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
@@ -34,6 +34,26 @@ properties:
     description: used for reset chip control, RESET_N pin B7.
     maxItems: 1
 
+  analogix,lane0-swing:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    minItems: 1
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane0 PHY, please don't
+      add this property, or contact vendor.
+
+  analogix,lane1-swing:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    minItems: 1
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane1 PHY, please don't
+      add this property, or contact vendor.
+
+  analogix,audio-enable:
+    type: boolean
+    description: let the driver enable audio HDMI codec function or not.
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
@@ -41,13 +61,43 @@ properties:
       port@0:
         $ref: /schemas/graph.yaml#/properties/port
         description:
-          Video port for MIPI DSI input.
+          MIPI DSI/DPI input.
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            type: object
+            additionalProperties: false
+
+            properties:
+              remote-endpoint: true
+              bus-type: true
+              data-lanes: true
+
+            required:
+              - remote-endpoint
+
+        required:
+          - endpoint
+
 
       port@1:
         $ref: /schemas/graph.yaml#/properties/port
         description:
           Video port for panel or connector.
 
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            type: object
+            additionalProperties: false
+
+            properties:
+              remote-endpoint: true
+
+            required:
+              - remote-endpoint
+
     required:
       - port@0
       - port@1
@@ -73,6 +123,10 @@ examples:
             enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
             reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
 
+            analogix,audio-enable;
+            analogix,lane0-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
+            analogix,lane1-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
+
             ports {
                 #address-cells = <1>;
                 #size-cells = <0>;
@@ -81,6 +135,8 @@ examples:
                     reg = <0>;
                     anx7625_in: endpoint {
                         remote-endpoint = <&mipi_dsi>;
+                        bus-type = <5>;
+                        data-lanes = <0 1 2 3>;
                     };
                 };
 
-- 
2.25.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v6 2/5] drm/bridge: anx7625: fix not correct return value
  2021-03-19  6:31 ` Xin Ji
  (?)
@ 2021-03-19  6:33   ` Xin Ji
  -1 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:33 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: Neil Armstrong, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Dan Carpenter, David Airlie, Daniel Vetter, Boris Brezillon,
	Sam Ravnborg, Hsin-Yi Wang, Torsten Duwe, Vasily Khoruzhick,
	Marek Szyprowski, Sheng Pan, Bernie Liang, Zhen Li, dri-devel,
	linux-kernel, devel

At some time, the original code may return non zero value, force return 0
if operation finished.

Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 65cc05982f82..04536cc7afe7 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -189,10 +189,10 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
 			       AP_AUX_CTRL_STATUS);
 	if (val < 0 || (val & 0x0F)) {
 		DRM_DEV_ERROR(dev, "aux status %02x\n", val);
-		val = -EIO;
+		return -EIO;
 	}
 
-	return val;
+	return 0;
 }
 
 static int anx7625_video_mute_control(struct anx7625_data *ctx,
-- 
2.25.1


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

* [PATCH v6 2/5] drm/bridge: anx7625: fix not correct return value
@ 2021-03-19  6:33   ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:33 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: devel, Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, linux-kernel, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe,
	Laurent Pinchart, Daniel Vetter, Hsin-Yi Wang, Sam Ravnborg,
	Dan Carpenter, Marek Szyprowski

At some time, the original code may return non zero value, force return 0
if operation finished.

Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 65cc05982f82..04536cc7afe7 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -189,10 +189,10 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
 			       AP_AUX_CTRL_STATUS);
 	if (val < 0 || (val & 0x0F)) {
 		DRM_DEV_ERROR(dev, "aux status %02x\n", val);
-		val = -EIO;
+		return -EIO;
 	}
 
-	return val;
+	return 0;
 }
 
 static int anx7625_video_mute_control(struct anx7625_data *ctx,
-- 
2.25.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* [PATCH v6 2/5] drm/bridge: anx7625: fix not correct return value
@ 2021-03-19  6:33   ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:33 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: devel, Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, linux-kernel, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe,
	Laurent Pinchart, Hsin-Yi Wang, Sam Ravnborg, Dan Carpenter,
	Marek Szyprowski

At some time, the original code may return non zero value, force return 0
if operation finished.

Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 65cc05982f82..04536cc7afe7 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -189,10 +189,10 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
 			       AP_AUX_CTRL_STATUS);
 	if (val < 0 || (val & 0x0F)) {
 		DRM_DEV_ERROR(dev, "aux status %02x\n", val);
-		val = -EIO;
+		return -EIO;
 	}
 
-	return val;
+	return 0;
 }
 
 static int anx7625_video_mute_control(struct anx7625_data *ctx,
-- 
2.25.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v6 3/5] drm/bridge: anx7625: add MIPI DPI input feature support
  2021-03-19  6:31 ` Xin Ji
  (?)
@ 2021-03-19  6:34   ` Xin Ji
  -1 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:34 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: Neil Armstrong, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Dan Carpenter, David Airlie, Daniel Vetter, Boris Brezillon,
	Sam Ravnborg, Hsin-Yi Wang, Torsten Duwe, Vasily Khoruzhick,
	Marek Szyprowski, Sheng Pan, Bernie Liang, Zhen Li, dri-devel,
	linux-kernel, devel

Add MIPI rx DPI input support.

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 245 ++++++++++++++++------
 drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
 2 files changed, 203 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 04536cc7afe7..8c514b46d361 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -150,18 +150,18 @@ static int anx7625_write_and(struct anx7625_data *ctx,
 	return anx7625_reg_write(ctx, client, offset, (val & (mask)));
 }
 
-static int anx7625_write_and_or(struct anx7625_data *ctx,
-				struct i2c_client *client,
-				u8 offset, u8 and_mask, u8 or_mask)
+static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
 {
-	int val;
+	int i, ret;
 
-	val = anx7625_reg_read(ctx, client, offset);
-	if (val < 0)
-		return val;
+	ret = anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
+			       AUDIO_CONTROL_REGISTER, 0x80);
+	for (i = 0; i < 13; i++)
+		ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
+					 VIDEO_BIT_MATRIX_12 + i,
+					 0x18 + i);
 
-	return anx7625_reg_write(ctx, client,
-				 offset, (val & and_mask) | (or_mask));
+	return ret;
 }
 
 static int anx7625_read_ctrl_status_p0(struct anx7625_data *ctx)
@@ -219,38 +219,6 @@ static int anx7625_video_mute_control(struct anx7625_data *ctx,
 	return ret;
 }
 
-static int anx7625_config_audio_input(struct anx7625_data *ctx)
-{
-	struct device *dev = &ctx->client->dev;
-	int ret;
-
-	/* Channel num */
-	ret = anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
-				AUDIO_CHANNEL_STATUS_6, I2S_CH_2 << 5);
-
-	/* FS */
-	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
-				    AUDIO_CHANNEL_STATUS_4,
-				    0xf0, AUDIO_FS_48K);
-	/* Word length */
-	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
-				    AUDIO_CHANNEL_STATUS_5,
-				    0xf0, AUDIO_W_LEN_24_24MAX);
-	/* I2S */
-	ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
-				AUDIO_CHANNEL_STATUS_6, I2S_SLAVE_MODE);
-	ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
-				 AUDIO_CONTROL_REGISTER, ~TDM_TIMING_MODE);
-	/* Audio change flag */
-	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
-				AP_AV_STATUS, AP_AUDIO_CHG);
-
-	if (ret < 0)
-		DRM_DEV_ERROR(dev, "fail to config audio.\n");
-
-	return ret;
-}
-
 /* Reduction of fraction a/b */
 static void anx7625_reduction_of_a_fraction(unsigned long *a, unsigned long *b)
 {
@@ -410,7 +378,7 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
 	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
 			MIPI_LANE_CTRL_0, 0xfc);
 	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client,
-				MIPI_LANE_CTRL_0, 3);
+				MIPI_LANE_CTRL_0, ctx->pdata.mipi_lanes - 1);
 
 	/* Htotal */
 	htotal = ctx->dt.hactive.min + ctx->dt.hfront_porch.min +
@@ -595,6 +563,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
 	return ret;
 }
 
+static int anx7625_api_dpi_config(struct anx7625_data *ctx)
+{
+	struct device *dev = &ctx->client->dev;
+	u16 freq = ctx->dt.pixelclock.min / 1000;
+	int ret;
+
+	/* configure pixel clock */
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				PIXEL_CLOCK_L, freq & 0xFF);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 PIXEL_CLOCK_H, (freq >> 8));
+
+	/* set DPI mode */
+	/* set to DPI PLL module sel */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_DIGITAL_PLL_9, 0x20);
+	/* power down MIPI */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_LANE_CTRL_10, 0x08);
+	/* enable DPI mode */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_DIGITAL_PLL_18, 0x1C);
+	/* set first edge */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
+				 VIDEO_CONTROL_0, 0x06);
+	if (ret < 0)
+		DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
+
+	return ret;
+}
+
+static int anx7625_dpi_config(struct anx7625_data *ctx)
+{
+	struct device *dev = &ctx->client->dev;
+	int ret;
+
+	DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
+
+	/* DSC disable */
+	ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
+				R_DSC_CTRL_0, ~DSC_EN);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
+		return ret;
+	}
+
+	ret = anx7625_config_bit_matrix(ctx);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
+		return ret;
+	}
+
+	ret = anx7625_api_dpi_config(ctx);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
+		return ret;
+	}
+
+	/* set MIPI RX EN */
+	ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
+			       AP_AV_STATUS, AP_MIPI_RX_EN);
+	/* clear mute flag */
+	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
+				 AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
+	if (ret < 0)
+		DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
+
+	return ret;
+}
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
 	int ret;
@@ -605,9 +643,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
 		return;
 	}
 
-	anx7625_config_audio_input(ctx);
-
-	ret = anx7625_dsi_config(ctx);
+	if (ctx->pdata.is_dpi)
+		ret = anx7625_dpi_config(ctx);
+	else
+		ret = anx7625_dsi_config(ctx);
 
 	if (ret < 0)
 		DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
@@ -1051,6 +1090,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
 		return;
 	}
 
+	ctx->hpd_status = 1;
 	ctx->hpd_high_cnt++;
 
 	/* Not support HDCP */
@@ -1060,8 +1100,10 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
 	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
 	/* Interrupt for DRM */
 	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
-	if (ret < 0)
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "fail to setting HDCP/auth\n");
 		return;
+	}
 
 	ret = anx7625_reg_read(ctx, ctx->i2c.rx_p1_client, 0x86);
 	if (ret < 0)
@@ -1080,6 +1122,10 @@ static void anx7625_hpd_polling(struct anx7625_data *ctx)
 	int ret, val;
 	struct device *dev = &ctx->client->dev;
 
+	/* Interrupt mode, no need poll HPD status, just return */
+	if (ctx->pdata.intp_irq)
+		return;
+
 	if (atomic_read(&ctx->power_status) != 1) {
 		DRM_DEV_DEBUG_DRIVER(dev, "No need to poling HPD status.\n");
 		return;
@@ -1130,6 +1176,21 @@ static void anx7625_remove_edid(struct anx7625_data *ctx)
 	ctx->slimport_edid_p.edid_block_num = -1;
 }
 
+static void anx7625_dp_adjust_swing(struct anx7625_data *ctx)
+{
+	int i;
+
+	for (i = 0; i < ctx->pdata.dp_lane0_swing_reg_cnt; i++)
+		anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
+				  DP_TX_LANE0_SWING_REG0 + i,
+				  ctx->pdata.lane0_reg_data[i] & 0xFF);
+
+	for (i = 0; i < ctx->pdata.dp_lane1_swing_reg_cnt; i++)
+		anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
+				  DP_TX_LANE1_SWING_REG0 + i,
+				  ctx->pdata.lane1_reg_data[i] & 0xFF);
+}
+
 static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
 {
 	struct device *dev = &ctx->client->dev;
@@ -1145,9 +1206,8 @@ static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
 	} else {
 		DRM_DEV_DEBUG_DRIVER(dev, " HPD high\n");
 		anx7625_start_dp_work(ctx);
+		anx7625_dp_adjust_swing(ctx);
 	}
-
-	ctx->hpd_status = 1;
 }
 
 static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
@@ -1224,20 +1284,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static int anx7625_get_swing_setting(struct device *dev,
+				     struct anx7625_platform_data *pdata)
+{
+	int num_regs;
+
+	if (of_get_property(dev->of_node,
+			    "analogix,lane0-swing", &num_regs)) {
+		if (num_regs > DP_TX_SWING_REG_CNT)
+			num_regs = DP_TX_SWING_REG_CNT;
+
+		pdata->dp_lane0_swing_reg_cnt = num_regs;
+		of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
+					   pdata->lane0_reg_data, num_regs);
+	}
+
+	if (of_get_property(dev->of_node,
+			    "analogix,lane1-swing", &num_regs)) {
+		if (num_regs > DP_TX_SWING_REG_CNT)
+			num_regs = DP_TX_SWING_REG_CNT;
+
+		pdata->dp_lane1_swing_reg_cnt = num_regs;
+		of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
+					   pdata->lane1_reg_data, num_regs);
+	}
+
+	return 0;
+}
+
 static int anx7625_parse_dt(struct device *dev,
 			    struct anx7625_platform_data *pdata)
 {
-	struct device_node *np = dev->of_node;
+	struct device_node *np = dev->of_node, *ep0;
 	struct drm_panel *panel;
 	int ret;
+	int bus_type, mipi_lanes;
 
+	anx7625_get_swing_setting(dev, pdata);
+
+	pdata->is_dpi = 1; /* default dpi mode */
 	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
 	if (!pdata->mipi_host_node) {
 		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
 		return -ENODEV;
 	}
 
-	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
+	bus_type = 5;
+	mipi_lanes = MAX_LANES_SUPPORT;
+	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
+	if (ep0) {
+		if (of_property_read_u32(ep0, "bus-type", &bus_type))
+			bus_type = 0;
+
+		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
+	}
+
+	if (bus_type == 5) /* bus type is Parallel(DSI) */
+		pdata->is_dpi = 0;
+
+	pdata->mipi_lanes = mipi_lanes;
+	if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
+		pdata->mipi_lanes = MAX_LANES_SUPPORT;
+
+	if (pdata->is_dpi)
+		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
+	else
+		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
 
 	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
 	if (ret < 0) {
@@ -1300,9 +1412,13 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
 {
 	struct device *dev = &ctx->client->dev;
 
-	DRM_DEV_DEBUG_DRIVER(dev, "sink detect, return connected\n");
+	DRM_DEV_DEBUG_DRIVER(dev, "sink detect\n");
+
+	if (ctx->pdata.panel_bridge)
+		return connector_status_connected;
 
-	return connector_status_connected;
+	return ctx->hpd_status ? connector_status_connected :
+				     connector_status_disconnected;
 }
 
 static int anx7625_attach_dsi(struct anx7625_data *ctx)
@@ -1330,7 +1446,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
 		return -EINVAL;
 	}
 
-	dsi->lanes = 4;
+	dsi->lanes = ctx->pdata.mipi_lanes;
 	dsi->format = MIPI_DSI_FMT_RGB888;
 	dsi->mode_flags = MIPI_DSI_MODE_VIDEO	|
 		MIPI_DSI_MODE_VIDEO_SYNC_PULSE	|
@@ -1376,10 +1492,12 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
 		return -ENODEV;
 	}
 
-	err = anx7625_attach_dsi(ctx);
-	if (err) {
-		DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
-		return err;
+	if (!ctx->pdata.is_dpi) {
+		err = anx7625_attach_dsi(ctx);
+		if (err) {
+			DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
+			return err;
+		}
 	}
 
 	if (ctx->pdata.panel_bridge) {
@@ -1478,6 +1596,10 @@ static bool anx7625_bridge_mode_fixup(struct drm_bridge *bridge,
 
 	DRM_DEV_DEBUG_DRIVER(dev, "drm mode fixup set\n");
 
+	/* No need fixup for external monitor */
+	if (!ctx->pdata.panel_bridge)
+		return true;
+
 	hsync = mode->hsync_end - mode->hsync_start;
 	hfp = mode->hsync_start - mode->hdisplay;
 	hbp = mode->htotal - mode->hsync_end;
@@ -1786,8 +1908,13 @@ static int anx7625_i2c_probe(struct i2c_client *client,
 
 	platform->bridge.funcs = &anx7625_bridge_funcs;
 	platform->bridge.of_node = client->dev.of_node;
-	platform->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
-	platform->bridge.type = DRM_MODE_CONNECTOR_eDP;
+	platform->bridge.ops = DRM_BRIDGE_OP_EDID;
+	if (!platform->pdata.panel_bridge)
+		platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
+					DRM_BRIDGE_OP_DETECT;
+	platform->bridge.type = platform->pdata.panel_bridge ?
+				    DRM_MODE_CONNECTOR_eDP :
+				    DRM_MODE_CONNECTOR_DisplayPort;
 	drm_bridge_add(&platform->bridge);
 
 	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 193ad86c5450..beee95da2155 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -141,12 +141,20 @@
 #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
 
 /******** END of I2C Address 0x72 *********/
+
+/***************************************************************/
+/* Register definition of device address 0x7a */
+#define DP_TX_SWING_REG_CNT		0x14
+#define DP_TX_LANE0_SWING_REG0		0x00
+#define DP_TX_LANE1_SWING_REG0		0x14
+/******** END of I2C Address 0x7a *********/
+
 /***************************************************************/
 /* Register definition of device address 0x7e */
 
 #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
 
-#define FLASH_LOAD_STA 0x05
+#define FLASH_LOAD_STA          0x05
 #define FLASH_LOAD_STA_CHK	BIT(7)
 
 #define  XTAL_FRQ_SEL    0x3F
@@ -347,11 +355,19 @@ struct s_edid_data {
 
 /***************** Display End *****************/
 
+#define MAX_LANES_SUPPORT	4
+
 struct anx7625_platform_data {
 	struct gpio_desc *gpio_p_on;
 	struct gpio_desc *gpio_reset;
 	struct drm_bridge *panel_bridge;
 	int intp_irq;
+	int is_dpi;
+	int mipi_lanes;
+	int dp_lane0_swing_reg_cnt;
+	int lane0_reg_data[DP_TX_SWING_REG_CNT];
+	int dp_lane1_swing_reg_cnt;
+	int lane1_reg_data[DP_TX_SWING_REG_CNT];
 	u32 low_power_mode;
 	struct device_node *mipi_host_node;
 };
-- 
2.25.1


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

* [PATCH v6 3/5] drm/bridge: anx7625: add MIPI DPI input feature support
@ 2021-03-19  6:34   ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:34 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: devel, Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, linux-kernel, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe,
	Laurent Pinchart, Daniel Vetter, Hsin-Yi Wang, Sam Ravnborg,
	Dan Carpenter, Marek Szyprowski

Add MIPI rx DPI input support.

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 245 ++++++++++++++++------
 drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
 2 files changed, 203 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 04536cc7afe7..8c514b46d361 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -150,18 +150,18 @@ static int anx7625_write_and(struct anx7625_data *ctx,
 	return anx7625_reg_write(ctx, client, offset, (val & (mask)));
 }
 
-static int anx7625_write_and_or(struct anx7625_data *ctx,
-				struct i2c_client *client,
-				u8 offset, u8 and_mask, u8 or_mask)
+static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
 {
-	int val;
+	int i, ret;
 
-	val = anx7625_reg_read(ctx, client, offset);
-	if (val < 0)
-		return val;
+	ret = anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
+			       AUDIO_CONTROL_REGISTER, 0x80);
+	for (i = 0; i < 13; i++)
+		ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
+					 VIDEO_BIT_MATRIX_12 + i,
+					 0x18 + i);
 
-	return anx7625_reg_write(ctx, client,
-				 offset, (val & and_mask) | (or_mask));
+	return ret;
 }
 
 static int anx7625_read_ctrl_status_p0(struct anx7625_data *ctx)
@@ -219,38 +219,6 @@ static int anx7625_video_mute_control(struct anx7625_data *ctx,
 	return ret;
 }
 
-static int anx7625_config_audio_input(struct anx7625_data *ctx)
-{
-	struct device *dev = &ctx->client->dev;
-	int ret;
-
-	/* Channel num */
-	ret = anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
-				AUDIO_CHANNEL_STATUS_6, I2S_CH_2 << 5);
-
-	/* FS */
-	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
-				    AUDIO_CHANNEL_STATUS_4,
-				    0xf0, AUDIO_FS_48K);
-	/* Word length */
-	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
-				    AUDIO_CHANNEL_STATUS_5,
-				    0xf0, AUDIO_W_LEN_24_24MAX);
-	/* I2S */
-	ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
-				AUDIO_CHANNEL_STATUS_6, I2S_SLAVE_MODE);
-	ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
-				 AUDIO_CONTROL_REGISTER, ~TDM_TIMING_MODE);
-	/* Audio change flag */
-	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
-				AP_AV_STATUS, AP_AUDIO_CHG);
-
-	if (ret < 0)
-		DRM_DEV_ERROR(dev, "fail to config audio.\n");
-
-	return ret;
-}
-
 /* Reduction of fraction a/b */
 static void anx7625_reduction_of_a_fraction(unsigned long *a, unsigned long *b)
 {
@@ -410,7 +378,7 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
 	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
 			MIPI_LANE_CTRL_0, 0xfc);
 	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client,
-				MIPI_LANE_CTRL_0, 3);
+				MIPI_LANE_CTRL_0, ctx->pdata.mipi_lanes - 1);
 
 	/* Htotal */
 	htotal = ctx->dt.hactive.min + ctx->dt.hfront_porch.min +
@@ -595,6 +563,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
 	return ret;
 }
 
+static int anx7625_api_dpi_config(struct anx7625_data *ctx)
+{
+	struct device *dev = &ctx->client->dev;
+	u16 freq = ctx->dt.pixelclock.min / 1000;
+	int ret;
+
+	/* configure pixel clock */
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				PIXEL_CLOCK_L, freq & 0xFF);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 PIXEL_CLOCK_H, (freq >> 8));
+
+	/* set DPI mode */
+	/* set to DPI PLL module sel */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_DIGITAL_PLL_9, 0x20);
+	/* power down MIPI */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_LANE_CTRL_10, 0x08);
+	/* enable DPI mode */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_DIGITAL_PLL_18, 0x1C);
+	/* set first edge */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
+				 VIDEO_CONTROL_0, 0x06);
+	if (ret < 0)
+		DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
+
+	return ret;
+}
+
+static int anx7625_dpi_config(struct anx7625_data *ctx)
+{
+	struct device *dev = &ctx->client->dev;
+	int ret;
+
+	DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
+
+	/* DSC disable */
+	ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
+				R_DSC_CTRL_0, ~DSC_EN);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
+		return ret;
+	}
+
+	ret = anx7625_config_bit_matrix(ctx);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
+		return ret;
+	}
+
+	ret = anx7625_api_dpi_config(ctx);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
+		return ret;
+	}
+
+	/* set MIPI RX EN */
+	ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
+			       AP_AV_STATUS, AP_MIPI_RX_EN);
+	/* clear mute flag */
+	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
+				 AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
+	if (ret < 0)
+		DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
+
+	return ret;
+}
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
 	int ret;
@@ -605,9 +643,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
 		return;
 	}
 
-	anx7625_config_audio_input(ctx);
-
-	ret = anx7625_dsi_config(ctx);
+	if (ctx->pdata.is_dpi)
+		ret = anx7625_dpi_config(ctx);
+	else
+		ret = anx7625_dsi_config(ctx);
 
 	if (ret < 0)
 		DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
@@ -1051,6 +1090,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
 		return;
 	}
 
+	ctx->hpd_status = 1;
 	ctx->hpd_high_cnt++;
 
 	/* Not support HDCP */
@@ -1060,8 +1100,10 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
 	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
 	/* Interrupt for DRM */
 	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
-	if (ret < 0)
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "fail to setting HDCP/auth\n");
 		return;
+	}
 
 	ret = anx7625_reg_read(ctx, ctx->i2c.rx_p1_client, 0x86);
 	if (ret < 0)
@@ -1080,6 +1122,10 @@ static void anx7625_hpd_polling(struct anx7625_data *ctx)
 	int ret, val;
 	struct device *dev = &ctx->client->dev;
 
+	/* Interrupt mode, no need poll HPD status, just return */
+	if (ctx->pdata.intp_irq)
+		return;
+
 	if (atomic_read(&ctx->power_status) != 1) {
 		DRM_DEV_DEBUG_DRIVER(dev, "No need to poling HPD status.\n");
 		return;
@@ -1130,6 +1176,21 @@ static void anx7625_remove_edid(struct anx7625_data *ctx)
 	ctx->slimport_edid_p.edid_block_num = -1;
 }
 
+static void anx7625_dp_adjust_swing(struct anx7625_data *ctx)
+{
+	int i;
+
+	for (i = 0; i < ctx->pdata.dp_lane0_swing_reg_cnt; i++)
+		anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
+				  DP_TX_LANE0_SWING_REG0 + i,
+				  ctx->pdata.lane0_reg_data[i] & 0xFF);
+
+	for (i = 0; i < ctx->pdata.dp_lane1_swing_reg_cnt; i++)
+		anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
+				  DP_TX_LANE1_SWING_REG0 + i,
+				  ctx->pdata.lane1_reg_data[i] & 0xFF);
+}
+
 static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
 {
 	struct device *dev = &ctx->client->dev;
@@ -1145,9 +1206,8 @@ static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
 	} else {
 		DRM_DEV_DEBUG_DRIVER(dev, " HPD high\n");
 		anx7625_start_dp_work(ctx);
+		anx7625_dp_adjust_swing(ctx);
 	}
-
-	ctx->hpd_status = 1;
 }
 
 static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
@@ -1224,20 +1284,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static int anx7625_get_swing_setting(struct device *dev,
+				     struct anx7625_platform_data *pdata)
+{
+	int num_regs;
+
+	if (of_get_property(dev->of_node,
+			    "analogix,lane0-swing", &num_regs)) {
+		if (num_regs > DP_TX_SWING_REG_CNT)
+			num_regs = DP_TX_SWING_REG_CNT;
+
+		pdata->dp_lane0_swing_reg_cnt = num_regs;
+		of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
+					   pdata->lane0_reg_data, num_regs);
+	}
+
+	if (of_get_property(dev->of_node,
+			    "analogix,lane1-swing", &num_regs)) {
+		if (num_regs > DP_TX_SWING_REG_CNT)
+			num_regs = DP_TX_SWING_REG_CNT;
+
+		pdata->dp_lane1_swing_reg_cnt = num_regs;
+		of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
+					   pdata->lane1_reg_data, num_regs);
+	}
+
+	return 0;
+}
+
 static int anx7625_parse_dt(struct device *dev,
 			    struct anx7625_platform_data *pdata)
 {
-	struct device_node *np = dev->of_node;
+	struct device_node *np = dev->of_node, *ep0;
 	struct drm_panel *panel;
 	int ret;
+	int bus_type, mipi_lanes;
 
+	anx7625_get_swing_setting(dev, pdata);
+
+	pdata->is_dpi = 1; /* default dpi mode */
 	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
 	if (!pdata->mipi_host_node) {
 		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
 		return -ENODEV;
 	}
 
-	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
+	bus_type = 5;
+	mipi_lanes = MAX_LANES_SUPPORT;
+	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
+	if (ep0) {
+		if (of_property_read_u32(ep0, "bus-type", &bus_type))
+			bus_type = 0;
+
+		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
+	}
+
+	if (bus_type == 5) /* bus type is Parallel(DSI) */
+		pdata->is_dpi = 0;
+
+	pdata->mipi_lanes = mipi_lanes;
+	if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
+		pdata->mipi_lanes = MAX_LANES_SUPPORT;
+
+	if (pdata->is_dpi)
+		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
+	else
+		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
 
 	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
 	if (ret < 0) {
@@ -1300,9 +1412,13 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
 {
 	struct device *dev = &ctx->client->dev;
 
-	DRM_DEV_DEBUG_DRIVER(dev, "sink detect, return connected\n");
+	DRM_DEV_DEBUG_DRIVER(dev, "sink detect\n");
+
+	if (ctx->pdata.panel_bridge)
+		return connector_status_connected;
 
-	return connector_status_connected;
+	return ctx->hpd_status ? connector_status_connected :
+				     connector_status_disconnected;
 }
 
 static int anx7625_attach_dsi(struct anx7625_data *ctx)
@@ -1330,7 +1446,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
 		return -EINVAL;
 	}
 
-	dsi->lanes = 4;
+	dsi->lanes = ctx->pdata.mipi_lanes;
 	dsi->format = MIPI_DSI_FMT_RGB888;
 	dsi->mode_flags = MIPI_DSI_MODE_VIDEO	|
 		MIPI_DSI_MODE_VIDEO_SYNC_PULSE	|
@@ -1376,10 +1492,12 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
 		return -ENODEV;
 	}
 
-	err = anx7625_attach_dsi(ctx);
-	if (err) {
-		DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
-		return err;
+	if (!ctx->pdata.is_dpi) {
+		err = anx7625_attach_dsi(ctx);
+		if (err) {
+			DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
+			return err;
+		}
 	}
 
 	if (ctx->pdata.panel_bridge) {
@@ -1478,6 +1596,10 @@ static bool anx7625_bridge_mode_fixup(struct drm_bridge *bridge,
 
 	DRM_DEV_DEBUG_DRIVER(dev, "drm mode fixup set\n");
 
+	/* No need fixup for external monitor */
+	if (!ctx->pdata.panel_bridge)
+		return true;
+
 	hsync = mode->hsync_end - mode->hsync_start;
 	hfp = mode->hsync_start - mode->hdisplay;
 	hbp = mode->htotal - mode->hsync_end;
@@ -1786,8 +1908,13 @@ static int anx7625_i2c_probe(struct i2c_client *client,
 
 	platform->bridge.funcs = &anx7625_bridge_funcs;
 	platform->bridge.of_node = client->dev.of_node;
-	platform->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
-	platform->bridge.type = DRM_MODE_CONNECTOR_eDP;
+	platform->bridge.ops = DRM_BRIDGE_OP_EDID;
+	if (!platform->pdata.panel_bridge)
+		platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
+					DRM_BRIDGE_OP_DETECT;
+	platform->bridge.type = platform->pdata.panel_bridge ?
+				    DRM_MODE_CONNECTOR_eDP :
+				    DRM_MODE_CONNECTOR_DisplayPort;
 	drm_bridge_add(&platform->bridge);
 
 	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 193ad86c5450..beee95da2155 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -141,12 +141,20 @@
 #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
 
 /******** END of I2C Address 0x72 *********/
+
+/***************************************************************/
+/* Register definition of device address 0x7a */
+#define DP_TX_SWING_REG_CNT		0x14
+#define DP_TX_LANE0_SWING_REG0		0x00
+#define DP_TX_LANE1_SWING_REG0		0x14
+/******** END of I2C Address 0x7a *********/
+
 /***************************************************************/
 /* Register definition of device address 0x7e */
 
 #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
 
-#define FLASH_LOAD_STA 0x05
+#define FLASH_LOAD_STA          0x05
 #define FLASH_LOAD_STA_CHK	BIT(7)
 
 #define  XTAL_FRQ_SEL    0x3F
@@ -347,11 +355,19 @@ struct s_edid_data {
 
 /***************** Display End *****************/
 
+#define MAX_LANES_SUPPORT	4
+
 struct anx7625_platform_data {
 	struct gpio_desc *gpio_p_on;
 	struct gpio_desc *gpio_reset;
 	struct drm_bridge *panel_bridge;
 	int intp_irq;
+	int is_dpi;
+	int mipi_lanes;
+	int dp_lane0_swing_reg_cnt;
+	int lane0_reg_data[DP_TX_SWING_REG_CNT];
+	int dp_lane1_swing_reg_cnt;
+	int lane1_reg_data[DP_TX_SWING_REG_CNT];
 	u32 low_power_mode;
 	struct device_node *mipi_host_node;
 };
-- 
2.25.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* [PATCH v6 3/5] drm/bridge: anx7625: add MIPI DPI input feature support
@ 2021-03-19  6:34   ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:34 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: devel, Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, linux-kernel, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe,
	Laurent Pinchart, Hsin-Yi Wang, Sam Ravnborg, Dan Carpenter,
	Marek Szyprowski

Add MIPI rx DPI input support.

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 245 ++++++++++++++++------
 drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
 2 files changed, 203 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 04536cc7afe7..8c514b46d361 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -150,18 +150,18 @@ static int anx7625_write_and(struct anx7625_data *ctx,
 	return anx7625_reg_write(ctx, client, offset, (val & (mask)));
 }
 
-static int anx7625_write_and_or(struct anx7625_data *ctx,
-				struct i2c_client *client,
-				u8 offset, u8 and_mask, u8 or_mask)
+static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
 {
-	int val;
+	int i, ret;
 
-	val = anx7625_reg_read(ctx, client, offset);
-	if (val < 0)
-		return val;
+	ret = anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
+			       AUDIO_CONTROL_REGISTER, 0x80);
+	for (i = 0; i < 13; i++)
+		ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
+					 VIDEO_BIT_MATRIX_12 + i,
+					 0x18 + i);
 
-	return anx7625_reg_write(ctx, client,
-				 offset, (val & and_mask) | (or_mask));
+	return ret;
 }
 
 static int anx7625_read_ctrl_status_p0(struct anx7625_data *ctx)
@@ -219,38 +219,6 @@ static int anx7625_video_mute_control(struct anx7625_data *ctx,
 	return ret;
 }
 
-static int anx7625_config_audio_input(struct anx7625_data *ctx)
-{
-	struct device *dev = &ctx->client->dev;
-	int ret;
-
-	/* Channel num */
-	ret = anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
-				AUDIO_CHANNEL_STATUS_6, I2S_CH_2 << 5);
-
-	/* FS */
-	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
-				    AUDIO_CHANNEL_STATUS_4,
-				    0xf0, AUDIO_FS_48K);
-	/* Word length */
-	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
-				    AUDIO_CHANNEL_STATUS_5,
-				    0xf0, AUDIO_W_LEN_24_24MAX);
-	/* I2S */
-	ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
-				AUDIO_CHANNEL_STATUS_6, I2S_SLAVE_MODE);
-	ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
-				 AUDIO_CONTROL_REGISTER, ~TDM_TIMING_MODE);
-	/* Audio change flag */
-	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
-				AP_AV_STATUS, AP_AUDIO_CHG);
-
-	if (ret < 0)
-		DRM_DEV_ERROR(dev, "fail to config audio.\n");
-
-	return ret;
-}
-
 /* Reduction of fraction a/b */
 static void anx7625_reduction_of_a_fraction(unsigned long *a, unsigned long *b)
 {
@@ -410,7 +378,7 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
 	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
 			MIPI_LANE_CTRL_0, 0xfc);
 	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client,
-				MIPI_LANE_CTRL_0, 3);
+				MIPI_LANE_CTRL_0, ctx->pdata.mipi_lanes - 1);
 
 	/* Htotal */
 	htotal = ctx->dt.hactive.min + ctx->dt.hfront_porch.min +
@@ -595,6 +563,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
 	return ret;
 }
 
+static int anx7625_api_dpi_config(struct anx7625_data *ctx)
+{
+	struct device *dev = &ctx->client->dev;
+	u16 freq = ctx->dt.pixelclock.min / 1000;
+	int ret;
+
+	/* configure pixel clock */
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				PIXEL_CLOCK_L, freq & 0xFF);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 PIXEL_CLOCK_H, (freq >> 8));
+
+	/* set DPI mode */
+	/* set to DPI PLL module sel */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_DIGITAL_PLL_9, 0x20);
+	/* power down MIPI */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_LANE_CTRL_10, 0x08);
+	/* enable DPI mode */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_DIGITAL_PLL_18, 0x1C);
+	/* set first edge */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
+				 VIDEO_CONTROL_0, 0x06);
+	if (ret < 0)
+		DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
+
+	return ret;
+}
+
+static int anx7625_dpi_config(struct anx7625_data *ctx)
+{
+	struct device *dev = &ctx->client->dev;
+	int ret;
+
+	DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
+
+	/* DSC disable */
+	ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
+				R_DSC_CTRL_0, ~DSC_EN);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
+		return ret;
+	}
+
+	ret = anx7625_config_bit_matrix(ctx);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
+		return ret;
+	}
+
+	ret = anx7625_api_dpi_config(ctx);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
+		return ret;
+	}
+
+	/* set MIPI RX EN */
+	ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
+			       AP_AV_STATUS, AP_MIPI_RX_EN);
+	/* clear mute flag */
+	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
+				 AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
+	if (ret < 0)
+		DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
+
+	return ret;
+}
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
 	int ret;
@@ -605,9 +643,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
 		return;
 	}
 
-	anx7625_config_audio_input(ctx);
-
-	ret = anx7625_dsi_config(ctx);
+	if (ctx->pdata.is_dpi)
+		ret = anx7625_dpi_config(ctx);
+	else
+		ret = anx7625_dsi_config(ctx);
 
 	if (ret < 0)
 		DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
@@ -1051,6 +1090,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
 		return;
 	}
 
+	ctx->hpd_status = 1;
 	ctx->hpd_high_cnt++;
 
 	/* Not support HDCP */
@@ -1060,8 +1100,10 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
 	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
 	/* Interrupt for DRM */
 	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
-	if (ret < 0)
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "fail to setting HDCP/auth\n");
 		return;
+	}
 
 	ret = anx7625_reg_read(ctx, ctx->i2c.rx_p1_client, 0x86);
 	if (ret < 0)
@@ -1080,6 +1122,10 @@ static void anx7625_hpd_polling(struct anx7625_data *ctx)
 	int ret, val;
 	struct device *dev = &ctx->client->dev;
 
+	/* Interrupt mode, no need poll HPD status, just return */
+	if (ctx->pdata.intp_irq)
+		return;
+
 	if (atomic_read(&ctx->power_status) != 1) {
 		DRM_DEV_DEBUG_DRIVER(dev, "No need to poling HPD status.\n");
 		return;
@@ -1130,6 +1176,21 @@ static void anx7625_remove_edid(struct anx7625_data *ctx)
 	ctx->slimport_edid_p.edid_block_num = -1;
 }
 
+static void anx7625_dp_adjust_swing(struct anx7625_data *ctx)
+{
+	int i;
+
+	for (i = 0; i < ctx->pdata.dp_lane0_swing_reg_cnt; i++)
+		anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
+				  DP_TX_LANE0_SWING_REG0 + i,
+				  ctx->pdata.lane0_reg_data[i] & 0xFF);
+
+	for (i = 0; i < ctx->pdata.dp_lane1_swing_reg_cnt; i++)
+		anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
+				  DP_TX_LANE1_SWING_REG0 + i,
+				  ctx->pdata.lane1_reg_data[i] & 0xFF);
+}
+
 static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
 {
 	struct device *dev = &ctx->client->dev;
@@ -1145,9 +1206,8 @@ static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
 	} else {
 		DRM_DEV_DEBUG_DRIVER(dev, " HPD high\n");
 		anx7625_start_dp_work(ctx);
+		anx7625_dp_adjust_swing(ctx);
 	}
-
-	ctx->hpd_status = 1;
 }
 
 static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
@@ -1224,20 +1284,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static int anx7625_get_swing_setting(struct device *dev,
+				     struct anx7625_platform_data *pdata)
+{
+	int num_regs;
+
+	if (of_get_property(dev->of_node,
+			    "analogix,lane0-swing", &num_regs)) {
+		if (num_regs > DP_TX_SWING_REG_CNT)
+			num_regs = DP_TX_SWING_REG_CNT;
+
+		pdata->dp_lane0_swing_reg_cnt = num_regs;
+		of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
+					   pdata->lane0_reg_data, num_regs);
+	}
+
+	if (of_get_property(dev->of_node,
+			    "analogix,lane1-swing", &num_regs)) {
+		if (num_regs > DP_TX_SWING_REG_CNT)
+			num_regs = DP_TX_SWING_REG_CNT;
+
+		pdata->dp_lane1_swing_reg_cnt = num_regs;
+		of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
+					   pdata->lane1_reg_data, num_regs);
+	}
+
+	return 0;
+}
+
 static int anx7625_parse_dt(struct device *dev,
 			    struct anx7625_platform_data *pdata)
 {
-	struct device_node *np = dev->of_node;
+	struct device_node *np = dev->of_node, *ep0;
 	struct drm_panel *panel;
 	int ret;
+	int bus_type, mipi_lanes;
 
+	anx7625_get_swing_setting(dev, pdata);
+
+	pdata->is_dpi = 1; /* default dpi mode */
 	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
 	if (!pdata->mipi_host_node) {
 		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
 		return -ENODEV;
 	}
 
-	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
+	bus_type = 5;
+	mipi_lanes = MAX_LANES_SUPPORT;
+	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
+	if (ep0) {
+		if (of_property_read_u32(ep0, "bus-type", &bus_type))
+			bus_type = 0;
+
+		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
+	}
+
+	if (bus_type == 5) /* bus type is Parallel(DSI) */
+		pdata->is_dpi = 0;
+
+	pdata->mipi_lanes = mipi_lanes;
+	if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
+		pdata->mipi_lanes = MAX_LANES_SUPPORT;
+
+	if (pdata->is_dpi)
+		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
+	else
+		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
 
 	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
 	if (ret < 0) {
@@ -1300,9 +1412,13 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
 {
 	struct device *dev = &ctx->client->dev;
 
-	DRM_DEV_DEBUG_DRIVER(dev, "sink detect, return connected\n");
+	DRM_DEV_DEBUG_DRIVER(dev, "sink detect\n");
+
+	if (ctx->pdata.panel_bridge)
+		return connector_status_connected;
 
-	return connector_status_connected;
+	return ctx->hpd_status ? connector_status_connected :
+				     connector_status_disconnected;
 }
 
 static int anx7625_attach_dsi(struct anx7625_data *ctx)
@@ -1330,7 +1446,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
 		return -EINVAL;
 	}
 
-	dsi->lanes = 4;
+	dsi->lanes = ctx->pdata.mipi_lanes;
 	dsi->format = MIPI_DSI_FMT_RGB888;
 	dsi->mode_flags = MIPI_DSI_MODE_VIDEO	|
 		MIPI_DSI_MODE_VIDEO_SYNC_PULSE	|
@@ -1376,10 +1492,12 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
 		return -ENODEV;
 	}
 
-	err = anx7625_attach_dsi(ctx);
-	if (err) {
-		DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
-		return err;
+	if (!ctx->pdata.is_dpi) {
+		err = anx7625_attach_dsi(ctx);
+		if (err) {
+			DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
+			return err;
+		}
 	}
 
 	if (ctx->pdata.panel_bridge) {
@@ -1478,6 +1596,10 @@ static bool anx7625_bridge_mode_fixup(struct drm_bridge *bridge,
 
 	DRM_DEV_DEBUG_DRIVER(dev, "drm mode fixup set\n");
 
+	/* No need fixup for external monitor */
+	if (!ctx->pdata.panel_bridge)
+		return true;
+
 	hsync = mode->hsync_end - mode->hsync_start;
 	hfp = mode->hsync_start - mode->hdisplay;
 	hbp = mode->htotal - mode->hsync_end;
@@ -1786,8 +1908,13 @@ static int anx7625_i2c_probe(struct i2c_client *client,
 
 	platform->bridge.funcs = &anx7625_bridge_funcs;
 	platform->bridge.of_node = client->dev.of_node;
-	platform->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
-	platform->bridge.type = DRM_MODE_CONNECTOR_eDP;
+	platform->bridge.ops = DRM_BRIDGE_OP_EDID;
+	if (!platform->pdata.panel_bridge)
+		platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
+					DRM_BRIDGE_OP_DETECT;
+	platform->bridge.type = platform->pdata.panel_bridge ?
+				    DRM_MODE_CONNECTOR_eDP :
+				    DRM_MODE_CONNECTOR_DisplayPort;
 	drm_bridge_add(&platform->bridge);
 
 	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 193ad86c5450..beee95da2155 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -141,12 +141,20 @@
 #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
 
 /******** END of I2C Address 0x72 *********/
+
+/***************************************************************/
+/* Register definition of device address 0x7a */
+#define DP_TX_SWING_REG_CNT		0x14
+#define DP_TX_LANE0_SWING_REG0		0x00
+#define DP_TX_LANE1_SWING_REG0		0x14
+/******** END of I2C Address 0x7a *********/
+
 /***************************************************************/
 /* Register definition of device address 0x7e */
 
 #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
 
-#define FLASH_LOAD_STA 0x05
+#define FLASH_LOAD_STA          0x05
 #define FLASH_LOAD_STA_CHK	BIT(7)
 
 #define  XTAL_FRQ_SEL    0x3F
@@ -347,11 +355,19 @@ struct s_edid_data {
 
 /***************** Display End *****************/
 
+#define MAX_LANES_SUPPORT	4
+
 struct anx7625_platform_data {
 	struct gpio_desc *gpio_p_on;
 	struct gpio_desc *gpio_reset;
 	struct drm_bridge *panel_bridge;
 	int intp_irq;
+	int is_dpi;
+	int mipi_lanes;
+	int dp_lane0_swing_reg_cnt;
+	int lane0_reg_data[DP_TX_SWING_REG_CNT];
+	int dp_lane1_swing_reg_cnt;
+	int lane1_reg_data[DP_TX_SWING_REG_CNT];
 	u32 low_power_mode;
 	struct device_node *mipi_host_node;
 };
-- 
2.25.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
  2021-03-19  6:31 ` Xin Ji
  (?)
@ 2021-03-19  6:34   ` Xin Ji
  -1 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:34 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: Neil Armstrong, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Dan Carpenter, David Airlie, Daniel Vetter, Boris Brezillon,
	Sam Ravnborg, Hsin-Yi Wang, Torsten Duwe, Vasily Khoruzhick,
	Marek Szyprowski, Sheng Pan, Bernie Liang, Zhen Li, dri-devel,
	linux-kernel, devel

Add HDCP feature, enable HDCP function through chip internal key
and downstream's capability.

Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 147 ++++++++++++++++++++++
 drivers/gpu/drm/bridge/analogix/anx7625.h |  36 ++++++
 2 files changed, 183 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 8c514b46d361..b424a570effa 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -633,6 +633,150 @@ static int anx7625_dpi_config(struct anx7625_data *ctx)
 	return ret;
 }
 
+static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
+				 u8 addrh, u8 addrm, u8 addrl,
+				 u8 len, u8 *buf)
+{
+	struct device *dev = &ctx->client->dev;
+	int ret;
+	u8 cmd;
+
+	if (len > MAX_DPCD_BUFFER_SIZE) {
+		DRM_DEV_ERROR(dev, "exceed aux buffer len.\n");
+		return -E2BIG;
+	}
+
+	cmd = ((len - 1) << 4) | 0x09;
+
+	/* Set command and length */
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				AP_AUX_COMMAND, cmd);
+
+	/* Set aux access address */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 AP_AUX_ADDR_7_0, addrl);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 AP_AUX_ADDR_15_8, addrm);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 AP_AUX_ADDR_19_16, addrh);
+
+	/* Enable aux access */
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
+				AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
+
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "cannot access aux related register.\n");
+		return -EIO;
+	}
+
+	usleep_range(2000, 2100);
+
+	ret = wait_aux_op_finish(ctx);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "aux IO error: wait aux op finish.\n");
+		return ret;
+	}
+
+	ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
+				     AP_AUX_BUFF_START, len, buf);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "read dpcd register failed\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int anx7625_read_flash_status(struct anx7625_data *ctx)
+{
+	return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, R_RAM_CTRL);
+}
+
+static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
+{
+	int ret, val;
+	struct device *dev = &ctx->client->dev;
+	u8 ident[32];
+
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				FLASH_ADDR_HIGH, 0x91);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 FLASH_ADDR_LOW, 0xA0);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : set key flash address.\n");
+		return ret;
+	}
+
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				FLASH_LEN_HIGH, (FLASH_BUF_LEN - 1) >> 8);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 FLASH_LEN_LOW, (FLASH_BUF_LEN - 1) & 0xFF);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : set key flash len.\n");
+		return ret;
+	}
+
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				R_FLASH_RW_CTRL, FLASH_READ);
+	ret |= readx_poll_timeout(anx7625_read_flash_status,
+				  ctx, val,
+				  ((val & FLASH_DONE) || (val < 0)),
+				  2000,
+				  2000 * 150);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "flash read access fail!\n");
+		return -EIO;
+	}
+
+	ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
+				     FLASH_BUF_BASE_ADDR,
+				     FLASH_BUF_LEN, ident);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "read flash data fail!\n");
+		return -EIO;
+	}
+
+	if (ident[29] == 0xFF && ident[30] == 0xFF && ident[31] == 0xFF)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int anx7625_hdcp_setting(struct anx7625_data *ctx)
+{
+	u8 bcap;
+	int ret;
+	struct device *dev = &ctx->client->dev;
+
+	ret = anx7625_hdcp_key_probe(ctx);
+	if (ret) {
+		DRM_DEV_DEBUG_DRIVER(dev, "disable HDCP by config\n");
+		return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+					 0xee, 0x9f);
+	}
+
+	anx7625_aux_dpcd_read(ctx, 0x06, 0x80, 0x28, 1, &bcap);
+	if (!(bcap & 0x01)) {
+		DRM_DEV_DEBUG_DRIVER(dev, "bcap(0x%x) not support HDCP 1.4.\n",
+				     bcap);
+		return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+					 0xee, 0x9f);
+	}
+
+	DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
+
+	ret = anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
+
+	/* Try auth flag */
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
+	/* Interrupt for DRM */
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
+	if (ret < 0)
+		DRM_DEV_ERROR(dev, "fail to enable HDCP\n");
+
+	return ret;
+}
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
 	int ret;
@@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
 		return;
 	}
 
+	/* HDCP config */
+	anx7625_hdcp_setting(ctx);
+
 	if (ctx->pdata.is_dpi)
 		ret = anx7625_dpi_config(ctx);
 	else
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index beee95da2155..c6f93e4df0ed 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -154,9 +154,45 @@
 
 #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
 
+#define FLASH_SRAM_SEL          0x00
+#define SRAM_ADDR_HIGH          0x01
+#define SRAM_ADDR_LOW           0x02
+#define SRAM_LEN_HIGH           0x03
+#define SRAM_LEN_LOW            0x04
 #define FLASH_LOAD_STA          0x05
 #define FLASH_LOAD_STA_CHK	BIT(7)
 
+#define R_RAM_CTRL              0x05
+/* bit positions */
+#define FLASH_DONE              BIT(7)
+#define BOOT_LOAD_DONE          BIT(6)
+#define CRC_OK                  BIT(5)
+#define LOAD_DONE               BIT(4)
+#define O_RW_DONE               BIT(3)
+#define FUSE_BUSY               BIT(2)
+#define DECRYPT_EN              BIT(1)
+#define LOAD_START              BIT(0)
+
+#define FLASH_ADDR_HIGH         0x0F
+#define FLASH_ADDR_LOW          0x10
+#define FLASH_LEN_HIGH          0x31
+#define FLASH_LEN_LOW           0x32
+
+#define R_FLASH_RW_CTRL         0x33
+/* bit positions */
+#define READ_DELAY_SELECT       BIT(7)
+#define GENERAL_INSTRUCTION_EN  BIT(6)
+#define FLASH_ERASE_EN          BIT(5)
+#define RDID_READ_EN            BIT(4)
+#define REMS_READ_EN            BIT(3)
+#define WRITE_STATUS_EN         BIT(2)
+#define FLASH_READ              BIT(1)
+#define FLASH_WRITE             BIT(0)
+
+#define FLASH_BUF_BASE_ADDR     0x60
+#define FLASH_BUF_LEN           0x20
+#define FLASH_KEY_OFFSET        0x8000
+
 #define  XTAL_FRQ_SEL    0x3F
 /* bit field positions */
 #define  XTAL_FRQ_SEL_POS    5
-- 
2.25.1


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

* [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-03-19  6:34   ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:34 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: devel, Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, linux-kernel, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe,
	Laurent Pinchart, Daniel Vetter, Hsin-Yi Wang, Sam Ravnborg,
	Dan Carpenter, Marek Szyprowski

Add HDCP feature, enable HDCP function through chip internal key
and downstream's capability.

Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 147 ++++++++++++++++++++++
 drivers/gpu/drm/bridge/analogix/anx7625.h |  36 ++++++
 2 files changed, 183 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 8c514b46d361..b424a570effa 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -633,6 +633,150 @@ static int anx7625_dpi_config(struct anx7625_data *ctx)
 	return ret;
 }
 
+static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
+				 u8 addrh, u8 addrm, u8 addrl,
+				 u8 len, u8 *buf)
+{
+	struct device *dev = &ctx->client->dev;
+	int ret;
+	u8 cmd;
+
+	if (len > MAX_DPCD_BUFFER_SIZE) {
+		DRM_DEV_ERROR(dev, "exceed aux buffer len.\n");
+		return -E2BIG;
+	}
+
+	cmd = ((len - 1) << 4) | 0x09;
+
+	/* Set command and length */
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				AP_AUX_COMMAND, cmd);
+
+	/* Set aux access address */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 AP_AUX_ADDR_7_0, addrl);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 AP_AUX_ADDR_15_8, addrm);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 AP_AUX_ADDR_19_16, addrh);
+
+	/* Enable aux access */
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
+				AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
+
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "cannot access aux related register.\n");
+		return -EIO;
+	}
+
+	usleep_range(2000, 2100);
+
+	ret = wait_aux_op_finish(ctx);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "aux IO error: wait aux op finish.\n");
+		return ret;
+	}
+
+	ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
+				     AP_AUX_BUFF_START, len, buf);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "read dpcd register failed\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int anx7625_read_flash_status(struct anx7625_data *ctx)
+{
+	return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, R_RAM_CTRL);
+}
+
+static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
+{
+	int ret, val;
+	struct device *dev = &ctx->client->dev;
+	u8 ident[32];
+
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				FLASH_ADDR_HIGH, 0x91);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 FLASH_ADDR_LOW, 0xA0);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : set key flash address.\n");
+		return ret;
+	}
+
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				FLASH_LEN_HIGH, (FLASH_BUF_LEN - 1) >> 8);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 FLASH_LEN_LOW, (FLASH_BUF_LEN - 1) & 0xFF);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : set key flash len.\n");
+		return ret;
+	}
+
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				R_FLASH_RW_CTRL, FLASH_READ);
+	ret |= readx_poll_timeout(anx7625_read_flash_status,
+				  ctx, val,
+				  ((val & FLASH_DONE) || (val < 0)),
+				  2000,
+				  2000 * 150);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "flash read access fail!\n");
+		return -EIO;
+	}
+
+	ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
+				     FLASH_BUF_BASE_ADDR,
+				     FLASH_BUF_LEN, ident);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "read flash data fail!\n");
+		return -EIO;
+	}
+
+	if (ident[29] == 0xFF && ident[30] == 0xFF && ident[31] == 0xFF)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int anx7625_hdcp_setting(struct anx7625_data *ctx)
+{
+	u8 bcap;
+	int ret;
+	struct device *dev = &ctx->client->dev;
+
+	ret = anx7625_hdcp_key_probe(ctx);
+	if (ret) {
+		DRM_DEV_DEBUG_DRIVER(dev, "disable HDCP by config\n");
+		return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+					 0xee, 0x9f);
+	}
+
+	anx7625_aux_dpcd_read(ctx, 0x06, 0x80, 0x28, 1, &bcap);
+	if (!(bcap & 0x01)) {
+		DRM_DEV_DEBUG_DRIVER(dev, "bcap(0x%x) not support HDCP 1.4.\n",
+				     bcap);
+		return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+					 0xee, 0x9f);
+	}
+
+	DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
+
+	ret = anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
+
+	/* Try auth flag */
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
+	/* Interrupt for DRM */
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
+	if (ret < 0)
+		DRM_DEV_ERROR(dev, "fail to enable HDCP\n");
+
+	return ret;
+}
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
 	int ret;
@@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
 		return;
 	}
 
+	/* HDCP config */
+	anx7625_hdcp_setting(ctx);
+
 	if (ctx->pdata.is_dpi)
 		ret = anx7625_dpi_config(ctx);
 	else
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index beee95da2155..c6f93e4df0ed 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -154,9 +154,45 @@
 
 #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
 
+#define FLASH_SRAM_SEL          0x00
+#define SRAM_ADDR_HIGH          0x01
+#define SRAM_ADDR_LOW           0x02
+#define SRAM_LEN_HIGH           0x03
+#define SRAM_LEN_LOW            0x04
 #define FLASH_LOAD_STA          0x05
 #define FLASH_LOAD_STA_CHK	BIT(7)
 
+#define R_RAM_CTRL              0x05
+/* bit positions */
+#define FLASH_DONE              BIT(7)
+#define BOOT_LOAD_DONE          BIT(6)
+#define CRC_OK                  BIT(5)
+#define LOAD_DONE               BIT(4)
+#define O_RW_DONE               BIT(3)
+#define FUSE_BUSY               BIT(2)
+#define DECRYPT_EN              BIT(1)
+#define LOAD_START              BIT(0)
+
+#define FLASH_ADDR_HIGH         0x0F
+#define FLASH_ADDR_LOW          0x10
+#define FLASH_LEN_HIGH          0x31
+#define FLASH_LEN_LOW           0x32
+
+#define R_FLASH_RW_CTRL         0x33
+/* bit positions */
+#define READ_DELAY_SELECT       BIT(7)
+#define GENERAL_INSTRUCTION_EN  BIT(6)
+#define FLASH_ERASE_EN          BIT(5)
+#define RDID_READ_EN            BIT(4)
+#define REMS_READ_EN            BIT(3)
+#define WRITE_STATUS_EN         BIT(2)
+#define FLASH_READ              BIT(1)
+#define FLASH_WRITE             BIT(0)
+
+#define FLASH_BUF_BASE_ADDR     0x60
+#define FLASH_BUF_LEN           0x20
+#define FLASH_KEY_OFFSET        0x8000
+
 #define  XTAL_FRQ_SEL    0x3F
 /* bit field positions */
 #define  XTAL_FRQ_SEL_POS    5
-- 
2.25.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-03-19  6:34   ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:34 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: devel, Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, linux-kernel, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe,
	Laurent Pinchart, Hsin-Yi Wang, Sam Ravnborg, Dan Carpenter,
	Marek Szyprowski

Add HDCP feature, enable HDCP function through chip internal key
and downstream's capability.

Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 147 ++++++++++++++++++++++
 drivers/gpu/drm/bridge/analogix/anx7625.h |  36 ++++++
 2 files changed, 183 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 8c514b46d361..b424a570effa 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -633,6 +633,150 @@ static int anx7625_dpi_config(struct anx7625_data *ctx)
 	return ret;
 }
 
+static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
+				 u8 addrh, u8 addrm, u8 addrl,
+				 u8 len, u8 *buf)
+{
+	struct device *dev = &ctx->client->dev;
+	int ret;
+	u8 cmd;
+
+	if (len > MAX_DPCD_BUFFER_SIZE) {
+		DRM_DEV_ERROR(dev, "exceed aux buffer len.\n");
+		return -E2BIG;
+	}
+
+	cmd = ((len - 1) << 4) | 0x09;
+
+	/* Set command and length */
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				AP_AUX_COMMAND, cmd);
+
+	/* Set aux access address */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 AP_AUX_ADDR_7_0, addrl);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 AP_AUX_ADDR_15_8, addrm);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 AP_AUX_ADDR_19_16, addrh);
+
+	/* Enable aux access */
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
+				AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
+
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "cannot access aux related register.\n");
+		return -EIO;
+	}
+
+	usleep_range(2000, 2100);
+
+	ret = wait_aux_op_finish(ctx);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "aux IO error: wait aux op finish.\n");
+		return ret;
+	}
+
+	ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
+				     AP_AUX_BUFF_START, len, buf);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "read dpcd register failed\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int anx7625_read_flash_status(struct anx7625_data *ctx)
+{
+	return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, R_RAM_CTRL);
+}
+
+static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
+{
+	int ret, val;
+	struct device *dev = &ctx->client->dev;
+	u8 ident[32];
+
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				FLASH_ADDR_HIGH, 0x91);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 FLASH_ADDR_LOW, 0xA0);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : set key flash address.\n");
+		return ret;
+	}
+
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				FLASH_LEN_HIGH, (FLASH_BUF_LEN - 1) >> 8);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 FLASH_LEN_LOW, (FLASH_BUF_LEN - 1) & 0xFF);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : set key flash len.\n");
+		return ret;
+	}
+
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				R_FLASH_RW_CTRL, FLASH_READ);
+	ret |= readx_poll_timeout(anx7625_read_flash_status,
+				  ctx, val,
+				  ((val & FLASH_DONE) || (val < 0)),
+				  2000,
+				  2000 * 150);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "flash read access fail!\n");
+		return -EIO;
+	}
+
+	ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
+				     FLASH_BUF_BASE_ADDR,
+				     FLASH_BUF_LEN, ident);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "read flash data fail!\n");
+		return -EIO;
+	}
+
+	if (ident[29] == 0xFF && ident[30] == 0xFF && ident[31] == 0xFF)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int anx7625_hdcp_setting(struct anx7625_data *ctx)
+{
+	u8 bcap;
+	int ret;
+	struct device *dev = &ctx->client->dev;
+
+	ret = anx7625_hdcp_key_probe(ctx);
+	if (ret) {
+		DRM_DEV_DEBUG_DRIVER(dev, "disable HDCP by config\n");
+		return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+					 0xee, 0x9f);
+	}
+
+	anx7625_aux_dpcd_read(ctx, 0x06, 0x80, 0x28, 1, &bcap);
+	if (!(bcap & 0x01)) {
+		DRM_DEV_DEBUG_DRIVER(dev, "bcap(0x%x) not support HDCP 1.4.\n",
+				     bcap);
+		return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+					 0xee, 0x9f);
+	}
+
+	DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
+
+	ret = anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
+
+	/* Try auth flag */
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
+	/* Interrupt for DRM */
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
+	if (ret < 0)
+		DRM_DEV_ERROR(dev, "fail to enable HDCP\n");
+
+	return ret;
+}
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
 	int ret;
@@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
 		return;
 	}
 
+	/* HDCP config */
+	anx7625_hdcp_setting(ctx);
+
 	if (ctx->pdata.is_dpi)
 		ret = anx7625_dpi_config(ctx);
 	else
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index beee95da2155..c6f93e4df0ed 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -154,9 +154,45 @@
 
 #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
 
+#define FLASH_SRAM_SEL          0x00
+#define SRAM_ADDR_HIGH          0x01
+#define SRAM_ADDR_LOW           0x02
+#define SRAM_LEN_HIGH           0x03
+#define SRAM_LEN_LOW            0x04
 #define FLASH_LOAD_STA          0x05
 #define FLASH_LOAD_STA_CHK	BIT(7)
 
+#define R_RAM_CTRL              0x05
+/* bit positions */
+#define FLASH_DONE              BIT(7)
+#define BOOT_LOAD_DONE          BIT(6)
+#define CRC_OK                  BIT(5)
+#define LOAD_DONE               BIT(4)
+#define O_RW_DONE               BIT(3)
+#define FUSE_BUSY               BIT(2)
+#define DECRYPT_EN              BIT(1)
+#define LOAD_START              BIT(0)
+
+#define FLASH_ADDR_HIGH         0x0F
+#define FLASH_ADDR_LOW          0x10
+#define FLASH_LEN_HIGH          0x31
+#define FLASH_LEN_LOW           0x32
+
+#define R_FLASH_RW_CTRL         0x33
+/* bit positions */
+#define READ_DELAY_SELECT       BIT(7)
+#define GENERAL_INSTRUCTION_EN  BIT(6)
+#define FLASH_ERASE_EN          BIT(5)
+#define RDID_READ_EN            BIT(4)
+#define REMS_READ_EN            BIT(3)
+#define WRITE_STATUS_EN         BIT(2)
+#define FLASH_READ              BIT(1)
+#define FLASH_WRITE             BIT(0)
+
+#define FLASH_BUF_BASE_ADDR     0x60
+#define FLASH_BUF_LEN           0x20
+#define FLASH_KEY_OFFSET        0x8000
+
 #define  XTAL_FRQ_SEL    0x3F
 /* bit field positions */
 #define  XTAL_FRQ_SEL_POS    5
-- 
2.25.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v6 5/5] drm/bridge: anx7625: add HDMI audio function
  2021-03-19  6:31 ` Xin Ji
  (?)
@ 2021-03-19  6:35   ` Xin Ji
  -1 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:35 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: Neil Armstrong, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Dan Carpenter, David Airlie, Daniel Vetter, Boris Brezillon,
	Sam Ravnborg, Hsin-Yi Wang, Torsten Duwe, Vasily Khoruzhick,
	Marek Szyprowski, Sheng Pan, Bernie Liang, Zhen Li, dri-devel,
	linux-kernel, devel

Add audio HDMI codec function support, enable it through device true flag
"analogix,audio-enable".

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 227 ++++++++++++++++++++++
 drivers/gpu/drm/bridge/analogix/anx7625.h |   5 +
 2 files changed, 232 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index b424a570effa..02bb169d9c57 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -30,6 +30,8 @@
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
+#include <sound/hdmi-codec.h>
+
 #include <video/display_timing.h>
 
 #include "anx7625.h"
@@ -150,6 +152,20 @@ static int anx7625_write_and(struct anx7625_data *ctx,
 	return anx7625_reg_write(ctx, client, offset, (val & (mask)));
 }
 
+static int anx7625_write_and_or(struct anx7625_data *ctx,
+				struct i2c_client *client,
+				u8 offset, u8 and_mask, u8 or_mask)
+{
+	int val;
+
+	val = anx7625_reg_read(ctx, client, offset);
+	if (val < 0)
+		return val;
+
+	return anx7625_reg_write(ctx, client,
+				 offset, (val & and_mask) | (or_mask));
+}
+
 static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
 {
 	int i, ret;
@@ -1498,6 +1514,9 @@ static int anx7625_parse_dt(struct device *dev,
 	else
 		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
 
+	if (of_property_read_bool(np, "analogix,audio-enable"))
+		pdata->audio_en = 1;
+
 	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
 	if (ret < 0) {
 		if (ret == -ENODEV)
@@ -1568,6 +1587,208 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
 				     connector_status_disconnected;
 }
 
+static int anx7625_audio_hw_params(struct device *dev, void *data,
+				   struct hdmi_codec_daifmt *fmt,
+				   struct hdmi_codec_params *params)
+{
+	struct anx7625_data *ctx = dev_get_drvdata(dev);
+	int wl, ch, rate;
+	int ret = 0;
+
+	if (fmt->fmt != HDMI_DSP_A) {
+		DRM_DEV_ERROR(dev, "only supports DSP_A\n");
+		return -EINVAL;
+	}
+
+	DRM_DEV_DEBUG_DRIVER(dev, "setting %d Hz, %d bit, %d channels\n",
+			     params->sample_rate, params->sample_width,
+			     params->cea.channels);
+
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+				    AUDIO_CHANNEL_STATUS_6,
+				    ~I2S_SLAVE_MODE,
+				    TDM_SLAVE_MODE);
+
+	/* Word length */
+	switch (params->sample_width) {
+	case 16:
+		wl = AUDIO_W_LEN_16_20MAX;
+		break;
+	case 18:
+		wl = AUDIO_W_LEN_18_20MAX;
+		break;
+	case 20:
+		wl = AUDIO_W_LEN_20_20MAX;
+		break;
+	case 24:
+		wl = AUDIO_W_LEN_24_24MAX;
+		break;
+	default:
+		DRM_DEV_DEBUG_DRIVER(dev, "wordlength: %d bit not support",
+				     params->sample_width);
+		return -EINVAL;
+	}
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+				    AUDIO_CHANNEL_STATUS_5,
+				    0xf0, wl);
+
+	/* Channel num */
+	switch (params->cea.channels) {
+	case 2:
+		ch = I2S_CH_2;
+		break;
+	case 4:
+		ch = TDM_CH_4;
+		break;
+	case 6:
+		ch = TDM_CH_6;
+		break;
+	case 8:
+		ch = TDM_CH_8;
+		break;
+	default:
+		DRM_DEV_DEBUG_DRIVER(dev, "channel number: %d not support",
+				     params->cea.channels);
+		return -EINVAL;
+	}
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+			       AUDIO_CHANNEL_STATUS_6, 0x1f, ch << 5);
+	if (ch > I2S_CH_2)
+		ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
+				AUDIO_CHANNEL_STATUS_6, AUDIO_LAYOUT);
+	else
+		ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
+				AUDIO_CHANNEL_STATUS_6, ~AUDIO_LAYOUT);
+
+	/* FS */
+	switch (params->sample_rate) {
+	case 32000:
+		rate = AUDIO_FS_32K;
+		break;
+	case 44100:
+		rate = AUDIO_FS_441K;
+		break;
+	case 48000:
+		rate = AUDIO_FS_48K;
+		break;
+	case 88200:
+		rate = AUDIO_FS_882K;
+		break;
+	case 96000:
+		rate = AUDIO_FS_96K;
+		break;
+	case 176400:
+		rate = AUDIO_FS_1764K;
+		break;
+	case 192000:
+		rate = AUDIO_FS_192K;
+		break;
+	default:
+		DRM_DEV_DEBUG_DRIVER(dev, "sample rate: %d not support",
+				     params->sample_rate);
+		return -EINVAL;
+	}
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+				    AUDIO_CHANNEL_STATUS_4,
+				    0xf0, rate);
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
+				AP_AV_STATUS, AP_AUDIO_CHG);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : config audio.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void anx7625_audio_shutdown(struct device *dev, void *data)
+{
+	DRM_DEV_DEBUG_DRIVER(dev, "stop audio\n");
+}
+
+static int anx7625_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
+				       struct device_node *endpoint)
+{
+	struct of_endpoint of_ep;
+	int ret;
+
+	ret = of_graph_parse_endpoint(endpoint, &of_ep);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * HDMI sound should be located at external DPI port
+	 * Didn't have good way to check where is internal(DSI)
+	 * or external(DPI) bridge
+	 */
+	return 0;
+}
+
+static void
+anx7625_audio_update_connector_status(struct anx7625_data *ctx,
+				      enum drm_connector_status status)
+{
+	if (ctx->plugged_cb && ctx->codec_dev) {
+		ctx->plugged_cb(ctx->codec_dev,
+				status == connector_status_connected);
+	}
+}
+
+static int anx7625_audio_hook_plugged_cb(struct device *dev, void *data,
+					 hdmi_codec_plugged_cb fn,
+					 struct device *codec_dev)
+{
+	struct anx7625_data *ctx = data;
+
+	ctx->plugged_cb = fn;
+	ctx->codec_dev = codec_dev;
+	anx7625_audio_update_connector_status(ctx, anx7625_sink_detect(ctx));
+
+	return 0;
+}
+
+static const struct hdmi_codec_ops anx7625_codec_ops = {
+	.hw_params	= anx7625_audio_hw_params,
+	.audio_shutdown = anx7625_audio_shutdown,
+	.get_dai_id	= anx7625_hdmi_i2s_get_dai_id,
+	.hook_plugged_cb = anx7625_audio_hook_plugged_cb,
+};
+
+static void anx7625_unregister_audio(struct anx7625_data *ctx)
+{
+	struct device *dev = &ctx->client->dev;
+
+	if (ctx->audio_pdev) {
+		platform_device_unregister(ctx->audio_pdev);
+		ctx->audio_pdev = NULL;
+	}
+
+	DRM_DEV_DEBUG_DRIVER(dev, "unbound to %s", HDMI_CODEC_DRV_NAME);
+}
+
+static int anx7625_register_audio(struct device *dev, struct anx7625_data *ctx)
+{
+	struct hdmi_codec_pdata codec_data = {
+		.ops = &anx7625_codec_ops,
+		.max_i2s_channels = 8,
+		.i2s = 1,
+		.data = ctx,
+	};
+
+	ctx->audio_pdev = platform_device_register_data(dev,
+							HDMI_CODEC_DRV_NAME,
+							PLATFORM_DEVID_AUTO,
+							&codec_data,
+							sizeof(codec_data));
+
+	if (IS_ERR(ctx->audio_pdev))
+		return IS_ERR(ctx->audio_pdev);
+
+	DRM_DEV_DEBUG_DRIVER(dev, "bound to %s", HDMI_CODEC_DRV_NAME);
+
+	return 0;
+}
+
 static int anx7625_attach_dsi(struct anx7625_data *ctx)
 {
 	struct mipi_dsi_device *dsi;
@@ -2064,6 +2285,9 @@ static int anx7625_i2c_probe(struct i2c_client *client,
 				    DRM_MODE_CONNECTOR_DisplayPort;
 	drm_bridge_add(&platform->bridge);
 
+	if (platform->pdata.audio_en)
+		anx7625_register_audio(dev, platform);
+
 	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
 
 	return 0;
@@ -2089,6 +2313,9 @@ static int anx7625_i2c_remove(struct i2c_client *client)
 
 	anx7625_unregister_i2c_dummy_clients(platform);
 
+	if (platform->pdata.audio_en)
+		anx7625_unregister_audio(platform);
+
 	kfree(platform);
 	return 0;
 }
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index c6f93e4df0ed..d6be2a83fad9 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -111,6 +111,7 @@
 #define AUDIO_CHANNEL_STATUS_6 0xd5
 #define TDM_SLAVE_MODE 0x10
 #define I2S_SLAVE_MODE 0x08
+#define AUDIO_LAYOUT   0x01
 
 #define AUDIO_CONTROL_REGISTER 0xe6
 #define TDM_TIMING_MODE 0x08
@@ -400,6 +401,7 @@ struct anx7625_platform_data {
 	int intp_irq;
 	int is_dpi;
 	int mipi_lanes;
+	int audio_en;
 	int dp_lane0_swing_reg_cnt;
 	int lane0_reg_data[DP_TX_SWING_REG_CNT];
 	int dp_lane1_swing_reg_cnt;
@@ -420,6 +422,7 @@ struct anx7625_i2c_client {
 
 struct anx7625_data {
 	struct anx7625_platform_data pdata;
+	struct platform_device *audio_pdev;
 	atomic_t power_status;
 	int hpd_status;
 	int hpd_high_cnt;
@@ -429,6 +432,8 @@ struct anx7625_data {
 	struct anx7625_i2c_client i2c;
 	struct i2c_client *last_client;
 	struct s_edid_data slimport_edid_p;
+	struct device *codec_dev;
+	hdmi_codec_plugged_cb plugged_cb;
 	struct work_struct work;
 	struct workqueue_struct *workqueue;
 	char edid_block;
-- 
2.25.1


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

* [PATCH v6 5/5] drm/bridge: anx7625: add HDMI audio function
@ 2021-03-19  6:35   ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:35 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: devel, Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, linux-kernel, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe,
	Laurent Pinchart, Daniel Vetter, Hsin-Yi Wang, Sam Ravnborg,
	Dan Carpenter, Marek Szyprowski

Add audio HDMI codec function support, enable it through device true flag
"analogix,audio-enable".

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 227 ++++++++++++++++++++++
 drivers/gpu/drm/bridge/analogix/anx7625.h |   5 +
 2 files changed, 232 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index b424a570effa..02bb169d9c57 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -30,6 +30,8 @@
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
+#include <sound/hdmi-codec.h>
+
 #include <video/display_timing.h>
 
 #include "anx7625.h"
@@ -150,6 +152,20 @@ static int anx7625_write_and(struct anx7625_data *ctx,
 	return anx7625_reg_write(ctx, client, offset, (val & (mask)));
 }
 
+static int anx7625_write_and_or(struct anx7625_data *ctx,
+				struct i2c_client *client,
+				u8 offset, u8 and_mask, u8 or_mask)
+{
+	int val;
+
+	val = anx7625_reg_read(ctx, client, offset);
+	if (val < 0)
+		return val;
+
+	return anx7625_reg_write(ctx, client,
+				 offset, (val & and_mask) | (or_mask));
+}
+
 static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
 {
 	int i, ret;
@@ -1498,6 +1514,9 @@ static int anx7625_parse_dt(struct device *dev,
 	else
 		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
 
+	if (of_property_read_bool(np, "analogix,audio-enable"))
+		pdata->audio_en = 1;
+
 	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
 	if (ret < 0) {
 		if (ret == -ENODEV)
@@ -1568,6 +1587,208 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
 				     connector_status_disconnected;
 }
 
+static int anx7625_audio_hw_params(struct device *dev, void *data,
+				   struct hdmi_codec_daifmt *fmt,
+				   struct hdmi_codec_params *params)
+{
+	struct anx7625_data *ctx = dev_get_drvdata(dev);
+	int wl, ch, rate;
+	int ret = 0;
+
+	if (fmt->fmt != HDMI_DSP_A) {
+		DRM_DEV_ERROR(dev, "only supports DSP_A\n");
+		return -EINVAL;
+	}
+
+	DRM_DEV_DEBUG_DRIVER(dev, "setting %d Hz, %d bit, %d channels\n",
+			     params->sample_rate, params->sample_width,
+			     params->cea.channels);
+
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+				    AUDIO_CHANNEL_STATUS_6,
+				    ~I2S_SLAVE_MODE,
+				    TDM_SLAVE_MODE);
+
+	/* Word length */
+	switch (params->sample_width) {
+	case 16:
+		wl = AUDIO_W_LEN_16_20MAX;
+		break;
+	case 18:
+		wl = AUDIO_W_LEN_18_20MAX;
+		break;
+	case 20:
+		wl = AUDIO_W_LEN_20_20MAX;
+		break;
+	case 24:
+		wl = AUDIO_W_LEN_24_24MAX;
+		break;
+	default:
+		DRM_DEV_DEBUG_DRIVER(dev, "wordlength: %d bit not support",
+				     params->sample_width);
+		return -EINVAL;
+	}
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+				    AUDIO_CHANNEL_STATUS_5,
+				    0xf0, wl);
+
+	/* Channel num */
+	switch (params->cea.channels) {
+	case 2:
+		ch = I2S_CH_2;
+		break;
+	case 4:
+		ch = TDM_CH_4;
+		break;
+	case 6:
+		ch = TDM_CH_6;
+		break;
+	case 8:
+		ch = TDM_CH_8;
+		break;
+	default:
+		DRM_DEV_DEBUG_DRIVER(dev, "channel number: %d not support",
+				     params->cea.channels);
+		return -EINVAL;
+	}
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+			       AUDIO_CHANNEL_STATUS_6, 0x1f, ch << 5);
+	if (ch > I2S_CH_2)
+		ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
+				AUDIO_CHANNEL_STATUS_6, AUDIO_LAYOUT);
+	else
+		ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
+				AUDIO_CHANNEL_STATUS_6, ~AUDIO_LAYOUT);
+
+	/* FS */
+	switch (params->sample_rate) {
+	case 32000:
+		rate = AUDIO_FS_32K;
+		break;
+	case 44100:
+		rate = AUDIO_FS_441K;
+		break;
+	case 48000:
+		rate = AUDIO_FS_48K;
+		break;
+	case 88200:
+		rate = AUDIO_FS_882K;
+		break;
+	case 96000:
+		rate = AUDIO_FS_96K;
+		break;
+	case 176400:
+		rate = AUDIO_FS_1764K;
+		break;
+	case 192000:
+		rate = AUDIO_FS_192K;
+		break;
+	default:
+		DRM_DEV_DEBUG_DRIVER(dev, "sample rate: %d not support",
+				     params->sample_rate);
+		return -EINVAL;
+	}
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+				    AUDIO_CHANNEL_STATUS_4,
+				    0xf0, rate);
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
+				AP_AV_STATUS, AP_AUDIO_CHG);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : config audio.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void anx7625_audio_shutdown(struct device *dev, void *data)
+{
+	DRM_DEV_DEBUG_DRIVER(dev, "stop audio\n");
+}
+
+static int anx7625_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
+				       struct device_node *endpoint)
+{
+	struct of_endpoint of_ep;
+	int ret;
+
+	ret = of_graph_parse_endpoint(endpoint, &of_ep);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * HDMI sound should be located at external DPI port
+	 * Didn't have good way to check where is internal(DSI)
+	 * or external(DPI) bridge
+	 */
+	return 0;
+}
+
+static void
+anx7625_audio_update_connector_status(struct anx7625_data *ctx,
+				      enum drm_connector_status status)
+{
+	if (ctx->plugged_cb && ctx->codec_dev) {
+		ctx->plugged_cb(ctx->codec_dev,
+				status == connector_status_connected);
+	}
+}
+
+static int anx7625_audio_hook_plugged_cb(struct device *dev, void *data,
+					 hdmi_codec_plugged_cb fn,
+					 struct device *codec_dev)
+{
+	struct anx7625_data *ctx = data;
+
+	ctx->plugged_cb = fn;
+	ctx->codec_dev = codec_dev;
+	anx7625_audio_update_connector_status(ctx, anx7625_sink_detect(ctx));
+
+	return 0;
+}
+
+static const struct hdmi_codec_ops anx7625_codec_ops = {
+	.hw_params	= anx7625_audio_hw_params,
+	.audio_shutdown = anx7625_audio_shutdown,
+	.get_dai_id	= anx7625_hdmi_i2s_get_dai_id,
+	.hook_plugged_cb = anx7625_audio_hook_plugged_cb,
+};
+
+static void anx7625_unregister_audio(struct anx7625_data *ctx)
+{
+	struct device *dev = &ctx->client->dev;
+
+	if (ctx->audio_pdev) {
+		platform_device_unregister(ctx->audio_pdev);
+		ctx->audio_pdev = NULL;
+	}
+
+	DRM_DEV_DEBUG_DRIVER(dev, "unbound to %s", HDMI_CODEC_DRV_NAME);
+}
+
+static int anx7625_register_audio(struct device *dev, struct anx7625_data *ctx)
+{
+	struct hdmi_codec_pdata codec_data = {
+		.ops = &anx7625_codec_ops,
+		.max_i2s_channels = 8,
+		.i2s = 1,
+		.data = ctx,
+	};
+
+	ctx->audio_pdev = platform_device_register_data(dev,
+							HDMI_CODEC_DRV_NAME,
+							PLATFORM_DEVID_AUTO,
+							&codec_data,
+							sizeof(codec_data));
+
+	if (IS_ERR(ctx->audio_pdev))
+		return IS_ERR(ctx->audio_pdev);
+
+	DRM_DEV_DEBUG_DRIVER(dev, "bound to %s", HDMI_CODEC_DRV_NAME);
+
+	return 0;
+}
+
 static int anx7625_attach_dsi(struct anx7625_data *ctx)
 {
 	struct mipi_dsi_device *dsi;
@@ -2064,6 +2285,9 @@ static int anx7625_i2c_probe(struct i2c_client *client,
 				    DRM_MODE_CONNECTOR_DisplayPort;
 	drm_bridge_add(&platform->bridge);
 
+	if (platform->pdata.audio_en)
+		anx7625_register_audio(dev, platform);
+
 	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
 
 	return 0;
@@ -2089,6 +2313,9 @@ static int anx7625_i2c_remove(struct i2c_client *client)
 
 	anx7625_unregister_i2c_dummy_clients(platform);
 
+	if (platform->pdata.audio_en)
+		anx7625_unregister_audio(platform);
+
 	kfree(platform);
 	return 0;
 }
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index c6f93e4df0ed..d6be2a83fad9 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -111,6 +111,7 @@
 #define AUDIO_CHANNEL_STATUS_6 0xd5
 #define TDM_SLAVE_MODE 0x10
 #define I2S_SLAVE_MODE 0x08
+#define AUDIO_LAYOUT   0x01
 
 #define AUDIO_CONTROL_REGISTER 0xe6
 #define TDM_TIMING_MODE 0x08
@@ -400,6 +401,7 @@ struct anx7625_platform_data {
 	int intp_irq;
 	int is_dpi;
 	int mipi_lanes;
+	int audio_en;
 	int dp_lane0_swing_reg_cnt;
 	int lane0_reg_data[DP_TX_SWING_REG_CNT];
 	int dp_lane1_swing_reg_cnt;
@@ -420,6 +422,7 @@ struct anx7625_i2c_client {
 
 struct anx7625_data {
 	struct anx7625_platform_data pdata;
+	struct platform_device *audio_pdev;
 	atomic_t power_status;
 	int hpd_status;
 	int hpd_high_cnt;
@@ -429,6 +432,8 @@ struct anx7625_data {
 	struct anx7625_i2c_client i2c;
 	struct i2c_client *last_client;
 	struct s_edid_data slimport_edid_p;
+	struct device *codec_dev;
+	hdmi_codec_plugged_cb plugged_cb;
 	struct work_struct work;
 	struct workqueue_struct *workqueue;
 	char edid_block;
-- 
2.25.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* [PATCH v6 5/5] drm/bridge: anx7625: add HDMI audio function
@ 2021-03-19  6:35   ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-19  6:35 UTC (permalink / raw)
  To: Robert Foss, Nicolas Boichat, Andrzej Hajda
  Cc: devel, Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, linux-kernel, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe,
	Laurent Pinchart, Hsin-Yi Wang, Sam Ravnborg, Dan Carpenter,
	Marek Szyprowski

Add audio HDMI codec function support, enable it through device true flag
"analogix,audio-enable".

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 227 ++++++++++++++++++++++
 drivers/gpu/drm/bridge/analogix/anx7625.h |   5 +
 2 files changed, 232 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index b424a570effa..02bb169d9c57 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -30,6 +30,8 @@
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
+#include <sound/hdmi-codec.h>
+
 #include <video/display_timing.h>
 
 #include "anx7625.h"
@@ -150,6 +152,20 @@ static int anx7625_write_and(struct anx7625_data *ctx,
 	return anx7625_reg_write(ctx, client, offset, (val & (mask)));
 }
 
+static int anx7625_write_and_or(struct anx7625_data *ctx,
+				struct i2c_client *client,
+				u8 offset, u8 and_mask, u8 or_mask)
+{
+	int val;
+
+	val = anx7625_reg_read(ctx, client, offset);
+	if (val < 0)
+		return val;
+
+	return anx7625_reg_write(ctx, client,
+				 offset, (val & and_mask) | (or_mask));
+}
+
 static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
 {
 	int i, ret;
@@ -1498,6 +1514,9 @@ static int anx7625_parse_dt(struct device *dev,
 	else
 		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
 
+	if (of_property_read_bool(np, "analogix,audio-enable"))
+		pdata->audio_en = 1;
+
 	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
 	if (ret < 0) {
 		if (ret == -ENODEV)
@@ -1568,6 +1587,208 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
 				     connector_status_disconnected;
 }
 
+static int anx7625_audio_hw_params(struct device *dev, void *data,
+				   struct hdmi_codec_daifmt *fmt,
+				   struct hdmi_codec_params *params)
+{
+	struct anx7625_data *ctx = dev_get_drvdata(dev);
+	int wl, ch, rate;
+	int ret = 0;
+
+	if (fmt->fmt != HDMI_DSP_A) {
+		DRM_DEV_ERROR(dev, "only supports DSP_A\n");
+		return -EINVAL;
+	}
+
+	DRM_DEV_DEBUG_DRIVER(dev, "setting %d Hz, %d bit, %d channels\n",
+			     params->sample_rate, params->sample_width,
+			     params->cea.channels);
+
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+				    AUDIO_CHANNEL_STATUS_6,
+				    ~I2S_SLAVE_MODE,
+				    TDM_SLAVE_MODE);
+
+	/* Word length */
+	switch (params->sample_width) {
+	case 16:
+		wl = AUDIO_W_LEN_16_20MAX;
+		break;
+	case 18:
+		wl = AUDIO_W_LEN_18_20MAX;
+		break;
+	case 20:
+		wl = AUDIO_W_LEN_20_20MAX;
+		break;
+	case 24:
+		wl = AUDIO_W_LEN_24_24MAX;
+		break;
+	default:
+		DRM_DEV_DEBUG_DRIVER(dev, "wordlength: %d bit not support",
+				     params->sample_width);
+		return -EINVAL;
+	}
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+				    AUDIO_CHANNEL_STATUS_5,
+				    0xf0, wl);
+
+	/* Channel num */
+	switch (params->cea.channels) {
+	case 2:
+		ch = I2S_CH_2;
+		break;
+	case 4:
+		ch = TDM_CH_4;
+		break;
+	case 6:
+		ch = TDM_CH_6;
+		break;
+	case 8:
+		ch = TDM_CH_8;
+		break;
+	default:
+		DRM_DEV_DEBUG_DRIVER(dev, "channel number: %d not support",
+				     params->cea.channels);
+		return -EINVAL;
+	}
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+			       AUDIO_CHANNEL_STATUS_6, 0x1f, ch << 5);
+	if (ch > I2S_CH_2)
+		ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
+				AUDIO_CHANNEL_STATUS_6, AUDIO_LAYOUT);
+	else
+		ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
+				AUDIO_CHANNEL_STATUS_6, ~AUDIO_LAYOUT);
+
+	/* FS */
+	switch (params->sample_rate) {
+	case 32000:
+		rate = AUDIO_FS_32K;
+		break;
+	case 44100:
+		rate = AUDIO_FS_441K;
+		break;
+	case 48000:
+		rate = AUDIO_FS_48K;
+		break;
+	case 88200:
+		rate = AUDIO_FS_882K;
+		break;
+	case 96000:
+		rate = AUDIO_FS_96K;
+		break;
+	case 176400:
+		rate = AUDIO_FS_1764K;
+		break;
+	case 192000:
+		rate = AUDIO_FS_192K;
+		break;
+	default:
+		DRM_DEV_DEBUG_DRIVER(dev, "sample rate: %d not support",
+				     params->sample_rate);
+		return -EINVAL;
+	}
+	ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
+				    AUDIO_CHANNEL_STATUS_4,
+				    0xf0, rate);
+	ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
+				AP_AV_STATUS, AP_AUDIO_CHG);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : config audio.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void anx7625_audio_shutdown(struct device *dev, void *data)
+{
+	DRM_DEV_DEBUG_DRIVER(dev, "stop audio\n");
+}
+
+static int anx7625_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
+				       struct device_node *endpoint)
+{
+	struct of_endpoint of_ep;
+	int ret;
+
+	ret = of_graph_parse_endpoint(endpoint, &of_ep);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * HDMI sound should be located at external DPI port
+	 * Didn't have good way to check where is internal(DSI)
+	 * or external(DPI) bridge
+	 */
+	return 0;
+}
+
+static void
+anx7625_audio_update_connector_status(struct anx7625_data *ctx,
+				      enum drm_connector_status status)
+{
+	if (ctx->plugged_cb && ctx->codec_dev) {
+		ctx->plugged_cb(ctx->codec_dev,
+				status == connector_status_connected);
+	}
+}
+
+static int anx7625_audio_hook_plugged_cb(struct device *dev, void *data,
+					 hdmi_codec_plugged_cb fn,
+					 struct device *codec_dev)
+{
+	struct anx7625_data *ctx = data;
+
+	ctx->plugged_cb = fn;
+	ctx->codec_dev = codec_dev;
+	anx7625_audio_update_connector_status(ctx, anx7625_sink_detect(ctx));
+
+	return 0;
+}
+
+static const struct hdmi_codec_ops anx7625_codec_ops = {
+	.hw_params	= anx7625_audio_hw_params,
+	.audio_shutdown = anx7625_audio_shutdown,
+	.get_dai_id	= anx7625_hdmi_i2s_get_dai_id,
+	.hook_plugged_cb = anx7625_audio_hook_plugged_cb,
+};
+
+static void anx7625_unregister_audio(struct anx7625_data *ctx)
+{
+	struct device *dev = &ctx->client->dev;
+
+	if (ctx->audio_pdev) {
+		platform_device_unregister(ctx->audio_pdev);
+		ctx->audio_pdev = NULL;
+	}
+
+	DRM_DEV_DEBUG_DRIVER(dev, "unbound to %s", HDMI_CODEC_DRV_NAME);
+}
+
+static int anx7625_register_audio(struct device *dev, struct anx7625_data *ctx)
+{
+	struct hdmi_codec_pdata codec_data = {
+		.ops = &anx7625_codec_ops,
+		.max_i2s_channels = 8,
+		.i2s = 1,
+		.data = ctx,
+	};
+
+	ctx->audio_pdev = platform_device_register_data(dev,
+							HDMI_CODEC_DRV_NAME,
+							PLATFORM_DEVID_AUTO,
+							&codec_data,
+							sizeof(codec_data));
+
+	if (IS_ERR(ctx->audio_pdev))
+		return IS_ERR(ctx->audio_pdev);
+
+	DRM_DEV_DEBUG_DRIVER(dev, "bound to %s", HDMI_CODEC_DRV_NAME);
+
+	return 0;
+}
+
 static int anx7625_attach_dsi(struct anx7625_data *ctx)
 {
 	struct mipi_dsi_device *dsi;
@@ -2064,6 +2285,9 @@ static int anx7625_i2c_probe(struct i2c_client *client,
 				    DRM_MODE_CONNECTOR_DisplayPort;
 	drm_bridge_add(&platform->bridge);
 
+	if (platform->pdata.audio_en)
+		anx7625_register_audio(dev, platform);
+
 	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
 
 	return 0;
@@ -2089,6 +2313,9 @@ static int anx7625_i2c_remove(struct i2c_client *client)
 
 	anx7625_unregister_i2c_dummy_clients(platform);
 
+	if (platform->pdata.audio_en)
+		anx7625_unregister_audio(platform);
+
 	kfree(platform);
 	return 0;
 }
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index c6f93e4df0ed..d6be2a83fad9 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -111,6 +111,7 @@
 #define AUDIO_CHANNEL_STATUS_6 0xd5
 #define TDM_SLAVE_MODE 0x10
 #define I2S_SLAVE_MODE 0x08
+#define AUDIO_LAYOUT   0x01
 
 #define AUDIO_CONTROL_REGISTER 0xe6
 #define TDM_TIMING_MODE 0x08
@@ -400,6 +401,7 @@ struct anx7625_platform_data {
 	int intp_irq;
 	int is_dpi;
 	int mipi_lanes;
+	int audio_en;
 	int dp_lane0_swing_reg_cnt;
 	int lane0_reg_data[DP_TX_SWING_REG_CNT];
 	int dp_lane1_swing_reg_cnt;
@@ -420,6 +422,7 @@ struct anx7625_i2c_client {
 
 struct anx7625_data {
 	struct anx7625_platform_data pdata;
+	struct platform_device *audio_pdev;
 	atomic_t power_status;
 	int hpd_status;
 	int hpd_high_cnt;
@@ -429,6 +432,8 @@ struct anx7625_data {
 	struct anx7625_i2c_client i2c;
 	struct i2c_client *last_client;
 	struct s_edid_data slimport_edid_p;
+	struct device *codec_dev;
+	hdmi_codec_plugged_cb plugged_cb;
 	struct work_struct work;
 	struct workqueue_struct *workqueue;
 	char edid_block;
-- 
2.25.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 1/5] dt-bindings:drm/bridge:anx7625:add vendor define flags
  2021-03-19  6:32   ` Xin Ji
@ 2021-03-21 12:00     ` Laurent Pinchart
  -1 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2021-03-21 12:00 UTC (permalink / raw)
  To: Xin Ji
  Cc: Rob Herring, David Airlie, Nicolas Boichat, Hsin-Yi Wang,
	Daniel Vetter, Sam Ravnborg, Maxime Ripard, Mark Brown,
	Ricardo Cañuelo, dri-devel, devicetree, Bernie Liang,
	Sheng Pan, Zhen Li, linux-kernel

Hi Xin,

Thank you for the patch.

On Fri, Mar 19, 2021 at 02:32:39PM +0800, Xin Ji wrote:
> Add 'bus-type' and 'data-lanes' define for port0. Define DP tx lane0,
> lane1 swing register array define, and audio enable flag.
> 
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  .../display/bridge/analogix,anx7625.yaml      | 58 ++++++++++++++++++-
>  1 file changed, 57 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> index c789784efe30..3f54d5876982 100644
> --- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> @@ -34,6 +34,26 @@ properties:
>      description: used for reset chip control, RESET_N pin B7.
>      maxItems: 1
>  
> +  analogix,lane0-swing:
> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +    minItems: 1
> +    maxItems: 20
> +    description:
> +      an array of swing register setting for DP tx lane0 PHY, please don't
> +      add this property, or contact vendor.

DT properties need to be documented. Contacting the vendor doesn't count
as documentation I'm afraid.

> +
> +  analogix,lane1-swing:
> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +    minItems: 1
> +    maxItems: 20
> +    description:
> +      an array of swing register setting for DP tx lane1 PHY, please don't
> +      add this property, or contact vendor.
> +
> +  analogix,audio-enable:
> +    type: boolean
> +    description: let the driver enable audio HDMI codec function or not.
> +
>    ports:
>      $ref: /schemas/graph.yaml#/properties/ports
>  
> @@ -41,13 +61,43 @@ properties:
>        port@0:
>          $ref: /schemas/graph.yaml#/properties/port
>          description:
> -          Video port for MIPI DSI input.
> +          MIPI DSI/DPI input.
> +
> +        properties:
> +          endpoint:
> +            $ref: /schemas/media/video-interfaces.yaml#
> +            type: object
> +            additionalProperties: false
> +
> +            properties:
> +              remote-endpoint: true
> +              bus-type: true
> +              data-lanes: true
> +
> +            required:
> +              - remote-endpoint
> +
> +        required:
> +          - endpoint
> +
>  
>        port@1:
>          $ref: /schemas/graph.yaml#/properties/port
>          description:
>            Video port for panel or connector.
>  
> +        properties:
> +          endpoint:
> +            $ref: /schemas/media/video-interfaces.yaml#
> +            type: object
> +            additionalProperties: false
> +
> +            properties:
> +              remote-endpoint: true
> +
> +            required:
> +              - remote-endpoint
> +
>      required:
>        - port@0
>        - port@1
> @@ -73,6 +123,10 @@ examples:
>              enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
>              reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
>  
> +            analogix,audio-enable;
> +            analogix,lane0-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> +            analogix,lane1-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> +
>              ports {
>                  #address-cells = <1>;
>                  #size-cells = <0>;
> @@ -81,6 +135,8 @@ examples:
>                      reg = <0>;
>                      anx7625_in: endpoint {
>                          remote-endpoint = <&mipi_dsi>;
> +                        bus-type = <5>;
> +                        data-lanes = <0 1 2 3>;
>                      };
>                  };
>  

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v6 1/5] dt-bindings:drm/bridge:anx7625:add vendor define flags
@ 2021-03-21 12:00     ` Laurent Pinchart
  0 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2021-03-21 12:00 UTC (permalink / raw)
  To: Xin Ji
  Cc: Nicolas Boichat, devicetree, David Airlie, Ricardo Cañuelo,
	Mark Brown, Zhen Li, linux-kernel, Rob Herring, dri-devel,
	Hsin-Yi Wang, Sam Ravnborg, Bernie Liang, Sheng Pan

Hi Xin,

Thank you for the patch.

On Fri, Mar 19, 2021 at 02:32:39PM +0800, Xin Ji wrote:
> Add 'bus-type' and 'data-lanes' define for port0. Define DP tx lane0,
> lane1 swing register array define, and audio enable flag.
> 
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  .../display/bridge/analogix,anx7625.yaml      | 58 ++++++++++++++++++-
>  1 file changed, 57 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> index c789784efe30..3f54d5876982 100644
> --- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> @@ -34,6 +34,26 @@ properties:
>      description: used for reset chip control, RESET_N pin B7.
>      maxItems: 1
>  
> +  analogix,lane0-swing:
> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +    minItems: 1
> +    maxItems: 20
> +    description:
> +      an array of swing register setting for DP tx lane0 PHY, please don't
> +      add this property, or contact vendor.

DT properties need to be documented. Contacting the vendor doesn't count
as documentation I'm afraid.

> +
> +  analogix,lane1-swing:
> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +    minItems: 1
> +    maxItems: 20
> +    description:
> +      an array of swing register setting for DP tx lane1 PHY, please don't
> +      add this property, or contact vendor.
> +
> +  analogix,audio-enable:
> +    type: boolean
> +    description: let the driver enable audio HDMI codec function or not.
> +
>    ports:
>      $ref: /schemas/graph.yaml#/properties/ports
>  
> @@ -41,13 +61,43 @@ properties:
>        port@0:
>          $ref: /schemas/graph.yaml#/properties/port
>          description:
> -          Video port for MIPI DSI input.
> +          MIPI DSI/DPI input.
> +
> +        properties:
> +          endpoint:
> +            $ref: /schemas/media/video-interfaces.yaml#
> +            type: object
> +            additionalProperties: false
> +
> +            properties:
> +              remote-endpoint: true
> +              bus-type: true
> +              data-lanes: true
> +
> +            required:
> +              - remote-endpoint
> +
> +        required:
> +          - endpoint
> +
>  
>        port@1:
>          $ref: /schemas/graph.yaml#/properties/port
>          description:
>            Video port for panel or connector.
>  
> +        properties:
> +          endpoint:
> +            $ref: /schemas/media/video-interfaces.yaml#
> +            type: object
> +            additionalProperties: false
> +
> +            properties:
> +              remote-endpoint: true
> +
> +            required:
> +              - remote-endpoint
> +
>      required:
>        - port@0
>        - port@1
> @@ -73,6 +123,10 @@ examples:
>              enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
>              reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
>  
> +            analogix,audio-enable;
> +            analogix,lane0-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> +            analogix,lane1-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> +
>              ports {
>                  #address-cells = <1>;
>                  #size-cells = <0>;
> @@ -81,6 +135,8 @@ examples:
>                      reg = <0>;
>                      anx7625_in: endpoint {
>                          remote-endpoint = <&mipi_dsi>;
> +                        bus-type = <5>;
> +                        data-lanes = <0 1 2 3>;
>                      };
>                  };
>  

-- 
Regards,

Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 2/5] drm/bridge: anx7625: fix not correct return value
  2021-03-19  6:33   ` Xin Ji
  (?)
@ 2021-03-22  9:36     ` Robert Foss
  -1 siblings, 0 replies; 52+ messages in thread
From: Robert Foss @ 2021-03-22  9:36 UTC (permalink / raw)
  To: Xin Ji
  Cc: Nicolas Boichat, Andrzej Hajda, Neil Armstrong, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Dan Carpenter, David Airlie,
	Daniel Vetter, Boris Brezillon, Sam Ravnborg, Hsin-Yi Wang,
	Torsten Duwe, Vasily Khoruzhick, Marek Szyprowski, Sheng Pan,
	Bernie Liang, Zhen Li, dri-devel, linux-kernel, devel

Hey Xin,

This patch looks good to me.

Reviewed-by: Robert Foss <robert.foss@linaro.org>

On Fri, 19 Mar 2021 at 07:33, Xin Ji <xji@analogixsemi.com> wrote:
>
> At some time, the original code may return non zero value, force return 0
> if operation finished.
>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 65cc05982f82..04536cc7afe7 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -189,10 +189,10 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
>                                AP_AUX_CTRL_STATUS);
>         if (val < 0 || (val & 0x0F)) {
>                 DRM_DEV_ERROR(dev, "aux status %02x\n", val);
> -               val = -EIO;
> +               return -EIO;
>         }
>
> -       return val;
> +       return 0;
>  }
>
>  static int anx7625_video_mute_control(struct anx7625_data *ctx,
> --
> 2.25.1
>

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

* Re: [PATCH v6 2/5] drm/bridge: anx7625: fix not correct return value
@ 2021-03-22  9:36     ` Robert Foss
  0 siblings, 0 replies; 52+ messages in thread
From: Robert Foss @ 2021-03-22  9:36 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sheng Pan, Jonas Karlman,
	David Airlie, Bernie Liang, Neil Armstrong, Zhen Li,
	linux-kernel, dri-devel, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Laurent Pinchart, Daniel Vetter,
	Hsin-Yi Wang, Sam Ravnborg, Dan Carpenter, Marek Szyprowski

Hey Xin,

This patch looks good to me.

Reviewed-by: Robert Foss <robert.foss@linaro.org>

On Fri, 19 Mar 2021 at 07:33, Xin Ji <xji@analogixsemi.com> wrote:
>
> At some time, the original code may return non zero value, force return 0
> if operation finished.
>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 65cc05982f82..04536cc7afe7 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -189,10 +189,10 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
>                                AP_AUX_CTRL_STATUS);
>         if (val < 0 || (val & 0x0F)) {
>                 DRM_DEV_ERROR(dev, "aux status %02x\n", val);
> -               val = -EIO;
> +               return -EIO;
>         }
>
> -       return val;
> +       return 0;
>  }
>
>  static int anx7625_video_mute_control(struct anx7625_data *ctx,
> --
> 2.25.1
>
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v6 2/5] drm/bridge: anx7625: fix not correct return value
@ 2021-03-22  9:36     ` Robert Foss
  0 siblings, 0 replies; 52+ messages in thread
From: Robert Foss @ 2021-03-22  9:36 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sheng Pan, Jonas Karlman,
	David Airlie, Bernie Liang, Neil Armstrong, Zhen Li,
	linux-kernel, dri-devel, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Laurent Pinchart, Hsin-Yi Wang,
	Sam Ravnborg, Dan Carpenter, Marek Szyprowski

Hey Xin,

This patch looks good to me.

Reviewed-by: Robert Foss <robert.foss@linaro.org>

On Fri, 19 Mar 2021 at 07:33, Xin Ji <xji@analogixsemi.com> wrote:
>
> At some time, the original code may return non zero value, force return 0
> if operation finished.
>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 65cc05982f82..04536cc7afe7 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -189,10 +189,10 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
>                                AP_AUX_CTRL_STATUS);
>         if (val < 0 || (val & 0x0F)) {
>                 DRM_DEV_ERROR(dev, "aux status %02x\n", val);
> -               val = -EIO;
> +               return -EIO;
>         }
>
> -       return val;
> +       return 0;
>  }
>
>  static int anx7625_video_mute_control(struct anx7625_data *ctx,
> --
> 2.25.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 1/5] dt-bindings:drm/bridge:anx7625:add vendor define flags
  2021-03-21 12:00     ` Laurent Pinchart
@ 2021-03-24  7:51       ` Xin Ji
  -1 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-24  7:51 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Rob Herring, David Airlie, Nicolas Boichat, Hsin-Yi Wang,
	Daniel Vetter, Sam Ravnborg, Laurent Pinchart, Maxime Ripard,
	Mark Brown, Ricardo Cañuelo, dri-devel, devicetree,
	Bernie Liang, Sheng Pan, Zhen Li, linux-kernel

On Sun, Mar 21, 2021 at 02:00:38PM +0200, Laurent Pinchart wrote:
> Hi Xin,
> 
> Thank you for the patch.
> 
> On Fri, Mar 19, 2021 at 02:32:39PM +0800, Xin Ji wrote:
> > Add 'bus-type' and 'data-lanes' define for port0. Define DP tx lane0,
> > lane1 swing register array define, and audio enable flag.
> > 
> > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > ---
> >  .../display/bridge/analogix,anx7625.yaml      | 58 ++++++++++++++++++-
> >  1 file changed, 57 insertions(+), 1 deletion(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > index c789784efe30..3f54d5876982 100644
> > --- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > @@ -34,6 +34,26 @@ properties:
> >      description: used for reset chip control, RESET_N pin B7.
> >      maxItems: 1
> >  
> > +  analogix,lane0-swing:
> > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > +    minItems: 1
> > +    maxItems: 20
> > +    description:
> > +      an array of swing register setting for DP tx lane0 PHY, please don't
> > +      add this property, or contact vendor.
> 
> DT properties need to be documented. Contacting the vendor doesn't count
> as documentation I'm afraid.
Hi Laurent Pinchart, thanks for your comment. For the DP phy swing
setting, it is hard to describe in here, needs to refer the anx7625
datasheet and programming guide. Basically, no need to change the DP phy
swing setting.

Thanks,
Xin
> 
> > +
> > +  analogix,lane1-swing:
> > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > +    minItems: 1
> > +    maxItems: 20
> > +    description:
> > +      an array of swing register setting for DP tx lane1 PHY, please don't
> > +      add this property, or contact vendor.
> > +
> > +  analogix,audio-enable:
> > +    type: boolean
> > +    description: let the driver enable audio HDMI codec function or not.
> > +
> >    ports:
> >      $ref: /schemas/graph.yaml#/properties/ports
> >  
> > @@ -41,13 +61,43 @@ properties:
> >        port@0:
> >          $ref: /schemas/graph.yaml#/properties/port
> >          description:
> > -          Video port for MIPI DSI input.
> > +          MIPI DSI/DPI input.
> > +
> > +        properties:
> > +          endpoint:
> > +            $ref: /schemas/media/video-interfaces.yaml#
> > +            type: object
> > +            additionalProperties: false
> > +
> > +            properties:
> > +              remote-endpoint: true
> > +              bus-type: true
> > +              data-lanes: true
> > +
> > +            required:
> > +              - remote-endpoint
> > +
> > +        required:
> > +          - endpoint
> > +
> >  
> >        port@1:
> >          $ref: /schemas/graph.yaml#/properties/port
> >          description:
> >            Video port for panel or connector.
> >  
> > +        properties:
> > +          endpoint:
> > +            $ref: /schemas/media/video-interfaces.yaml#
> > +            type: object
> > +            additionalProperties: false
> > +
> > +            properties:
> > +              remote-endpoint: true
> > +
> > +            required:
> > +              - remote-endpoint
> > +
> >      required:
> >        - port@0
> >        - port@1
> > @@ -73,6 +123,10 @@ examples:
> >              enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
> >              reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
> >  
> > +            analogix,audio-enable;
> > +            analogix,lane0-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > +            analogix,lane1-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > +
> >              ports {
> >                  #address-cells = <1>;
> >                  #size-cells = <0>;
> > @@ -81,6 +135,8 @@ examples:
> >                      reg = <0>;
> >                      anx7625_in: endpoint {
> >                          remote-endpoint = <&mipi_dsi>;
> > +                        bus-type = <5>;
> > +                        data-lanes = <0 1 2 3>;
> >                      };
> >                  };
> >  
> 
> -- 
> Regards,
> 
> Laurent Pinchart

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

* Re: [PATCH v6 1/5] dt-bindings:drm/bridge:anx7625:add vendor define flags
@ 2021-03-24  7:51       ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-24  7:51 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Nicolas Boichat, Laurent Pinchart, devicetree, David Airlie,
	Ricardo Cañuelo, Mark Brown, Zhen Li, linux-kernel,
	Rob Herring, dri-devel, Hsin-Yi Wang, Sam Ravnborg, Bernie Liang,
	Sheng Pan

On Sun, Mar 21, 2021 at 02:00:38PM +0200, Laurent Pinchart wrote:
> Hi Xin,
> 
> Thank you for the patch.
> 
> On Fri, Mar 19, 2021 at 02:32:39PM +0800, Xin Ji wrote:
> > Add 'bus-type' and 'data-lanes' define for port0. Define DP tx lane0,
> > lane1 swing register array define, and audio enable flag.
> > 
> > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > ---
> >  .../display/bridge/analogix,anx7625.yaml      | 58 ++++++++++++++++++-
> >  1 file changed, 57 insertions(+), 1 deletion(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > index c789784efe30..3f54d5876982 100644
> > --- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > @@ -34,6 +34,26 @@ properties:
> >      description: used for reset chip control, RESET_N pin B7.
> >      maxItems: 1
> >  
> > +  analogix,lane0-swing:
> > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > +    minItems: 1
> > +    maxItems: 20
> > +    description:
> > +      an array of swing register setting for DP tx lane0 PHY, please don't
> > +      add this property, or contact vendor.
> 
> DT properties need to be documented. Contacting the vendor doesn't count
> as documentation I'm afraid.
Hi Laurent Pinchart, thanks for your comment. For the DP phy swing
setting, it is hard to describe in here, needs to refer the anx7625
datasheet and programming guide. Basically, no need to change the DP phy
swing setting.

Thanks,
Xin
> 
> > +
> > +  analogix,lane1-swing:
> > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > +    minItems: 1
> > +    maxItems: 20
> > +    description:
> > +      an array of swing register setting for DP tx lane1 PHY, please don't
> > +      add this property, or contact vendor.
> > +
> > +  analogix,audio-enable:
> > +    type: boolean
> > +    description: let the driver enable audio HDMI codec function or not.
> > +
> >    ports:
> >      $ref: /schemas/graph.yaml#/properties/ports
> >  
> > @@ -41,13 +61,43 @@ properties:
> >        port@0:
> >          $ref: /schemas/graph.yaml#/properties/port
> >          description:
> > -          Video port for MIPI DSI input.
> > +          MIPI DSI/DPI input.
> > +
> > +        properties:
> > +          endpoint:
> > +            $ref: /schemas/media/video-interfaces.yaml#
> > +            type: object
> > +            additionalProperties: false
> > +
> > +            properties:
> > +              remote-endpoint: true
> > +              bus-type: true
> > +              data-lanes: true
> > +
> > +            required:
> > +              - remote-endpoint
> > +
> > +        required:
> > +          - endpoint
> > +
> >  
> >        port@1:
> >          $ref: /schemas/graph.yaml#/properties/port
> >          description:
> >            Video port for panel or connector.
> >  
> > +        properties:
> > +          endpoint:
> > +            $ref: /schemas/media/video-interfaces.yaml#
> > +            type: object
> > +            additionalProperties: false
> > +
> > +            properties:
> > +              remote-endpoint: true
> > +
> > +            required:
> > +              - remote-endpoint
> > +
> >      required:
> >        - port@0
> >        - port@1
> > @@ -73,6 +123,10 @@ examples:
> >              enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
> >              reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
> >  
> > +            analogix,audio-enable;
> > +            analogix,lane0-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > +            analogix,lane1-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > +
> >              ports {
> >                  #address-cells = <1>;
> >                  #size-cells = <0>;
> > @@ -81,6 +135,8 @@ examples:
> >                      reg = <0>;
> >                      anx7625_in: endpoint {
> >                          remote-endpoint = <&mipi_dsi>;
> > +                        bus-type = <5>;
> > +                        data-lanes = <0 1 2 3>;
> >                      };
> >                  };
> >  
> 
> -- 
> Regards,
> 
> Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
  2021-03-19  6:34   ` Xin Ji
  (?)
@ 2021-03-25 18:19     ` Sean Paul
  -1 siblings, 0 replies; 52+ messages in thread
From: Sean Paul @ 2021-03-25 18:19 UTC (permalink / raw)
  To: Xin Ji
  Cc: Robert Foss, Nicolas Boichat, Andrzej Hajda, devel,
	Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, LKML, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe,
	Laurent Pinchart, Hsin-Yi Wang, Sam Ravnborg, Dan Carpenter,
	Marek Szyprowski

On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
>
> Add HDCP feature, enable HDCP function through chip internal key
> and downstream's capability.
>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 147 ++++++++++++++++++++++
>  drivers/gpu/drm/bridge/analogix/anx7625.h |  36 ++++++
>  2 files changed, 183 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 8c514b46d361..b424a570effa 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -633,6 +633,150 @@ static int anx7625_dpi_config(struct anx7625_data *ctx)
>         return ret;
>  }
>
> +static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
> +                                u8 addrh, u8 addrm, u8 addrl,
> +                                u8 len, u8 *buf)
> +{
> +       struct device *dev = &ctx->client->dev;
> +       int ret;
> +       u8 cmd;
> +
> +       if (len > MAX_DPCD_BUFFER_SIZE) {
> +               DRM_DEV_ERROR(dev, "exceed aux buffer len.\n");
> +               return -E2BIG;
> +       }
> +
> +       cmd = ((len - 1) << 4) | 0x09;
> +
> +       /* Set command and length */
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               AP_AUX_COMMAND, cmd);
> +
> +       /* Set aux access address */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AUX_ADDR_7_0, addrl);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AUX_ADDR_15_8, addrm);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AUX_ADDR_19_16, addrh);
> +
> +       /* Enable aux access */
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> +                               AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
> +
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "cannot access aux related register.\n");
> +               return -EIO;
> +       }
> +
> +       usleep_range(2000, 2100);
> +
> +       ret = wait_aux_op_finish(ctx);
> +       if (ret) {
> +               DRM_DEV_ERROR(dev, "aux IO error: wait aux op finish.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> +                                    AP_AUX_BUFF_START, len, buf);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "read dpcd register failed\n");
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +static int anx7625_read_flash_status(struct anx7625_data *ctx)
> +{
> +       return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, R_RAM_CTRL);
> +}
> +
> +static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
> +{
> +       int ret, val;
> +       struct device *dev = &ctx->client->dev;
> +       u8 ident[32];
> +
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               FLASH_ADDR_HIGH, 0x91);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                FLASH_ADDR_LOW, 0xA0);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : set key flash address.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               FLASH_LEN_HIGH, (FLASH_BUF_LEN - 1) >> 8);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                FLASH_LEN_LOW, (FLASH_BUF_LEN - 1) & 0xFF);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : set key flash len.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               R_FLASH_RW_CTRL, FLASH_READ);
> +       ret |= readx_poll_timeout(anx7625_read_flash_status,
> +                                 ctx, val,
> +                                 ((val & FLASH_DONE) || (val < 0)),
> +                                 2000,
> +                                 2000 * 150);
> +       if (ret) {
> +               DRM_DEV_ERROR(dev, "flash read access fail!\n");
> +               return -EIO;
> +       }
> +
> +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> +                                    FLASH_BUF_BASE_ADDR,
> +                                    FLASH_BUF_LEN, ident);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "read flash data fail!\n");
> +               return -EIO;
> +       }
> +
> +       if (ident[29] == 0xFF && ident[30] == 0xFF && ident[31] == 0xFF)
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static int anx7625_hdcp_setting(struct anx7625_data *ctx)
> +{
> +       u8 bcap;
> +       int ret;
> +       struct device *dev = &ctx->client->dev;
> +
> +       ret = anx7625_hdcp_key_probe(ctx);
> +       if (ret) {
> +               DRM_DEV_DEBUG_DRIVER(dev, "disable HDCP by config\n");
> +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> +                                        0xee, 0x9f);
> +       }
> +
> +       anx7625_aux_dpcd_read(ctx, 0x06, 0x80, 0x28, 1, &bcap);
> +       if (!(bcap & 0x01)) {
> +               DRM_DEV_DEBUG_DRIVER(dev, "bcap(0x%x) not support HDCP 1.4.\n",
> +                                    bcap);
> +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> +                                        0xee, 0x9f);
> +       }
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
> +
> +       ret = anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
> +
> +       /* Try auth flag */
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
> +       /* Interrupt for DRM */
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
> +       if (ret < 0)
> +               DRM_DEV_ERROR(dev, "fail to enable HDCP\n");
> +
> +       return ret;
> +}
> +
>  static void anx7625_dp_start(struct anx7625_data *ctx)
>  {
>         int ret;
> @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
>                 return;
>         }
>
> +       /* HDCP config */
> +       anx7625_hdcp_setting(ctx);

You should really use the "Content Protection" property to
enable/disable HDCP instead of force-enabling it at all times.

Sean

> +
>         if (ctx->pdata.is_dpi)
>                 ret = anx7625_dpi_config(ctx);
>         else
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> index beee95da2155..c6f93e4df0ed 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> @@ -154,9 +154,45 @@
>
>  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
>
> +#define FLASH_SRAM_SEL          0x00
> +#define SRAM_ADDR_HIGH          0x01
> +#define SRAM_ADDR_LOW           0x02
> +#define SRAM_LEN_HIGH           0x03
> +#define SRAM_LEN_LOW            0x04
>  #define FLASH_LOAD_STA          0x05
>  #define FLASH_LOAD_STA_CHK     BIT(7)
>
> +#define R_RAM_CTRL              0x05
> +/* bit positions */
> +#define FLASH_DONE              BIT(7)
> +#define BOOT_LOAD_DONE          BIT(6)
> +#define CRC_OK                  BIT(5)
> +#define LOAD_DONE               BIT(4)
> +#define O_RW_DONE               BIT(3)
> +#define FUSE_BUSY               BIT(2)
> +#define DECRYPT_EN              BIT(1)
> +#define LOAD_START              BIT(0)
> +
> +#define FLASH_ADDR_HIGH         0x0F
> +#define FLASH_ADDR_LOW          0x10
> +#define FLASH_LEN_HIGH          0x31
> +#define FLASH_LEN_LOW           0x32
> +
> +#define R_FLASH_RW_CTRL         0x33
> +/* bit positions */
> +#define READ_DELAY_SELECT       BIT(7)
> +#define GENERAL_INSTRUCTION_EN  BIT(6)
> +#define FLASH_ERASE_EN          BIT(5)
> +#define RDID_READ_EN            BIT(4)
> +#define REMS_READ_EN            BIT(3)
> +#define WRITE_STATUS_EN         BIT(2)
> +#define FLASH_READ              BIT(1)
> +#define FLASH_WRITE             BIT(0)
> +
> +#define FLASH_BUF_BASE_ADDR     0x60
> +#define FLASH_BUF_LEN           0x20
> +#define FLASH_KEY_OFFSET        0x8000
> +
>  #define  XTAL_FRQ_SEL    0x3F
>  /* bit field positions */
>  #define  XTAL_FRQ_SEL_POS    5
> --
> 2.25.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-03-25 18:19     ` Sean Paul
  0 siblings, 0 replies; 52+ messages in thread
From: Sean Paul @ 2021-03-25 18:19 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Zhen Li, dri-devel, Neil Armstrong,
	LKML, Robert Foss, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Sheng Pan, Hsin-Yi Wang,
	Marek Szyprowski, Bernie Liang, Dan Carpenter, Laurent Pinchart

On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
>
> Add HDCP feature, enable HDCP function through chip internal key
> and downstream's capability.
>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 147 ++++++++++++++++++++++
>  drivers/gpu/drm/bridge/analogix/anx7625.h |  36 ++++++
>  2 files changed, 183 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 8c514b46d361..b424a570effa 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -633,6 +633,150 @@ static int anx7625_dpi_config(struct anx7625_data *ctx)
>         return ret;
>  }
>
> +static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
> +                                u8 addrh, u8 addrm, u8 addrl,
> +                                u8 len, u8 *buf)
> +{
> +       struct device *dev = &ctx->client->dev;
> +       int ret;
> +       u8 cmd;
> +
> +       if (len > MAX_DPCD_BUFFER_SIZE) {
> +               DRM_DEV_ERROR(dev, "exceed aux buffer len.\n");
> +               return -E2BIG;
> +       }
> +
> +       cmd = ((len - 1) << 4) | 0x09;
> +
> +       /* Set command and length */
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               AP_AUX_COMMAND, cmd);
> +
> +       /* Set aux access address */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AUX_ADDR_7_0, addrl);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AUX_ADDR_15_8, addrm);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AUX_ADDR_19_16, addrh);
> +
> +       /* Enable aux access */
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> +                               AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
> +
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "cannot access aux related register.\n");
> +               return -EIO;
> +       }
> +
> +       usleep_range(2000, 2100);
> +
> +       ret = wait_aux_op_finish(ctx);
> +       if (ret) {
> +               DRM_DEV_ERROR(dev, "aux IO error: wait aux op finish.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> +                                    AP_AUX_BUFF_START, len, buf);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "read dpcd register failed\n");
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +static int anx7625_read_flash_status(struct anx7625_data *ctx)
> +{
> +       return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, R_RAM_CTRL);
> +}
> +
> +static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
> +{
> +       int ret, val;
> +       struct device *dev = &ctx->client->dev;
> +       u8 ident[32];
> +
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               FLASH_ADDR_HIGH, 0x91);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                FLASH_ADDR_LOW, 0xA0);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : set key flash address.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               FLASH_LEN_HIGH, (FLASH_BUF_LEN - 1) >> 8);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                FLASH_LEN_LOW, (FLASH_BUF_LEN - 1) & 0xFF);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : set key flash len.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               R_FLASH_RW_CTRL, FLASH_READ);
> +       ret |= readx_poll_timeout(anx7625_read_flash_status,
> +                                 ctx, val,
> +                                 ((val & FLASH_DONE) || (val < 0)),
> +                                 2000,
> +                                 2000 * 150);
> +       if (ret) {
> +               DRM_DEV_ERROR(dev, "flash read access fail!\n");
> +               return -EIO;
> +       }
> +
> +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> +                                    FLASH_BUF_BASE_ADDR,
> +                                    FLASH_BUF_LEN, ident);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "read flash data fail!\n");
> +               return -EIO;
> +       }
> +
> +       if (ident[29] == 0xFF && ident[30] == 0xFF && ident[31] == 0xFF)
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static int anx7625_hdcp_setting(struct anx7625_data *ctx)
> +{
> +       u8 bcap;
> +       int ret;
> +       struct device *dev = &ctx->client->dev;
> +
> +       ret = anx7625_hdcp_key_probe(ctx);
> +       if (ret) {
> +               DRM_DEV_DEBUG_DRIVER(dev, "disable HDCP by config\n");
> +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> +                                        0xee, 0x9f);
> +       }
> +
> +       anx7625_aux_dpcd_read(ctx, 0x06, 0x80, 0x28, 1, &bcap);
> +       if (!(bcap & 0x01)) {
> +               DRM_DEV_DEBUG_DRIVER(dev, "bcap(0x%x) not support HDCP 1.4.\n",
> +                                    bcap);
> +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> +                                        0xee, 0x9f);
> +       }
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
> +
> +       ret = anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
> +
> +       /* Try auth flag */
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
> +       /* Interrupt for DRM */
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
> +       if (ret < 0)
> +               DRM_DEV_ERROR(dev, "fail to enable HDCP\n");
> +
> +       return ret;
> +}
> +
>  static void anx7625_dp_start(struct anx7625_data *ctx)
>  {
>         int ret;
> @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
>                 return;
>         }
>
> +       /* HDCP config */
> +       anx7625_hdcp_setting(ctx);

You should really use the "Content Protection" property to
enable/disable HDCP instead of force-enabling it at all times.

Sean

> +
>         if (ctx->pdata.is_dpi)
>                 ret = anx7625_dpi_config(ctx);
>         else
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> index beee95da2155..c6f93e4df0ed 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> @@ -154,9 +154,45 @@
>
>  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
>
> +#define FLASH_SRAM_SEL          0x00
> +#define SRAM_ADDR_HIGH          0x01
> +#define SRAM_ADDR_LOW           0x02
> +#define SRAM_LEN_HIGH           0x03
> +#define SRAM_LEN_LOW            0x04
>  #define FLASH_LOAD_STA          0x05
>  #define FLASH_LOAD_STA_CHK     BIT(7)
>
> +#define R_RAM_CTRL              0x05
> +/* bit positions */
> +#define FLASH_DONE              BIT(7)
> +#define BOOT_LOAD_DONE          BIT(6)
> +#define CRC_OK                  BIT(5)
> +#define LOAD_DONE               BIT(4)
> +#define O_RW_DONE               BIT(3)
> +#define FUSE_BUSY               BIT(2)
> +#define DECRYPT_EN              BIT(1)
> +#define LOAD_START              BIT(0)
> +
> +#define FLASH_ADDR_HIGH         0x0F
> +#define FLASH_ADDR_LOW          0x10
> +#define FLASH_LEN_HIGH          0x31
> +#define FLASH_LEN_LOW           0x32
> +
> +#define R_FLASH_RW_CTRL         0x33
> +/* bit positions */
> +#define READ_DELAY_SELECT       BIT(7)
> +#define GENERAL_INSTRUCTION_EN  BIT(6)
> +#define FLASH_ERASE_EN          BIT(5)
> +#define RDID_READ_EN            BIT(4)
> +#define REMS_READ_EN            BIT(3)
> +#define WRITE_STATUS_EN         BIT(2)
> +#define FLASH_READ              BIT(1)
> +#define FLASH_WRITE             BIT(0)
> +
> +#define FLASH_BUF_BASE_ADDR     0x60
> +#define FLASH_BUF_LEN           0x20
> +#define FLASH_KEY_OFFSET        0x8000
> +
>  #define  XTAL_FRQ_SEL    0x3F
>  /* bit field positions */
>  #define  XTAL_FRQ_SEL_POS    5
> --
> 2.25.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-03-25 18:19     ` Sean Paul
  0 siblings, 0 replies; 52+ messages in thread
From: Sean Paul @ 2021-03-25 18:19 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Zhen Li, dri-devel, Neil Armstrong,
	LKML, Robert Foss, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Sheng Pan, Hsin-Yi Wang,
	Marek Szyprowski, Bernie Liang, Dan Carpenter, Laurent Pinchart

On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
>
> Add HDCP feature, enable HDCP function through chip internal key
> and downstream's capability.
>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 147 ++++++++++++++++++++++
>  drivers/gpu/drm/bridge/analogix/anx7625.h |  36 ++++++
>  2 files changed, 183 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 8c514b46d361..b424a570effa 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -633,6 +633,150 @@ static int anx7625_dpi_config(struct anx7625_data *ctx)
>         return ret;
>  }
>
> +static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
> +                                u8 addrh, u8 addrm, u8 addrl,
> +                                u8 len, u8 *buf)
> +{
> +       struct device *dev = &ctx->client->dev;
> +       int ret;
> +       u8 cmd;
> +
> +       if (len > MAX_DPCD_BUFFER_SIZE) {
> +               DRM_DEV_ERROR(dev, "exceed aux buffer len.\n");
> +               return -E2BIG;
> +       }
> +
> +       cmd = ((len - 1) << 4) | 0x09;
> +
> +       /* Set command and length */
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               AP_AUX_COMMAND, cmd);
> +
> +       /* Set aux access address */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AUX_ADDR_7_0, addrl);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AUX_ADDR_15_8, addrm);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AUX_ADDR_19_16, addrh);
> +
> +       /* Enable aux access */
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> +                               AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
> +
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "cannot access aux related register.\n");
> +               return -EIO;
> +       }
> +
> +       usleep_range(2000, 2100);
> +
> +       ret = wait_aux_op_finish(ctx);
> +       if (ret) {
> +               DRM_DEV_ERROR(dev, "aux IO error: wait aux op finish.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> +                                    AP_AUX_BUFF_START, len, buf);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "read dpcd register failed\n");
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +static int anx7625_read_flash_status(struct anx7625_data *ctx)
> +{
> +       return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, R_RAM_CTRL);
> +}
> +
> +static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
> +{
> +       int ret, val;
> +       struct device *dev = &ctx->client->dev;
> +       u8 ident[32];
> +
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               FLASH_ADDR_HIGH, 0x91);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                FLASH_ADDR_LOW, 0xA0);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : set key flash address.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               FLASH_LEN_HIGH, (FLASH_BUF_LEN - 1) >> 8);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                FLASH_LEN_LOW, (FLASH_BUF_LEN - 1) & 0xFF);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : set key flash len.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               R_FLASH_RW_CTRL, FLASH_READ);
> +       ret |= readx_poll_timeout(anx7625_read_flash_status,
> +                                 ctx, val,
> +                                 ((val & FLASH_DONE) || (val < 0)),
> +                                 2000,
> +                                 2000 * 150);
> +       if (ret) {
> +               DRM_DEV_ERROR(dev, "flash read access fail!\n");
> +               return -EIO;
> +       }
> +
> +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> +                                    FLASH_BUF_BASE_ADDR,
> +                                    FLASH_BUF_LEN, ident);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "read flash data fail!\n");
> +               return -EIO;
> +       }
> +
> +       if (ident[29] == 0xFF && ident[30] == 0xFF && ident[31] == 0xFF)
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static int anx7625_hdcp_setting(struct anx7625_data *ctx)
> +{
> +       u8 bcap;
> +       int ret;
> +       struct device *dev = &ctx->client->dev;
> +
> +       ret = anx7625_hdcp_key_probe(ctx);
> +       if (ret) {
> +               DRM_DEV_DEBUG_DRIVER(dev, "disable HDCP by config\n");
> +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> +                                        0xee, 0x9f);
> +       }
> +
> +       anx7625_aux_dpcd_read(ctx, 0x06, 0x80, 0x28, 1, &bcap);
> +       if (!(bcap & 0x01)) {
> +               DRM_DEV_DEBUG_DRIVER(dev, "bcap(0x%x) not support HDCP 1.4.\n",
> +                                    bcap);
> +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> +                                        0xee, 0x9f);
> +       }
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
> +
> +       ret = anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
> +
> +       /* Try auth flag */
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
> +       /* Interrupt for DRM */
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
> +       if (ret < 0)
> +               DRM_DEV_ERROR(dev, "fail to enable HDCP\n");
> +
> +       return ret;
> +}
> +
>  static void anx7625_dp_start(struct anx7625_data *ctx)
>  {
>         int ret;
> @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
>                 return;
>         }
>
> +       /* HDCP config */
> +       anx7625_hdcp_setting(ctx);

You should really use the "Content Protection" property to
enable/disable HDCP instead of force-enabling it at all times.

Sean

> +
>         if (ctx->pdata.is_dpi)
>                 ret = anx7625_dpi_config(ctx);
>         else
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> index beee95da2155..c6f93e4df0ed 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> @@ -154,9 +154,45 @@
>
>  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
>
> +#define FLASH_SRAM_SEL          0x00
> +#define SRAM_ADDR_HIGH          0x01
> +#define SRAM_ADDR_LOW           0x02
> +#define SRAM_LEN_HIGH           0x03
> +#define SRAM_LEN_LOW            0x04
>  #define FLASH_LOAD_STA          0x05
>  #define FLASH_LOAD_STA_CHK     BIT(7)
>
> +#define R_RAM_CTRL              0x05
> +/* bit positions */
> +#define FLASH_DONE              BIT(7)
> +#define BOOT_LOAD_DONE          BIT(6)
> +#define CRC_OK                  BIT(5)
> +#define LOAD_DONE               BIT(4)
> +#define O_RW_DONE               BIT(3)
> +#define FUSE_BUSY               BIT(2)
> +#define DECRYPT_EN              BIT(1)
> +#define LOAD_START              BIT(0)
> +
> +#define FLASH_ADDR_HIGH         0x0F
> +#define FLASH_ADDR_LOW          0x10
> +#define FLASH_LEN_HIGH          0x31
> +#define FLASH_LEN_LOW           0x32
> +
> +#define R_FLASH_RW_CTRL         0x33
> +/* bit positions */
> +#define READ_DELAY_SELECT       BIT(7)
> +#define GENERAL_INSTRUCTION_EN  BIT(6)
> +#define FLASH_ERASE_EN          BIT(5)
> +#define RDID_READ_EN            BIT(4)
> +#define REMS_READ_EN            BIT(3)
> +#define WRITE_STATUS_EN         BIT(2)
> +#define FLASH_READ              BIT(1)
> +#define FLASH_WRITE             BIT(0)
> +
> +#define FLASH_BUF_BASE_ADDR     0x60
> +#define FLASH_BUF_LEN           0x20
> +#define FLASH_KEY_OFFSET        0x8000
> +
>  #define  XTAL_FRQ_SEL    0x3F
>  /* bit field positions */
>  #define  XTAL_FRQ_SEL_POS    5
> --
> 2.25.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
  2021-03-25 18:19     ` Sean Paul
  (?)
@ 2021-03-29 10:27       ` Xin Ji
  -1 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-29 10:27 UTC (permalink / raw)
  To: Sean Paul
  Cc: Foss, Nicolas Boichat, Andrzej Hajda, devel, Jernej Skrabec,
	Sheng Pan, Jonas Karlman, David Airlie, Bernie Liang,
	Neil Armstrong, Zhen Li, LKML, dri-devel, Vasily Khoruzhick,
	Boris Brezillon, Torsten Duwe, Laurent Pinchart, Hsin-Yi Wang,
	Sam Ravnborg, Dan Carpenter, Marek Szyprowski

On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> >
> > Add HDCP feature, enable HDCP function through chip internal key
> > and downstream's capability.
> >
> > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > ---
> >  drivers/gpu/drm/bridge/analogix/anx7625.c | 147 ++++++++++++++++++++++
> >  drivers/gpu/drm/bridge/analogix/anx7625.h |  36 ++++++
> >  2 files changed, 183 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > index 8c514b46d361..b424a570effa 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > @@ -633,6 +633,150 @@ static int anx7625_dpi_config(struct anx7625_data *ctx)
> >         return ret;
> >  }
> >
> > +static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
> > +                                u8 addrh, u8 addrm, u8 addrl,
> > +                                u8 len, u8 *buf)
> > +{
> > +       struct device *dev = &ctx->client->dev;
> > +       int ret;
> > +       u8 cmd;
> > +
> > +       if (len > MAX_DPCD_BUFFER_SIZE) {
> > +               DRM_DEV_ERROR(dev, "exceed aux buffer len.\n");
> > +               return -E2BIG;
> > +       }
> > +
> > +       cmd = ((len - 1) << 4) | 0x09;
> > +
> > +       /* Set command and length */
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               AP_AUX_COMMAND, cmd);
> > +
> > +       /* Set aux access address */
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                AP_AUX_ADDR_7_0, addrl);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                AP_AUX_ADDR_15_8, addrm);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                AP_AUX_ADDR_19_16, addrh);
> > +
> > +       /* Enable aux access */
> > +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > +                               AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
> > +
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "cannot access aux related register.\n");
> > +               return -EIO;
> > +       }
> > +
> > +       usleep_range(2000, 2100);
> > +
> > +       ret = wait_aux_op_finish(ctx);
> > +       if (ret) {
> > +               DRM_DEV_ERROR(dev, "aux IO error: wait aux op finish.\n");
> > +               return ret;
> > +       }
> > +
> > +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> > +                                    AP_AUX_BUFF_START, len, buf);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "read dpcd register failed\n");
> > +               return -EIO;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int anx7625_read_flash_status(struct anx7625_data *ctx)
> > +{
> > +       return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, R_RAM_CTRL);
> > +}
> > +
> > +static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
> > +{
> > +       int ret, val;
> > +       struct device *dev = &ctx->client->dev;
> > +       u8 ident[32];
> > +
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               FLASH_ADDR_HIGH, 0x91);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                FLASH_ADDR_LOW, 0xA0);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "IO error : set key flash address.\n");
> > +               return ret;
> > +       }
> > +
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               FLASH_LEN_HIGH, (FLASH_BUF_LEN - 1) >> 8);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                FLASH_LEN_LOW, (FLASH_BUF_LEN - 1) & 0xFF);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "IO error : set key flash len.\n");
> > +               return ret;
> > +       }
> > +
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               R_FLASH_RW_CTRL, FLASH_READ);
> > +       ret |= readx_poll_timeout(anx7625_read_flash_status,
> > +                                 ctx, val,
> > +                                 ((val & FLASH_DONE) || (val < 0)),
> > +                                 2000,
> > +                                 2000 * 150);
> > +       if (ret) {
> > +               DRM_DEV_ERROR(dev, "flash read access fail!\n");
> > +               return -EIO;
> > +       }
> > +
> > +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> > +                                    FLASH_BUF_BASE_ADDR,
> > +                                    FLASH_BUF_LEN, ident);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "read flash data fail!\n");
> > +               return -EIO;
> > +       }
> > +
> > +       if (ident[29] == 0xFF && ident[30] == 0xFF && ident[31] == 0xFF)
> > +               return -EINVAL;
> > +
> > +       return 0;
> > +}
> > +
> > +static int anx7625_hdcp_setting(struct anx7625_data *ctx)
> > +{
> > +       u8 bcap;
> > +       int ret;
> > +       struct device *dev = &ctx->client->dev;
> > +
> > +       ret = anx7625_hdcp_key_probe(ctx);
> > +       if (ret) {
> > +               DRM_DEV_DEBUG_DRIVER(dev, "disable HDCP by config\n");
> > +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> > +                                        0xee, 0x9f);
> > +       }
> > +
> > +       anx7625_aux_dpcd_read(ctx, 0x06, 0x80, 0x28, 1, &bcap);
> > +       if (!(bcap & 0x01)) {
> > +               DRM_DEV_DEBUG_DRIVER(dev, "bcap(0x%x) not support HDCP 1.4.\n",
> > +                                    bcap);
> > +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> > +                                        0xee, 0x9f);
> > +       }
> > +
> > +       DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
> > +
> > +       ret = anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
> > +
> > +       /* Try auth flag */
> > +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
> > +       /* Interrupt for DRM */
> > +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
> > +       if (ret < 0)
> > +               DRM_DEV_ERROR(dev, "fail to enable HDCP\n");
> > +
> > +       return ret;
> > +}
> > +
> >  static void anx7625_dp_start(struct anx7625_data *ctx)
> >  {
> >         int ret;
> > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> >                 return;
> >         }
> >
> > +       /* HDCP config */
> > +       anx7625_hdcp_setting(ctx);
> 
> You should really use the "Content Protection" property to
> enable/disable HDCP instead of force-enabling it at all times.
> 
> Sean
Hi Sean, it's hard to implement "Content Protection" property, we have
implemented HDCP in firmware, it is not compatible with it. We don't
have interface to get Downstream Cert.
Thanks,
Xin
> 
> > +
> >         if (ctx->pdata.is_dpi)
> >                 ret = anx7625_dpi_config(ctx);
> >         else
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > index beee95da2155..c6f93e4df0ed 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > @@ -154,9 +154,45 @@
> >
> >  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
> >
> > +#define FLASH_SRAM_SEL          0x00
> > +#define SRAM_ADDR_HIGH          0x01
> > +#define SRAM_ADDR_LOW           0x02
> > +#define SRAM_LEN_HIGH           0x03
> > +#define SRAM_LEN_LOW            0x04
> >  #define FLASH_LOAD_STA          0x05
> >  #define FLASH_LOAD_STA_CHK     BIT(7)
> >
> > +#define R_RAM_CTRL              0x05
> > +/* bit positions */
> > +#define FLASH_DONE              BIT(7)
> > +#define BOOT_LOAD_DONE          BIT(6)
> > +#define CRC_OK                  BIT(5)
> > +#define LOAD_DONE               BIT(4)
> > +#define O_RW_DONE               BIT(3)
> > +#define FUSE_BUSY               BIT(2)
> > +#define DECRYPT_EN              BIT(1)
> > +#define LOAD_START              BIT(0)
> > +
> > +#define FLASH_ADDR_HIGH         0x0F
> > +#define FLASH_ADDR_LOW          0x10
> > +#define FLASH_LEN_HIGH          0x31
> > +#define FLASH_LEN_LOW           0x32
> > +
> > +#define R_FLASH_RW_CTRL         0x33
> > +/* bit positions */
> > +#define READ_DELAY_SELECT       BIT(7)
> > +#define GENERAL_INSTRUCTION_EN  BIT(6)
> > +#define FLASH_ERASE_EN          BIT(5)
> > +#define RDID_READ_EN            BIT(4)
> > +#define REMS_READ_EN            BIT(3)
> > +#define WRITE_STATUS_EN         BIT(2)
> > +#define FLASH_READ              BIT(1)
> > +#define FLASH_WRITE             BIT(0)
> > +
> > +#define FLASH_BUF_BASE_ADDR     0x60
> > +#define FLASH_BUF_LEN           0x20
> > +#define FLASH_KEY_OFFSET        0x8000
> > +
> >  #define  XTAL_FRQ_SEL    0x3F
> >  /* bit field positions */
> >  #define  XTAL_FRQ_SEL_POS    5
> > --
> > 2.25.1
> >
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-03-29 10:27       ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-29 10:27 UTC (permalink / raw)
  To: Sean Paul
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Zhen Li, dri-devel, Neil Armstrong,
	LKML, Foss, Vasily Khoruzhick, Andrzej Hajda, Boris Brezillon,
	Torsten Duwe, Sheng Pan, Hsin-Yi Wang, Marek Szyprowski,
	Bernie Liang, Dan Carpenter, Laurent Pinchart

On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> >
> > Add HDCP feature, enable HDCP function through chip internal key
> > and downstream's capability.
> >
> > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > ---
> >  drivers/gpu/drm/bridge/analogix/anx7625.c | 147 ++++++++++++++++++++++
> >  drivers/gpu/drm/bridge/analogix/anx7625.h |  36 ++++++
> >  2 files changed, 183 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > index 8c514b46d361..b424a570effa 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > @@ -633,6 +633,150 @@ static int anx7625_dpi_config(struct anx7625_data *ctx)
> >         return ret;
> >  }
> >
> > +static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
> > +                                u8 addrh, u8 addrm, u8 addrl,
> > +                                u8 len, u8 *buf)
> > +{
> > +       struct device *dev = &ctx->client->dev;
> > +       int ret;
> > +       u8 cmd;
> > +
> > +       if (len > MAX_DPCD_BUFFER_SIZE) {
> > +               DRM_DEV_ERROR(dev, "exceed aux buffer len.\n");
> > +               return -E2BIG;
> > +       }
> > +
> > +       cmd = ((len - 1) << 4) | 0x09;
> > +
> > +       /* Set command and length */
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               AP_AUX_COMMAND, cmd);
> > +
> > +       /* Set aux access address */
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                AP_AUX_ADDR_7_0, addrl);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                AP_AUX_ADDR_15_8, addrm);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                AP_AUX_ADDR_19_16, addrh);
> > +
> > +       /* Enable aux access */
> > +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > +                               AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
> > +
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "cannot access aux related register.\n");
> > +               return -EIO;
> > +       }
> > +
> > +       usleep_range(2000, 2100);
> > +
> > +       ret = wait_aux_op_finish(ctx);
> > +       if (ret) {
> > +               DRM_DEV_ERROR(dev, "aux IO error: wait aux op finish.\n");
> > +               return ret;
> > +       }
> > +
> > +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> > +                                    AP_AUX_BUFF_START, len, buf);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "read dpcd register failed\n");
> > +               return -EIO;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int anx7625_read_flash_status(struct anx7625_data *ctx)
> > +{
> > +       return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, R_RAM_CTRL);
> > +}
> > +
> > +static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
> > +{
> > +       int ret, val;
> > +       struct device *dev = &ctx->client->dev;
> > +       u8 ident[32];
> > +
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               FLASH_ADDR_HIGH, 0x91);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                FLASH_ADDR_LOW, 0xA0);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "IO error : set key flash address.\n");
> > +               return ret;
> > +       }
> > +
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               FLASH_LEN_HIGH, (FLASH_BUF_LEN - 1) >> 8);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                FLASH_LEN_LOW, (FLASH_BUF_LEN - 1) & 0xFF);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "IO error : set key flash len.\n");
> > +               return ret;
> > +       }
> > +
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               R_FLASH_RW_CTRL, FLASH_READ);
> > +       ret |= readx_poll_timeout(anx7625_read_flash_status,
> > +                                 ctx, val,
> > +                                 ((val & FLASH_DONE) || (val < 0)),
> > +                                 2000,
> > +                                 2000 * 150);
> > +       if (ret) {
> > +               DRM_DEV_ERROR(dev, "flash read access fail!\n");
> > +               return -EIO;
> > +       }
> > +
> > +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> > +                                    FLASH_BUF_BASE_ADDR,
> > +                                    FLASH_BUF_LEN, ident);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "read flash data fail!\n");
> > +               return -EIO;
> > +       }
> > +
> > +       if (ident[29] == 0xFF && ident[30] == 0xFF && ident[31] == 0xFF)
> > +               return -EINVAL;
> > +
> > +       return 0;
> > +}
> > +
> > +static int anx7625_hdcp_setting(struct anx7625_data *ctx)
> > +{
> > +       u8 bcap;
> > +       int ret;
> > +       struct device *dev = &ctx->client->dev;
> > +
> > +       ret = anx7625_hdcp_key_probe(ctx);
> > +       if (ret) {
> > +               DRM_DEV_DEBUG_DRIVER(dev, "disable HDCP by config\n");
> > +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> > +                                        0xee, 0x9f);
> > +       }
> > +
> > +       anx7625_aux_dpcd_read(ctx, 0x06, 0x80, 0x28, 1, &bcap);
> > +       if (!(bcap & 0x01)) {
> > +               DRM_DEV_DEBUG_DRIVER(dev, "bcap(0x%x) not support HDCP 1.4.\n",
> > +                                    bcap);
> > +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> > +                                        0xee, 0x9f);
> > +       }
> > +
> > +       DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
> > +
> > +       ret = anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
> > +
> > +       /* Try auth flag */
> > +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
> > +       /* Interrupt for DRM */
> > +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
> > +       if (ret < 0)
> > +               DRM_DEV_ERROR(dev, "fail to enable HDCP\n");
> > +
> > +       return ret;
> > +}
> > +
> >  static void anx7625_dp_start(struct anx7625_data *ctx)
> >  {
> >         int ret;
> > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> >                 return;
> >         }
> >
> > +       /* HDCP config */
> > +       anx7625_hdcp_setting(ctx);
> 
> You should really use the "Content Protection" property to
> enable/disable HDCP instead of force-enabling it at all times.
> 
> Sean
Hi Sean, it's hard to implement "Content Protection" property, we have
implemented HDCP in firmware, it is not compatible with it. We don't
have interface to get Downstream Cert.
Thanks,
Xin
> 
> > +
> >         if (ctx->pdata.is_dpi)
> >                 ret = anx7625_dpi_config(ctx);
> >         else
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > index beee95da2155..c6f93e4df0ed 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > @@ -154,9 +154,45 @@
> >
> >  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
> >
> > +#define FLASH_SRAM_SEL          0x00
> > +#define SRAM_ADDR_HIGH          0x01
> > +#define SRAM_ADDR_LOW           0x02
> > +#define SRAM_LEN_HIGH           0x03
> > +#define SRAM_LEN_LOW            0x04
> >  #define FLASH_LOAD_STA          0x05
> >  #define FLASH_LOAD_STA_CHK     BIT(7)
> >
> > +#define R_RAM_CTRL              0x05
> > +/* bit positions */
> > +#define FLASH_DONE              BIT(7)
> > +#define BOOT_LOAD_DONE          BIT(6)
> > +#define CRC_OK                  BIT(5)
> > +#define LOAD_DONE               BIT(4)
> > +#define O_RW_DONE               BIT(3)
> > +#define FUSE_BUSY               BIT(2)
> > +#define DECRYPT_EN              BIT(1)
> > +#define LOAD_START              BIT(0)
> > +
> > +#define FLASH_ADDR_HIGH         0x0F
> > +#define FLASH_ADDR_LOW          0x10
> > +#define FLASH_LEN_HIGH          0x31
> > +#define FLASH_LEN_LOW           0x32
> > +
> > +#define R_FLASH_RW_CTRL         0x33
> > +/* bit positions */
> > +#define READ_DELAY_SELECT       BIT(7)
> > +#define GENERAL_INSTRUCTION_EN  BIT(6)
> > +#define FLASH_ERASE_EN          BIT(5)
> > +#define RDID_READ_EN            BIT(4)
> > +#define REMS_READ_EN            BIT(3)
> > +#define WRITE_STATUS_EN         BIT(2)
> > +#define FLASH_READ              BIT(1)
> > +#define FLASH_WRITE             BIT(0)
> > +
> > +#define FLASH_BUF_BASE_ADDR     0x60
> > +#define FLASH_BUF_LEN           0x20
> > +#define FLASH_KEY_OFFSET        0x8000
> > +
> >  #define  XTAL_FRQ_SEL    0x3F
> >  /* bit field positions */
> >  #define  XTAL_FRQ_SEL_POS    5
> > --
> > 2.25.1
> >
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-03-29 10:27       ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-03-29 10:27 UTC (permalink / raw)
  To: Sean Paul
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Zhen Li, dri-devel, Neil Armstrong,
	LKML, Foss, Vasily Khoruzhick, Andrzej Hajda, Boris Brezillon,
	Torsten Duwe, Sheng Pan, Hsin-Yi Wang, Marek Szyprowski,
	Bernie Liang, Dan Carpenter, Laurent Pinchart

On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> >
> > Add HDCP feature, enable HDCP function through chip internal key
> > and downstream's capability.
> >
> > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > ---
> >  drivers/gpu/drm/bridge/analogix/anx7625.c | 147 ++++++++++++++++++++++
> >  drivers/gpu/drm/bridge/analogix/anx7625.h |  36 ++++++
> >  2 files changed, 183 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > index 8c514b46d361..b424a570effa 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > @@ -633,6 +633,150 @@ static int anx7625_dpi_config(struct anx7625_data *ctx)
> >         return ret;
> >  }
> >
> > +static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
> > +                                u8 addrh, u8 addrm, u8 addrl,
> > +                                u8 len, u8 *buf)
> > +{
> > +       struct device *dev = &ctx->client->dev;
> > +       int ret;
> > +       u8 cmd;
> > +
> > +       if (len > MAX_DPCD_BUFFER_SIZE) {
> > +               DRM_DEV_ERROR(dev, "exceed aux buffer len.\n");
> > +               return -E2BIG;
> > +       }
> > +
> > +       cmd = ((len - 1) << 4) | 0x09;
> > +
> > +       /* Set command and length */
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               AP_AUX_COMMAND, cmd);
> > +
> > +       /* Set aux access address */
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                AP_AUX_ADDR_7_0, addrl);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                AP_AUX_ADDR_15_8, addrm);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                AP_AUX_ADDR_19_16, addrh);
> > +
> > +       /* Enable aux access */
> > +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > +                               AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
> > +
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "cannot access aux related register.\n");
> > +               return -EIO;
> > +       }
> > +
> > +       usleep_range(2000, 2100);
> > +
> > +       ret = wait_aux_op_finish(ctx);
> > +       if (ret) {
> > +               DRM_DEV_ERROR(dev, "aux IO error: wait aux op finish.\n");
> > +               return ret;
> > +       }
> > +
> > +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> > +                                    AP_AUX_BUFF_START, len, buf);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "read dpcd register failed\n");
> > +               return -EIO;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int anx7625_read_flash_status(struct anx7625_data *ctx)
> > +{
> > +       return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, R_RAM_CTRL);
> > +}
> > +
> > +static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
> > +{
> > +       int ret, val;
> > +       struct device *dev = &ctx->client->dev;
> > +       u8 ident[32];
> > +
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               FLASH_ADDR_HIGH, 0x91);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                FLASH_ADDR_LOW, 0xA0);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "IO error : set key flash address.\n");
> > +               return ret;
> > +       }
> > +
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               FLASH_LEN_HIGH, (FLASH_BUF_LEN - 1) >> 8);
> > +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                                FLASH_LEN_LOW, (FLASH_BUF_LEN - 1) & 0xFF);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "IO error : set key flash len.\n");
> > +               return ret;
> > +       }
> > +
> > +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +                               R_FLASH_RW_CTRL, FLASH_READ);
> > +       ret |= readx_poll_timeout(anx7625_read_flash_status,
> > +                                 ctx, val,
> > +                                 ((val & FLASH_DONE) || (val < 0)),
> > +                                 2000,
> > +                                 2000 * 150);
> > +       if (ret) {
> > +               DRM_DEV_ERROR(dev, "flash read access fail!\n");
> > +               return -EIO;
> > +       }
> > +
> > +       ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> > +                                    FLASH_BUF_BASE_ADDR,
> > +                                    FLASH_BUF_LEN, ident);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "read flash data fail!\n");
> > +               return -EIO;
> > +       }
> > +
> > +       if (ident[29] == 0xFF && ident[30] == 0xFF && ident[31] == 0xFF)
> > +               return -EINVAL;
> > +
> > +       return 0;
> > +}
> > +
> > +static int anx7625_hdcp_setting(struct anx7625_data *ctx)
> > +{
> > +       u8 bcap;
> > +       int ret;
> > +       struct device *dev = &ctx->client->dev;
> > +
> > +       ret = anx7625_hdcp_key_probe(ctx);
> > +       if (ret) {
> > +               DRM_DEV_DEBUG_DRIVER(dev, "disable HDCP by config\n");
> > +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> > +                                        0xee, 0x9f);
> > +       }
> > +
> > +       anx7625_aux_dpcd_read(ctx, 0x06, 0x80, 0x28, 1, &bcap);
> > +       if (!(bcap & 0x01)) {
> > +               DRM_DEV_DEBUG_DRIVER(dev, "bcap(0x%x) not support HDCP 1.4.\n",
> > +                                    bcap);
> > +               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
> > +                                        0xee, 0x9f);
> > +       }
> > +
> > +       DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
> > +
> > +       ret = anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
> > +
> > +       /* Try auth flag */
> > +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
> > +       /* Interrupt for DRM */
> > +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
> > +       if (ret < 0)
> > +               DRM_DEV_ERROR(dev, "fail to enable HDCP\n");
> > +
> > +       return ret;
> > +}
> > +
> >  static void anx7625_dp_start(struct anx7625_data *ctx)
> >  {
> >         int ret;
> > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> >                 return;
> >         }
> >
> > +       /* HDCP config */
> > +       anx7625_hdcp_setting(ctx);
> 
> You should really use the "Content Protection" property to
> enable/disable HDCP instead of force-enabling it at all times.
> 
> Sean
Hi Sean, it's hard to implement "Content Protection" property, we have
implemented HDCP in firmware, it is not compatible with it. We don't
have interface to get Downstream Cert.
Thanks,
Xin
> 
> > +
> >         if (ctx->pdata.is_dpi)
> >                 ret = anx7625_dpi_config(ctx);
> >         else
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > index beee95da2155..c6f93e4df0ed 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > @@ -154,9 +154,45 @@
> >
> >  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
> >
> > +#define FLASH_SRAM_SEL          0x00
> > +#define SRAM_ADDR_HIGH          0x01
> > +#define SRAM_ADDR_LOW           0x02
> > +#define SRAM_LEN_HIGH           0x03
> > +#define SRAM_LEN_LOW            0x04
> >  #define FLASH_LOAD_STA          0x05
> >  #define FLASH_LOAD_STA_CHK     BIT(7)
> >
> > +#define R_RAM_CTRL              0x05
> > +/* bit positions */
> > +#define FLASH_DONE              BIT(7)
> > +#define BOOT_LOAD_DONE          BIT(6)
> > +#define CRC_OK                  BIT(5)
> > +#define LOAD_DONE               BIT(4)
> > +#define O_RW_DONE               BIT(3)
> > +#define FUSE_BUSY               BIT(2)
> > +#define DECRYPT_EN              BIT(1)
> > +#define LOAD_START              BIT(0)
> > +
> > +#define FLASH_ADDR_HIGH         0x0F
> > +#define FLASH_ADDR_LOW          0x10
> > +#define FLASH_LEN_HIGH          0x31
> > +#define FLASH_LEN_LOW           0x32
> > +
> > +#define R_FLASH_RW_CTRL         0x33
> > +/* bit positions */
> > +#define READ_DELAY_SELECT       BIT(7)
> > +#define GENERAL_INSTRUCTION_EN  BIT(6)
> > +#define FLASH_ERASE_EN          BIT(5)
> > +#define RDID_READ_EN            BIT(4)
> > +#define REMS_READ_EN            BIT(3)
> > +#define WRITE_STATUS_EN         BIT(2)
> > +#define FLASH_READ              BIT(1)
> > +#define FLASH_WRITE             BIT(0)
> > +
> > +#define FLASH_BUF_BASE_ADDR     0x60
> > +#define FLASH_BUF_LEN           0x20
> > +#define FLASH_KEY_OFFSET        0x8000
> > +
> >  #define  XTAL_FRQ_SEL    0x3F
> >  /* bit field positions */
> >  #define  XTAL_FRQ_SEL_POS    5
> > --
> > 2.25.1
> >
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
  2021-03-29 10:27       ` Xin Ji
  (?)
@ 2021-03-29 18:02         ` Sean Paul
  -1 siblings, 0 replies; 52+ messages in thread
From: Sean Paul @ 2021-03-29 18:02 UTC (permalink / raw)
  To: Xin Ji
  Cc: Foss, Nicolas Boichat, Andrzej Hajda, devel, Jernej Skrabec,
	Sheng Pan, Jonas Karlman, David Airlie, Bernie Liang,
	Neil Armstrong, Zhen Li, LKML, dri-devel, Vasily Khoruzhick,
	Boris Brezillon, Torsten Duwe, Laurent Pinchart, Hsin-Yi Wang,
	Sam Ravnborg, Dan Carpenter, Marek Szyprowski

On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
>
> On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > >
> > > Add HDCP feature, enable HDCP function through chip internal key
> > > and downstream's capability.
> > >
> > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > ---

/snip

> > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > >  {
> > >         int ret;
> > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > >                 return;
> > >         }
> > >
> > > +       /* HDCP config */
> > > +       anx7625_hdcp_setting(ctx);
> >
> > You should really use the "Content Protection" property to
> > enable/disable HDCP instead of force-enabling it at all times.
> >
> > Sean
> Hi Sean, it's hard to implement "Content Protection" property, we have
> implemented HDCP in firmware, it is not compatible with it. We don't
> have interface to get Downstream Cert.
> Thanks,
> Xin

Hi Xin,
I'm sorry, I don't understand what you mean when you say you don't
have an interface to get Downstream Cert.

The Content Protection property is just a means through which
userspace can turn on and turn off HDCP when it needs. As far as I can
tell, your patch turns on HDCP when the display is enabled and leaves
it on until it is disabled. This is undesirable since it forces HDCP
on the user.

Is it impossible to enable/disable HDCP outside of display
enable/disable on your hardware?

Thanks,

Sean

> >
> > > +
> > >         if (ctx->pdata.is_dpi)
> > >                 ret = anx7625_dpi_config(ctx);
> > >         else

/snip

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-03-29 18:02         ` Sean Paul
  0 siblings, 0 replies; 52+ messages in thread
From: Sean Paul @ 2021-03-29 18:02 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Zhen Li, dri-devel, Neil Armstrong,
	LKML, Foss, Vasily Khoruzhick, Andrzej Hajda, Boris Brezillon,
	Torsten Duwe, Sheng Pan, Hsin-Yi Wang, Marek Szyprowski,
	Bernie Liang, Dan Carpenter, Laurent Pinchart

On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
>
> On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > >
> > > Add HDCP feature, enable HDCP function through chip internal key
> > > and downstream's capability.
> > >
> > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > ---

/snip

> > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > >  {
> > >         int ret;
> > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > >                 return;
> > >         }
> > >
> > > +       /* HDCP config */
> > > +       anx7625_hdcp_setting(ctx);
> >
> > You should really use the "Content Protection" property to
> > enable/disable HDCP instead of force-enabling it at all times.
> >
> > Sean
> Hi Sean, it's hard to implement "Content Protection" property, we have
> implemented HDCP in firmware, it is not compatible with it. We don't
> have interface to get Downstream Cert.
> Thanks,
> Xin

Hi Xin,
I'm sorry, I don't understand what you mean when you say you don't
have an interface to get Downstream Cert.

The Content Protection property is just a means through which
userspace can turn on and turn off HDCP when it needs. As far as I can
tell, your patch turns on HDCP when the display is enabled and leaves
it on until it is disabled. This is undesirable since it forces HDCP
on the user.

Is it impossible to enable/disable HDCP outside of display
enable/disable on your hardware?

Thanks,

Sean

> >
> > > +
> > >         if (ctx->pdata.is_dpi)
> > >                 ret = anx7625_dpi_config(ctx);
> > >         else

/snip
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-03-29 18:02         ` Sean Paul
  0 siblings, 0 replies; 52+ messages in thread
From: Sean Paul @ 2021-03-29 18:02 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Zhen Li, dri-devel, Neil Armstrong,
	LKML, Foss, Vasily Khoruzhick, Andrzej Hajda, Boris Brezillon,
	Torsten Duwe, Sheng Pan, Hsin-Yi Wang, Marek Szyprowski,
	Bernie Liang, Dan Carpenter, Laurent Pinchart

On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
>
> On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > >
> > > Add HDCP feature, enable HDCP function through chip internal key
> > > and downstream's capability.
> > >
> > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > ---

/snip

> > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > >  {
> > >         int ret;
> > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > >                 return;
> > >         }
> > >
> > > +       /* HDCP config */
> > > +       anx7625_hdcp_setting(ctx);
> >
> > You should really use the "Content Protection" property to
> > enable/disable HDCP instead of force-enabling it at all times.
> >
> > Sean
> Hi Sean, it's hard to implement "Content Protection" property, we have
> implemented HDCP in firmware, it is not compatible with it. We don't
> have interface to get Downstream Cert.
> Thanks,
> Xin

Hi Xin,
I'm sorry, I don't understand what you mean when you say you don't
have an interface to get Downstream Cert.

The Content Protection property is just a means through which
userspace can turn on and turn off HDCP when it needs. As far as I can
tell, your patch turns on HDCP when the display is enabled and leaves
it on until it is disabled. This is undesirable since it forces HDCP
on the user.

Is it impossible to enable/disable HDCP outside of display
enable/disable on your hardware?

Thanks,

Sean

> >
> > > +
> > >         if (ctx->pdata.is_dpi)
> > >                 ret = anx7625_dpi_config(ctx);
> > >         else

/snip
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 1/5] dt-bindings:drm/bridge:anx7625:add vendor define flags
  2021-03-24  7:51       ` Xin Ji
@ 2021-04-01 12:33         ` Robert Foss
  -1 siblings, 0 replies; 52+ messages in thread
From: Robert Foss @ 2021-04-01 12:33 UTC (permalink / raw)
  To: Xin Ji
  Cc: Laurent Pinchart, Rob Herring, David Airlie, Nicolas Boichat,
	Hsin-Yi Wang, Daniel Vetter, Sam Ravnborg, Laurent Pinchart,
	Maxime Ripard, Mark Brown, Ricardo Cañuelo, dri-devel,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Bernie Liang, Sheng Pan, Zhen Li, linux-kernel

Hey Xin,

This series no longer applies to drm-misc/drm-misc-next, please rebase it.

On Wed, 24 Mar 2021 at 08:52, Xin Ji <xji@analogixsemi.com> wrote:
>
> On Sun, Mar 21, 2021 at 02:00:38PM +0200, Laurent Pinchart wrote:
> > Hi Xin,
> >
> > Thank you for the patch.
> >
> > On Fri, Mar 19, 2021 at 02:32:39PM +0800, Xin Ji wrote:
> > > Add 'bus-type' and 'data-lanes' define for port0. Define DP tx lane0,
> > > lane1 swing register array define, and audio enable flag.
> > >
> > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > ---
> > >  .../display/bridge/analogix,anx7625.yaml      | 58 ++++++++++++++++++-
> > >  1 file changed, 57 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > index c789784efe30..3f54d5876982 100644
> > > --- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > @@ -34,6 +34,26 @@ properties:
> > >      description: used for reset chip control, RESET_N pin B7.
> > >      maxItems: 1
> > >
> > > +  analogix,lane0-swing:
> > > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > > +    minItems: 1
> > > +    maxItems: 20
> > > +    description:
> > > +      an array of swing register setting for DP tx lane0 PHY, please don't
> > > +      add this property, or contact vendor.
> >
> > DT properties need to be documented. Contacting the vendor doesn't count
> > as documentation I'm afraid.
>
> Hi Laurent Pinchart, thanks for your comment. For the DP phy swing
> setting, it is hard to describe in here, needs to refer the anx7625
> datasheet and programming guide. Basically, no need to change the DP phy
> swing setting.
>

Laurent is right. But if the value practically is a constant, you can
move the swing register into the driver. It should still be documented
as well as possible, but we can be a little bit more flexible.

> > > @@ -73,6 +123,10 @@ examples:
> > >              enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
> > >              reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
> > >
> > > +            analogix,audio-enable;
> > > +            analogix,lane0-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > > +            analogix,lane1-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > > +
> > >              ports {
> > >                  #address-cells = <1>;
> > >                  #size-cells = <0>;

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

* Re: [PATCH v6 1/5] dt-bindings:drm/bridge:anx7625:add vendor define flags
@ 2021-04-01 12:33         ` Robert Foss
  0 siblings, 0 replies; 52+ messages in thread
From: Robert Foss @ 2021-04-01 12:33 UTC (permalink / raw)
  To: Xin Ji
  Cc: Nicolas Boichat, Laurent Pinchart, dri-devel,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	David Airlie, Ricardo Cañuelo, Mark Brown, Zhen Li,
	linux-kernel, Rob Herring, Laurent Pinchart, Hsin-Yi Wang,
	Sam Ravnborg, Bernie Liang, Sheng Pan

Hey Xin,

This series no longer applies to drm-misc/drm-misc-next, please rebase it.

On Wed, 24 Mar 2021 at 08:52, Xin Ji <xji@analogixsemi.com> wrote:
>
> On Sun, Mar 21, 2021 at 02:00:38PM +0200, Laurent Pinchart wrote:
> > Hi Xin,
> >
> > Thank you for the patch.
> >
> > On Fri, Mar 19, 2021 at 02:32:39PM +0800, Xin Ji wrote:
> > > Add 'bus-type' and 'data-lanes' define for port0. Define DP tx lane0,
> > > lane1 swing register array define, and audio enable flag.
> > >
> > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > ---
> > >  .../display/bridge/analogix,anx7625.yaml      | 58 ++++++++++++++++++-
> > >  1 file changed, 57 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > index c789784efe30..3f54d5876982 100644
> > > --- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > @@ -34,6 +34,26 @@ properties:
> > >      description: used for reset chip control, RESET_N pin B7.
> > >      maxItems: 1
> > >
> > > +  analogix,lane0-swing:
> > > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > > +    minItems: 1
> > > +    maxItems: 20
> > > +    description:
> > > +      an array of swing register setting for DP tx lane0 PHY, please don't
> > > +      add this property, or contact vendor.
> >
> > DT properties need to be documented. Contacting the vendor doesn't count
> > as documentation I'm afraid.
>
> Hi Laurent Pinchart, thanks for your comment. For the DP phy swing
> setting, it is hard to describe in here, needs to refer the anx7625
> datasheet and programming guide. Basically, no need to change the DP phy
> swing setting.
>

Laurent is right. But if the value practically is a constant, you can
move the swing register into the driver. It should still be documented
as well as possible, but we can be a little bit more flexible.

> > > @@ -73,6 +123,10 @@ examples:
> > >              enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
> > >              reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
> > >
> > > +            analogix,audio-enable;
> > > +            analogix,lane0-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > > +            analogix,lane1-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > > +
> > >              ports {
> > >                  #address-cells = <1>;
> > >                  #size-cells = <0>;
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 3/5] drm/bridge: anx7625: add MIPI DPI input feature support
  2021-03-19  6:34   ` Xin Ji
  (?)
@ 2021-04-01 13:53     ` Robert Foss
  -1 siblings, 0 replies; 52+ messages in thread
From: Robert Foss @ 2021-04-01 13:53 UTC (permalink / raw)
  To: Xin Ji
  Cc: Nicolas Boichat, Andrzej Hajda, Neil Armstrong, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Dan Carpenter, David Airlie,
	Daniel Vetter, Boris Brezillon, Sam Ravnborg, Hsin-Yi Wang,
	Torsten Duwe, Vasily Khoruzhick, Marek Szyprowski, Sheng Pan,
	Bernie Liang, Zhen Li, dri-devel, linux-kernel, devel

Hey Xin,

This patch looks good to me, feel free to add my r-b.

Reviewed-by: Robert Foss <robert.foss@linaro.org>

On Fri, 19 Mar 2021 at 07:34, Xin Ji <xji@analogixsemi.com> wrote:
>
> Add MIPI rx DPI input support.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 245 ++++++++++++++++------
>  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
>  2 files changed, 203 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 04536cc7afe7..8c514b46d361 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -150,18 +150,18 @@ static int anx7625_write_and(struct anx7625_data *ctx,
>         return anx7625_reg_write(ctx, client, offset, (val & (mask)));
>  }
>
> -static int anx7625_write_and_or(struct anx7625_data *ctx,
> -                               struct i2c_client *client,
> -                               u8 offset, u8 and_mask, u8 or_mask)
> +static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
>  {
> -       int val;
> +       int i, ret;
>
> -       val = anx7625_reg_read(ctx, client, offset);
> -       if (val < 0)
> -               return val;
> +       ret = anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
> +                              AUDIO_CONTROL_REGISTER, 0x80);
> +       for (i = 0; i < 13; i++)
> +               ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> +                                        VIDEO_BIT_MATRIX_12 + i,
> +                                        0x18 + i);
>
> -       return anx7625_reg_write(ctx, client,
> -                                offset, (val & and_mask) | (or_mask));
> +       return ret;
>  }
>
>  static int anx7625_read_ctrl_status_p0(struct anx7625_data *ctx)
> @@ -219,38 +219,6 @@ static int anx7625_video_mute_control(struct anx7625_data *ctx,
>         return ret;
>  }
>
> -static int anx7625_config_audio_input(struct anx7625_data *ctx)
> -{
> -       struct device *dev = &ctx->client->dev;
> -       int ret;
> -
> -       /* Channel num */
> -       ret = anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> -                               AUDIO_CHANNEL_STATUS_6, I2S_CH_2 << 5);
> -
> -       /* FS */
> -       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> -                                   AUDIO_CHANNEL_STATUS_4,
> -                                   0xf0, AUDIO_FS_48K);
> -       /* Word length */
> -       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> -                                   AUDIO_CHANNEL_STATUS_5,
> -                                   0xf0, AUDIO_W_LEN_24_24MAX);
> -       /* I2S */
> -       ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
> -                               AUDIO_CHANNEL_STATUS_6, I2S_SLAVE_MODE);
> -       ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
> -                                AUDIO_CONTROL_REGISTER, ~TDM_TIMING_MODE);
> -       /* Audio change flag */
> -       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> -                               AP_AV_STATUS, AP_AUDIO_CHG);
> -
> -       if (ret < 0)
> -               DRM_DEV_ERROR(dev, "fail to config audio.\n");
> -
> -       return ret;
> -}
> -
>  /* Reduction of fraction a/b */
>  static void anx7625_reduction_of_a_fraction(unsigned long *a, unsigned long *b)
>  {
> @@ -410,7 +378,7 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
>         ret |= anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
>                         MIPI_LANE_CTRL_0, 0xfc);
>         ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client,
> -                               MIPI_LANE_CTRL_0, 3);
> +                               MIPI_LANE_CTRL_0, ctx->pdata.mipi_lanes - 1);
>
>         /* Htotal */
>         htotal = ctx->dt.hactive.min + ctx->dt.hfront_porch.min +
> @@ -595,6 +563,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
>         return ret;
>  }
>
> +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> +{
> +       struct device *dev = &ctx->client->dev;
> +       u16 freq = ctx->dt.pixelclock.min / 1000;
> +       int ret;
> +
> +       /* configure pixel clock */
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               PIXEL_CLOCK_L, freq & 0xFF);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                PIXEL_CLOCK_H, (freq >> 8));
> +
> +       /* set DPI mode */
> +       /* set to DPI PLL module sel */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +                                MIPI_DIGITAL_PLL_9, 0x20);
> +       /* power down MIPI */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +                                MIPI_LANE_CTRL_10, 0x08);
> +       /* enable DPI mode */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +                                MIPI_DIGITAL_PLL_18, 0x1C);
> +       /* set first edge */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> +                                VIDEO_CONTROL_0, 0x06);
> +       if (ret < 0)
> +               DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> +
> +       return ret;
> +}
> +
> +static int anx7625_dpi_config(struct anx7625_data *ctx)
> +{
> +       struct device *dev = &ctx->client->dev;
> +       int ret;
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> +
> +       /* DSC disable */
> +       ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> +                               R_DSC_CTRL_0, ~DSC_EN);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_config_bit_matrix(ctx);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_api_dpi_config(ctx);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> +               return ret;
> +       }
> +
> +       /* set MIPI RX EN */
> +       ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> +                              AP_AV_STATUS, AP_MIPI_RX_EN);
> +       /* clear mute flag */
> +       ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> +       if (ret < 0)
> +               DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> +
> +       return ret;
> +}
> +
>  static void anx7625_dp_start(struct anx7625_data *ctx)
>  {
>         int ret;
> @@ -605,9 +643,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
>                 return;
>         }
>
> -       anx7625_config_audio_input(ctx);
> -
> -       ret = anx7625_dsi_config(ctx);
> +       if (ctx->pdata.is_dpi)
> +               ret = anx7625_dpi_config(ctx);
> +       else
> +               ret = anx7625_dsi_config(ctx);
>
>         if (ret < 0)
>                 DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> @@ -1051,6 +1090,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
>                 return;
>         }
>
> +       ctx->hpd_status = 1;
>         ctx->hpd_high_cnt++;
>
>         /* Not support HDCP */
> @@ -1060,8 +1100,10 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
>         ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
>         /* Interrupt for DRM */
>         ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
> -       if (ret < 0)
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "fail to setting HDCP/auth\n");
>                 return;
> +       }
>
>         ret = anx7625_reg_read(ctx, ctx->i2c.rx_p1_client, 0x86);
>         if (ret < 0)
> @@ -1080,6 +1122,10 @@ static void anx7625_hpd_polling(struct anx7625_data *ctx)
>         int ret, val;
>         struct device *dev = &ctx->client->dev;
>
> +       /* Interrupt mode, no need poll HPD status, just return */
> +       if (ctx->pdata.intp_irq)
> +               return;
> +
>         if (atomic_read(&ctx->power_status) != 1) {
>                 DRM_DEV_DEBUG_DRIVER(dev, "No need to poling HPD status.\n");
>                 return;
> @@ -1130,6 +1176,21 @@ static void anx7625_remove_edid(struct anx7625_data *ctx)
>         ctx->slimport_edid_p.edid_block_num = -1;
>  }
>
> +static void anx7625_dp_adjust_swing(struct anx7625_data *ctx)
> +{
> +       int i;
> +
> +       for (i = 0; i < ctx->pdata.dp_lane0_swing_reg_cnt; i++)
> +               anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
> +                                 DP_TX_LANE0_SWING_REG0 + i,
> +                                 ctx->pdata.lane0_reg_data[i] & 0xFF);
> +
> +       for (i = 0; i < ctx->pdata.dp_lane1_swing_reg_cnt; i++)
> +               anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
> +                                 DP_TX_LANE1_SWING_REG0 + i,
> +                                 ctx->pdata.lane1_reg_data[i] & 0xFF);
> +}
> +
>  static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
>  {
>         struct device *dev = &ctx->client->dev;
> @@ -1145,9 +1206,8 @@ static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
>         } else {
>                 DRM_DEV_DEBUG_DRIVER(dev, " HPD high\n");
>                 anx7625_start_dp_work(ctx);
> +               anx7625_dp_adjust_swing(ctx);
>         }
> -
> -       ctx->hpd_status = 1;
>  }
>
>  static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
> @@ -1224,20 +1284,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
>         return IRQ_HANDLED;
>  }
>
> +static int anx7625_get_swing_setting(struct device *dev,
> +                                    struct anx7625_platform_data *pdata)
> +{
> +       int num_regs;
> +
> +       if (of_get_property(dev->of_node,
> +                           "analogix,lane0-swing", &num_regs)) {
> +               if (num_regs > DP_TX_SWING_REG_CNT)
> +                       num_regs = DP_TX_SWING_REG_CNT;
> +
> +               pdata->dp_lane0_swing_reg_cnt = num_regs;
> +               of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> +                                          pdata->lane0_reg_data, num_regs);
> +       }
> +
> +       if (of_get_property(dev->of_node,
> +                           "analogix,lane1-swing", &num_regs)) {
> +               if (num_regs > DP_TX_SWING_REG_CNT)
> +                       num_regs = DP_TX_SWING_REG_CNT;
> +
> +               pdata->dp_lane1_swing_reg_cnt = num_regs;
> +               of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> +                                          pdata->lane1_reg_data, num_regs);
> +       }
> +
> +       return 0;
> +}
> +
>  static int anx7625_parse_dt(struct device *dev,
>                             struct anx7625_platform_data *pdata)
>  {
> -       struct device_node *np = dev->of_node;
> +       struct device_node *np = dev->of_node, *ep0;
>         struct drm_panel *panel;
>         int ret;
> +       int bus_type, mipi_lanes;
>
> +       anx7625_get_swing_setting(dev, pdata);
> +
> +       pdata->is_dpi = 1; /* default dpi mode */
>         pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
>         if (!pdata->mipi_host_node) {
>                 DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
>                 return -ENODEV;
>         }
>
> -       DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> +       bus_type = 5;
> +       mipi_lanes = MAX_LANES_SUPPORT;
> +       ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> +       if (ep0) {
> +               if (of_property_read_u32(ep0, "bus-type", &bus_type))
> +                       bus_type = 0;
> +
> +               mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> +       }
> +
> +       if (bus_type == 5) /* bus type is Parallel(DSI) */
> +               pdata->is_dpi = 0;
> +
> +       pdata->mipi_lanes = mipi_lanes;
> +       if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> +               pdata->mipi_lanes = MAX_LANES_SUPPORT;
> +
> +       if (pdata->is_dpi)
> +               DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> +       else
> +               DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
>
>         ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
>         if (ret < 0) {
> @@ -1300,9 +1412,13 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
>  {
>         struct device *dev = &ctx->client->dev;
>
> -       DRM_DEV_DEBUG_DRIVER(dev, "sink detect, return connected\n");
> +       DRM_DEV_DEBUG_DRIVER(dev, "sink detect\n");
> +
> +       if (ctx->pdata.panel_bridge)
> +               return connector_status_connected;
>
> -       return connector_status_connected;
> +       return ctx->hpd_status ? connector_status_connected :
> +                                    connector_status_disconnected;
>  }
>
>  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> @@ -1330,7 +1446,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
>                 return -EINVAL;
>         }
>
> -       dsi->lanes = 4;
> +       dsi->lanes = ctx->pdata.mipi_lanes;
>         dsi->format = MIPI_DSI_FMT_RGB888;
>         dsi->mode_flags = MIPI_DSI_MODE_VIDEO   |
>                 MIPI_DSI_MODE_VIDEO_SYNC_PULSE  |
> @@ -1376,10 +1492,12 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
>                 return -ENODEV;
>         }
>
> -       err = anx7625_attach_dsi(ctx);
> -       if (err) {
> -               DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
> -               return err;
> +       if (!ctx->pdata.is_dpi) {
> +               err = anx7625_attach_dsi(ctx);
> +               if (err) {
> +                       DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
> +                       return err;
> +               }
>         }
>
>         if (ctx->pdata.panel_bridge) {
> @@ -1478,6 +1596,10 @@ static bool anx7625_bridge_mode_fixup(struct drm_bridge *bridge,
>
>         DRM_DEV_DEBUG_DRIVER(dev, "drm mode fixup set\n");
>
> +       /* No need fixup for external monitor */
> +       if (!ctx->pdata.panel_bridge)
> +               return true;
> +
>         hsync = mode->hsync_end - mode->hsync_start;
>         hfp = mode->hsync_start - mode->hdisplay;
>         hbp = mode->htotal - mode->hsync_end;
> @@ -1786,8 +1908,13 @@ static int anx7625_i2c_probe(struct i2c_client *client,
>
>         platform->bridge.funcs = &anx7625_bridge_funcs;
>         platform->bridge.of_node = client->dev.of_node;
> -       platform->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
> -       platform->bridge.type = DRM_MODE_CONNECTOR_eDP;
> +       platform->bridge.ops = DRM_BRIDGE_OP_EDID;
> +       if (!platform->pdata.panel_bridge)
> +               platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
> +                                       DRM_BRIDGE_OP_DETECT;
> +       platform->bridge.type = platform->pdata.panel_bridge ?
> +                                   DRM_MODE_CONNECTOR_eDP :
> +                                   DRM_MODE_CONNECTOR_DisplayPort;
>         drm_bridge_add(&platform->bridge);
>
>         DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> index 193ad86c5450..beee95da2155 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> @@ -141,12 +141,20 @@
>  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
>
>  /******** END of I2C Address 0x72 *********/
> +
> +/***************************************************************/
> +/* Register definition of device address 0x7a */
> +#define DP_TX_SWING_REG_CNT            0x14
> +#define DP_TX_LANE0_SWING_REG0         0x00
> +#define DP_TX_LANE1_SWING_REG0         0x14
> +/******** END of I2C Address 0x7a *********/
> +
>  /***************************************************************/
>  /* Register definition of device address 0x7e */
>devm_drm_panel_bridge_add
>  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
>
> -#define FLASH_LOAD_STA 0x05
> +#define FLASH_LOAD_STA          0x05
>  #define FLASH_LOAD_STA_CHK     BIT(7)
>
>  #define  XTAL_FRQ_SEL    0x3F
> @@ -347,11 +355,19 @@ struct s_edid_data {
>
>  /***************** Display End *****************/
>
> +#define MAX_LANES_SUPPORT      4
> +
>  struct anx7625_platform_data {
>         struct gpio_desc *gpio_p_on;
>         struct gpio_desc *gpio_reset;
>         struct drm_bridge *panel_bridge;
>         int intp_irq;
> +       int is_dpi;
> +       int mipi_lanes;
> +       int dp_lane0_swing_reg_cnt;
> +       int lane0_reg_data[DP_TX_SWING_REG_CNT];
> +       int dp_lane1_swing_reg_cnt;
> +       int lane1_reg_data[DP_TX_SWING_REG_CNT];
>         u32 low_power_mode;
>         struct device_node *mipi_host_node;
>  };
> --
> 2.25.1
>

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

* Re: [PATCH v6 3/5] drm/bridge: anx7625: add MIPI DPI input feature support
@ 2021-04-01 13:53     ` Robert Foss
  0 siblings, 0 replies; 52+ messages in thread
From: Robert Foss @ 2021-04-01 13:53 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sheng Pan, Jonas Karlman,
	David Airlie, Bernie Liang, Neil Armstrong, Zhen Li,
	linux-kernel, dri-devel, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Laurent Pinchart, Daniel Vetter,
	Hsin-Yi Wang, Sam Ravnborg, Dan Carpenter, Marek Szyprowski

Hey Xin,

This patch looks good to me, feel free to add my r-b.

Reviewed-by: Robert Foss <robert.foss@linaro.org>

On Fri, 19 Mar 2021 at 07:34, Xin Ji <xji@analogixsemi.com> wrote:
>
> Add MIPI rx DPI input support.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 245 ++++++++++++++++------
>  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
>  2 files changed, 203 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 04536cc7afe7..8c514b46d361 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -150,18 +150,18 @@ static int anx7625_write_and(struct anx7625_data *ctx,
>         return anx7625_reg_write(ctx, client, offset, (val & (mask)));
>  }
>
> -static int anx7625_write_and_or(struct anx7625_data *ctx,
> -                               struct i2c_client *client,
> -                               u8 offset, u8 and_mask, u8 or_mask)
> +static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
>  {
> -       int val;
> +       int i, ret;
>
> -       val = anx7625_reg_read(ctx, client, offset);
> -       if (val < 0)
> -               return val;
> +       ret = anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
> +                              AUDIO_CONTROL_REGISTER, 0x80);
> +       for (i = 0; i < 13; i++)
> +               ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> +                                        VIDEO_BIT_MATRIX_12 + i,
> +                                        0x18 + i);
>
> -       return anx7625_reg_write(ctx, client,
> -                                offset, (val & and_mask) | (or_mask));
> +       return ret;
>  }
>
>  static int anx7625_read_ctrl_status_p0(struct anx7625_data *ctx)
> @@ -219,38 +219,6 @@ static int anx7625_video_mute_control(struct anx7625_data *ctx,
>         return ret;
>  }
>
> -static int anx7625_config_audio_input(struct anx7625_data *ctx)
> -{
> -       struct device *dev = &ctx->client->dev;
> -       int ret;
> -
> -       /* Channel num */
> -       ret = anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> -                               AUDIO_CHANNEL_STATUS_6, I2S_CH_2 << 5);
> -
> -       /* FS */
> -       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> -                                   AUDIO_CHANNEL_STATUS_4,
> -                                   0xf0, AUDIO_FS_48K);
> -       /* Word length */
> -       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> -                                   AUDIO_CHANNEL_STATUS_5,
> -                                   0xf0, AUDIO_W_LEN_24_24MAX);
> -       /* I2S */
> -       ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
> -                               AUDIO_CHANNEL_STATUS_6, I2S_SLAVE_MODE);
> -       ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
> -                                AUDIO_CONTROL_REGISTER, ~TDM_TIMING_MODE);
> -       /* Audio change flag */
> -       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> -                               AP_AV_STATUS, AP_AUDIO_CHG);
> -
> -       if (ret < 0)
> -               DRM_DEV_ERROR(dev, "fail to config audio.\n");
> -
> -       return ret;
> -}
> -
>  /* Reduction of fraction a/b */
>  static void anx7625_reduction_of_a_fraction(unsigned long *a, unsigned long *b)
>  {
> @@ -410,7 +378,7 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
>         ret |= anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
>                         MIPI_LANE_CTRL_0, 0xfc);
>         ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client,
> -                               MIPI_LANE_CTRL_0, 3);
> +                               MIPI_LANE_CTRL_0, ctx->pdata.mipi_lanes - 1);
>
>         /* Htotal */
>         htotal = ctx->dt.hactive.min + ctx->dt.hfront_porch.min +
> @@ -595,6 +563,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
>         return ret;
>  }
>
> +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> +{
> +       struct device *dev = &ctx->client->dev;
> +       u16 freq = ctx->dt.pixelclock.min / 1000;
> +       int ret;
> +
> +       /* configure pixel clock */
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               PIXEL_CLOCK_L, freq & 0xFF);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                PIXEL_CLOCK_H, (freq >> 8));
> +
> +       /* set DPI mode */
> +       /* set to DPI PLL module sel */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +                                MIPI_DIGITAL_PLL_9, 0x20);
> +       /* power down MIPI */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +                                MIPI_LANE_CTRL_10, 0x08);
> +       /* enable DPI mode */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +                                MIPI_DIGITAL_PLL_18, 0x1C);
> +       /* set first edge */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> +                                VIDEO_CONTROL_0, 0x06);
> +       if (ret < 0)
> +               DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> +
> +       return ret;
> +}
> +
> +static int anx7625_dpi_config(struct anx7625_data *ctx)
> +{
> +       struct device *dev = &ctx->client->dev;
> +       int ret;
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> +
> +       /* DSC disable */
> +       ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> +                               R_DSC_CTRL_0, ~DSC_EN);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_config_bit_matrix(ctx);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_api_dpi_config(ctx);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> +               return ret;
> +       }
> +
> +       /* set MIPI RX EN */
> +       ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> +                              AP_AV_STATUS, AP_MIPI_RX_EN);
> +       /* clear mute flag */
> +       ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> +       if (ret < 0)
> +               DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> +
> +       return ret;
> +}
> +
>  static void anx7625_dp_start(struct anx7625_data *ctx)
>  {
>         int ret;
> @@ -605,9 +643,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
>                 return;
>         }
>
> -       anx7625_config_audio_input(ctx);
> -
> -       ret = anx7625_dsi_config(ctx);
> +       if (ctx->pdata.is_dpi)
> +               ret = anx7625_dpi_config(ctx);
> +       else
> +               ret = anx7625_dsi_config(ctx);
>
>         if (ret < 0)
>                 DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> @@ -1051,6 +1090,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
>                 return;
>         }
>
> +       ctx->hpd_status = 1;
>         ctx->hpd_high_cnt++;
>
>         /* Not support HDCP */
> @@ -1060,8 +1100,10 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
>         ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
>         /* Interrupt for DRM */
>         ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
> -       if (ret < 0)
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "fail to setting HDCP/auth\n");
>                 return;
> +       }
>
>         ret = anx7625_reg_read(ctx, ctx->i2c.rx_p1_client, 0x86);
>         if (ret < 0)
> @@ -1080,6 +1122,10 @@ static void anx7625_hpd_polling(struct anx7625_data *ctx)
>         int ret, val;
>         struct device *dev = &ctx->client->dev;
>
> +       /* Interrupt mode, no need poll HPD status, just return */
> +       if (ctx->pdata.intp_irq)
> +               return;
> +
>         if (atomic_read(&ctx->power_status) != 1) {
>                 DRM_DEV_DEBUG_DRIVER(dev, "No need to poling HPD status.\n");
>                 return;
> @@ -1130,6 +1176,21 @@ static void anx7625_remove_edid(struct anx7625_data *ctx)
>         ctx->slimport_edid_p.edid_block_num = -1;
>  }
>
> +static void anx7625_dp_adjust_swing(struct anx7625_data *ctx)
> +{
> +       int i;
> +
> +       for (i = 0; i < ctx->pdata.dp_lane0_swing_reg_cnt; i++)
> +               anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
> +                                 DP_TX_LANE0_SWING_REG0 + i,
> +                                 ctx->pdata.lane0_reg_data[i] & 0xFF);
> +
> +       for (i = 0; i < ctx->pdata.dp_lane1_swing_reg_cnt; i++)
> +               anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
> +                                 DP_TX_LANE1_SWING_REG0 + i,
> +                                 ctx->pdata.lane1_reg_data[i] & 0xFF);
> +}
> +
>  static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
>  {
>         struct device *dev = &ctx->client->dev;
> @@ -1145,9 +1206,8 @@ static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
>         } else {
>                 DRM_DEV_DEBUG_DRIVER(dev, " HPD high\n");
>                 anx7625_start_dp_work(ctx);
> +               anx7625_dp_adjust_swing(ctx);
>         }
> -
> -       ctx->hpd_status = 1;
>  }
>
>  static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
> @@ -1224,20 +1284,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
>         return IRQ_HANDLED;
>  }
>
> +static int anx7625_get_swing_setting(struct device *dev,
> +                                    struct anx7625_platform_data *pdata)
> +{
> +       int num_regs;
> +
> +       if (of_get_property(dev->of_node,
> +                           "analogix,lane0-swing", &num_regs)) {
> +               if (num_regs > DP_TX_SWING_REG_CNT)
> +                       num_regs = DP_TX_SWING_REG_CNT;
> +
> +               pdata->dp_lane0_swing_reg_cnt = num_regs;
> +               of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> +                                          pdata->lane0_reg_data, num_regs);
> +       }
> +
> +       if (of_get_property(dev->of_node,
> +                           "analogix,lane1-swing", &num_regs)) {
> +               if (num_regs > DP_TX_SWING_REG_CNT)
> +                       num_regs = DP_TX_SWING_REG_CNT;
> +
> +               pdata->dp_lane1_swing_reg_cnt = num_regs;
> +               of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> +                                          pdata->lane1_reg_data, num_regs);
> +       }
> +
> +       return 0;
> +}
> +
>  static int anx7625_parse_dt(struct device *dev,
>                             struct anx7625_platform_data *pdata)
>  {
> -       struct device_node *np = dev->of_node;
> +       struct device_node *np = dev->of_node, *ep0;
>         struct drm_panel *panel;
>         int ret;
> +       int bus_type, mipi_lanes;
>
> +       anx7625_get_swing_setting(dev, pdata);
> +
> +       pdata->is_dpi = 1; /* default dpi mode */
>         pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
>         if (!pdata->mipi_host_node) {
>                 DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
>                 return -ENODEV;
>         }
>
> -       DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> +       bus_type = 5;
> +       mipi_lanes = MAX_LANES_SUPPORT;
> +       ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> +       if (ep0) {
> +               if (of_property_read_u32(ep0, "bus-type", &bus_type))
> +                       bus_type = 0;
> +
> +               mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> +       }
> +
> +       if (bus_type == 5) /* bus type is Parallel(DSI) */
> +               pdata->is_dpi = 0;
> +
> +       pdata->mipi_lanes = mipi_lanes;
> +       if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> +               pdata->mipi_lanes = MAX_LANES_SUPPORT;
> +
> +       if (pdata->is_dpi)
> +               DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> +       else
> +               DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
>
>         ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
>         if (ret < 0) {
> @@ -1300,9 +1412,13 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
>  {
>         struct device *dev = &ctx->client->dev;
>
> -       DRM_DEV_DEBUG_DRIVER(dev, "sink detect, return connected\n");
> +       DRM_DEV_DEBUG_DRIVER(dev, "sink detect\n");
> +
> +       if (ctx->pdata.panel_bridge)
> +               return connector_status_connected;
>
> -       return connector_status_connected;
> +       return ctx->hpd_status ? connector_status_connected :
> +                                    connector_status_disconnected;
>  }
>
>  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> @@ -1330,7 +1446,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
>                 return -EINVAL;
>         }
>
> -       dsi->lanes = 4;
> +       dsi->lanes = ctx->pdata.mipi_lanes;
>         dsi->format = MIPI_DSI_FMT_RGB888;
>         dsi->mode_flags = MIPI_DSI_MODE_VIDEO   |
>                 MIPI_DSI_MODE_VIDEO_SYNC_PULSE  |
> @@ -1376,10 +1492,12 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
>                 return -ENODEV;
>         }
>
> -       err = anx7625_attach_dsi(ctx);
> -       if (err) {
> -               DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
> -               return err;
> +       if (!ctx->pdata.is_dpi) {
> +               err = anx7625_attach_dsi(ctx);
> +               if (err) {
> +                       DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
> +                       return err;
> +               }
>         }
>
>         if (ctx->pdata.panel_bridge) {
> @@ -1478,6 +1596,10 @@ static bool anx7625_bridge_mode_fixup(struct drm_bridge *bridge,
>
>         DRM_DEV_DEBUG_DRIVER(dev, "drm mode fixup set\n");
>
> +       /* No need fixup for external monitor */
> +       if (!ctx->pdata.panel_bridge)
> +               return true;
> +
>         hsync = mode->hsync_end - mode->hsync_start;
>         hfp = mode->hsync_start - mode->hdisplay;
>         hbp = mode->htotal - mode->hsync_end;
> @@ -1786,8 +1908,13 @@ static int anx7625_i2c_probe(struct i2c_client *client,
>
>         platform->bridge.funcs = &anx7625_bridge_funcs;
>         platform->bridge.of_node = client->dev.of_node;
> -       platform->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
> -       platform->bridge.type = DRM_MODE_CONNECTOR_eDP;
> +       platform->bridge.ops = DRM_BRIDGE_OP_EDID;
> +       if (!platform->pdata.panel_bridge)
> +               platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
> +                                       DRM_BRIDGE_OP_DETECT;
> +       platform->bridge.type = platform->pdata.panel_bridge ?
> +                                   DRM_MODE_CONNECTOR_eDP :
> +                                   DRM_MODE_CONNECTOR_DisplayPort;
>         drm_bridge_add(&platform->bridge);
>
>         DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> index 193ad86c5450..beee95da2155 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> @@ -141,12 +141,20 @@
>  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
>
>  /******** END of I2C Address 0x72 *********/
> +
> +/***************************************************************/
> +/* Register definition of device address 0x7a */
> +#define DP_TX_SWING_REG_CNT            0x14
> +#define DP_TX_LANE0_SWING_REG0         0x00
> +#define DP_TX_LANE1_SWING_REG0         0x14
> +/******** END of I2C Address 0x7a *********/
> +
>  /***************************************************************/
>  /* Register definition of device address 0x7e */
>devm_drm_panel_bridge_add
>  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
>
> -#define FLASH_LOAD_STA 0x05
> +#define FLASH_LOAD_STA          0x05
>  #define FLASH_LOAD_STA_CHK     BIT(7)
>
>  #define  XTAL_FRQ_SEL    0x3F
> @@ -347,11 +355,19 @@ struct s_edid_data {
>
>  /***************** Display End *****************/
>
> +#define MAX_LANES_SUPPORT      4
> +
>  struct anx7625_platform_data {
>         struct gpio_desc *gpio_p_on;
>         struct gpio_desc *gpio_reset;
>         struct drm_bridge *panel_bridge;
>         int intp_irq;
> +       int is_dpi;
> +       int mipi_lanes;
> +       int dp_lane0_swing_reg_cnt;
> +       int lane0_reg_data[DP_TX_SWING_REG_CNT];
> +       int dp_lane1_swing_reg_cnt;
> +       int lane1_reg_data[DP_TX_SWING_REG_CNT];
>         u32 low_power_mode;
>         struct device_node *mipi_host_node;
>  };
> --
> 2.25.1
>
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v6 3/5] drm/bridge: anx7625: add MIPI DPI input feature support
@ 2021-04-01 13:53     ` Robert Foss
  0 siblings, 0 replies; 52+ messages in thread
From: Robert Foss @ 2021-04-01 13:53 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sheng Pan, Jonas Karlman,
	David Airlie, Bernie Liang, Neil Armstrong, Zhen Li,
	linux-kernel, dri-devel, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Laurent Pinchart, Hsin-Yi Wang,
	Sam Ravnborg, Dan Carpenter, Marek Szyprowski

Hey Xin,

This patch looks good to me, feel free to add my r-b.

Reviewed-by: Robert Foss <robert.foss@linaro.org>

On Fri, 19 Mar 2021 at 07:34, Xin Ji <xji@analogixsemi.com> wrote:
>
> Add MIPI rx DPI input support.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 245 ++++++++++++++++------
>  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
>  2 files changed, 203 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 04536cc7afe7..8c514b46d361 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -150,18 +150,18 @@ static int anx7625_write_and(struct anx7625_data *ctx,
>         return anx7625_reg_write(ctx, client, offset, (val & (mask)));
>  }
>
> -static int anx7625_write_and_or(struct anx7625_data *ctx,
> -                               struct i2c_client *client,
> -                               u8 offset, u8 and_mask, u8 or_mask)
> +static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
>  {
> -       int val;
> +       int i, ret;
>
> -       val = anx7625_reg_read(ctx, client, offset);
> -       if (val < 0)
> -               return val;
> +       ret = anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
> +                              AUDIO_CONTROL_REGISTER, 0x80);
> +       for (i = 0; i < 13; i++)
> +               ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> +                                        VIDEO_BIT_MATRIX_12 + i,
> +                                        0x18 + i);
>
> -       return anx7625_reg_write(ctx, client,
> -                                offset, (val & and_mask) | (or_mask));
> +       return ret;
>  }
>
>  static int anx7625_read_ctrl_status_p0(struct anx7625_data *ctx)
> @@ -219,38 +219,6 @@ static int anx7625_video_mute_control(struct anx7625_data *ctx,
>         return ret;
>  }
>
> -static int anx7625_config_audio_input(struct anx7625_data *ctx)
> -{
> -       struct device *dev = &ctx->client->dev;
> -       int ret;
> -
> -       /* Channel num */
> -       ret = anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> -                               AUDIO_CHANNEL_STATUS_6, I2S_CH_2 << 5);
> -
> -       /* FS */
> -       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> -                                   AUDIO_CHANNEL_STATUS_4,
> -                                   0xf0, AUDIO_FS_48K);
> -       /* Word length */
> -       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> -                                   AUDIO_CHANNEL_STATUS_5,
> -                                   0xf0, AUDIO_W_LEN_24_24MAX);
> -       /* I2S */
> -       ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
> -                               AUDIO_CHANNEL_STATUS_6, I2S_SLAVE_MODE);
> -       ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
> -                                AUDIO_CONTROL_REGISTER, ~TDM_TIMING_MODE);
> -       /* Audio change flag */
> -       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> -                               AP_AV_STATUS, AP_AUDIO_CHG);
> -
> -       if (ret < 0)
> -               DRM_DEV_ERROR(dev, "fail to config audio.\n");
> -
> -       return ret;
> -}
> -
>  /* Reduction of fraction a/b */
>  static void anx7625_reduction_of_a_fraction(unsigned long *a, unsigned long *b)
>  {
> @@ -410,7 +378,7 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
>         ret |= anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
>                         MIPI_LANE_CTRL_0, 0xfc);
>         ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client,
> -                               MIPI_LANE_CTRL_0, 3);
> +                               MIPI_LANE_CTRL_0, ctx->pdata.mipi_lanes - 1);
>
>         /* Htotal */
>         htotal = ctx->dt.hactive.min + ctx->dt.hfront_porch.min +
> @@ -595,6 +563,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
>         return ret;
>  }
>
> +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> +{
> +       struct device *dev = &ctx->client->dev;
> +       u16 freq = ctx->dt.pixelclock.min / 1000;
> +       int ret;
> +
> +       /* configure pixel clock */
> +       ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                               PIXEL_CLOCK_L, freq & 0xFF);
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +                                PIXEL_CLOCK_H, (freq >> 8));
> +
> +       /* set DPI mode */
> +       /* set to DPI PLL module sel */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +                                MIPI_DIGITAL_PLL_9, 0x20);
> +       /* power down MIPI */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +                                MIPI_LANE_CTRL_10, 0x08);
> +       /* enable DPI mode */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +                                MIPI_DIGITAL_PLL_18, 0x1C);
> +       /* set first edge */
> +       ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> +                                VIDEO_CONTROL_0, 0x06);
> +       if (ret < 0)
> +               DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> +
> +       return ret;
> +}
> +
> +static int anx7625_dpi_config(struct anx7625_data *ctx)
> +{
> +       struct device *dev = &ctx->client->dev;
> +       int ret;
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> +
> +       /* DSC disable */
> +       ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> +                               R_DSC_CTRL_0, ~DSC_EN);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_config_bit_matrix(ctx);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> +               return ret;
> +       }
> +
> +       ret = anx7625_api_dpi_config(ctx);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> +               return ret;
> +       }
> +
> +       /* set MIPI RX EN */
> +       ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> +                              AP_AV_STATUS, AP_MIPI_RX_EN);
> +       /* clear mute flag */
> +       ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> +                                AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> +       if (ret < 0)
> +               DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> +
> +       return ret;
> +}
> +
>  static void anx7625_dp_start(struct anx7625_data *ctx)
>  {
>         int ret;
> @@ -605,9 +643,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
>                 return;
>         }
>
> -       anx7625_config_audio_input(ctx);
> -
> -       ret = anx7625_dsi_config(ctx);
> +       if (ctx->pdata.is_dpi)
> +               ret = anx7625_dpi_config(ctx);
> +       else
> +               ret = anx7625_dsi_config(ctx);
>
>         if (ret < 0)
>                 DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> @@ -1051,6 +1090,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
>                 return;
>         }
>
> +       ctx->hpd_status = 1;
>         ctx->hpd_high_cnt++;
>
>         /* Not support HDCP */
> @@ -1060,8 +1100,10 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
>         ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
>         /* Interrupt for DRM */
>         ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
> -       if (ret < 0)
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "fail to setting HDCP/auth\n");
>                 return;
> +       }
>
>         ret = anx7625_reg_read(ctx, ctx->i2c.rx_p1_client, 0x86);
>         if (ret < 0)
> @@ -1080,6 +1122,10 @@ static void anx7625_hpd_polling(struct anx7625_data *ctx)
>         int ret, val;
>         struct device *dev = &ctx->client->dev;
>
> +       /* Interrupt mode, no need poll HPD status, just return */
> +       if (ctx->pdata.intp_irq)
> +               return;
> +
>         if (atomic_read(&ctx->power_status) != 1) {
>                 DRM_DEV_DEBUG_DRIVER(dev, "No need to poling HPD status.\n");
>                 return;
> @@ -1130,6 +1176,21 @@ static void anx7625_remove_edid(struct anx7625_data *ctx)
>         ctx->slimport_edid_p.edid_block_num = -1;
>  }
>
> +static void anx7625_dp_adjust_swing(struct anx7625_data *ctx)
> +{
> +       int i;
> +
> +       for (i = 0; i < ctx->pdata.dp_lane0_swing_reg_cnt; i++)
> +               anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
> +                                 DP_TX_LANE0_SWING_REG0 + i,
> +                                 ctx->pdata.lane0_reg_data[i] & 0xFF);
> +
> +       for (i = 0; i < ctx->pdata.dp_lane1_swing_reg_cnt; i++)
> +               anx7625_reg_write(ctx, ctx->i2c.tx_p1_client,
> +                                 DP_TX_LANE1_SWING_REG0 + i,
> +                                 ctx->pdata.lane1_reg_data[i] & 0xFF);
> +}
> +
>  static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
>  {
>         struct device *dev = &ctx->client->dev;
> @@ -1145,9 +1206,8 @@ static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
>         } else {
>                 DRM_DEV_DEBUG_DRIVER(dev, " HPD high\n");
>                 anx7625_start_dp_work(ctx);
> +               anx7625_dp_adjust_swing(ctx);
>         }
> -
> -       ctx->hpd_status = 1;
>  }
>
>  static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
> @@ -1224,20 +1284,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
>         return IRQ_HANDLED;
>  }
>
> +static int anx7625_get_swing_setting(struct device *dev,
> +                                    struct anx7625_platform_data *pdata)
> +{
> +       int num_regs;
> +
> +       if (of_get_property(dev->of_node,
> +                           "analogix,lane0-swing", &num_regs)) {
> +               if (num_regs > DP_TX_SWING_REG_CNT)
> +                       num_regs = DP_TX_SWING_REG_CNT;
> +
> +               pdata->dp_lane0_swing_reg_cnt = num_regs;
> +               of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> +                                          pdata->lane0_reg_data, num_regs);
> +       }
> +
> +       if (of_get_property(dev->of_node,
> +                           "analogix,lane1-swing", &num_regs)) {
> +               if (num_regs > DP_TX_SWING_REG_CNT)
> +                       num_regs = DP_TX_SWING_REG_CNT;
> +
> +               pdata->dp_lane1_swing_reg_cnt = num_regs;
> +               of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> +                                          pdata->lane1_reg_data, num_regs);
> +       }
> +
> +       return 0;
> +}
> +
>  static int anx7625_parse_dt(struct device *dev,
>                             struct anx7625_platform_data *pdata)
>  {
> -       struct device_node *np = dev->of_node;
> +       struct device_node *np = dev->of_node, *ep0;
>         struct drm_panel *panel;
>         int ret;
> +       int bus_type, mipi_lanes;
>
> +       anx7625_get_swing_setting(dev, pdata);
> +
> +       pdata->is_dpi = 1; /* default dpi mode */
>         pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
>         if (!pdata->mipi_host_node) {
>                 DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
>                 return -ENODEV;
>         }
>
> -       DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> +       bus_type = 5;
> +       mipi_lanes = MAX_LANES_SUPPORT;
> +       ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> +       if (ep0) {
> +               if (of_property_read_u32(ep0, "bus-type", &bus_type))
> +                       bus_type = 0;
> +
> +               mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> +       }
> +
> +       if (bus_type == 5) /* bus type is Parallel(DSI) */
> +               pdata->is_dpi = 0;
> +
> +       pdata->mipi_lanes = mipi_lanes;
> +       if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> +               pdata->mipi_lanes = MAX_LANES_SUPPORT;
> +
> +       if (pdata->is_dpi)
> +               DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> +       else
> +               DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
>
>         ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
>         if (ret < 0) {
> @@ -1300,9 +1412,13 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
>  {
>         struct device *dev = &ctx->client->dev;
>
> -       DRM_DEV_DEBUG_DRIVER(dev, "sink detect, return connected\n");
> +       DRM_DEV_DEBUG_DRIVER(dev, "sink detect\n");
> +
> +       if (ctx->pdata.panel_bridge)
> +               return connector_status_connected;
>
> -       return connector_status_connected;
> +       return ctx->hpd_status ? connector_status_connected :
> +                                    connector_status_disconnected;
>  }
>
>  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> @@ -1330,7 +1446,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
>                 return -EINVAL;
>         }
>
> -       dsi->lanes = 4;
> +       dsi->lanes = ctx->pdata.mipi_lanes;
>         dsi->format = MIPI_DSI_FMT_RGB888;
>         dsi->mode_flags = MIPI_DSI_MODE_VIDEO   |
>                 MIPI_DSI_MODE_VIDEO_SYNC_PULSE  |
> @@ -1376,10 +1492,12 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
>                 return -ENODEV;
>         }
>
> -       err = anx7625_attach_dsi(ctx);
> -       if (err) {
> -               DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
> -               return err;
> +       if (!ctx->pdata.is_dpi) {
> +               err = anx7625_attach_dsi(ctx);
> +               if (err) {
> +                       DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", err);
> +                       return err;
> +               }
>         }
>
>         if (ctx->pdata.panel_bridge) {
> @@ -1478,6 +1596,10 @@ static bool anx7625_bridge_mode_fixup(struct drm_bridge *bridge,
>
>         DRM_DEV_DEBUG_DRIVER(dev, "drm mode fixup set\n");
>
> +       /* No need fixup for external monitor */
> +       if (!ctx->pdata.panel_bridge)
> +               return true;
> +
>         hsync = mode->hsync_end - mode->hsync_start;
>         hfp = mode->hsync_start - mode->hdisplay;
>         hbp = mode->htotal - mode->hsync_end;
> @@ -1786,8 +1908,13 @@ static int anx7625_i2c_probe(struct i2c_client *client,
>
>         platform->bridge.funcs = &anx7625_bridge_funcs;
>         platform->bridge.of_node = client->dev.of_node;
> -       platform->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD;
> -       platform->bridge.type = DRM_MODE_CONNECTOR_eDP;
> +       platform->bridge.ops = DRM_BRIDGE_OP_EDID;
> +       if (!platform->pdata.panel_bridge)
> +               platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
> +                                       DRM_BRIDGE_OP_DETECT;
> +       platform->bridge.type = platform->pdata.panel_bridge ?
> +                                   DRM_MODE_CONNECTOR_eDP :
> +                                   DRM_MODE_CONNECTOR_DisplayPort;
>         drm_bridge_add(&platform->bridge);
>
>         DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> index 193ad86c5450..beee95da2155 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> @@ -141,12 +141,20 @@
>  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
>
>  /******** END of I2C Address 0x72 *********/
> +
> +/***************************************************************/
> +/* Register definition of device address 0x7a */
> +#define DP_TX_SWING_REG_CNT            0x14
> +#define DP_TX_LANE0_SWING_REG0         0x00
> +#define DP_TX_LANE1_SWING_REG0         0x14
> +/******** END of I2C Address 0x7a *********/
> +
>  /***************************************************************/
>  /* Register definition of device address 0x7e */
>devm_drm_panel_bridge_add
>  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
>
> -#define FLASH_LOAD_STA 0x05
> +#define FLASH_LOAD_STA          0x05
>  #define FLASH_LOAD_STA_CHK     BIT(7)
>
>  #define  XTAL_FRQ_SEL    0x3F
> @@ -347,11 +355,19 @@ struct s_edid_data {
>
>  /***************** Display End *****************/
>
> +#define MAX_LANES_SUPPORT      4
> +
>  struct anx7625_platform_data {
>         struct gpio_desc *gpio_p_on;
>         struct gpio_desc *gpio_reset;
>         struct drm_bridge *panel_bridge;
>         int intp_irq;
> +       int is_dpi;
> +       int mipi_lanes;
> +       int dp_lane0_swing_reg_cnt;
> +       int lane0_reg_data[DP_TX_SWING_REG_CNT];
> +       int dp_lane1_swing_reg_cnt;
> +       int lane1_reg_data[DP_TX_SWING_REG_CNT];
>         u32 low_power_mode;
>         struct device_node *mipi_host_node;
>  };
> --
> 2.25.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 5/5] drm/bridge: anx7625: add HDMI audio function
  2021-03-19  6:35   ` Xin Ji
  (?)
@ 2021-04-01 13:58     ` Robert Foss
  -1 siblings, 0 replies; 52+ messages in thread
From: Robert Foss @ 2021-04-01 13:58 UTC (permalink / raw)
  To: Xin Ji
  Cc: Nicolas Boichat, Andrzej Hajda, Neil Armstrong, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Dan Carpenter, David Airlie,
	Daniel Vetter, Boris Brezillon, Sam Ravnborg, Hsin-Yi Wang,
	Torsten Duwe, Vasily Khoruzhick, Marek Szyprowski, Sheng Pan,
	Bernie Liang, Zhen Li, dri-devel, linux-kernel, devel

Hey Xin,

This patch looks good to me.

Reviewed-by: Robert Foss <robert.foss@linaro.org>

On Fri, 19 Mar 2021 at 07:35, Xin Ji <xji@analogixsemi.com> wrote:
>
> Add audio HDMI codec function support, enable it through device true flag
> "analogix,audio-enable".
>
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 227 ++++++++++++++++++++++
>  drivers/gpu/drm/bridge/analogix/anx7625.h |   5 +
>  2 files changed, 232 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index b424a570effa..02bb169d9c57 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -30,6 +30,8 @@
>  #include <drm/drm_print.h>
>  #include <drm/drm_probe_helper.h>
>
> +#include <sound/hdmi-codec.h>
> +
>  #include <video/display_timing.h>
>
>  #include "anx7625.h"
> @@ -150,6 +152,20 @@ static int anx7625_write_and(struct anx7625_data *ctx,
>         return anx7625_reg_write(ctx, client, offset, (val & (mask)));
>  }
>
> +static int anx7625_write_and_or(struct anx7625_data *ctx,
> +                               struct i2c_client *client,
> +                               u8 offset, u8 and_mask, u8 or_mask)
> +{
> +       int val;
> +
> +       val = anx7625_reg_read(ctx, client, offset);
> +       if (val < 0)
> +               return val;
> +
> +       return anx7625_reg_write(ctx, client,
> +                                offset, (val & and_mask) | (or_mask));
> +}
> +
>  static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
>  {
>         int i, ret;
> @@ -1498,6 +1514,9 @@ static int anx7625_parse_dt(struct device *dev,
>         else
>                 DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
>
> +       if (of_property_read_bool(np, "analogix,audio-enable"))
> +               pdata->audio_en = 1;
> +
>         ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
>         if (ret < 0) {
>                 if (ret == -ENODEV)
> @@ -1568,6 +1587,208 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
>                                      connector_status_disconnected;
>  }
>
> +static int anx7625_audio_hw_params(struct device *dev, void *data,
> +                                  struct hdmi_codec_daifmt *fmt,
> +                                  struct hdmi_codec_params *params)
> +{
> +       struct anx7625_data *ctx = dev_get_drvdata(dev);
> +       int wl, ch, rate;
> +       int ret = 0;
> +
> +       if (fmt->fmt != HDMI_DSP_A) {
> +               DRM_DEV_ERROR(dev, "only supports DSP_A\n");
> +               return -EINVAL;
> +       }
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "setting %d Hz, %d bit, %d channels\n",
> +                            params->sample_rate, params->sample_width,
> +                            params->cea.channels);
> +
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                                   AUDIO_CHANNEL_STATUS_6,
> +                                   ~I2S_SLAVE_MODE,
> +                                   TDM_SLAVE_MODE);
> +
> +       /* Word length */
> +       switch (params->sample_width) {
> +       case 16:
> +               wl = AUDIO_W_LEN_16_20MAX;
> +               break;
> +       case 18:
> +               wl = AUDIO_W_LEN_18_20MAX;
> +               break;
> +       case 20:
> +               wl = AUDIO_W_LEN_20_20MAX;
> +               break;
> +       case 24:
> +               wl = AUDIO_W_LEN_24_24MAX;
> +               break;
> +       default:
> +               DRM_DEV_DEBUG_DRIVER(dev, "wordlength: %d bit not support",
> +                                    params->sample_width);
> +               return -EINVAL;
> +       }
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                                   AUDIO_CHANNEL_STATUS_5,
> +                                   0xf0, wl);
> +
> +       /* Channel num */
> +       switch (params->cea.channels) {
> +       case 2:
> +               ch = I2S_CH_2;
> +               break;
> +       case 4:
> +               ch = TDM_CH_4;
> +               break;
> +       case 6:
> +               ch = TDM_CH_6;
> +               break;
> +       case 8:
> +               ch = TDM_CH_8;
> +               break;
> +       default:
> +               DRM_DEV_DEBUG_DRIVER(dev, "channel number: %d not support",
> +                                    params->cea.channels);
> +               return -EINVAL;
> +       }
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                              AUDIO_CHANNEL_STATUS_6, 0x1f, ch << 5);
> +       if (ch > I2S_CH_2)
> +               ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
> +                               AUDIO_CHANNEL_STATUS_6, AUDIO_LAYOUT);
> +       else
> +               ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
> +                               AUDIO_CHANNEL_STATUS_6, ~AUDIO_LAYOUT);
> +
> +       /* FS */
> +       switch (params->sample_rate) {
> +       case 32000:
> +               rate = AUDIO_FS_32K;
> +               break;
> +       case 44100:
> +               rate = AUDIO_FS_441K;
> +               break;
> +       case 48000:
> +               rate = AUDIO_FS_48K;
> +               break;
> +       case 88200:
> +               rate = AUDIO_FS_882K;
> +               break;
> +       case 96000:
> +               rate = AUDIO_FS_96K;
> +               break;
> +       case 176400:
> +               rate = AUDIO_FS_1764K;
> +               break;
> +       case 192000:
> +               rate = AUDIO_FS_192K;
> +               break;
> +       default:
> +               DRM_DEV_DEBUG_DRIVER(dev, "sample rate: %d not support",
> +                                    params->sample_rate);
> +               return -EINVAL;
> +       }
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                                   AUDIO_CHANNEL_STATUS_4,
> +                                   0xf0, rate);
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> +                               AP_AV_STATUS, AP_AUDIO_CHG);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : config audio.\n");
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +static void anx7625_audio_shutdown(struct device *dev, void *data)
> +{
> +       DRM_DEV_DEBUG_DRIVER(dev, "stop audio\n");
> +}
> +
> +static int anx7625_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
> +                                      struct device_node *endpoint)
> +{
> +       struct of_endpoint of_ep;
> +       int ret;
> +
> +       ret = of_graph_parse_endpoint(endpoint, &of_ep);
> +       if (ret < 0)
> +               return ret;
> +
> +       /*
> +        * HDMI sound should be located at external DPI port
> +        * Didn't have good way to check where is internal(DSI)
> +        * or external(DPI) bridge
> +        */
> +       return 0;
> +}
> +
> +static void
> +anx7625_audio_update_connector_status(struct anx7625_data *ctx,
> +                                     enum drm_connector_status status)
> +{
> +       if (ctx->plugged_cb && ctx->codec_dev) {
> +               ctx->plugged_cb(ctx->codec_dev,
> +                               status == connector_status_connected);
> +       }
> +}
> +
> +static int anx7625_audio_hook_plugged_cb(struct device *dev, void *data,
> +                                        hdmi_codec_plugged_cb fn,
> +                                        struct device *codec_dev)
> +{
> +       struct anx7625_data *ctx = data;
> +
> +       ctx->plugged_cb = fn;
> +       ctx->codec_dev = codec_dev;
> +       anx7625_audio_update_connector_status(ctx, anx7625_sink_detect(ctx));
> +
> +       return 0;
> +}
> +
> +static const struct hdmi_codec_ops anx7625_codec_ops = {
> +       .hw_params      = anx7625_audio_hw_params,
> +       .audio_shutdown = anx7625_audio_shutdown,
> +       .get_dai_id     = anx7625_hdmi_i2s_get_dai_id,
> +       .hook_plugged_cb = anx7625_audio_hook_plugged_cb,
> +};
> +
> +static void anx7625_unregister_audio(struct anx7625_data *ctx)
> +{
> +       struct device *dev = &ctx->client->dev;
> +
> +       if (ctx->audio_pdev) {
> +               platform_device_unregister(ctx->audio_pdev);
> +               ctx->audio_pdev = NULL;
> +       }
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "unbound to %s", HDMI_CODEC_DRV_NAME);
> +}
> +
> +static int anx7625_register_audio(struct device *dev, struct anx7625_data *ctx)
> +{
> +       struct hdmi_codec_pdata codec_data = {
> +               .ops = &anx7625_codec_ops,
> +               .max_i2s_channels = 8,
> +               .i2s = 1,
> +               .data = ctx,
> +       };
> +
> +       ctx->audio_pdev = platform_device_register_data(dev,
> +                                                       HDMI_CODEC_DRV_NAME,
> +                                                       PLATFORM_DEVID_AUTO,
> +                                                       &codec_data,
> +                                                       sizeof(codec_data));
> +
> +       if (IS_ERR(ctx->audio_pdev))
> +               return IS_ERR(ctx->audio_pdev);
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "bound to %s", HDMI_CODEC_DRV_NAME);
> +
> +       return 0;
> +}
> +
>  static int anx7625_attach_dsi(struct anx7625_data *ctx)
>  {
>         struct mipi_dsi_device *dsi;
> @@ -2064,6 +2285,9 @@ static int anx7625_i2c_probe(struct i2c_client *client,
>                                     DRM_MODE_CONNECTOR_DisplayPort;
>         drm_bridge_add(&platform->bridge);
>
> +       if (platform->pdata.audio_en)
> +               anx7625_register_audio(dev, platform);
> +
>         DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
>
>         return 0;
> @@ -2089,6 +2313,9 @@ static int anx7625_i2c_remove(struct i2c_client *client)
>
>         anx7625_unregister_i2c_dummy_clients(platform);
>
> +       if (platform->pdata.audio_en)
> +               anx7625_unregister_audio(platform);
> +
>         kfree(platform);
>         return 0;
>  }
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> index c6f93e4df0ed..d6be2a83fad9 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> @@ -111,6 +111,7 @@
>  #define AUDIO_CHANNEL_STATUS_6 0xd5
>  #define TDM_SLAVE_MODE 0x10
>  #define I2S_SLAVE_MODE 0x08
> +#define AUDIO_LAYOUT   0x01
>
>  #define AUDIO_CONTROL_REGISTER 0xe6
>  #define TDM_TIMING_MODE 0x08
> @@ -400,6 +401,7 @@ struct anx7625_platform_data {
>         int intp_irq;
>         int is_dpi;
>         int mipi_lanes;
> +       int audio_en;
>         int dp_lane0_swing_reg_cnt;
>         int lane0_reg_data[DP_TX_SWING_REG_CNT];
>         int dp_lane1_swing_reg_cnt;
> @@ -420,6 +422,7 @@ struct anx7625_i2c_client {
>
>  struct anx7625_data {
>         struct anx7625_platform_data pdata;
> +       struct platform_device *audio_pdev;
>         atomic_t power_status;
>         int hpd_status;
>         int hpd_high_cnt;
> @@ -429,6 +432,8 @@ struct anx7625_data {
>         struct anx7625_i2c_client i2c;
>         struct i2c_client *last_client;
>         struct s_edid_data slimport_edid_p;
> +       struct device *codec_dev;
> +       hdmi_codec_plugged_cb plugged_cb;
>         struct work_struct work;
>         struct workqueue_struct *workqueue;
>         char edid_block;
> --
> 2.25.1
>

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

* Re: [PATCH v6 5/5] drm/bridge: anx7625: add HDMI audio function
@ 2021-04-01 13:58     ` Robert Foss
  0 siblings, 0 replies; 52+ messages in thread
From: Robert Foss @ 2021-04-01 13:58 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sheng Pan, Jonas Karlman,
	David Airlie, Bernie Liang, Neil Armstrong, Zhen Li,
	linux-kernel, dri-devel, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Laurent Pinchart, Daniel Vetter,
	Hsin-Yi Wang, Sam Ravnborg, Dan Carpenter, Marek Szyprowski

Hey Xin,

This patch looks good to me.

Reviewed-by: Robert Foss <robert.foss@linaro.org>

On Fri, 19 Mar 2021 at 07:35, Xin Ji <xji@analogixsemi.com> wrote:
>
> Add audio HDMI codec function support, enable it through device true flag
> "analogix,audio-enable".
>
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 227 ++++++++++++++++++++++
>  drivers/gpu/drm/bridge/analogix/anx7625.h |   5 +
>  2 files changed, 232 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index b424a570effa..02bb169d9c57 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -30,6 +30,8 @@
>  #include <drm/drm_print.h>
>  #include <drm/drm_probe_helper.h>
>
> +#include <sound/hdmi-codec.h>
> +
>  #include <video/display_timing.h>
>
>  #include "anx7625.h"
> @@ -150,6 +152,20 @@ static int anx7625_write_and(struct anx7625_data *ctx,
>         return anx7625_reg_write(ctx, client, offset, (val & (mask)));
>  }
>
> +static int anx7625_write_and_or(struct anx7625_data *ctx,
> +                               struct i2c_client *client,
> +                               u8 offset, u8 and_mask, u8 or_mask)
> +{
> +       int val;
> +
> +       val = anx7625_reg_read(ctx, client, offset);
> +       if (val < 0)
> +               return val;
> +
> +       return anx7625_reg_write(ctx, client,
> +                                offset, (val & and_mask) | (or_mask));
> +}
> +
>  static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
>  {
>         int i, ret;
> @@ -1498,6 +1514,9 @@ static int anx7625_parse_dt(struct device *dev,
>         else
>                 DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
>
> +       if (of_property_read_bool(np, "analogix,audio-enable"))
> +               pdata->audio_en = 1;
> +
>         ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
>         if (ret < 0) {
>                 if (ret == -ENODEV)
> @@ -1568,6 +1587,208 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
>                                      connector_status_disconnected;
>  }
>
> +static int anx7625_audio_hw_params(struct device *dev, void *data,
> +                                  struct hdmi_codec_daifmt *fmt,
> +                                  struct hdmi_codec_params *params)
> +{
> +       struct anx7625_data *ctx = dev_get_drvdata(dev);
> +       int wl, ch, rate;
> +       int ret = 0;
> +
> +       if (fmt->fmt != HDMI_DSP_A) {
> +               DRM_DEV_ERROR(dev, "only supports DSP_A\n");
> +               return -EINVAL;
> +       }
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "setting %d Hz, %d bit, %d channels\n",
> +                            params->sample_rate, params->sample_width,
> +                            params->cea.channels);
> +
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                                   AUDIO_CHANNEL_STATUS_6,
> +                                   ~I2S_SLAVE_MODE,
> +                                   TDM_SLAVE_MODE);
> +
> +       /* Word length */
> +       switch (params->sample_width) {
> +       case 16:
> +               wl = AUDIO_W_LEN_16_20MAX;
> +               break;
> +       case 18:
> +               wl = AUDIO_W_LEN_18_20MAX;
> +               break;
> +       case 20:
> +               wl = AUDIO_W_LEN_20_20MAX;
> +               break;
> +       case 24:
> +               wl = AUDIO_W_LEN_24_24MAX;
> +               break;
> +       default:
> +               DRM_DEV_DEBUG_DRIVER(dev, "wordlength: %d bit not support",
> +                                    params->sample_width);
> +               return -EINVAL;
> +       }
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                                   AUDIO_CHANNEL_STATUS_5,
> +                                   0xf0, wl);
> +
> +       /* Channel num */
> +       switch (params->cea.channels) {
> +       case 2:
> +               ch = I2S_CH_2;
> +               break;
> +       case 4:
> +               ch = TDM_CH_4;
> +               break;
> +       case 6:
> +               ch = TDM_CH_6;
> +               break;
> +       case 8:
> +               ch = TDM_CH_8;
> +               break;
> +       default:
> +               DRM_DEV_DEBUG_DRIVER(dev, "channel number: %d not support",
> +                                    params->cea.channels);
> +               return -EINVAL;
> +       }
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                              AUDIO_CHANNEL_STATUS_6, 0x1f, ch << 5);
> +       if (ch > I2S_CH_2)
> +               ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
> +                               AUDIO_CHANNEL_STATUS_6, AUDIO_LAYOUT);
> +       else
> +               ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
> +                               AUDIO_CHANNEL_STATUS_6, ~AUDIO_LAYOUT);
> +
> +       /* FS */
> +       switch (params->sample_rate) {
> +       case 32000:
> +               rate = AUDIO_FS_32K;
> +               break;
> +       case 44100:
> +               rate = AUDIO_FS_441K;
> +               break;
> +       case 48000:
> +               rate = AUDIO_FS_48K;
> +               break;
> +       case 88200:
> +               rate = AUDIO_FS_882K;
> +               break;
> +       case 96000:
> +               rate = AUDIO_FS_96K;
> +               break;
> +       case 176400:
> +               rate = AUDIO_FS_1764K;
> +               break;
> +       case 192000:
> +               rate = AUDIO_FS_192K;
> +               break;
> +       default:
> +               DRM_DEV_DEBUG_DRIVER(dev, "sample rate: %d not support",
> +                                    params->sample_rate);
> +               return -EINVAL;
> +       }
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                                   AUDIO_CHANNEL_STATUS_4,
> +                                   0xf0, rate);
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> +                               AP_AV_STATUS, AP_AUDIO_CHG);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : config audio.\n");
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +static void anx7625_audio_shutdown(struct device *dev, void *data)
> +{
> +       DRM_DEV_DEBUG_DRIVER(dev, "stop audio\n");
> +}
> +
> +static int anx7625_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
> +                                      struct device_node *endpoint)
> +{
> +       struct of_endpoint of_ep;
> +       int ret;
> +
> +       ret = of_graph_parse_endpoint(endpoint, &of_ep);
> +       if (ret < 0)
> +               return ret;
> +
> +       /*
> +        * HDMI sound should be located at external DPI port
> +        * Didn't have good way to check where is internal(DSI)
> +        * or external(DPI) bridge
> +        */
> +       return 0;
> +}
> +
> +static void
> +anx7625_audio_update_connector_status(struct anx7625_data *ctx,
> +                                     enum drm_connector_status status)
> +{
> +       if (ctx->plugged_cb && ctx->codec_dev) {
> +               ctx->plugged_cb(ctx->codec_dev,
> +                               status == connector_status_connected);
> +       }
> +}
> +
> +static int anx7625_audio_hook_plugged_cb(struct device *dev, void *data,
> +                                        hdmi_codec_plugged_cb fn,
> +                                        struct device *codec_dev)
> +{
> +       struct anx7625_data *ctx = data;
> +
> +       ctx->plugged_cb = fn;
> +       ctx->codec_dev = codec_dev;
> +       anx7625_audio_update_connector_status(ctx, anx7625_sink_detect(ctx));
> +
> +       return 0;
> +}
> +
> +static const struct hdmi_codec_ops anx7625_codec_ops = {
> +       .hw_params      = anx7625_audio_hw_params,
> +       .audio_shutdown = anx7625_audio_shutdown,
> +       .get_dai_id     = anx7625_hdmi_i2s_get_dai_id,
> +       .hook_plugged_cb = anx7625_audio_hook_plugged_cb,
> +};
> +
> +static void anx7625_unregister_audio(struct anx7625_data *ctx)
> +{
> +       struct device *dev = &ctx->client->dev;
> +
> +       if (ctx->audio_pdev) {
> +               platform_device_unregister(ctx->audio_pdev);
> +               ctx->audio_pdev = NULL;
> +       }
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "unbound to %s", HDMI_CODEC_DRV_NAME);
> +}
> +
> +static int anx7625_register_audio(struct device *dev, struct anx7625_data *ctx)
> +{
> +       struct hdmi_codec_pdata codec_data = {
> +               .ops = &anx7625_codec_ops,
> +               .max_i2s_channels = 8,
> +               .i2s = 1,
> +               .data = ctx,
> +       };
> +
> +       ctx->audio_pdev = platform_device_register_data(dev,
> +                                                       HDMI_CODEC_DRV_NAME,
> +                                                       PLATFORM_DEVID_AUTO,
> +                                                       &codec_data,
> +                                                       sizeof(codec_data));
> +
> +       if (IS_ERR(ctx->audio_pdev))
> +               return IS_ERR(ctx->audio_pdev);
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "bound to %s", HDMI_CODEC_DRV_NAME);
> +
> +       return 0;
> +}
> +
>  static int anx7625_attach_dsi(struct anx7625_data *ctx)
>  {
>         struct mipi_dsi_device *dsi;
> @@ -2064,6 +2285,9 @@ static int anx7625_i2c_probe(struct i2c_client *client,
>                                     DRM_MODE_CONNECTOR_DisplayPort;
>         drm_bridge_add(&platform->bridge);
>
> +       if (platform->pdata.audio_en)
> +               anx7625_register_audio(dev, platform);
> +
>         DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
>
>         return 0;
> @@ -2089,6 +2313,9 @@ static int anx7625_i2c_remove(struct i2c_client *client)
>
>         anx7625_unregister_i2c_dummy_clients(platform);
>
> +       if (platform->pdata.audio_en)
> +               anx7625_unregister_audio(platform);
> +
>         kfree(platform);
>         return 0;
>  }
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> index c6f93e4df0ed..d6be2a83fad9 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> @@ -111,6 +111,7 @@
>  #define AUDIO_CHANNEL_STATUS_6 0xd5
>  #define TDM_SLAVE_MODE 0x10
>  #define I2S_SLAVE_MODE 0x08
> +#define AUDIO_LAYOUT   0x01
>
>  #define AUDIO_CONTROL_REGISTER 0xe6
>  #define TDM_TIMING_MODE 0x08
> @@ -400,6 +401,7 @@ struct anx7625_platform_data {
>         int intp_irq;
>         int is_dpi;
>         int mipi_lanes;
> +       int audio_en;
>         int dp_lane0_swing_reg_cnt;
>         int lane0_reg_data[DP_TX_SWING_REG_CNT];
>         int dp_lane1_swing_reg_cnt;
> @@ -420,6 +422,7 @@ struct anx7625_i2c_client {
>
>  struct anx7625_data {
>         struct anx7625_platform_data pdata;
> +       struct platform_device *audio_pdev;
>         atomic_t power_status;
>         int hpd_status;
>         int hpd_high_cnt;
> @@ -429,6 +432,8 @@ struct anx7625_data {
>         struct anx7625_i2c_client i2c;
>         struct i2c_client *last_client;
>         struct s_edid_data slimport_edid_p;
> +       struct device *codec_dev;
> +       hdmi_codec_plugged_cb plugged_cb;
>         struct work_struct work;
>         struct workqueue_struct *workqueue;
>         char edid_block;
> --
> 2.25.1
>
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v6 5/5] drm/bridge: anx7625: add HDMI audio function
@ 2021-04-01 13:58     ` Robert Foss
  0 siblings, 0 replies; 52+ messages in thread
From: Robert Foss @ 2021-04-01 13:58 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sheng Pan, Jonas Karlman,
	David Airlie, Bernie Liang, Neil Armstrong, Zhen Li,
	linux-kernel, dri-devel, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Laurent Pinchart, Hsin-Yi Wang,
	Sam Ravnborg, Dan Carpenter, Marek Szyprowski

Hey Xin,

This patch looks good to me.

Reviewed-by: Robert Foss <robert.foss@linaro.org>

On Fri, 19 Mar 2021 at 07:35, Xin Ji <xji@analogixsemi.com> wrote:
>
> Add audio HDMI codec function support, enable it through device true flag
> "analogix,audio-enable".
>
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 227 ++++++++++++++++++++++
>  drivers/gpu/drm/bridge/analogix/anx7625.h |   5 +
>  2 files changed, 232 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index b424a570effa..02bb169d9c57 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -30,6 +30,8 @@
>  #include <drm/drm_print.h>
>  #include <drm/drm_probe_helper.h>
>
> +#include <sound/hdmi-codec.h>
> +
>  #include <video/display_timing.h>
>
>  #include "anx7625.h"
> @@ -150,6 +152,20 @@ static int anx7625_write_and(struct anx7625_data *ctx,
>         return anx7625_reg_write(ctx, client, offset, (val & (mask)));
>  }
>
> +static int anx7625_write_and_or(struct anx7625_data *ctx,
> +                               struct i2c_client *client,
> +                               u8 offset, u8 and_mask, u8 or_mask)
> +{
> +       int val;
> +
> +       val = anx7625_reg_read(ctx, client, offset);
> +       if (val < 0)
> +               return val;
> +
> +       return anx7625_reg_write(ctx, client,
> +                                offset, (val & and_mask) | (or_mask));
> +}
> +
>  static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
>  {
>         int i, ret;
> @@ -1498,6 +1514,9 @@ static int anx7625_parse_dt(struct device *dev,
>         else
>                 DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
>
> +       if (of_property_read_bool(np, "analogix,audio-enable"))
> +               pdata->audio_en = 1;
> +
>         ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
>         if (ret < 0) {
>                 if (ret == -ENODEV)
> @@ -1568,6 +1587,208 @@ static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
>                                      connector_status_disconnected;
>  }
>
> +static int anx7625_audio_hw_params(struct device *dev, void *data,
> +                                  struct hdmi_codec_daifmt *fmt,
> +                                  struct hdmi_codec_params *params)
> +{
> +       struct anx7625_data *ctx = dev_get_drvdata(dev);
> +       int wl, ch, rate;
> +       int ret = 0;
> +
> +       if (fmt->fmt != HDMI_DSP_A) {
> +               DRM_DEV_ERROR(dev, "only supports DSP_A\n");
> +               return -EINVAL;
> +       }
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "setting %d Hz, %d bit, %d channels\n",
> +                            params->sample_rate, params->sample_width,
> +                            params->cea.channels);
> +
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                                   AUDIO_CHANNEL_STATUS_6,
> +                                   ~I2S_SLAVE_MODE,
> +                                   TDM_SLAVE_MODE);
> +
> +       /* Word length */
> +       switch (params->sample_width) {
> +       case 16:
> +               wl = AUDIO_W_LEN_16_20MAX;
> +               break;
> +       case 18:
> +               wl = AUDIO_W_LEN_18_20MAX;
> +               break;
> +       case 20:
> +               wl = AUDIO_W_LEN_20_20MAX;
> +               break;
> +       case 24:
> +               wl = AUDIO_W_LEN_24_24MAX;
> +               break;
> +       default:
> +               DRM_DEV_DEBUG_DRIVER(dev, "wordlength: %d bit not support",
> +                                    params->sample_width);
> +               return -EINVAL;
> +       }
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                                   AUDIO_CHANNEL_STATUS_5,
> +                                   0xf0, wl);
> +
> +       /* Channel num */
> +       switch (params->cea.channels) {
> +       case 2:
> +               ch = I2S_CH_2;
> +               break;
> +       case 4:
> +               ch = TDM_CH_4;
> +               break;
> +       case 6:
> +               ch = TDM_CH_6;
> +               break;
> +       case 8:
> +               ch = TDM_CH_8;
> +               break;
> +       default:
> +               DRM_DEV_DEBUG_DRIVER(dev, "channel number: %d not support",
> +                                    params->cea.channels);
> +               return -EINVAL;
> +       }
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                              AUDIO_CHANNEL_STATUS_6, 0x1f, ch << 5);
> +       if (ch > I2S_CH_2)
> +               ret |= anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
> +                               AUDIO_CHANNEL_STATUS_6, AUDIO_LAYOUT);
> +       else
> +               ret |= anx7625_write_and(ctx, ctx->i2c.tx_p2_client,
> +                               AUDIO_CHANNEL_STATUS_6, ~AUDIO_LAYOUT);
> +
> +       /* FS */
> +       switch (params->sample_rate) {
> +       case 32000:
> +               rate = AUDIO_FS_32K;
> +               break;
> +       case 44100:
> +               rate = AUDIO_FS_441K;
> +               break;
> +       case 48000:
> +               rate = AUDIO_FS_48K;
> +               break;
> +       case 88200:
> +               rate = AUDIO_FS_882K;
> +               break;
> +       case 96000:
> +               rate = AUDIO_FS_96K;
> +               break;
> +       case 176400:
> +               rate = AUDIO_FS_1764K;
> +               break;
> +       case 192000:
> +               rate = AUDIO_FS_192K;
> +               break;
> +       default:
> +               DRM_DEV_DEBUG_DRIVER(dev, "sample rate: %d not support",
> +                                    params->sample_rate);
> +               return -EINVAL;
> +       }
> +       ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> +                                   AUDIO_CHANNEL_STATUS_4,
> +                                   0xf0, rate);
> +       ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> +                               AP_AV_STATUS, AP_AUDIO_CHG);
> +       if (ret < 0) {
> +               DRM_DEV_ERROR(dev, "IO error : config audio.\n");
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +static void anx7625_audio_shutdown(struct device *dev, void *data)
> +{
> +       DRM_DEV_DEBUG_DRIVER(dev, "stop audio\n");
> +}
> +
> +static int anx7625_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
> +                                      struct device_node *endpoint)
> +{
> +       struct of_endpoint of_ep;
> +       int ret;
> +
> +       ret = of_graph_parse_endpoint(endpoint, &of_ep);
> +       if (ret < 0)
> +               return ret;
> +
> +       /*
> +        * HDMI sound should be located at external DPI port
> +        * Didn't have good way to check where is internal(DSI)
> +        * or external(DPI) bridge
> +        */
> +       return 0;
> +}
> +
> +static void
> +anx7625_audio_update_connector_status(struct anx7625_data *ctx,
> +                                     enum drm_connector_status status)
> +{
> +       if (ctx->plugged_cb && ctx->codec_dev) {
> +               ctx->plugged_cb(ctx->codec_dev,
> +                               status == connector_status_connected);
> +       }
> +}
> +
> +static int anx7625_audio_hook_plugged_cb(struct device *dev, void *data,
> +                                        hdmi_codec_plugged_cb fn,
> +                                        struct device *codec_dev)
> +{
> +       struct anx7625_data *ctx = data;
> +
> +       ctx->plugged_cb = fn;
> +       ctx->codec_dev = codec_dev;
> +       anx7625_audio_update_connector_status(ctx, anx7625_sink_detect(ctx));
> +
> +       return 0;
> +}
> +
> +static const struct hdmi_codec_ops anx7625_codec_ops = {
> +       .hw_params      = anx7625_audio_hw_params,
> +       .audio_shutdown = anx7625_audio_shutdown,
> +       .get_dai_id     = anx7625_hdmi_i2s_get_dai_id,
> +       .hook_plugged_cb = anx7625_audio_hook_plugged_cb,
> +};
> +
> +static void anx7625_unregister_audio(struct anx7625_data *ctx)
> +{
> +       struct device *dev = &ctx->client->dev;
> +
> +       if (ctx->audio_pdev) {
> +               platform_device_unregister(ctx->audio_pdev);
> +               ctx->audio_pdev = NULL;
> +       }
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "unbound to %s", HDMI_CODEC_DRV_NAME);
> +}
> +
> +static int anx7625_register_audio(struct device *dev, struct anx7625_data *ctx)
> +{
> +       struct hdmi_codec_pdata codec_data = {
> +               .ops = &anx7625_codec_ops,
> +               .max_i2s_channels = 8,
> +               .i2s = 1,
> +               .data = ctx,
> +       };
> +
> +       ctx->audio_pdev = platform_device_register_data(dev,
> +                                                       HDMI_CODEC_DRV_NAME,
> +                                                       PLATFORM_DEVID_AUTO,
> +                                                       &codec_data,
> +                                                       sizeof(codec_data));
> +
> +       if (IS_ERR(ctx->audio_pdev))
> +               return IS_ERR(ctx->audio_pdev);
> +
> +       DRM_DEV_DEBUG_DRIVER(dev, "bound to %s", HDMI_CODEC_DRV_NAME);
> +
> +       return 0;
> +}
> +
>  static int anx7625_attach_dsi(struct anx7625_data *ctx)
>  {
>         struct mipi_dsi_device *dsi;
> @@ -2064,6 +2285,9 @@ static int anx7625_i2c_probe(struct i2c_client *client,
>                                     DRM_MODE_CONNECTOR_DisplayPort;
>         drm_bridge_add(&platform->bridge);
>
> +       if (platform->pdata.audio_en)
> +               anx7625_register_audio(dev, platform);
> +
>         DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
>
>         return 0;
> @@ -2089,6 +2313,9 @@ static int anx7625_i2c_remove(struct i2c_client *client)
>
>         anx7625_unregister_i2c_dummy_clients(platform);
>
> +       if (platform->pdata.audio_en)
> +               anx7625_unregister_audio(platform);
> +
>         kfree(platform);
>         return 0;
>  }
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> index c6f93e4df0ed..d6be2a83fad9 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> @@ -111,6 +111,7 @@
>  #define AUDIO_CHANNEL_STATUS_6 0xd5
>  #define TDM_SLAVE_MODE 0x10
>  #define I2S_SLAVE_MODE 0x08
> +#define AUDIO_LAYOUT   0x01
>
>  #define AUDIO_CONTROL_REGISTER 0xe6
>  #define TDM_TIMING_MODE 0x08
> @@ -400,6 +401,7 @@ struct anx7625_platform_data {
>         int intp_irq;
>         int is_dpi;
>         int mipi_lanes;
> +       int audio_en;
>         int dp_lane0_swing_reg_cnt;
>         int lane0_reg_data[DP_TX_SWING_REG_CNT];
>         int dp_lane1_swing_reg_cnt;
> @@ -420,6 +422,7 @@ struct anx7625_i2c_client {
>
>  struct anx7625_data {
>         struct anx7625_platform_data pdata;
> +       struct platform_device *audio_pdev;
>         atomic_t power_status;
>         int hpd_status;
>         int hpd_high_cnt;
> @@ -429,6 +432,8 @@ struct anx7625_data {
>         struct anx7625_i2c_client i2c;
>         struct i2c_client *last_client;
>         struct s_edid_data slimport_edid_p;
> +       struct device *codec_dev;
> +       hdmi_codec_plugged_cb plugged_cb;
>         struct work_struct work;
>         struct workqueue_struct *workqueue;
>         char edid_block;
> --
> 2.25.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
  2021-03-29 18:02         ` Sean Paul
  (?)
@ 2021-04-02  2:27           ` Xin Ji
  -1 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-04-02  2:27 UTC (permalink / raw)
  To: Sean Paul
  Cc: Foss, Nicolas Boichat, Andrzej Hajda, devel, Jernej Skrabec,
	Sheng Pan, Jonas Karlman, David Airlie, Bernie Liang,
	Neil Armstrong, Zhen Li, LKML, dri-devel, Vasily Khoruzhick,
	Boris Brezillon, Torsten Duwe, Laurent Pinchart, Hsin-Yi Wang,
	Sam Ravnborg, Dan Carpenter, Marek Szyprowski

On Mon, Mar 29, 2021 at 02:02:08PM -0400, Sean Paul wrote:
> On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
> >
> > On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > >
> > > > Add HDCP feature, enable HDCP function through chip internal key
> > > > and downstream's capability.
> > > >
> > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > ---
> 
> /snip
> 
> > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > >  {
> > > >         int ret;
> > > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > >                 return;
> > > >         }
> > > >
> > > > +       /* HDCP config */
> > > > +       anx7625_hdcp_setting(ctx);
> > >
> > > You should really use the "Content Protection" property to
> > > enable/disable HDCP instead of force-enabling it at all times.
> > >
> > > Sean
> > Hi Sean, it's hard to implement "Content Protection" property, we have
> > implemented HDCP in firmware, it is not compatible with it. We don't
> > have interface to get Downstream Cert.
> > Thanks,
> > Xin
> 
> Hi Xin,
> I'm sorry, I don't understand what you mean when you say you don't
> have an interface to get Downstream Cert.
> 
> The Content Protection property is just a means through which
> userspace can turn on and turn off HDCP when it needs. As far as I can
> tell, your patch turns on HDCP when the display is enabled and leaves
> it on until it is disabled. This is undesirable since it forces HDCP
> on the user.
> 
> Is it impossible to enable/disable HDCP outside of display
> enable/disable on your hardware?
> 
> Thanks,
> 
> Sean
Hi Sean, I have commit a test patch on google review site, can you
please help to review it? I'll use Connector's ".atomic_check()"
interface to detect Content Protection property change.
(https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2674580)
Thanks,
Xin
> 
> > >
> > > > +
> > > >         if (ctx->pdata.is_dpi)
> > > >                 ret = anx7625_dpi_config(ctx);
> > > >         else
> 
> /snip

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-04-02  2:27           ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-04-02  2:27 UTC (permalink / raw)
  To: Sean Paul
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Zhen Li, dri-devel, Neil Armstrong,
	LKML, Foss, Vasily Khoruzhick, Andrzej Hajda, Boris Brezillon,
	Torsten Duwe, Sheng Pan, Hsin-Yi Wang, Marek Szyprowski,
	Bernie Liang, Dan Carpenter, Laurent Pinchart

On Mon, Mar 29, 2021 at 02:02:08PM -0400, Sean Paul wrote:
> On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
> >
> > On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > >
> > > > Add HDCP feature, enable HDCP function through chip internal key
> > > > and downstream's capability.
> > > >
> > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > ---
> 
> /snip
> 
> > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > >  {
> > > >         int ret;
> > > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > >                 return;
> > > >         }
> > > >
> > > > +       /* HDCP config */
> > > > +       anx7625_hdcp_setting(ctx);
> > >
> > > You should really use the "Content Protection" property to
> > > enable/disable HDCP instead of force-enabling it at all times.
> > >
> > > Sean
> > Hi Sean, it's hard to implement "Content Protection" property, we have
> > implemented HDCP in firmware, it is not compatible with it. We don't
> > have interface to get Downstream Cert.
> > Thanks,
> > Xin
> 
> Hi Xin,
> I'm sorry, I don't understand what you mean when you say you don't
> have an interface to get Downstream Cert.
> 
> The Content Protection property is just a means through which
> userspace can turn on and turn off HDCP when it needs. As far as I can
> tell, your patch turns on HDCP when the display is enabled and leaves
> it on until it is disabled. This is undesirable since it forces HDCP
> on the user.
> 
> Is it impossible to enable/disable HDCP outside of display
> enable/disable on your hardware?
> 
> Thanks,
> 
> Sean
Hi Sean, I have commit a test patch on google review site, can you
please help to review it? I'll use Connector's ".atomic_check()"
interface to detect Content Protection property change.
(https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2674580)
Thanks,
Xin
> 
> > >
> > > > +
> > > >         if (ctx->pdata.is_dpi)
> > > >                 ret = anx7625_dpi_config(ctx);
> > > >         else
> 
> /snip
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-04-02  2:27           ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-04-02  2:27 UTC (permalink / raw)
  To: Sean Paul
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Zhen Li, dri-devel, Neil Armstrong,
	LKML, Foss, Vasily Khoruzhick, Andrzej Hajda, Boris Brezillon,
	Torsten Duwe, Sheng Pan, Hsin-Yi Wang, Marek Szyprowski,
	Bernie Liang, Dan Carpenter, Laurent Pinchart

On Mon, Mar 29, 2021 at 02:02:08PM -0400, Sean Paul wrote:
> On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
> >
> > On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > >
> > > > Add HDCP feature, enable HDCP function through chip internal key
> > > > and downstream's capability.
> > > >
> > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > ---
> 
> /snip
> 
> > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > >  {
> > > >         int ret;
> > > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > >                 return;
> > > >         }
> > > >
> > > > +       /* HDCP config */
> > > > +       anx7625_hdcp_setting(ctx);
> > >
> > > You should really use the "Content Protection" property to
> > > enable/disable HDCP instead of force-enabling it at all times.
> > >
> > > Sean
> > Hi Sean, it's hard to implement "Content Protection" property, we have
> > implemented HDCP in firmware, it is not compatible with it. We don't
> > have interface to get Downstream Cert.
> > Thanks,
> > Xin
> 
> Hi Xin,
> I'm sorry, I don't understand what you mean when you say you don't
> have an interface to get Downstream Cert.
> 
> The Content Protection property is just a means through which
> userspace can turn on and turn off HDCP when it needs. As far as I can
> tell, your patch turns on HDCP when the display is enabled and leaves
> it on until it is disabled. This is undesirable since it forces HDCP
> on the user.
> 
> Is it impossible to enable/disable HDCP outside of display
> enable/disable on your hardware?
> 
> Thanks,
> 
> Sean
Hi Sean, I have commit a test patch on google review site, can you
please help to review it? I'll use Connector's ".atomic_check()"
interface to detect Content Protection property change.
(https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2674580)
Thanks,
Xin
> 
> > >
> > > > +
> > > >         if (ctx->pdata.is_dpi)
> > > >                 ret = anx7625_dpi_config(ctx);
> > > >         else
> 
> /snip
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 1/5] dt-bindings:drm/bridge:anx7625:add vendor define flags
  2021-04-01 12:33         ` Robert Foss
@ 2021-04-02  2:29           ` Xin Ji
  -1 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-04-02  2:29 UTC (permalink / raw)
  To: Robert Foss
  Cc: Laurent Pinchart, Rob Herring, David Airlie, Nicolas Boichat,
	Hsin-Yi Wang, Daniel Vetter, Sam Ravnborg, Laurent Pinchart,
	Maxime Ripard, Mark Brown, Ricardo Cañuelo, dri-devel,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Bernie Liang, Sheng Pan, Zhen Li, linux-kernel

On Thu, Apr 01, 2021 at 02:33:47PM +0200, Robert Foss wrote:
> Hey Xin,
> 
> This series no longer applies to drm-misc/drm-misc-next, please rebase it.
Hi Robert Foss, OK, I'll rebase it on the drm-misc-next after confirmed
HDCP patch with Sean Paul.
Thanks,
Xin
> 
> On Wed, 24 Mar 2021 at 08:52, Xin Ji <xji@analogixsemi.com> wrote:
> >
> > On Sun, Mar 21, 2021 at 02:00:38PM +0200, Laurent Pinchart wrote:
> > > Hi Xin,
> > >
> > > Thank you for the patch.
> > >
> > > On Fri, Mar 19, 2021 at 02:32:39PM +0800, Xin Ji wrote:
> > > > Add 'bus-type' and 'data-lanes' define for port0. Define DP tx lane0,
> > > > lane1 swing register array define, and audio enable flag.
> > > >
> > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > ---
> > > >  .../display/bridge/analogix,anx7625.yaml      | 58 ++++++++++++++++++-
> > > >  1 file changed, 57 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > > index c789784efe30..3f54d5876982 100644
> > > > --- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > > +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > > @@ -34,6 +34,26 @@ properties:
> > > >      description: used for reset chip control, RESET_N pin B7.
> > > >      maxItems: 1
> > > >
> > > > +  analogix,lane0-swing:
> > > > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > > > +    minItems: 1
> > > > +    maxItems: 20
> > > > +    description:
> > > > +      an array of swing register setting for DP tx lane0 PHY, please don't
> > > > +      add this property, or contact vendor.
> > >
> > > DT properties need to be documented. Contacting the vendor doesn't count
> > > as documentation I'm afraid.
> >
> > Hi Laurent Pinchart, thanks for your comment. For the DP phy swing
> > setting, it is hard to describe in here, needs to refer the anx7625
> > datasheet and programming guide. Basically, no need to change the DP phy
> > swing setting.
> >
> 
> Laurent is right. But if the value practically is a constant, you can
> move the swing register into the driver. It should still be documented
> as well as possible, but we can be a little bit more flexible.
> 
> > > > @@ -73,6 +123,10 @@ examples:
> > > >              enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
> > > >              reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
> > > >
> > > > +            analogix,audio-enable;
> > > > +            analogix,lane0-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > > > +            analogix,lane1-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > > > +
> > > >              ports {
> > > >                  #address-cells = <1>;
> > > >                  #size-cells = <0>;

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

* Re: [PATCH v6 1/5] dt-bindings:drm/bridge:anx7625:add vendor define flags
@ 2021-04-02  2:29           ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-04-02  2:29 UTC (permalink / raw)
  To: Robert Foss
  Cc: Nicolas Boichat, Laurent Pinchart, dri-devel,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	David Airlie, Ricardo Cañuelo, Mark Brown, Zhen Li,
	linux-kernel, Rob Herring, Laurent Pinchart, Hsin-Yi Wang,
	Sam Ravnborg, Bernie Liang, Sheng Pan

On Thu, Apr 01, 2021 at 02:33:47PM +0200, Robert Foss wrote:
> Hey Xin,
> 
> This series no longer applies to drm-misc/drm-misc-next, please rebase it.
Hi Robert Foss, OK, I'll rebase it on the drm-misc-next after confirmed
HDCP patch with Sean Paul.
Thanks,
Xin
> 
> On Wed, 24 Mar 2021 at 08:52, Xin Ji <xji@analogixsemi.com> wrote:
> >
> > On Sun, Mar 21, 2021 at 02:00:38PM +0200, Laurent Pinchart wrote:
> > > Hi Xin,
> > >
> > > Thank you for the patch.
> > >
> > > On Fri, Mar 19, 2021 at 02:32:39PM +0800, Xin Ji wrote:
> > > > Add 'bus-type' and 'data-lanes' define for port0. Define DP tx lane0,
> > > > lane1 swing register array define, and audio enable flag.
> > > >
> > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > ---
> > > >  .../display/bridge/analogix,anx7625.yaml      | 58 ++++++++++++++++++-
> > > >  1 file changed, 57 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > > index c789784efe30..3f54d5876982 100644
> > > > --- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > > +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> > > > @@ -34,6 +34,26 @@ properties:
> > > >      description: used for reset chip control, RESET_N pin B7.
> > > >      maxItems: 1
> > > >
> > > > +  analogix,lane0-swing:
> > > > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > > > +    minItems: 1
> > > > +    maxItems: 20
> > > > +    description:
> > > > +      an array of swing register setting for DP tx lane0 PHY, please don't
> > > > +      add this property, or contact vendor.
> > >
> > > DT properties need to be documented. Contacting the vendor doesn't count
> > > as documentation I'm afraid.
> >
> > Hi Laurent Pinchart, thanks for your comment. For the DP phy swing
> > setting, it is hard to describe in here, needs to refer the anx7625
> > datasheet and programming guide. Basically, no need to change the DP phy
> > swing setting.
> >
> 
> Laurent is right. But if the value practically is a constant, you can
> move the swing register into the driver. It should still be documented
> as well as possible, but we can be a little bit more flexible.
> 
> > > > @@ -73,6 +123,10 @@ examples:
> > > >              enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
> > > >              reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
> > > >
> > > > +            analogix,audio-enable;
> > > > +            analogix,lane0-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > > > +            analogix,lane1-swing = <0x14 0x54 0x64 0x74 0x29 0x7b 0x77 0x5b>;
> > > > +
> > > >              ports {
> > > >                  #address-cells = <1>;
> > > >                  #size-cells = <0>;
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
  2021-04-02  2:27           ` Xin Ji
  (?)
@ 2021-04-02  8:59             ` Laurent Pinchart
  -1 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2021-04-02  8:59 UTC (permalink / raw)
  To: Xin Ji
  Cc: Sean Paul, Foss, Nicolas Boichat, Andrzej Hajda, devel,
	Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, LKML, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe, Hsin-Yi Wang,
	Sam Ravnborg, Dan Carpenter, Marek Szyprowski

Hi Xin,

On Fri, Apr 02, 2021 at 10:27:08AM +0800, Xin Ji wrote:
> On Mon, Mar 29, 2021 at 02:02:08PM -0400, Sean Paul wrote:
> > On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
> > >
> > > On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > > > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > > >
> > > > > Add HDCP feature, enable HDCP function through chip internal key
> > > > > and downstream's capability.
> > > > >
> > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > ---
> > 
> > /snip
> > 
> > > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > >  {
> > > > >         int ret;
> > > > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > >                 return;
> > > > >         }
> > > > >
> > > > > +       /* HDCP config */
> > > > > +       anx7625_hdcp_setting(ctx);
> > > >
> > > > You should really use the "Content Protection" property to
> > > > enable/disable HDCP instead of force-enabling it at all times.
> > >
> > > Hi Sean, it's hard to implement "Content Protection" property, we have
> > > implemented HDCP in firmware, it is not compatible with it. We don't
> > > have interface to get Downstream Cert.
> > > Thanks,
> > > Xin
> > 
> > Hi Xin,
> > I'm sorry, I don't understand what you mean when you say you don't
> > have an interface to get Downstream Cert.
> > 
> > The Content Protection property is just a means through which
> > userspace can turn on and turn off HDCP when it needs. As far as I can
> > tell, your patch turns on HDCP when the display is enabled and leaves
> > it on until it is disabled. This is undesirable since it forces HDCP
> > on the user.
> > 
> > Is it impossible to enable/disable HDCP outside of display
> > enable/disable on your hardware?
>
> Hi Sean, I have commit a test patch on google review site, can you
> please help to review it? I'll use Connector's ".atomic_check()"
> interface to detect Content Protection property change.
> (https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2674580)

Please note that upstream review happens on mailing lists, not in
gerrit. Internal reviews for Chrome OS development are certainly fine
there, but that will not mean the patch will then be accepted upstream
as-is, it will still need to go through the upstream review process,
without any shortcut. I strongly recommend using an upstream-first
strategy, with public review.

> > > > > +
> > > > >         if (ctx->pdata.is_dpi)
> > > > >                 ret = anx7625_dpi_config(ctx);
> > > > >         else
> > 
> > /snip

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-04-02  8:59             ` Laurent Pinchart
  0 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2021-04-02  8:59 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Bernie Liang, dri-devel,
	Neil Armstrong, LKML, Foss, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Sheng Pan, Zhen Li, Hsin-Yi Wang,
	Sean Paul, Dan Carpenter, Marek Szyprowski

Hi Xin,

On Fri, Apr 02, 2021 at 10:27:08AM +0800, Xin Ji wrote:
> On Mon, Mar 29, 2021 at 02:02:08PM -0400, Sean Paul wrote:
> > On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
> > >
> > > On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > > > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > > >
> > > > > Add HDCP feature, enable HDCP function through chip internal key
> > > > > and downstream's capability.
> > > > >
> > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > ---
> > 
> > /snip
> > 
> > > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > >  {
> > > > >         int ret;
> > > > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > >                 return;
> > > > >         }
> > > > >
> > > > > +       /* HDCP config */
> > > > > +       anx7625_hdcp_setting(ctx);
> > > >
> > > > You should really use the "Content Protection" property to
> > > > enable/disable HDCP instead of force-enabling it at all times.
> > >
> > > Hi Sean, it's hard to implement "Content Protection" property, we have
> > > implemented HDCP in firmware, it is not compatible with it. We don't
> > > have interface to get Downstream Cert.
> > > Thanks,
> > > Xin
> > 
> > Hi Xin,
> > I'm sorry, I don't understand what you mean when you say you don't
> > have an interface to get Downstream Cert.
> > 
> > The Content Protection property is just a means through which
> > userspace can turn on and turn off HDCP when it needs. As far as I can
> > tell, your patch turns on HDCP when the display is enabled and leaves
> > it on until it is disabled. This is undesirable since it forces HDCP
> > on the user.
> > 
> > Is it impossible to enable/disable HDCP outside of display
> > enable/disable on your hardware?
>
> Hi Sean, I have commit a test patch on google review site, can you
> please help to review it? I'll use Connector's ".atomic_check()"
> interface to detect Content Protection property change.
> (https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2674580)

Please note that upstream review happens on mailing lists, not in
gerrit. Internal reviews for Chrome OS development are certainly fine
there, but that will not mean the patch will then be accepted upstream
as-is, it will still need to go through the upstream review process,
without any shortcut. I strongly recommend using an upstream-first
strategy, with public review.

> > > > > +
> > > > >         if (ctx->pdata.is_dpi)
> > > > >                 ret = anx7625_dpi_config(ctx);
> > > > >         else
> > 
> > /snip

-- 
Regards,

Laurent Pinchart
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-04-02  8:59             ` Laurent Pinchart
  0 siblings, 0 replies; 52+ messages in thread
From: Laurent Pinchart @ 2021-04-02  8:59 UTC (permalink / raw)
  To: Xin Ji
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Bernie Liang, dri-devel,
	Neil Armstrong, LKML, Foss, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Sheng Pan, Zhen Li, Hsin-Yi Wang,
	Sean Paul, Dan Carpenter, Marek Szyprowski

Hi Xin,

On Fri, Apr 02, 2021 at 10:27:08AM +0800, Xin Ji wrote:
> On Mon, Mar 29, 2021 at 02:02:08PM -0400, Sean Paul wrote:
> > On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
> > >
> > > On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > > > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > > >
> > > > > Add HDCP feature, enable HDCP function through chip internal key
> > > > > and downstream's capability.
> > > > >
> > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > ---
> > 
> > /snip
> > 
> > > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > >  {
> > > > >         int ret;
> > > > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > >                 return;
> > > > >         }
> > > > >
> > > > > +       /* HDCP config */
> > > > > +       anx7625_hdcp_setting(ctx);
> > > >
> > > > You should really use the "Content Protection" property to
> > > > enable/disable HDCP instead of force-enabling it at all times.
> > >
> > > Hi Sean, it's hard to implement "Content Protection" property, we have
> > > implemented HDCP in firmware, it is not compatible with it. We don't
> > > have interface to get Downstream Cert.
> > > Thanks,
> > > Xin
> > 
> > Hi Xin,
> > I'm sorry, I don't understand what you mean when you say you don't
> > have an interface to get Downstream Cert.
> > 
> > The Content Protection property is just a means through which
> > userspace can turn on and turn off HDCP when it needs. As far as I can
> > tell, your patch turns on HDCP when the display is enabled and leaves
> > it on until it is disabled. This is undesirable since it forces HDCP
> > on the user.
> > 
> > Is it impossible to enable/disable HDCP outside of display
> > enable/disable on your hardware?
>
> Hi Sean, I have commit a test patch on google review site, can you
> please help to review it? I'll use Connector's ".atomic_check()"
> interface to detect Content Protection property change.
> (https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2674580)

Please note that upstream review happens on mailing lists, not in
gerrit. Internal reviews for Chrome OS development are certainly fine
there, but that will not mean the patch will then be accepted upstream
as-is, it will still need to go through the upstream review process,
without any shortcut. I strongly recommend using an upstream-first
strategy, with public review.

> > > > > +
> > > > >         if (ctx->pdata.is_dpi)
> > > > >                 ret = anx7625_dpi_config(ctx);
> > > > >         else
> > 
> > /snip

-- 
Regards,

Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
  2021-04-02  8:59             ` Laurent Pinchart
  (?)
@ 2021-04-02  9:15               ` Xin Ji
  -1 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-04-02  9:15 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Sean Paul, Foss, Nicolas Boichat, Andrzej Hajda, devel,
	Jernej Skrabec, Sheng Pan, Jonas Karlman, David Airlie,
	Bernie Liang, Neil Armstrong, Zhen Li, LKML, dri-devel,
	Vasily Khoruzhick, Boris Brezillon, Torsten Duwe, Hsin-Yi Wang,
	Sam Ravnborg, Dan Carpenter, Marek Szyprowski

On Fri, Apr 02, 2021 at 11:59:39AM +0300, Laurent Pinchart wrote:
> Hi Xin,
> 
> On Fri, Apr 02, 2021 at 10:27:08AM +0800, Xin Ji wrote:
> > On Mon, Mar 29, 2021 at 02:02:08PM -0400, Sean Paul wrote:
> > > On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > >
> > > > On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > > > > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > > > >
> > > > > > Add HDCP feature, enable HDCP function through chip internal key
> > > > > > and downstream's capability.
> > > > > >
> > > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > > ---
> > > 
> > > /snip
> > > 
> > > > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > >  {
> > > > > >         int ret;
> > > > > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > >                 return;
> > > > > >         }
> > > > > >
> > > > > > +       /* HDCP config */
> > > > > > +       anx7625_hdcp_setting(ctx);
> > > > >
> > > > > You should really use the "Content Protection" property to
> > > > > enable/disable HDCP instead of force-enabling it at all times.
> > > >
> > > > Hi Sean, it's hard to implement "Content Protection" property, we have
> > > > implemented HDCP in firmware, it is not compatible with it. We don't
> > > > have interface to get Downstream Cert.
> > > > Thanks,
> > > > Xin
> > > 
> > > Hi Xin,
> > > I'm sorry, I don't understand what you mean when you say you don't
> > > have an interface to get Downstream Cert.
> > > 
> > > The Content Protection property is just a means through which
> > > userspace can turn on and turn off HDCP when it needs. As far as I can
> > > tell, your patch turns on HDCP when the display is enabled and leaves
> > > it on until it is disabled. This is undesirable since it forces HDCP
> > > on the user.
> > > 
> > > Is it impossible to enable/disable HDCP outside of display
> > > enable/disable on your hardware?
> >
> > Hi Sean, I have commit a test patch on google review site, can you
> > please help to review it? I'll use Connector's ".atomic_check()"
> > interface to detect Content Protection property change.
> > (https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fchromium-review.googlesource.com%2Fc%2Fchromiumos%2Fthird_party%2Fkernel%2F%2B%2F2674580&amp;data=04%7C01%7Cxji%40analogixsemi.com%7Cd778885f3d0d4b4358a908d8f5b5c273%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637529508334886979%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=vo8zP8SAhLrQk0%2FWh1OhXHAZzLU9lJ4NLaYddI6t2ZU%3D&amp;reserved=0)
> 
> Please note that upstream review happens on mailing lists, not in
> gerrit. Internal reviews for Chrome OS development are certainly fine
> there, but that will not mean the patch will then be accepted upstream
> as-is, it will still need to go through the upstream review process,
> without any shortcut. I strongly recommend using an upstream-first
> strategy, with public review.
Hi Laurent Pinchart, OK, got it, thanks for the note.

Thanks,
Xin
> 
> > > > > > +
> > > > > >         if (ctx->pdata.is_dpi)
> > > > > >                 ret = anx7625_dpi_config(ctx);
> > > > > >         else
> > > 
> > > /snip
> 
> -- 
> Regards,
> 
> Laurent Pinchart

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-04-02  9:15               ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-04-02  9:15 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Bernie Liang, dri-devel,
	Neil Armstrong, LKML, Foss, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Sheng Pan, Zhen Li, Hsin-Yi Wang,
	Sean Paul, Dan Carpenter, Marek Szyprowski

On Fri, Apr 02, 2021 at 11:59:39AM +0300, Laurent Pinchart wrote:
> Hi Xin,
> 
> On Fri, Apr 02, 2021 at 10:27:08AM +0800, Xin Ji wrote:
> > On Mon, Mar 29, 2021 at 02:02:08PM -0400, Sean Paul wrote:
> > > On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > >
> > > > On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > > > > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > > > >
> > > > > > Add HDCP feature, enable HDCP function through chip internal key
> > > > > > and downstream's capability.
> > > > > >
> > > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > > ---
> > > 
> > > /snip
> > > 
> > > > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > >  {
> > > > > >         int ret;
> > > > > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > >                 return;
> > > > > >         }
> > > > > >
> > > > > > +       /* HDCP config */
> > > > > > +       anx7625_hdcp_setting(ctx);
> > > > >
> > > > > You should really use the "Content Protection" property to
> > > > > enable/disable HDCP instead of force-enabling it at all times.
> > > >
> > > > Hi Sean, it's hard to implement "Content Protection" property, we have
> > > > implemented HDCP in firmware, it is not compatible with it. We don't
> > > > have interface to get Downstream Cert.
> > > > Thanks,
> > > > Xin
> > > 
> > > Hi Xin,
> > > I'm sorry, I don't understand what you mean when you say you don't
> > > have an interface to get Downstream Cert.
> > > 
> > > The Content Protection property is just a means through which
> > > userspace can turn on and turn off HDCP when it needs. As far as I can
> > > tell, your patch turns on HDCP when the display is enabled and leaves
> > > it on until it is disabled. This is undesirable since it forces HDCP
> > > on the user.
> > > 
> > > Is it impossible to enable/disable HDCP outside of display
> > > enable/disable on your hardware?
> >
> > Hi Sean, I have commit a test patch on google review site, can you
> > please help to review it? I'll use Connector's ".atomic_check()"
> > interface to detect Content Protection property change.
> > (https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fchromium-review.googlesource.com%2Fc%2Fchromiumos%2Fthird_party%2Fkernel%2F%2B%2F2674580&amp;data=04%7C01%7Cxji%40analogixsemi.com%7Cd778885f3d0d4b4358a908d8f5b5c273%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637529508334886979%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=vo8zP8SAhLrQk0%2FWh1OhXHAZzLU9lJ4NLaYddI6t2ZU%3D&amp;reserved=0)
> 
> Please note that upstream review happens on mailing lists, not in
> gerrit. Internal reviews for Chrome OS development are certainly fine
> there, but that will not mean the patch will then be accepted upstream
> as-is, it will still need to go through the upstream review process,
> without any shortcut. I strongly recommend using an upstream-first
> strategy, with public review.
Hi Laurent Pinchart, OK, got it, thanks for the note.

Thanks,
Xin
> 
> > > > > > +
> > > > > >         if (ctx->pdata.is_dpi)
> > > > > >                 ret = anx7625_dpi_config(ctx);
> > > > > >         else
> > > 
> > > /snip
> 
> -- 
> Regards,
> 
> Laurent Pinchart
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support
@ 2021-04-02  9:15               ` Xin Ji
  0 siblings, 0 replies; 52+ messages in thread
From: Xin Ji @ 2021-04-02  9:15 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: devel, Nicolas Boichat, Jernej Skrabec, Sam Ravnborg,
	Jonas Karlman, David Airlie, Bernie Liang, dri-devel,
	Neil Armstrong, LKML, Foss, Vasily Khoruzhick, Andrzej Hajda,
	Boris Brezillon, Torsten Duwe, Sheng Pan, Zhen Li, Hsin-Yi Wang,
	Sean Paul, Dan Carpenter, Marek Szyprowski

On Fri, Apr 02, 2021 at 11:59:39AM +0300, Laurent Pinchart wrote:
> Hi Xin,
> 
> On Fri, Apr 02, 2021 at 10:27:08AM +0800, Xin Ji wrote:
> > On Mon, Mar 29, 2021 at 02:02:08PM -0400, Sean Paul wrote:
> > > On Mon, Mar 29, 2021 at 6:27 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > >
> > > > On Thu, Mar 25, 2021 at 02:19:23PM -0400, Sean Paul wrote:
> > > > > On Fri, Mar 19, 2021 at 2:35 AM Xin Ji <xji@analogixsemi.com> wrote:
> > > > > >
> > > > > > Add HDCP feature, enable HDCP function through chip internal key
> > > > > > and downstream's capability.
> > > > > >
> > > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > > ---
> > > 
> > > /snip
> > > 
> > > > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > >  {
> > > > > >         int ret;
> > > > > > @@ -643,6 +787,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > >                 return;
> > > > > >         }
> > > > > >
> > > > > > +       /* HDCP config */
> > > > > > +       anx7625_hdcp_setting(ctx);
> > > > >
> > > > > You should really use the "Content Protection" property to
> > > > > enable/disable HDCP instead of force-enabling it at all times.
> > > >
> > > > Hi Sean, it's hard to implement "Content Protection" property, we have
> > > > implemented HDCP in firmware, it is not compatible with it. We don't
> > > > have interface to get Downstream Cert.
> > > > Thanks,
> > > > Xin
> > > 
> > > Hi Xin,
> > > I'm sorry, I don't understand what you mean when you say you don't
> > > have an interface to get Downstream Cert.
> > > 
> > > The Content Protection property is just a means through which
> > > userspace can turn on and turn off HDCP when it needs. As far as I can
> > > tell, your patch turns on HDCP when the display is enabled and leaves
> > > it on until it is disabled. This is undesirable since it forces HDCP
> > > on the user.
> > > 
> > > Is it impossible to enable/disable HDCP outside of display
> > > enable/disable on your hardware?
> >
> > Hi Sean, I have commit a test patch on google review site, can you
> > please help to review it? I'll use Connector's ".atomic_check()"
> > interface to detect Content Protection property change.
> > (https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fchromium-review.googlesource.com%2Fc%2Fchromiumos%2Fthird_party%2Fkernel%2F%2B%2F2674580&amp;data=04%7C01%7Cxji%40analogixsemi.com%7Cd778885f3d0d4b4358a908d8f5b5c273%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637529508334886979%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=vo8zP8SAhLrQk0%2FWh1OhXHAZzLU9lJ4NLaYddI6t2ZU%3D&amp;reserved=0)
> 
> Please note that upstream review happens on mailing lists, not in
> gerrit. Internal reviews for Chrome OS development are certainly fine
> there, but that will not mean the patch will then be accepted upstream
> as-is, it will still need to go through the upstream review process,
> without any shortcut. I strongly recommend using an upstream-first
> strategy, with public review.
Hi Laurent Pinchart, OK, got it, thanks for the note.

Thanks,
Xin
> 
> > > > > > +
> > > > > >         if (ctx->pdata.is_dpi)
> > > > > >                 ret = anx7625_dpi_config(ctx);
> > > > > >         else
> > > 
> > > /snip
> 
> -- 
> Regards,
> 
> Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2021-04-02  9:16 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-19  6:31 [PATCH v6 0/5] Add MIPI rx DPI support Xin Ji
2021-03-19  6:31 ` Xin Ji
2021-03-19  6:31 ` Xin Ji
2021-03-19  6:32 ` [PATCH v6 1/5] dt-bindings:drm/bridge:anx7625:add vendor define flags Xin Ji
2021-03-19  6:32   ` Xin Ji
2021-03-21 12:00   ` Laurent Pinchart
2021-03-21 12:00     ` Laurent Pinchart
2021-03-24  7:51     ` Xin Ji
2021-03-24  7:51       ` Xin Ji
2021-04-01 12:33       ` Robert Foss
2021-04-01 12:33         ` Robert Foss
2021-04-02  2:29         ` Xin Ji
2021-04-02  2:29           ` Xin Ji
2021-03-19  6:33 ` [PATCH v6 2/5] drm/bridge: anx7625: fix not correct return value Xin Ji
2021-03-19  6:33   ` Xin Ji
2021-03-19  6:33   ` Xin Ji
2021-03-22  9:36   ` Robert Foss
2021-03-22  9:36     ` Robert Foss
2021-03-22  9:36     ` Robert Foss
2021-03-19  6:34 ` [PATCH v6 3/5] drm/bridge: anx7625: add MIPI DPI input feature support Xin Ji
2021-03-19  6:34   ` Xin Ji
2021-03-19  6:34   ` Xin Ji
2021-04-01 13:53   ` Robert Foss
2021-04-01 13:53     ` Robert Foss
2021-04-01 13:53     ` Robert Foss
2021-03-19  6:34 ` [PATCH v6 4/5] drm/bridge: anx7625: add HDCP support Xin Ji
2021-03-19  6:34   ` Xin Ji
2021-03-19  6:34   ` Xin Ji
2021-03-25 18:19   ` Sean Paul
2021-03-25 18:19     ` Sean Paul
2021-03-25 18:19     ` Sean Paul
2021-03-29 10:27     ` Xin Ji
2021-03-29 10:27       ` Xin Ji
2021-03-29 10:27       ` Xin Ji
2021-03-29 18:02       ` Sean Paul
2021-03-29 18:02         ` Sean Paul
2021-03-29 18:02         ` Sean Paul
2021-04-02  2:27         ` Xin Ji
2021-04-02  2:27           ` Xin Ji
2021-04-02  2:27           ` Xin Ji
2021-04-02  8:59           ` Laurent Pinchart
2021-04-02  8:59             ` Laurent Pinchart
2021-04-02  8:59             ` Laurent Pinchart
2021-04-02  9:15             ` Xin Ji
2021-04-02  9:15               ` Xin Ji
2021-04-02  9:15               ` Xin Ji
2021-03-19  6:35 ` [PATCH v6 5/5] drm/bridge: anx7625: add HDMI audio function Xin Ji
2021-03-19  6:35   ` Xin Ji
2021-03-19  6:35   ` Xin Ji
2021-04-01 13:58   ` Robert Foss
2021-04-01 13:58     ` Robert Foss
2021-04-01 13:58     ` Robert Foss

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.