Skip to contentSkip to conversation

Add MIPI rx DPI support

PATCH Superseded Xin Ji 4 participants 15 messages Jan 28, 2021 – Feb 25, 2021

Subsystems (4)

v4 of 12 Superseded Latest is v12 →

lore
Share & tools
lore

Xin Ji

author
#0 lore raw

v4 cover Add MIPI rx DPI support

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

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

Change history:
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 (3):
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

 .../bindings/display/bridge/analogix,anx7625.yaml  |  54 +++-
 drivers/gpu/drm/bridge/analogix/anx7625.c          | 330 +++++++++++++++++----
 drivers/gpu/drm/bridge/analogix/anx7625.h          |  20 +-
 3 files changed, 340 insertions(+), 64 deletions(-)
Signature · 1 line
2.7.4
author
#1 lore raw

PATCH v4 1/3 dt-bindings:drm/bridge:anx7625:add vendor define flags

Add 'bus-type' and 'data-lanes' define for port0, add HDCP support flag and DP tx lane0 and lane1 swing register array define.

---
 .../bindings/display/bridge/analogix,anx7625.yaml  | 54 +++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +53 -1
index c789784..048deec 100644
@@ -34,6 +34,24 @@ properties:
     description: used for reset chip control, RESET_N pin B7.
     maxItems: 1
 
+  analogix,lane0-swing:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    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
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane1 PHY, please don't
+      add this property, or contact vendor.
+
+  analogix,hdcp-support:
+    type: boolean
+    description: indicate the DP tx HDCP support or not.
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
@@ -41,13 +59,45 @@ properties:
       port@0:
         $ref: /schemas/graph.yaml#/properties/port
         description:
-          Video port for MIPI DSI input.
+          Video port for MIPI input.
+
+        properties:
+          endpoint:
+            type: object
+            additionalProperties: false
+
+            # Properties described in
+            # Documentation/devicetree/bindings/media/video-interfaces.txt
+            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:
+            type: object
+            additionalProperties: false
+
+            # Properties described in
+            # Documentation/devicetree/bindings/media/video-interfaces.txt
+            properties:
+              remote-endpoint: true
+
+            required:
+              - remote-endpoint
+
     required:
       - port@0
       - port@1
@@ -81,6 +131,8 @@ examples:
                     reg = <0>;
                     anx7625_in: endpoint {
                         remote-endpoint = <&mipi_dsi>;
+                        bus-type = <5>;
+                        data-lanes = <0 1 2 3>;
                     };
                 };
 
Signature · 1 line
2.7.4
#2 lore raw

Re: [PATCH v4 1/3] dt-bindings:drm/bridge:anx7625:add vendor define flags

Hey Xin,

Quoted 39 lines · Xin Ji

Add 'bus-type' and 'data-lanes' define for port0, add HDCP support flag and DP tx lane0 and lane1 swing register array define.

---
 .../bindings/display/bridge/analogix,anx7625.yaml  | 54 +++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +18 -0
index c789784..048deec 100644
@@ -34,6 +34,24 @@ properties:
     description: used for reset chip control, RESET_N pin B7.
     maxItems: 1
 
+  analogix,lane0-swing:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    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
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane1 PHY, please don't
+      add this property, or contact vendor.
+
+  analogix,hdcp-support:
+    type: boolean
+    description: indicate the DP tx HDCP support or not.
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 

Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml properties: · line 62

Quoted 5 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +1 -1
@@ -41,13 +59,45 @@ properties:
       port@0:
         $ref: /schemas/graph.yaml#/properties/port
         description:
-          Video port for MIPI DSI input.
+          Video port for MIPI input.

Maybe MIPI DSI/DPI input is more correct, since there are a lot of other MIPI standards.

Quoted 53 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +34 -1
+
+        properties:
+          endpoint:
+            type: object
+            additionalProperties: false
+
+            # Properties described in
+            # Documentation/devicetree/bindings/media/video-interfaces.txt
+            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:
+            type: object
+            additionalProperties: false
+
+            # Properties described in
+            # Documentation/devicetree/bindings/media/video-interfaces.txt
+            properties:
+              remote-endpoint: true
+
+            required:
+              - remote-endpoint
+
     required:
       - port@0
       - port@1
@@ -81,6 +131,8 @@ examples:
                     reg = <0>;
                     anx7625_in: endpoint {
                         remote-endpoint = <&mipi_dsi>;
+                        bus-type = <5>;
+                        data-lanes = <0 1 2 3>;
                     };
                 };
 
--

2.7.4

author
#3 lore raw

Re: [PATCH v4 1/3] dt-bindings:drm/bridge:anx7625:add vendor define flags

Quoted 41 lines · Robert Foss

Hey Xin,

Quoted 38 lines · Xin Ji

Add 'bus-type' and 'data-lanes' define for port0, add HDCP support flag and DP tx lane0 and lane1 swing register array define.

---
 .../bindings/display/bridge/analogix,anx7625.yaml  | 54 +++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +18 -0
index c789784..048deec 100644
@@ -34,6 +34,24 @@ properties:
     description: used for reset chip control, RESET_N pin B7.
     maxItems: 1
 
+  analogix,lane0-swing:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    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
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane1 PHY, please don't
+      add this property, or contact vendor.
+
+  analogix,hdcp-support:
+    type: boolean
+    description: indicate the DP tx HDCP support or not.
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
Quoted 9 lines

Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml properties: · line 62

Quoted 6 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +1 -1
@@ -41,13 +59,45 @@ properties:
       port@0:
         $ref: /schemas/graph.yaml#/properties/port
         description:
-          Video port for MIPI DSI input.
+          Video port for MIPI input.

Maybe MIPI DSI/DPI input is more correct, since there are a lot of other MIPI standards.

Hi Rob, OK, I'll change it in the next series.
Thanks,
Xin

Quoted 54 lines
Quoted 54 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +34 -1
+
+        properties:
+          endpoint:
+            type: object
+            additionalProperties: false
+
+            # Properties described in
+            # Documentation/devicetree/bindings/media/video-interfaces.txt
+            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:
+            type: object
+            additionalProperties: false
+
+            # Properties described in
+            # Documentation/devicetree/bindings/media/video-interfaces.txt
+            properties:
+              remote-endpoint: true
+
+            required:
+              - remote-endpoint
+
     required:
       - port@0
       - port@1
@@ -81,6 +131,8 @@ examples:
                     reg = <0>;
                     anx7625_in: endpoint {
                         remote-endpoint = <&mipi_dsi>;
+                        bus-type = <5>;
+                        data-lanes = <0 1 2 3>;
                     };
                 };
 
--

2.7.4

maintainer
#4 lore raw

Re: [PATCH v4 1/3] dt-bindings:drm/bridge:anx7625:add vendor define flags

In reply to Xin Ji
Quoted 23 lines · Xin Ji

Add 'bus-type' and 'data-lanes' define for port0, add HDCP support flag and DP tx lane0 and lane1 swing register array define.

---
 .../bindings/display/bridge/analogix,anx7625.yaml  | 54 +++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +7 -0
index c789784..048deec 100644
@@ -34,6 +34,24 @@ properties:
     description: used for reset chip control, RESET_N pin B7.
     maxItems: 1
 
+  analogix,lane0-swing:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane0 PHY, please don't
+      add this property, or contact vendor.
+

Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml properties: · line 53

Quoted 10 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +10 -0
+  analogix,lane1-swing:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane1 PHY, please don't
+      add this property, or contact vendor.
+
+  analogix,hdcp-support:
+    type: boolean
+    description: indicate the DP tx HDCP support or not.

Please show the new properties in the example.

Quoted 8 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +1 -0
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
@@ -41,13 +59,45 @@ properties:
       port@0:
         $ref: /schemas/graph.yaml#/properties/port
         description:

Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml properties: · line 70

Quoted 10 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +9 -1
-          Video port for MIPI DSI input.
+          Video port for MIPI input.
+
+        properties:
+          endpoint:
+            type: object
+            additionalProperties: false
+
+            # Properties described in
+            # Documentation/devicetree/bindings/media/video-interfaces.txt

Now video-interfaces.yaml which should have a $ref here. It's currently in media tree and linux-next. Follow the examples there. You'll also have to wait for 5.12-rc1 to apply to drm-misc.

Quoted 45 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +26 -0
+            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:
+            type: object
+            additionalProperties: false
+
+            # Properties described in
+            # Documentation/devicetree/bindings/media/video-interfaces.txt
+            properties:
+              remote-endpoint: true
+
+            required:
+              - remote-endpoint
+
     required:
       - port@0
       - port@1
@@ -81,6 +131,8 @@ examples:
                     reg = <0>;
                     anx7625_in: endpoint {
                         remote-endpoint = <&mipi_dsi>;
+                        bus-type = <5>;
+                        data-lanes = <0 1 2 3>;
                     };
                 };
 
Signature · 1 line
2.7.4

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

author
#5 lore raw

Re: [PATCH v4 1/3] dt-bindings:drm/bridge:anx7625:add vendor define flags

Hi Rob Herring, thanks for the comments.

Quoted 28 lines · Rob Herring
Quoted 27 lines · Xin Ji

Add 'bus-type' and 'data-lanes' define for port0, add HDCP support flag and DP tx lane0 and lane1 swing register array define.

---
 .../bindings/display/bridge/analogix,anx7625.yaml  | 54 +++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +11 -0
index c789784..048deec 100644
@@ -34,6 +34,24 @@ properties:
     description: used for reset chip control, RESET_N pin B7.
     maxItems: 1
 
+  analogix,lane0-swing:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    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
+    maxItems: 20
+    description:
Quoted 8 lines

Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml properties: · line 53

Quoted 6 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +6 -0
+      an array of swing register setting for DP tx lane1 PHY, please don't
+      add this property, or contact vendor.
+
+  analogix,hdcp-support:
+    type: boolean
+    description: indicate the DP tx HDCP support or not.

Please show the new properties in the example.

OK, I'll add it in the example.

Quoted 15 lines
Quoted 15 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +6 -1
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
@@ -41,13 +59,45 @@ properties:
       port@0:
         $ref: /schemas/graph.yaml#/properties/port
         description:
-          Video port for MIPI DSI input.
+          Video port for MIPI input.
+
+        properties:
+          endpoint:
+            type: object
Quoted 8 lines

Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml properties: · line 70

Quoted 4 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +4 -0
+            additionalProperties: false
+
+            # Properties described in
+            # Documentation/devicetree/bindings/media/video-interfaces.txt

Now video-interfaces.yaml which should have a $ref here. It's currently in media tree and linux-next. Follow the examples there. You'll also have to wait for 5.12-rc1 to apply to drm-misc.

OK.

Quoted 43 lines
Quoted 43 lines
Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +26 -0
+            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:
+            type: object
+            additionalProperties: false
+
+            # Properties described in
+            # Documentation/devicetree/bindings/media/video-interfaces.txt
+            properties:
+              remote-endpoint: true
+
+            required:
+              - remote-endpoint
+
     required:
       - port@0
       - port@1
@@ -81,6 +131,8 @@ examples:
                     reg = <0>;
                     anx7625_in: endpoint {
                         remote-endpoint = <&mipi_dsi>;
+                        bus-type = <5>;
+                        data-lanes = <0 1 2 3>;
                     };
                 };
 
Quoted 3 lines
Quoted 3 lines
Signature · 1 line
2.7.4

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

author
#6 lore raw

PATCH v4 2/3 drm/bridge: anx7625: fix not correct return value

In reply to Xin Ji

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

---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +2 -2
index 65cc059..04536cc 100644
@@ -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,
Signature · 1 line
2.7.4
Reviewed-by on v4 2/3
#7 lore raw

Re: [PATCH v4 2/3] drm/bridge: anx7625: fix not correct return value

Hi Xin,

Quoted 3 lines · Xin Ji

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

Missing "." at end of line.

Other than that, this patch looks fine. Feel free to add my r-b.

Quoted 26 lines
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +2 -3
index 65cc059..04536cc 100644
@@ -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.7.4

author
#8 lore raw

Re: [PATCH v4 2/3] drm/bridge: anx7625: fix not correct return value

Quoted 8 lines · Robert Foss

Hi Xin,

Quoted 3 lines · Xin Ji

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

Missing "." at end of line.

Hi Rob, OK, thanks, I'll add it in the next series. Thanks,
Xin

Quoted 30 lines

Other than that, this patch looks fine. Feel free to add my r-b.

Quoted 26 lines
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +2 -3
index 65cc059..04536cc 100644
@@ -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.7.4

author
#9 lore raw

PATCH v4 3/3 drm/bridge: anx7625: add MIPI DPI input feature support

In reply to Xin Ji

Add MIPI rx DPI input support

---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 326 ++++++++++++++++++++++++------
 drivers/gpu/drm/bridge/analogix/anx7625.h |  20 +-
 2 files changed, 285 insertions(+), 61 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +266 -60
index 04536cc..628ae43 100644
@@ -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)
@@ -195,6 +195,60 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
 	return 0;
 }
 
+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 -EINVAL;
+	}
+
+	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_write_and(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_video_mute_control(struct anx7625_data *ctx,
 				      u8 status)
 {
@@ -219,38 +273,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 +432,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 +617,101 @@ 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 int anx7625_hdcp_setting(struct anx7625_data *ctx)
+{
+	u8 bcap;
+	struct device *dev = &ctx->client->dev;
+
+	if (!ctx->pdata.hdcp_support || !ctx->hdcp_en) {
+		DRM_DEV_DEBUG_DRIVER(dev, "hdcp_support(%d), hdcp_en(%d)\n",
+				     ctx->pdata.hdcp_support, ctx->hdcp_en);
+		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_WARN("downstream not support HDCP 1.4, cap(%x).\n", bcap);
+		return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+					 0xee, 0x9f);
+	}
+
+	DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
+
+	return anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
+}
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
 	int ret;
@@ -605,9 +722,13 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
 		return;
 	}
 
-	anx7625_config_audio_input(ctx);
+	/* HDCP config */
+	anx7625_hdcp_setting(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");
@@ -688,8 +809,7 @@ static int sp_tx_get_edid_block(struct anx7625_data *ctx)
 	return c;
 }
 
-static int edid_read(struct anx7625_data *ctx,
-		     u8 offset, u8 *pblock_buf)
+static int edid_read(struct anx7625_data *ctx, u8 offset, u8 *pblock_buf)
 {
 	int ret, cnt;
 	struct device *dev = &ctx->client->dev;
@@ -992,8 +1112,9 @@ static void anx7625_chip_control(struct anx7625_data *ctx, int state)
 
 	if (state) {
 		atomic_inc(&ctx->power_status);
-		if (atomic_read(&ctx->power_status) == 1)
+		if (atomic_read(&ctx->power_status) == 1) {
 			anx7625_power_on_init(ctx);
+		}
 	} else {
 		if (atomic_read(&ctx->power_status)) {
 			atomic_dec(&ctx->power_status);
@@ -1051,6 +1172,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 +1182,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 +1204,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 +1258,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 +1288,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 +1366,69 @@ 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 drm_panel *panel;
 	int ret;
+	int bus_type;
+
+	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");
+	if (of_property_read_u32(pdata->mipi_host_node, "bus-type", &bus_type))
+		bus_type = 0;
+
+	if (bus_type == 5) /* bus type is Parallel(DSI) */
+		pdata->is_dpi = 0;
+
+	pdata->mipi_lanes = of_property_count_u32_elems(pdata->mipi_host_node,
+							"data-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");
+
+	if (of_property_read_bool(np, "analogix,hdcp-support"))
+		pdata->hdcp_support = 1;
 
 	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
 	if (ret < 0) {
@@ -1300,9 +1491,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 +1525,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 +1571,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 +1675,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 +1987,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");
drivers/gpu/drm/bridge/analogix/anx7625.h +19 -1
index 193ad86..127081e 100644
@@ -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,20 @@ 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 hdcp_support;
+	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;
 };
@@ -371,6 +388,7 @@ struct anx7625_data {
 	atomic_t power_status;
 	int hpd_status;
 	int hpd_high_cnt;
+	int hdcp_en;
 	/* Lock for work queue */
 	struct mutex lock;
 	struct i2c_client *client;
Signature · 1 line
2.7.4
#10 lore raw

Re: [PATCH v4 3/3] drm/bridge: anx7625: add MIPI DPI input feature support

Hey Xin,

Quoted 143 lines · Xin Ji

Add MIPI rx DPI input support

---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 326 ++++++++++++++++++++++++------
 drivers/gpu/drm/bridge/analogix/anx7625.h |  20 +-
 2 files changed, 285 insertions(+), 61 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +63 -41
index 04536cc..628ae43 100644
@@ -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)
@@ -195,6 +195,60 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
        return 0;
 }
 
+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 -EINVAL;
+       }
+
+       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_write_and(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_video_mute_control(struct anx7625_data *ctx,
                                      u8 status)
 {
@@ -219,38 +273,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)
 {

drivers/gpu/drm/bridge/analogix/anx7625.c static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx) · line 435

Quoted 5 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +1 -1
@@ -410,7 +432,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);

Is this mipi_lanes change independent of the rest of this patch? If so, extract it to a seperate patch.

Quoted 91 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +84 -0
        /* Htotal */
        htotal = ctx->dt.hactive.min + ctx->dt.hfront_porch.min +
@@ -595,6 +617,101 @@ 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 int anx7625_hdcp_setting(struct anx7625_data *ctx)
+{
+       u8 bcap;
+       struct device *dev = &ctx->client->dev;
+
+       if (!ctx->pdata.hdcp_support || !ctx->hdcp_en) {
+               DRM_DEV_DEBUG_DRIVER(dev, "hdcp_support(%d), hdcp_en(%d)\n",
+                                    ctx->pdata.hdcp_support, ctx->hdcp_en);
+               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);

drivers/gpu/drm/bridge/analogix/anx7625.c static int anx7625_dsi_config(struct anx7625_data *ctx) · line 713

Quoted 10 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +10 -0
+       if (!(bcap & 0x01)) {
+               DRM_WARN("downstream not support HDCP 1.4, cap(%x).\n", bcap);
+               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+                                        0xee, 0x9f);
+       }
+
+       DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
+
+       return anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
+}

Is the HDCP support change independent of the rest of this patch? If so, extract it to a seperate patch.

Quoted 21 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +7 -2
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
        int ret;
@@ -605,9 +722,13 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
                return;
        }
 
-       anx7625_config_audio_input(ctx);
+       /* HDCP config */
+       anx7625_hdcp_setting(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");

drivers/gpu/drm/bridge/analogix/anx7625.c static int sp_tx_get_edid_block(struct anx7625_data *ctx) · line 812

Quoted 6 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +1 -2
@@ -688,8 +809,7 @@ static int sp_tx_get_edid_block(struct anx7625_data *ctx)
        return c;
 }
 
-static int edid_read(struct anx7625_data *ctx,
-                    u8 offset, u8 *pblock_buf)
+static int edid_read(struct anx7625_data *ctx, u8 offset, u8 *pblock_buf)

No functional change here, let's try to maintain the 'git blame' history instead.

drivers/gpu/drm/bridge/analogix/anx7625.c static void anx7625_chip_control(struct anx7625_data *ctx, int state) · line 1117

Quoted 11 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +2 -1
 {
        int ret, cnt;
        struct device *dev = &ctx->client->dev;
@@ -992,8 +1112,9 @@ static void anx7625_chip_control(struct anx7625_data *ctx, int state)
 
        if (state) {
                atomic_inc(&ctx->power_status);
-               if (atomic_read(&ctx->power_status) == 1)
+               if (atomic_read(&ctx->power_status) == 1) {
                        anx7625_power_on_init(ctx);
+               }

This too is not a functional change, and the previous format preferred by the style guide.

Quoted 118 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +57 -4
        } else {
                if (atomic_read(&ctx->power_status)) {
                        atomic_dec(&ctx->power_status);
@@ -1051,6 +1172,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 +1182,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 +1204,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 +1258,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 +1288,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 +1366,69 @@ 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 drm_panel *panel;
        int ret;
+       int bus_type;
+
+       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");
+       if (of_property_read_u32(pdata->mipi_host_node, "bus-type", &bus_type))

drivers/gpu/drm/bridge/analogix/anx7625.c static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data) · line 1424

Quoted 10 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +10 -0
+               bus_type = 0;
+
+       if (bus_type == 5) /* bus type is Parallel(DSI) */
+               pdata->is_dpi = 0;
+
+       pdata->mipi_lanes = of_property_count_u32_elems(pdata->mipi_host_node,
+                                                       "data-lanes");
+       if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
+               pdata->mipi_lanes = MAX_LANES_SUPPORT;
+

Is this mipi_lanes change independent of the rest of this patch? If so, extract it to a seperate patch.

drivers/gpu/drm/bridge/analogix/anx7625.c static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data) · line 1431

Quoted 7 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +7 -0
+       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");
+
+       if (of_property_read_bool(np, "analogix,hdcp-support"))
+               pdata->hdcp_support = 1;

Extract hdcp_support change to separate patch.

Quoted 20 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +6 -2
        ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
        if (ret < 0) {
@@ -1300,9 +1491,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)

drivers/gpu/drm/bridge/analogix/anx7625.c static int anx7625_attach_dsi(struct anx7625_data *ctx) · line 1528

Quoted 5 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +1 -1
@@ -1330,7 +1525,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
                return -EINVAL;
        }
 
-       dsi->lanes = 4;
+       dsi->lanes = ctx->pdata.mipi_lanes;

Extract mipi_lanes change to separate patch.

Quoted 76 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +17 -6
        dsi->format = MIPI_DSI_FMT_RGB888;
        dsi->mode_flags = MIPI_DSI_MODE_VIDEO   |
                MIPI_DSI_MODE_VIDEO_SYNC_PULSE  |
@@ -1376,10 +1571,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 +1675,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 +1987,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");
drivers/gpu/drm/bridge/analogix/anx7625.h +9 -1
index 193ad86..127081e 100644
@@ -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,20 @@ struct s_edid_data {
 
 /***************** Display End *****************/

drivers/gpu/drm/bridge/analogix/anx7625.h struct s_edid_data { · line 366

Quoted 10 lines
drivers/gpu/drm/bridge/analogix/anx7625.h +4 -0
 
+#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;

Extract mipi_lanes change to separate patch.

drivers/gpu/drm/bridge/analogix/anx7625.h struct s_edid_data { · line 367

Quoted 1 line
drivers/gpu/drm/bridge/analogix/anx7625.h +1 -0
+       int hdcp_support;

Extract hdcp_support change to separate patch.

drivers/gpu/drm/bridge/analogix/anx7625.h struct anx7625_data { · line 391

Quoted 12 lines
drivers/gpu/drm/bridge/analogix/anx7625.h +5 -0
+       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;
 };
@@ -371,6 +388,7 @@ struct anx7625_data {
        atomic_t power_status;
        int hpd_status;
        int hpd_high_cnt;
+       int hdcp_en;

Extract hdcp_support change to separate patch.

Quoted 6 lines
drivers/gpu/drm/bridge/analogix/anx7625.h +0 -1
        /* Lock for work queue */
        struct mutex lock;
        struct i2c_client *client;
--

2.7.4

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

author
#11 lore raw

Re: [PATCH v4 3/3] drm/bridge: anx7625: add MIPI DPI input feature support

Quoted 1 line · Robert Foss

Hey Xin,

Hi Robert Foss, thanks for the comment, I'll split this patch at this seria. Thanks,
Xin

Quoted 145 lines · Xin Ji
Quoted 143 lines

Add MIPI rx DPI input support

---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 326 ++++++++++++++++++++++++------
 drivers/gpu/drm/bridge/analogix/anx7625.h |  20 +-
 2 files changed, 285 insertions(+), 61 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +63 -41
index 04536cc..628ae43 100644
@@ -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)
@@ -195,6 +195,60 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
        return 0;
 }
 
+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 -EINVAL;
+       }
+
+       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_write_and(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_video_mute_control(struct anx7625_data *ctx,
                                      u8 status)
 {
@@ -219,38 +273,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 +432,7 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
Quoted 8 lines

drivers/gpu/drm/bridge/analogix/anx7625.c static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx) · line 435

Quoted 5 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +1 -1
        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);

Is this mipi_lanes change independent of the rest of this patch? If so, extract it to a seperate patch.

OK, I'll extract it to a seperate patch.

Quoted 97 lines
Quoted 97 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +89 -0
        /* Htotal */
        htotal = ctx->dt.hactive.min + ctx->dt.hfront_porch.min +
@@ -595,6 +617,101 @@ 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 int anx7625_hdcp_setting(struct anx7625_data *ctx)
+{
+       u8 bcap;
+       struct device *dev = &ctx->client->dev;
+
+       if (!ctx->pdata.hdcp_support || !ctx->hdcp_en) {
+               DRM_DEV_DEBUG_DRIVER(dev, "hdcp_support(%d), hdcp_en(%d)\n",
+                                    ctx->pdata.hdcp_support, ctx->hdcp_en);
+               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_WARN("downstream not support HDCP 1.4, cap(%x).\n", bcap);
+               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+                                        0xee, 0x9f);
+       }
Quoted 8 lines

drivers/gpu/drm/bridge/analogix/anx7625.c static int anx7625_dsi_config(struct anx7625_data *ctx) · line 713

Quoted 5 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +5 -0
+
+       DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
+
+       return anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
+}

Is the HDCP support change independent of the rest of this patch? If so, extract it to a seperate patch.

OK, extract it to a seperate patch.

Quoted 25 lines
Quoted 25 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +7 -2
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
        int ret;
@@ -605,9 +722,13 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
                return;
        }
 
-       anx7625_config_audio_input(ctx);
+       /* HDCP config */
+       anx7625_hdcp_setting(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");
@@ -688,8 +809,7 @@ static int sp_tx_get_edid_block(struct anx7625_data *ctx)
        return c;
 }
 
Quoted 6 lines

drivers/gpu/drm/bridge/analogix/anx7625.c static int sp_tx_get_edid_block(struct anx7625_data *ctx) · line 812

Quoted 3 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +1 -2
-static int edid_read(struct anx7625_data *ctx,
-                    u8 offset, u8 *pblock_buf)
+static int edid_read(struct anx7625_data *ctx, u8 offset, u8 *pblock_buf)

No functional change here, let's try to maintain the 'git blame' history instead.

I'll keep the original code

Quoted 7 lines
Quoted 7 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +0 -0
 {
        int ret, cnt;
        struct device *dev = &ctx->client->dev;
@@ -992,8 +1112,9 @@ static void anx7625_chip_control(struct anx7625_data *ctx, int state)
 
Quoted 9 lines

drivers/gpu/drm/bridge/analogix/anx7625.c static void anx7625_chip_control(struct anx7625_data *ctx, int state) · line 1117

Quoted 6 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +2 -1
        if (state) {
                atomic_inc(&ctx->power_status);
-               if (atomic_read(&ctx->power_status) == 1)
+               if (atomic_read(&ctx->power_status) == 1) {
                        anx7625_power_on_init(ctx);
+               }

This too is not a functional change, and the previous format preferred by the style guide.

OK

Quoted 117 lines
Quoted 117 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +56 -3
        } else {
                if (atomic_read(&ctx->power_status)) {
                        atomic_dec(&ctx->power_status);
@@ -1051,6 +1172,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 +1182,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 +1204,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 +1258,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 +1288,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 +1366,69 @@ 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 drm_panel *panel;
        int ret;
+       int bus_type;
+
+       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;
        }
 
Quoted 15 lines

drivers/gpu/drm/bridge/analogix/anx7625.c static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data) · line 1424

Quoted 12 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +11 -1
-       DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
+       if (of_property_read_u32(pdata->mipi_host_node, "bus-type", &bus_type))
+               bus_type = 0;
+
+       if (bus_type == 5) /* bus type is Parallel(DSI) */
+               pdata->is_dpi = 0;
+
+       pdata->mipi_lanes = of_property_count_u32_elems(pdata->mipi_host_node,
+                                                       "data-lanes");
+       if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
+               pdata->mipi_lanes = MAX_LANES_SUPPORT;
+

Is this mipi_lanes change independent of the rest of this patch? If so, extract it to a seperate patch.

OK

Quoted 10 lines

drivers/gpu/drm/bridge/analogix/anx7625.c static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data) · line 1431

Quoted 8 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +7 -0
+       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");
+
+       if (of_property_read_bool(np, "analogix,hdcp-support"))
+               pdata->hdcp_support = 1;

Extract hdcp_support change to separate patch.

OK

Quoted 24 lines
Quoted 24 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +6 -2
        ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
        if (ret < 0) {
@@ -1300,9 +1491,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 +1525,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
                return -EINVAL;
        }
 
Quoted 4 lines

drivers/gpu/drm/bridge/analogix/anx7625.c static int anx7625_attach_dsi(struct anx7625_data *ctx) · line 1528

Quoted 2 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +1 -1
-       dsi->lanes = 4;
+       dsi->lanes = ctx->pdata.mipi_lanes;

Extract mipi_lanes change to separate patch.

OK

Quoted 78 lines
Quoted 78 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +17 -6
        dsi->format = MIPI_DSI_FMT_RGB888;
        dsi->mode_flags = MIPI_DSI_MODE_VIDEO   |
                MIPI_DSI_MODE_VIDEO_SYNC_PULSE  |
@@ -1376,10 +1571,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 +1675,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 +1987,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");
drivers/gpu/drm/bridge/analogix/anx7625.h +9 -1
index 193ad86..127081e 100644
@@ -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,20 @@ struct s_edid_data {
 
 /***************** Display End *****************/
 
Quoted 11 lines

drivers/gpu/drm/bridge/analogix/anx7625.h struct s_edid_data { · line 366

Quoted 9 lines
drivers/gpu/drm/bridge/analogix/anx7625.h +4 -0
+#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;

Extract mipi_lanes change to separate patch.

OK

Quoted 4 lines

drivers/gpu/drm/bridge/analogix/anx7625.h struct s_edid_data { · line 367

Quoted 2 lines
drivers/gpu/drm/bridge/analogix/anx7625.h +1 -0
+       int hdcp_support;

Extract hdcp_support change to separate patch.

OK

Quoted 15 lines

drivers/gpu/drm/bridge/analogix/anx7625.h struct anx7625_data { · line 391

Quoted 13 lines
drivers/gpu/drm/bridge/analogix/anx7625.h +5 -0
+       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;
 };
@@ -371,6 +388,7 @@ struct anx7625_data {
        atomic_t power_status;
        int hpd_status;
        int hpd_high_cnt;
+       int hdcp_en;

Extract hdcp_support change to separate patch.

OK

Quoted 7 lines
Quoted 7 lines
drivers/gpu/drm/bridge/analogix/anx7625.h +0 -1
        /* Lock for work queue */
        struct mutex lock;
        struct i2c_client *client;
--

2.7.4

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#12 lore raw

Re: [PATCH v4 3/3] drm/bridge: anx7625: add MIPI DPI input feature support

In reply to Xin Ji
Quoted 344 lines · Xin Ji

Add MIPI rx DPI input support

---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 326 ++++++++++++++++++++++++------
 drivers/gpu/drm/bridge/analogix/anx7625.h |  20 +-
 2 files changed, 285 insertions(+), 61 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +191 -48
index 04536cc..628ae43 100644
@@ -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)
@@ -195,6 +195,60 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
        return 0;
 }
 
+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 -EINVAL;
+       }
+
+       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_write_and(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_video_mute_control(struct anx7625_data *ctx,
                                      u8 status)
 {
@@ -219,38 +273,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 +432,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 +617,101 @@ 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 int anx7625_hdcp_setting(struct anx7625_data *ctx)
+{
+       u8 bcap;
+       struct device *dev = &ctx->client->dev;
+
+       if (!ctx->pdata.hdcp_support || !ctx->hdcp_en) {
+               DRM_DEV_DEBUG_DRIVER(dev, "hdcp_support(%d), hdcp_en(%d)\n",
+                                    ctx->pdata.hdcp_support, ctx->hdcp_en);
+               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_WARN("downstream not support HDCP 1.4, cap(%x).\n", bcap);
+               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+                                        0xee, 0x9f);
+       }
+
+       DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
+
+       return anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
+}
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
        int ret;
@@ -605,9 +722,13 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
                return;
        }
 
-       anx7625_config_audio_input(ctx);
+       /* HDCP config */
+       anx7625_hdcp_setting(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");
@@ -688,8 +809,7 @@ static int sp_tx_get_edid_block(struct anx7625_data *ctx)
        return c;
 }
 
-static int edid_read(struct anx7625_data *ctx,
-                    u8 offset, u8 *pblock_buf)
+static int edid_read(struct anx7625_data *ctx, u8 offset, u8 *pblock_buf)
 {
        int ret, cnt;
        struct device *dev = &ctx->client->dev;
@@ -992,8 +1112,9 @@ static void anx7625_chip_control(struct anx7625_data *ctx, int state)
 
        if (state) {
                atomic_inc(&ctx->power_status);
-               if (atomic_read(&ctx->power_status) == 1)
+               if (atomic_read(&ctx->power_status) == 1) {
                        anx7625_power_on_init(ctx);
+               }
        } else {
                if (atomic_read(&ctx->power_status)) {
                        atomic_dec(&ctx->power_status);
@@ -1051,6 +1172,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 +1182,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 +1204,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 +1258,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;

drivers/gpu/drm/bridge/analogix/anx7625.c static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on) · line 1291

Quoted 4 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +1 -0
@@ -1145,9 +1288,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;        is missing here
Quoted 47 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +31 -2
        }
-
-       ctx->hpd_status = 1;
 }
 
 static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
@@ -1224,20 +1366,69 @@ 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 drm_panel *panel;
        int ret;
+       int bus_type;
+
+       anx7625_get_swing_setting(dev, pdata);

drivers/gpu/drm/bridge/analogix/anx7625.c static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data) · line 1414

Quoted 10 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +2 -1
 
+       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");
+       if (of_property_read_u32(pdata->mipi_host_node, "bus-type", &bus_type))

According to previous patch, bus-type is added in endpoint node instead of remote node (dsi), so this part should be:

struct device_node *np = dev->of_node, *ep0;

ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
of_property_read_u32(ep0, "bus-type", &bus_type);

I modified it based on this patch:

(quoted diff) +0 -0

b/drivers/gpu/drm/bridge/analogix/anx7625.c
index f682b530dbfb6..343cc0bf785f6 100644

drivers/gpu/drm/bridge/analogix/anx7625.c +0 -0
@@ -1541,10 +1542,10 @@ static void

anx7625_unregister_usb_two_ports(struct anx7625_data *ctx) {
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;
+ int bus_type = 0;

        anx7625_get_swing_setting(dev, pdata);

@@ -1555,8 +1556,9 @@ static int anx7625_parse_dt(struct device *dev,

                return -ENODEV;
        }

- if (of_property_read_u32(pdata->mipi_host_node, "bus-type", &bus_type))
- bus_type = 0;
+ ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
+ if (ep0)
+ ret = of_property_read_u32(ep0, "bus-type", &bus_type);

        if (bus_type == 5) /* bus type is Parallel(DSI) */
Quoted 145 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +41 -9
+               bus_type = 0;
+
+       if (bus_type == 5) /* bus type is Parallel(DSI) */
+               pdata->is_dpi = 0;
+
+       pdata->mipi_lanes = of_property_count_u32_elems(pdata->mipi_host_node,
+                                                       "data-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");
+
+       if (of_property_read_bool(np, "analogix,hdcp-support"))
+               pdata->hdcp_support = 1;
 
        ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
        if (ret < 0) {
@@ -1300,9 +1491,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 +1525,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 +1571,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 +1675,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 +1987,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");
drivers/gpu/drm/bridge/analogix/anx7625.h +19 -2
index 193ad86..127081e 100644
@@ -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,20 @@ 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 hdcp_support;
+       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;
 };
@@ -371,6 +388,7 @@ struct anx7625_data {
        atomic_t power_status;
        int hpd_status;
        int hpd_high_cnt;
+       int hdcp_en;
        /* Lock for work queue */
        struct mutex lock;
        struct i2c_client *client;
--
Quoted 2 lines

2.7.4

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#13 lore raw

Re: [PATCH v4 3/3] drm/bridge: anx7625: add MIPI DPI input feature support

Quoted 343 lines · Hsin-Yi Wang
Quoted 341 lines · Xin Ji

Add MIPI rx DPI input support

---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 326 ++++++++++++++++++++++++------
 drivers/gpu/drm/bridge/analogix/anx7625.h |  20 +-
 2 files changed, 285 insertions(+), 61 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +191 -48
index 04536cc..628ae43 100644
@@ -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)
@@ -195,6 +195,60 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
        return 0;
 }
 
+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 -EINVAL;
+       }
+
+       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_write_and(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_video_mute_control(struct anx7625_data *ctx,
                                      u8 status)
 {
@@ -219,38 +273,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 +432,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 +617,101 @@ 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 int anx7625_hdcp_setting(struct anx7625_data *ctx)
+{
+       u8 bcap;
+       struct device *dev = &ctx->client->dev;
+
+       if (!ctx->pdata.hdcp_support || !ctx->hdcp_en) {
+               DRM_DEV_DEBUG_DRIVER(dev, "hdcp_support(%d), hdcp_en(%d)\n",
+                                    ctx->pdata.hdcp_support, ctx->hdcp_en);
+               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_WARN("downstream not support HDCP 1.4, cap(%x).\n", bcap);
+               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+                                        0xee, 0x9f);
+       }
+
+       DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
+
+       return anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
+}
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
        int ret;
@@ -605,9 +722,13 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
                return;
        }
 
-       anx7625_config_audio_input(ctx);
+       /* HDCP config */
+       anx7625_hdcp_setting(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");
@@ -688,8 +809,7 @@ static int sp_tx_get_edid_block(struct anx7625_data *ctx)
        return c;
 }
 
-static int edid_read(struct anx7625_data *ctx,
-                    u8 offset, u8 *pblock_buf)
+static int edid_read(struct anx7625_data *ctx, u8 offset, u8 *pblock_buf)
 {
        int ret, cnt;
        struct device *dev = &ctx->client->dev;
@@ -992,8 +1112,9 @@ static void anx7625_chip_control(struct anx7625_data *ctx, int state)
 
        if (state) {
                atomic_inc(&ctx->power_status);
-               if (atomic_read(&ctx->power_status) == 1)
+               if (atomic_read(&ctx->power_status) == 1) {
                        anx7625_power_on_init(ctx);
+               }
        } else {
                if (atomic_read(&ctx->power_status)) {
                        atomic_dec(&ctx->power_status);
@@ -1051,6 +1172,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 +1182,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 +1204,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 +1258,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)
Quoted 9 lines

drivers/gpu/drm/bridge/analogix/anx7625.c static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on) · line 1291

Quoted 7 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +1 -0
 {
        struct device *dev = &ctx->client->dev;
@@ -1145,9 +1288,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;        is missing here

Sorry, this is not needed. It's added in anx7625_start_dp_work().

Quoted 240 lines
Quoted 47 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +31 -2
        }
-
-       ctx->hpd_status = 1;
 }
 
 static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
@@ -1224,20 +1366,69 @@ 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 drm_panel *panel;
        int ret;
+       int bus_type;
+
+       anx7625_get_swing_setting(dev, pdata);

drivers/gpu/drm/bridge/analogix/anx7625.c static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data) · line 1414

Quoted 10 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +2 -1
 
+       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");
+       if (of_property_read_u32(pdata->mipi_host_node, "bus-type", &bus_type))

According to previous patch, bus-type is added in endpoint node instead of remote node (dsi), so this part should be:

struct device_node *np = dev->of_node, *ep0;

ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
of_property_read_u32(ep0, "bus-type", &bus_type);

I modified it based on this patch:

drivers/gpu/drm/bridge/analogix/anx7625.c +5 -4
index f682b530dbfb6..343cc0bf785f6 100644
@@ -1541,10 +1542,10 @@ static void
 anx7625_unregister_usb_two_ports(struct anx7625_data *ctx) {
 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;
+       int bus_type = 0;
 
        anx7625_get_swing_setting(dev, pdata);
@@ -1555,8 +1556,9 @@ static int anx7625_parse_dt(struct device *dev,
                return -ENODEV;
        }
 
-       if (of_property_read_u32(pdata->mipi_host_node, "bus-type", &bus_type))
-               bus_type = 0;
+       ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
+       if (ep0)
+               ret = of_property_read_u32(ep0, "bus-type", &bus_type);
 
 
        if (bus_type == 5) /* bus type is Parallel(DSI) */
Quoted 141 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +41 -9
+               bus_type = 0;
+
+       if (bus_type == 5) /* bus type is Parallel(DSI) */
+               pdata->is_dpi = 0;
+
+       pdata->mipi_lanes = of_property_count_u32_elems(pdata->mipi_host_node,
+                                                       "data-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");
+
+       if (of_property_read_bool(np, "analogix,hdcp-support"))
+               pdata->hdcp_support = 1;
 
        ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
        if (ret < 0) {
@@ -1300,9 +1491,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 +1525,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 +1571,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 +1675,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 +1987,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");
drivers/gpu/drm/bridge/analogix/anx7625.h +18 -1
index 193ad86..127081e 100644
@@ -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,20 @@ 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 hdcp_support;
+       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;
 };
@@ -371,6 +388,7 @@ struct anx7625_data {
        atomic_t power_status;
        int hpd_status;
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/bridge/analogix/anx7625.h +1 -1
        int hpd_high_cnt;
+       int hdcp_en;
        /* Lock for work queue */
        struct mutex lock;
        struct i2c_client *client;
--

2.7.4

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

author
#14 lore raw

Re: [PATCH v4 3/3] drm/bridge: anx7625: add MIPI DPI input feature support

In reply to Hsin-Yi Wang

Hi Hsin-Yi, thanks for the comment, I'll change it in the next serial.

As video-interfaces.yaml not exist in drm-next, I'm waiting for 5.12-rc1 to apply to drm-misc, then I'll upstream patch v5.

Thanks,
Xin

Quoted 342 lines · Hsin-Yi Wang
Quoted 341 lines · Xin Ji

Add MIPI rx DPI input support

---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 326 ++++++++++++++++++++++++------
 drivers/gpu/drm/bridge/analogix/anx7625.h |  20 +-
 2 files changed, 285 insertions(+), 61 deletions(-)
drivers/gpu/drm/bridge/analogix/anx7625.c +191 -48
index 04536cc..628ae43 100644
@@ -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)
@@ -195,6 +195,60 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
        return 0;
 }
 
+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 -EINVAL;
+       }
+
+       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_write_and(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_video_mute_control(struct anx7625_data *ctx,
                                      u8 status)
 {
@@ -219,38 +273,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 +432,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 +617,101 @@ 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 int anx7625_hdcp_setting(struct anx7625_data *ctx)
+{
+       u8 bcap;
+       struct device *dev = &ctx->client->dev;
+
+       if (!ctx->pdata.hdcp_support || !ctx->hdcp_en) {
+               DRM_DEV_DEBUG_DRIVER(dev, "hdcp_support(%d), hdcp_en(%d)\n",
+                                    ctx->pdata.hdcp_support, ctx->hdcp_en);
+               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_WARN("downstream not support HDCP 1.4, cap(%x).\n", bcap);
+               return anx7625_write_and(ctx, ctx->i2c.rx_p1_client,
+                                        0xee, 0x9f);
+       }
+
+       DRM_DEV_DEBUG_DRIVER(dev, "enable HDCP 1.4\n");
+
+       return anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
+}
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
        int ret;
@@ -605,9 +722,13 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
                return;
        }
 
-       anx7625_config_audio_input(ctx);
+       /* HDCP config */
+       anx7625_hdcp_setting(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");
@@ -688,8 +809,7 @@ static int sp_tx_get_edid_block(struct anx7625_data *ctx)
        return c;
 }
 
-static int edid_read(struct anx7625_data *ctx,
-                    u8 offset, u8 *pblock_buf)
+static int edid_read(struct anx7625_data *ctx, u8 offset, u8 *pblock_buf)
 {
        int ret, cnt;
        struct device *dev = &ctx->client->dev;
@@ -992,8 +1112,9 @@ static void anx7625_chip_control(struct anx7625_data *ctx, int state)
 
        if (state) {
                atomic_inc(&ctx->power_status);
-               if (atomic_read(&ctx->power_status) == 1)
+               if (atomic_read(&ctx->power_status) == 1) {
                        anx7625_power_on_init(ctx);
+               }
        } else {
                if (atomic_read(&ctx->power_status)) {
                        atomic_dec(&ctx->power_status);
@@ -1051,6 +1172,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 +1182,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 +1204,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 +1258,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)
Quoted 8 lines

drivers/gpu/drm/bridge/analogix/anx7625.c static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on) · line 1291

Quoted 7 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +1 -0
 {
        struct device *dev = &ctx->client->dev;
@@ -1145,9 +1288,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;        is missing here

Already move it to anx7625_start_dp_work function.

Quoted 90 lines
Quoted 48 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +31 -2
        }
-
-       ctx->hpd_status = 1;
 }
 
 static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
@@ -1224,20 +1366,69 @@ 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 drm_panel *panel;
        int ret;
+       int bus_type;
+
+       anx7625_get_swing_setting(dev, pdata);

drivers/gpu/drm/bridge/analogix/anx7625.c static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data) · line 1414

Quoted 10 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +2 -1
 
+       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");
+       if (of_property_read_u32(pdata->mipi_host_node, "bus-type", &bus_type))

According to previous patch, bus-type is added in endpoint node instead of remote node (dsi), so this part should be:

struct device_node *np = dev->of_node, *ep0;

ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
of_property_read_u32(ep0, "bus-type", &bus_type);

I modified it based on this patch:

drivers/gpu/drm/bridge/analogix/anx7625.c +2 -2
index f682b530dbfb6..343cc0bf785f6 100644
@@ -1541,10 +1542,10 @@ static void
 anx7625_unregister_usb_two_ports(struct anx7625_data *ctx) {
 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;
+       int bus_type = 0;
 
        anx7625_get_swing_setting(dev, pdata);
@@ -1555,8 +1556,9 @@ static int anx7625_parse_dt(struct device *dev,
                return -ENODEV;

drivers/gpu/drm/bridge/analogix/anx7625.c static int anx7625_parse_dt(struct device *dev, · line 1564

Quoted 10 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +3 -2
        }
 
-       if (of_property_read_u32(pdata->mipi_host_node, "bus-type", &bus_type))
-               bus_type = 0;
+       ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
+       if (ep0)
+               ret = of_property_read_u32(ep0, "bus-type", &bus_type);
 
 
        if (bus_type == 5) /* bus type is Parallel(DSI) */

OK, I'll merge it into next serial, thanks!

Quoted 141 lines
Quoted 141 lines
drivers/gpu/drm/bridge/analogix/anx7625.c +41 -9
+               bus_type = 0;
+
+       if (bus_type == 5) /* bus type is Parallel(DSI) */
+               pdata->is_dpi = 0;
+
+       pdata->mipi_lanes = of_property_count_u32_elems(pdata->mipi_host_node,
+                                                       "data-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");
+
+       if (of_property_read_bool(np, "analogix,hdcp-support"))
+               pdata->hdcp_support = 1;
 
        ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
        if (ret < 0) {
@@ -1300,9 +1491,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 +1525,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 +1571,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 +1675,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 +1987,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");
drivers/gpu/drm/bridge/analogix/anx7625.h +18 -1
index 193ad86..127081e 100644
@@ -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,20 @@ 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 hdcp_support;
+       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;
 };
@@ -371,6 +388,7 @@ struct anx7625_data {
        atomic_t power_status;
        int hpd_status;
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/bridge/analogix/anx7625.h +1 -1
        int hpd_high_cnt;
+       int hdcp_en;
        /* Lock for work queue */
        struct mutex lock;
        struct i2c_client *client;
--

2.7.4

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel