linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v12 1/4] dt-bindings:drm/bridge:anx7625:add vendor define
@ 2021-11-05  3:19 Xin Ji
  2021-11-05  3:19 ` [PATCH v12 2/4] drm/bridge: anx7625: fix not correct return value Xin Ji
                   ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: Xin Ji @ 2021-11-05  3:19 UTC (permalink / raw)
  To: a.hajda, narmstrong, dan.carpenter, robert.foss,
	Laurent.pinchart, jonas, jernej.skrabec, airlied, daniel, sam,
	pihsun, tzungbi, maxime, drinkcat, hsinyi, dri-devel,
	linux-kernel, bliang, qwen, robh+dt, devicetree
  Cc: Xin Ji, Rob Herring

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

The device which cannot pass DP tx PHY CTS caused by long PCB trace or
embedded MUX, adjusting ANX7625 PHY parameters can pass the CTS test. The
adjusting type include Pre-emphasis, Vp-p, Rterm(Resistor Termination)
and Rsel(Driven Strength). Each lane has maximum 20 registers for
these settings.

Signed-off-by: Xin Ji <xji@analogixsemi.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
 .../display/bridge/analogix,anx7625.yaml      | 65 ++++++++++++++++++-
 1 file changed, 63 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
index ab48ab2f4240..1d3e88daca04 100644
--- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
@@ -43,14 +43,70 @@ properties:
   vdd33-supply:
     description: Regulator that provides the supply 3.3V power.
 
+  analogix,lane0-swing:
+    $ref: /schemas/types.yaml#/definitions/uint8-array
+    minItems: 1
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane0 PHY.
+      Registers 0~9 are Swing0_Pre0, Swing1_Pre0, Swing2_Pre0,
+      Swing3_Pre0, Swing0_Pre1, Swing1_Pre1, Swing2_Pre1, Swing0_Pre2,
+      Swing1_Pre2, Swing0_Pre3, they are for [Boost control] and
+      [Swing control] setting.
+      Registers 0~9, bit 3:0 is [Boost control], these bits control
+      post cursor manual, increase the [Boost control] to increase
+      Pre-emphasis value.
+      Registers 0~9, bit 6:4 is [Swing control], these bits control
+      swing manual, increase [Swing control] setting to add Vp-p value
+      for each Swing, Pre.
+      Registers 10~19 are Swing0_Pre0, Swing1_Pre0, Swing2_Pre0,
+      Swing3_Pre0, Swing0_Pre1, Swing1_Pre1, Swing2_Pre1, Swing0_Pre2,
+      Swing1_Pre2, Swing0_Pre3, they are for [R select control] and
+      [R Termination control] setting.
+      Registers 10~19, bit 4:0 is [R select control], these bits are
+      compensation manual, increase it can enhance IO driven strength
+      and Vp-p.
+      Registers 10~19, bit 5:6 is [R termination control], these bits
+      adjust 50ohm impedance of DP tx termination. 00:55 ohm,
+      01:50 ohm(default), 10:45 ohm, 11:40 ohm.
+
+  analogix,lane1-swing:
+    $ref: /schemas/types.yaml#/definitions/uint8-array
+    minItems: 1
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane1 PHY.
+      DP TX lane1 swing register setting same with lane0
+      swing, please refer lane0-swing property description.
+
+  analogix,audio-enable:
+    type: boolean
+    description: let the driver enable audio HDMI codec function or not.
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
     properties:
       port@0:
-        $ref: /schemas/graph.yaml#/properties/port
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
         description:
-          Video port for MIPI DSI input.
+          MIPI DSI/DPI input.
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            type: object
+            additionalProperties: false
+
+            properties:
+              remote-endpoint: true
+
+              bus-type:
+                enum: [1, 5]
+                default: 1
+
+              data-lanes: true
 
       port@1:
         $ref: /schemas/graph.yaml#/properties/port
@@ -87,6 +143,9 @@ examples:
             vdd10-supply = <&pp1000_mipibrdg>;
             vdd18-supply = <&pp1800_mipibrdg>;
             vdd33-supply = <&pp3300_mipibrdg>;
+            analogix,audio-enable;
+            analogix,lane0-swing = /bits/ 8 <0x14 0x54 0x64 0x74>;
+            analogix,lane1-swing = /bits/ 8 <0x14 0x54 0x64 0x74>;
 
             ports {
                 #address-cells = <1>;
@@ -96,6 +155,8 @@ examples:
                     reg = <0>;
                     anx7625_in: endpoint {
                         remote-endpoint = <&mipi_dsi>;
+                        bus-type = <5>;
+                        data-lanes = <0 1 2 3>;
                     };
                 };
 
-- 
2.25.1


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

* [PATCH v12 2/4] drm/bridge: anx7625: fix not correct return value
  2021-11-05  3:19 [PATCH v12 1/4] dt-bindings:drm/bridge:anx7625:add vendor define Xin Ji
@ 2021-11-05  3:19 ` Xin Ji
  2021-11-05  3:19 ` [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature Xin Ji
  2021-11-05  3:19 ` [PATCH v12 4/4] drm/bridge: anx7625: add HDMI audio function Xin Ji
  2 siblings, 0 replies; 20+ messages in thread
From: Xin Ji @ 2021-11-05  3:19 UTC (permalink / raw)
  To: a.hajda, narmstrong, dan.carpenter, robert.foss,
	Laurent.pinchart, jonas, jernej.skrabec, airlied, daniel, sam,
	pihsun, tzungbi, maxime, drinkcat, hsinyi, dri-devel,
	linux-kernel, bliang, qwen, robh+dt, devicetree
  Cc: Xin Ji

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

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

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


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

* [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2021-11-05  3:19 [PATCH v12 1/4] dt-bindings:drm/bridge:anx7625:add vendor define Xin Ji
  2021-11-05  3:19 ` [PATCH v12 2/4] drm/bridge: anx7625: fix not correct return value Xin Ji
@ 2021-11-05  3:19 ` Xin Ji
  2022-03-06 17:13   ` Laurent Pinchart
  2021-11-05  3:19 ` [PATCH v12 4/4] drm/bridge: anx7625: add HDMI audio function Xin Ji
  2 siblings, 1 reply; 20+ messages in thread
From: Xin Ji @ 2021-11-05  3:19 UTC (permalink / raw)
  To: a.hajda, narmstrong, dan.carpenter, robert.foss,
	Laurent.pinchart, jonas, jernej.skrabec, airlied, daniel, sam,
	pihsun, tzungbi, maxime, drinkcat, hsinyi, dri-devel,
	linux-kernel, bliang, qwen, robh+dt, devicetree
  Cc: Xin Ji

The basic anx7625 driver only support MIPI DSI rx signal input.
This patch add MIPI DPI rx input configuration support, after apply
this patch, the driver can support DSI rx or DPI rx by adding
'bus-type' in DT.

Reviewed-by: Robert Foss <robert.foss@linaro.org>
Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
 drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
 2 files changed, 205 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index f48e91134c20..f7c3386c8929 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -32,6 +32,7 @@
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 
+#include <media/v4l2-fwnode.h>
 #include <video/display_timing.h>
 
 #include "anx7625.h"
@@ -152,18 +153,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)
@@ -221,38 +222,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)
 {
@@ -431,7 +400,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 +
@@ -615,6 +584,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
 	return ret;
 }
 
+static int anx7625_api_dpi_config(struct anx7625_data *ctx)
+{
+	struct device *dev = &ctx->client->dev;
+	u16 freq = ctx->dt.pixelclock.min / 1000;
+	int ret;
+
+	/* configure pixel clock */
+	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				PIXEL_CLOCK_L, freq & 0xFF);
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
+				 PIXEL_CLOCK_H, (freq >> 8));
+
+	/* set DPI mode */
+	/* set to DPI PLL module sel */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_DIGITAL_PLL_9, 0x20);
+	/* power down MIPI */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_LANE_CTRL_10, 0x08);
+	/* enable DPI mode */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
+				 MIPI_DIGITAL_PLL_18, 0x1C);
+	/* set first edge */
+	ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
+				 VIDEO_CONTROL_0, 0x06);
+	if (ret < 0)
+		DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
+
+	return ret;
+}
+
+static int anx7625_dpi_config(struct anx7625_data *ctx)
+{
+	struct device *dev = &ctx->client->dev;
+	int ret;
+
+	DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
+
+	/* DSC disable */
+	ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
+				R_DSC_CTRL_0, ~DSC_EN);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
+		return ret;
+	}
+
+	ret = anx7625_config_bit_matrix(ctx);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
+		return ret;
+	}
+
+	ret = anx7625_api_dpi_config(ctx);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
+		return ret;
+	}
+
+	/* set MIPI RX EN */
+	ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
+			       AP_AV_STATUS, AP_MIPI_RX_EN);
+	/* clear mute flag */
+	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
+				 AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
+	if (ret < 0)
+		DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
+
+	return ret;
+}
+
 static void anx7625_dp_start(struct anx7625_data *ctx)
 {
 	int ret;
@@ -625,9 +664,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
 		return;
 	}
 
-	anx7625_config_audio_input(ctx);
-
-	ret = anx7625_dsi_config(ctx);
+	if (ctx->pdata.is_dpi)
+		ret = anx7625_dpi_config(ctx);
+	else
+		ret = anx7625_dsi_config(ctx);
 
 	if (ret < 0)
 		DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
@@ -1075,6 +1115,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
 		return;
 	}
 
+	ctx->hpd_status = 1;
 	ctx->hpd_high_cnt++;
 
 	/* Not support HDCP */
@@ -1084,8 +1125,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)
@@ -1104,6 +1147,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;
+
 	ret = readx_poll_timeout(anx7625_read_hpd_status_p0,
 				 ctx, val,
 				 ((val & HPD_STATUS) || (val < 0)),
@@ -1131,6 +1178,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;
@@ -1146,9 +1208,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)
@@ -1225,20 +1286,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static int anx7625_get_swing_setting(struct device *dev,
+				     struct anx7625_platform_data *pdata)
+{
+	int num_regs;
+
+	if (of_get_property(dev->of_node,
+			    "analogix,lane0-swing", &num_regs)) {
+		if (num_regs > DP_TX_SWING_REG_CNT)
+			num_regs = DP_TX_SWING_REG_CNT;
+
+		pdata->dp_lane0_swing_reg_cnt = num_regs;
+		of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
+					   pdata->lane0_reg_data, num_regs);
+	}
+
+	if (of_get_property(dev->of_node,
+			    "analogix,lane1-swing", &num_regs)) {
+		if (num_regs > DP_TX_SWING_REG_CNT)
+			num_regs = DP_TX_SWING_REG_CNT;
+
+		pdata->dp_lane1_swing_reg_cnt = num_regs;
+		of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
+					   pdata->lane1_reg_data, num_regs);
+	}
+
+	return 0;
+}
+
 static int anx7625_parse_dt(struct device *dev,
 			    struct anx7625_platform_data *pdata)
 {
-	struct device_node *np = dev->of_node;
+	struct device_node *np = dev->of_node, *ep0;
 	struct drm_panel *panel;
 	int ret;
+	int bus_type, mipi_lanes;
+
+	anx7625_get_swing_setting(dev, pdata);
 
+	pdata->is_dpi = 1; /* default dpi mode */
 	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
 	if (!pdata->mipi_host_node) {
 		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
 		return -ENODEV;
 	}
 
-	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
+	bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
+	mipi_lanes = MAX_LANES_SUPPORT;
+	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
+	if (ep0) {
+		if (of_property_read_u32(ep0, "bus-type", &bus_type))
+			bus_type = 0;
+
+		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
+	}
+
+	if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
+		pdata->is_dpi = 0;
+
+	pdata->mipi_lanes = mipi_lanes;
+	if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
+		pdata->mipi_lanes = MAX_LANES_SUPPORT;
+
+	if (pdata->is_dpi)
+		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
+	else
+		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
 
 	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
 	if (ret < 0) {
@@ -1301,9 +1414,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");
 
-	return connector_status_connected;
+	if (ctx->pdata.panel_bridge)
+		return connector_status_connected;
+
+	return ctx->hpd_status ? connector_status_connected :
+				     connector_status_disconnected;
 }
 
 static int anx7625_attach_dsi(struct anx7625_data *ctx)
@@ -1332,7 +1449,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	|
@@ -1460,6 +1577,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;
@@ -1835,14 +1956,22 @@ 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);
 
-	ret = anx7625_attach_dsi(platform);
-	if (ret) {
-		DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
-		goto unregister_bridge;
+	if (!platform->pdata.is_dpi) {
+		ret = anx7625_attach_dsi(platform);
+		if (ret) {
+			DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
+			goto unregister_bridge;
+		}
 	}
 
 	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 6dcf64c703f9..3ef1d8f4e575 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -141,12 +141,20 @@
 #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
 
 /******** END of I2C Address 0x72 *********/
+
+/***************************************************************/
+/* Register definition of device address 0x7a */
+#define DP_TX_SWING_REG_CNT		0x14
+#define DP_TX_LANE0_SWING_REG0		0x00
+#define DP_TX_LANE1_SWING_REG0		0x14
+/******** END of I2C Address 0x7a *********/
+
 /***************************************************************/
 /* Register definition of device address 0x7e */
 
 #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
 
-#define FLASH_LOAD_STA 0x05
+#define FLASH_LOAD_STA          0x05
 #define FLASH_LOAD_STA_CHK	BIT(7)
 
 #define  XTAL_FRQ_SEL    0x3F
@@ -349,12 +357,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 regulator_bulk_data supplies[3];
 	struct drm_bridge *panel_bridge;
 	int intp_irq;
+	int is_dpi;
+	int mipi_lanes;
+	int dp_lane0_swing_reg_cnt;
+	int lane0_reg_data[DP_TX_SWING_REG_CNT];
+	int dp_lane1_swing_reg_cnt;
+	int lane1_reg_data[DP_TX_SWING_REG_CNT];
 	u32 low_power_mode;
 	struct device_node *mipi_host_node;
 };
-- 
2.25.1


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

* [PATCH v12 4/4] drm/bridge: anx7625: add HDMI audio function
  2021-11-05  3:19 [PATCH v12 1/4] dt-bindings:drm/bridge:anx7625:add vendor define Xin Ji
  2021-11-05  3:19 ` [PATCH v12 2/4] drm/bridge: anx7625: fix not correct return value Xin Ji
  2021-11-05  3:19 ` [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature Xin Ji
@ 2021-11-05  3:19 ` Xin Ji
  2 siblings, 0 replies; 20+ messages in thread
From: Xin Ji @ 2021-11-05  3:19 UTC (permalink / raw)
  To: a.hajda, narmstrong, dan.carpenter, robert.foss,
	Laurent.pinchart, jonas, jernej.skrabec, airlied, daniel, sam,
	pihsun, tzungbi, maxime, drinkcat, hsinyi, dri-devel,
	linux-kernel, bliang, qwen, robh+dt, devicetree
  Cc: Xin Ji

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

Reviewed-by: Robert Foss <robert.foss@linaro.org>
Signed-off-by: Xin Ji <xji@analogixsemi.com>
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 226 ++++++++++++++++++++++
 drivers/gpu/drm/bridge/analogix/anx7625.h |   5 +
 2 files changed, 231 insertions(+)

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


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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2021-11-05  3:19 ` [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature Xin Ji
@ 2022-03-06 17:13   ` Laurent Pinchart
  2022-03-07  3:22     ` Xin Ji
  2022-03-07  6:12     ` Chen-Yu Tsai
  0 siblings, 2 replies; 20+ messages in thread
From: Laurent Pinchart @ 2022-03-06 17:13 UTC (permalink / raw)
  To: Xin Ji
  Cc: a.hajda, narmstrong, dan.carpenter, robert.foss, jonas,
	jernej.skrabec, airlied, daniel, sam, pihsun, tzungbi, maxime,
	drinkcat, hsinyi, dri-devel, linux-kernel, bliang, qwen, robh+dt,
	devicetree

Hello Xin,

(Question for Rob below, and I'm afraid this is urgent as we need to
merge a fix in v5.17).

On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> The basic anx7625 driver only support MIPI DSI rx signal input.
> This patch add MIPI DPI rx input configuration support, after apply
> this patch, the driver can support DSI rx or DPI rx by adding
> 'bus-type' in DT.
> 
> Reviewed-by: Robert Foss <robert.foss@linaro.org>
> Signed-off-by: Xin Ji <xji@analogixsemi.com>
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
>  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
>  2 files changed, 205 insertions(+), 60 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index f48e91134c20..f7c3386c8929 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -32,6 +32,7 @@
>  #include <drm/drm_print.h>
>  #include <drm/drm_probe_helper.h>
>  
> +#include <media/v4l2-fwnode.h>
>  #include <video/display_timing.h>
>  
>  #include "anx7625.h"
> @@ -152,18 +153,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)
> @@ -221,38 +222,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)
>  {
> @@ -431,7 +400,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 +
> @@ -615,6 +584,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
>  	return ret;
>  }
>  
> +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> +{
> +	struct device *dev = &ctx->client->dev;
> +	u16 freq = ctx->dt.pixelclock.min / 1000;
> +	int ret;
> +
> +	/* configure pixel clock */
> +	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +				PIXEL_CLOCK_L, freq & 0xFF);
> +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> +				 PIXEL_CLOCK_H, (freq >> 8));
> +
> +	/* set DPI mode */
> +	/* set to DPI PLL module sel */
> +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +				 MIPI_DIGITAL_PLL_9, 0x20);
> +	/* power down MIPI */
> +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +				 MIPI_LANE_CTRL_10, 0x08);
> +	/* enable DPI mode */
> +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> +				 MIPI_DIGITAL_PLL_18, 0x1C);
> +	/* set first edge */
> +	ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> +				 VIDEO_CONTROL_0, 0x06);
> +	if (ret < 0)
> +		DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> +
> +	return ret;
> +}
> +
> +static int anx7625_dpi_config(struct anx7625_data *ctx)
> +{
> +	struct device *dev = &ctx->client->dev;
> +	int ret;
> +
> +	DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> +
> +	/* DSC disable */
> +	ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> +				R_DSC_CTRL_0, ~DSC_EN);
> +	if (ret < 0) {
> +		DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> +		return ret;
> +	}
> +
> +	ret = anx7625_config_bit_matrix(ctx);
> +	if (ret < 0) {
> +		DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> +		return ret;
> +	}
> +
> +	ret = anx7625_api_dpi_config(ctx);
> +	if (ret < 0) {
> +		DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> +		return ret;
> +	}
> +
> +	/* set MIPI RX EN */
> +	ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> +			       AP_AV_STATUS, AP_MIPI_RX_EN);
> +	/* clear mute flag */
> +	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> +				 AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> +	if (ret < 0)
> +		DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> +
> +	return ret;
> +}
> +
>  static void anx7625_dp_start(struct anx7625_data *ctx)
>  {
>  	int ret;
> @@ -625,9 +664,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
>  		return;
>  	}
>  
> -	anx7625_config_audio_input(ctx);
> -
> -	ret = anx7625_dsi_config(ctx);
> +	if (ctx->pdata.is_dpi)
> +		ret = anx7625_dpi_config(ctx);
> +	else
> +		ret = anx7625_dsi_config(ctx);
>  
>  	if (ret < 0)
>  		DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> @@ -1075,6 +1115,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
>  		return;
>  	}
>  
> +	ctx->hpd_status = 1;
>  	ctx->hpd_high_cnt++;
>  
>  	/* Not support HDCP */
> @@ -1084,8 +1125,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)
> @@ -1104,6 +1147,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;
> +
>  	ret = readx_poll_timeout(anx7625_read_hpd_status_p0,
>  				 ctx, val,
>  				 ((val & HPD_STATUS) || (val < 0)),
> @@ -1131,6 +1178,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;
> @@ -1146,9 +1208,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)
> @@ -1225,20 +1286,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
>  	return IRQ_HANDLED;
>  }
>  
> +static int anx7625_get_swing_setting(struct device *dev,
> +				     struct anx7625_platform_data *pdata)
> +{
> +	int num_regs;
> +
> +	if (of_get_property(dev->of_node,
> +			    "analogix,lane0-swing", &num_regs)) {
> +		if (num_regs > DP_TX_SWING_REG_CNT)
> +			num_regs = DP_TX_SWING_REG_CNT;
> +
> +		pdata->dp_lane0_swing_reg_cnt = num_regs;
> +		of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> +					   pdata->lane0_reg_data, num_regs);
> +	}
> +
> +	if (of_get_property(dev->of_node,
> +			    "analogix,lane1-swing", &num_regs)) {
> +		if (num_regs > DP_TX_SWING_REG_CNT)
> +			num_regs = DP_TX_SWING_REG_CNT;
> +
> +		pdata->dp_lane1_swing_reg_cnt = num_regs;
> +		of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> +					   pdata->lane1_reg_data, num_regs);
> +	}
> +
> +	return 0;
> +}
> +
>  static int anx7625_parse_dt(struct device *dev,
>  			    struct anx7625_platform_data *pdata)
>  {
> -	struct device_node *np = dev->of_node;
> +	struct device_node *np = dev->of_node, *ep0;
>  	struct drm_panel *panel;
>  	int ret;
> +	int bus_type, mipi_lanes;
> +
> +	anx7625_get_swing_setting(dev, pdata);
>  
> +	pdata->is_dpi = 1; /* default dpi mode */
>  	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
>  	if (!pdata->mipi_host_node) {
>  		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
>  		return -ENODEV;
>  	}
>  
> -	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> +	bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> +	mipi_lanes = MAX_LANES_SUPPORT;
> +	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> +	if (ep0) {
> +		if (of_property_read_u32(ep0, "bus-type", &bus_type))
> +			bus_type = 0;
> +
> +		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> +	}
> +
> +	if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */

This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
it's not an exact match.

This patch has landed in v5.17-rc1, along with the corresponding
bindings. As DT bindings are an ABI, we should really fix this before
v5.17 is released. There is no DSI bus types defined in DT, and adding
one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
me (unless Rob disagrees).

It would seem best to revert this series and the corresponding bindings,
and retry in v5.18.

> +		pdata->is_dpi = 0;
> +
> +	pdata->mipi_lanes = mipi_lanes;
> +	if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> +		pdata->mipi_lanes = MAX_LANES_SUPPORT;
> +
> +	if (pdata->is_dpi)
> +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> +	else
> +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
>  
>  	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
>  	if (ret < 0) {
> @@ -1301,9 +1414,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");
>  
> -	return connector_status_connected;
> +	if (ctx->pdata.panel_bridge)
> +		return connector_status_connected;
> +
> +	return ctx->hpd_status ? connector_status_connected :
> +				     connector_status_disconnected;
>  }
>  
>  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> @@ -1332,7 +1449,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	|
> @@ -1460,6 +1577,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;
> @@ -1835,14 +1956,22 @@ 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);
>  
> -	ret = anx7625_attach_dsi(platform);
> -	if (ret) {
> -		DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> -		goto unregister_bridge;
> +	if (!platform->pdata.is_dpi) {
> +		ret = anx7625_attach_dsi(platform);
> +		if (ret) {
> +			DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> +			goto unregister_bridge;
> +		}
>  	}
>  
>  	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> index 6dcf64c703f9..3ef1d8f4e575 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> @@ -141,12 +141,20 @@
>  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
>  
>  /******** END of I2C Address 0x72 *********/
> +
> +/***************************************************************/
> +/* Register definition of device address 0x7a */
> +#define DP_TX_SWING_REG_CNT		0x14
> +#define DP_TX_LANE0_SWING_REG0		0x00
> +#define DP_TX_LANE1_SWING_REG0		0x14
> +/******** END of I2C Address 0x7a *********/
> +
>  /***************************************************************/
>  /* Register definition of device address 0x7e */
>  
>  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
>  
> -#define FLASH_LOAD_STA 0x05
> +#define FLASH_LOAD_STA          0x05
>  #define FLASH_LOAD_STA_CHK	BIT(7)
>  
>  #define  XTAL_FRQ_SEL    0x3F
> @@ -349,12 +357,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 regulator_bulk_data supplies[3];
>  	struct drm_bridge *panel_bridge;
>  	int intp_irq;
> +	int is_dpi;
> +	int mipi_lanes;
> +	int dp_lane0_swing_reg_cnt;
> +	int lane0_reg_data[DP_TX_SWING_REG_CNT];
> +	int dp_lane1_swing_reg_cnt;
> +	int lane1_reg_data[DP_TX_SWING_REG_CNT];
>  	u32 low_power_mode;
>  	struct device_node *mipi_host_node;
>  };

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-06 17:13   ` Laurent Pinchart
@ 2022-03-07  3:22     ` Xin Ji
  2022-03-07  3:30       ` Laurent Pinchart
  2022-03-07  6:12     ` Chen-Yu Tsai
  1 sibling, 1 reply; 20+ messages in thread
From: Xin Ji @ 2022-03-07  3:22 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: a.hajda, narmstrong, dan.carpenter, robert.foss, jonas,
	jernej.skrabec, airlied, daniel, sam, pihsun, tzungbi, maxime,
	drinkcat, hsinyi, dri-devel, linux-kernel, bliang, qwen, robh+dt,
	devicetree

On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> Hello Xin,
> 
> (Question for Rob below, and I'm afraid this is urgent as we need to
> merge a fix in v5.17).
> 
> On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > The basic anx7625 driver only support MIPI DSI rx signal input.
> > This patch add MIPI DPI rx input configuration support, after apply
> > this patch, the driver can support DSI rx or DPI rx by adding
> > 'bus-type' in DT.
> > 
> > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > ---
> >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> >  2 files changed, 205 insertions(+), 60 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > index f48e91134c20..f7c3386c8929 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > @@ -32,6 +32,7 @@
> >  #include <drm/drm_print.h>
> >  #include <drm/drm_probe_helper.h>
> >  
> > +#include <media/v4l2-fwnode.h>
> >  #include <video/display_timing.h>
> >  
> >  #include "anx7625.h"
> > @@ -152,18 +153,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)
> > @@ -221,38 +222,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)
> >  {
> > @@ -431,7 +400,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 +
> > @@ -615,6 +584,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
> >  	return ret;
> >  }
> >  
> > +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> > +{
> > +	struct device *dev = &ctx->client->dev;
> > +	u16 freq = ctx->dt.pixelclock.min / 1000;
> > +	int ret;
> > +
> > +	/* configure pixel clock */
> > +	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +				PIXEL_CLOCK_L, freq & 0xFF);
> > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +				 PIXEL_CLOCK_H, (freq >> 8));
> > +
> > +	/* set DPI mode */
> > +	/* set to DPI PLL module sel */
> > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > +				 MIPI_DIGITAL_PLL_9, 0x20);
> > +	/* power down MIPI */
> > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > +				 MIPI_LANE_CTRL_10, 0x08);
> > +	/* enable DPI mode */
> > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > +				 MIPI_DIGITAL_PLL_18, 0x1C);
> > +	/* set first edge */
> > +	ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> > +				 VIDEO_CONTROL_0, 0x06);
> > +	if (ret < 0)
> > +		DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> > +
> > +	return ret;
> > +}
> > +
> > +static int anx7625_dpi_config(struct anx7625_data *ctx)
> > +{
> > +	struct device *dev = &ctx->client->dev;
> > +	int ret;
> > +
> > +	DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> > +
> > +	/* DSC disable */
> > +	ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > +				R_DSC_CTRL_0, ~DSC_EN);
> > +	if (ret < 0) {
> > +		DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> > +		return ret;
> > +	}
> > +
> > +	ret = anx7625_config_bit_matrix(ctx);
> > +	if (ret < 0) {
> > +		DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> > +		return ret;
> > +	}
> > +
> > +	ret = anx7625_api_dpi_config(ctx);
> > +	if (ret < 0) {
> > +		DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> > +		return ret;
> > +	}
> > +
> > +	/* set MIPI RX EN */
> > +	ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > +			       AP_AV_STATUS, AP_MIPI_RX_EN);
> > +	/* clear mute flag */
> > +	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > +				 AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> > +	if (ret < 0)
> > +		DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> > +
> > +	return ret;
> > +}
> > +
> >  static void anx7625_dp_start(struct anx7625_data *ctx)
> >  {
> >  	int ret;
> > @@ -625,9 +664,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> >  		return;
> >  	}
> >  
> > -	anx7625_config_audio_input(ctx);
> > -
> > -	ret = anx7625_dsi_config(ctx);
> > +	if (ctx->pdata.is_dpi)
> > +		ret = anx7625_dpi_config(ctx);
> > +	else
> > +		ret = anx7625_dsi_config(ctx);
> >  
> >  	if (ret < 0)
> >  		DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> > @@ -1075,6 +1115,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
> >  		return;
> >  	}
> >  
> > +	ctx->hpd_status = 1;
> >  	ctx->hpd_high_cnt++;
> >  
> >  	/* Not support HDCP */
> > @@ -1084,8 +1125,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)
> > @@ -1104,6 +1147,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;
> > +
> >  	ret = readx_poll_timeout(anx7625_read_hpd_status_p0,
> >  				 ctx, val,
> >  				 ((val & HPD_STATUS) || (val < 0)),
> > @@ -1131,6 +1178,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;
> > @@ -1146,9 +1208,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)
> > @@ -1225,20 +1286,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
> >  	return IRQ_HANDLED;
> >  }
> >  
> > +static int anx7625_get_swing_setting(struct device *dev,
> > +				     struct anx7625_platform_data *pdata)
> > +{
> > +	int num_regs;
> > +
> > +	if (of_get_property(dev->of_node,
> > +			    "analogix,lane0-swing", &num_regs)) {
> > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > +			num_regs = DP_TX_SWING_REG_CNT;
> > +
> > +		pdata->dp_lane0_swing_reg_cnt = num_regs;
> > +		of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> > +					   pdata->lane0_reg_data, num_regs);
> > +	}
> > +
> > +	if (of_get_property(dev->of_node,
> > +			    "analogix,lane1-swing", &num_regs)) {
> > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > +			num_regs = DP_TX_SWING_REG_CNT;
> > +
> > +		pdata->dp_lane1_swing_reg_cnt = num_regs;
> > +		of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> > +					   pdata->lane1_reg_data, num_regs);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static int anx7625_parse_dt(struct device *dev,
> >  			    struct anx7625_platform_data *pdata)
> >  {
> > -	struct device_node *np = dev->of_node;
> > +	struct device_node *np = dev->of_node, *ep0;
> >  	struct drm_panel *panel;
> >  	int ret;
> > +	int bus_type, mipi_lanes;
> > +
> > +	anx7625_get_swing_setting(dev, pdata);
> >  
> > +	pdata->is_dpi = 1; /* default dpi mode */
> >  	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> >  	if (!pdata->mipi_host_node) {
> >  		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> >  		return -ENODEV;
> >  	}
> >  
> > -	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > +	bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > +	mipi_lanes = MAX_LANES_SUPPORT;
> > +	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > +	if (ep0) {
> > +		if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > +			bus_type = 0;
> > +
> > +		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > +	}
> > +
> > +	if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> 
> This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> it's not an exact match.
> 
> This patch has landed in v5.17-rc1, along with the corresponding
> bindings. As DT bindings are an ABI, we should really fix this before
> v5.17 is released. There is no DSI bus types defined in DT, and adding
> one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> me (unless Rob disagrees).
> 
> It would seem best to revert this series and the corresponding bindings,
> and retry in v5.18.
Hi, what about make a patch to change this line to:
if (bus_type != V4L2_FWNODE_BUS_TYPE_PARALLEL), and then change the DTS
file?

Thanks,
Xin
> 
> > +		pdata->is_dpi = 0;
> > +
> > +	pdata->mipi_lanes = mipi_lanes;
> > +	if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> > +		pdata->mipi_lanes = MAX_LANES_SUPPORT;
> > +
> > +	if (pdata->is_dpi)
> > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> > +	else
> > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
> >  
> >  	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
> >  	if (ret < 0) {
> > @@ -1301,9 +1414,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");
> >  
> > -	return connector_status_connected;
> > +	if (ctx->pdata.panel_bridge)
> > +		return connector_status_connected;
> > +
> > +	return ctx->hpd_status ? connector_status_connected :
> > +				     connector_status_disconnected;
> >  }
> >  
> >  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> > @@ -1332,7 +1449,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	|
> > @@ -1460,6 +1577,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;
> > @@ -1835,14 +1956,22 @@ 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);
> >  
> > -	ret = anx7625_attach_dsi(platform);
> > -	if (ret) {
> > -		DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > -		goto unregister_bridge;
> > +	if (!platform->pdata.is_dpi) {
> > +		ret = anx7625_attach_dsi(platform);
> > +		if (ret) {
> > +			DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > +			goto unregister_bridge;
> > +		}
> >  	}
> >  
> >  	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > index 6dcf64c703f9..3ef1d8f4e575 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > @@ -141,12 +141,20 @@
> >  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
> >  
> >  /******** END of I2C Address 0x72 *********/
> > +
> > +/***************************************************************/
> > +/* Register definition of device address 0x7a */
> > +#define DP_TX_SWING_REG_CNT		0x14
> > +#define DP_TX_LANE0_SWING_REG0		0x00
> > +#define DP_TX_LANE1_SWING_REG0		0x14
> > +/******** END of I2C Address 0x7a *********/
> > +
> >  /***************************************************************/
> >  /* Register definition of device address 0x7e */
> >  
> >  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
> >  
> > -#define FLASH_LOAD_STA 0x05
> > +#define FLASH_LOAD_STA          0x05
> >  #define FLASH_LOAD_STA_CHK	BIT(7)
> >  
> >  #define  XTAL_FRQ_SEL    0x3F
> > @@ -349,12 +357,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 regulator_bulk_data supplies[3];
> >  	struct drm_bridge *panel_bridge;
> >  	int intp_irq;
> > +	int is_dpi;
> > +	int mipi_lanes;
> > +	int dp_lane0_swing_reg_cnt;
> > +	int lane0_reg_data[DP_TX_SWING_REG_CNT];
> > +	int dp_lane1_swing_reg_cnt;
> > +	int lane1_reg_data[DP_TX_SWING_REG_CNT];
> >  	u32 low_power_mode;
> >  	struct device_node *mipi_host_node;
> >  };
> 
> -- 
> Regards,
> 
> Laurent Pinchart

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-07  3:22     ` Xin Ji
@ 2022-03-07  3:30       ` Laurent Pinchart
  2022-03-07  4:32         ` Xin Ji
  0 siblings, 1 reply; 20+ messages in thread
From: Laurent Pinchart @ 2022-03-07  3:30 UTC (permalink / raw)
  To: Xin Ji
  Cc: a.hajda, narmstrong, dan.carpenter, robert.foss, jonas,
	jernej.skrabec, airlied, daniel, sam, pihsun, tzungbi, maxime,
	drinkcat, hsinyi, dri-devel, linux-kernel, bliang, qwen, robh+dt,
	devicetree

Hello Xin,

On Mon, Mar 07, 2022 at 11:22:48AM +0800, Xin Ji wrote:
> On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> > Hello Xin,
> > 
> > (Question for Rob below, and I'm afraid this is urgent as we need to
> > merge a fix in v5.17).
> > 
> > On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > > The basic anx7625 driver only support MIPI DSI rx signal input.
> > > This patch add MIPI DPI rx input configuration support, after apply
> > > this patch, the driver can support DSI rx or DPI rx by adding
> > > 'bus-type' in DT.
> > > 
> > > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > ---
> > >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> > >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> > >  2 files changed, 205 insertions(+), 60 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > index f48e91134c20..f7c3386c8929 100644
> > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > @@ -32,6 +32,7 @@
> > >  #include <drm/drm_print.h>
> > >  #include <drm/drm_probe_helper.h>
> > >  
> > > +#include <media/v4l2-fwnode.h>
> > >  #include <video/display_timing.h>
> > >  
> > >  #include "anx7625.h"
> > > @@ -152,18 +153,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)
> > > @@ -221,38 +222,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)
> > >  {
> > > @@ -431,7 +400,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 +
> > > @@ -615,6 +584,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
> > >  	return ret;
> > >  }
> > >  
> > > +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> > > +{
> > > +	struct device *dev = &ctx->client->dev;
> > > +	u16 freq = ctx->dt.pixelclock.min / 1000;
> > > +	int ret;
> > > +
> > > +	/* configure pixel clock */
> > > +	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > +				PIXEL_CLOCK_L, freq & 0xFF);
> > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > +				 PIXEL_CLOCK_H, (freq >> 8));
> > > +
> > > +	/* set DPI mode */
> > > +	/* set to DPI PLL module sel */
> > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > +				 MIPI_DIGITAL_PLL_9, 0x20);
> > > +	/* power down MIPI */
> > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > +				 MIPI_LANE_CTRL_10, 0x08);
> > > +	/* enable DPI mode */
> > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > +				 MIPI_DIGITAL_PLL_18, 0x1C);
> > > +	/* set first edge */
> > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> > > +				 VIDEO_CONTROL_0, 0x06);
> > > +	if (ret < 0)
> > > +		DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static int anx7625_dpi_config(struct anx7625_data *ctx)
> > > +{
> > > +	struct device *dev = &ctx->client->dev;
> > > +	int ret;
> > > +
> > > +	DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> > > +
> > > +	/* DSC disable */
> > > +	ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > +				R_DSC_CTRL_0, ~DSC_EN);
> > > +	if (ret < 0) {
> > > +		DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> > > +		return ret;
> > > +	}
> > > +
> > > +	ret = anx7625_config_bit_matrix(ctx);
> > > +	if (ret < 0) {
> > > +		DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> > > +		return ret;
> > > +	}
> > > +
> > > +	ret = anx7625_api_dpi_config(ctx);
> > > +	if (ret < 0) {
> > > +		DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> > > +		return ret;
> > > +	}
> > > +
> > > +	/* set MIPI RX EN */
> > > +	ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > > +			       AP_AV_STATUS, AP_MIPI_RX_EN);
> > > +	/* clear mute flag */
> > > +	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > +				 AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> > > +	if (ret < 0)
> > > +		DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> > > +
> > > +	return ret;
> > > +}
> > > +
> > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > >  {
> > >  	int ret;
> > > @@ -625,9 +664,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > >  		return;
> > >  	}
> > >  
> > > -	anx7625_config_audio_input(ctx);
> > > -
> > > -	ret = anx7625_dsi_config(ctx);
> > > +	if (ctx->pdata.is_dpi)
> > > +		ret = anx7625_dpi_config(ctx);
> > > +	else
> > > +		ret = anx7625_dsi_config(ctx);
> > >  
> > >  	if (ret < 0)
> > >  		DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> > > @@ -1075,6 +1115,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
> > >  		return;
> > >  	}
> > >  
> > > +	ctx->hpd_status = 1;
> > >  	ctx->hpd_high_cnt++;
> > >  
> > >  	/* Not support HDCP */
> > > @@ -1084,8 +1125,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)
> > > @@ -1104,6 +1147,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;
> > > +
> > >  	ret = readx_poll_timeout(anx7625_read_hpd_status_p0,
> > >  				 ctx, val,
> > >  				 ((val & HPD_STATUS) || (val < 0)),
> > > @@ -1131,6 +1178,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;
> > > @@ -1146,9 +1208,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)
> > > @@ -1225,20 +1286,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
> > >  	return IRQ_HANDLED;
> > >  }
> > >  
> > > +static int anx7625_get_swing_setting(struct device *dev,
> > > +				     struct anx7625_platform_data *pdata)
> > > +{
> > > +	int num_regs;
> > > +
> > > +	if (of_get_property(dev->of_node,
> > > +			    "analogix,lane0-swing", &num_regs)) {
> > > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > > +			num_regs = DP_TX_SWING_REG_CNT;
> > > +
> > > +		pdata->dp_lane0_swing_reg_cnt = num_regs;
> > > +		of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> > > +					   pdata->lane0_reg_data, num_regs);
> > > +	}
> > > +
> > > +	if (of_get_property(dev->of_node,
> > > +			    "analogix,lane1-swing", &num_regs)) {
> > > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > > +			num_regs = DP_TX_SWING_REG_CNT;
> > > +
> > > +		pdata->dp_lane1_swing_reg_cnt = num_regs;
> > > +		of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> > > +					   pdata->lane1_reg_data, num_regs);
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  static int anx7625_parse_dt(struct device *dev,
> > >  			    struct anx7625_platform_data *pdata)
> > >  {
> > > -	struct device_node *np = dev->of_node;
> > > +	struct device_node *np = dev->of_node, *ep0;
> > >  	struct drm_panel *panel;
> > >  	int ret;
> > > +	int bus_type, mipi_lanes;
> > > +
> > > +	anx7625_get_swing_setting(dev, pdata);
> > >  
> > > +	pdata->is_dpi = 1; /* default dpi mode */
> > >  	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> > >  	if (!pdata->mipi_host_node) {
> > >  		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> > >  		return -ENODEV;
> > >  	}
> > >  
> > > -	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > +	bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > +	mipi_lanes = MAX_LANES_SUPPORT;
> > > +	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > +	if (ep0) {
> > > +		if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > +			bus_type = 0;
> > > +
> > > +		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > +	}
> > > +
> > > +	if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> > 
> > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > it's not an exact match.
> > 
> > This patch has landed in v5.17-rc1, along with the corresponding
> > bindings. As DT bindings are an ABI, we should really fix this before
> > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > me (unless Rob disagrees).
> > 
> > It would seem best to revert this series and the corresponding bindings,
> > and retry in v5.18.
>
> Hi, what about make a patch to change this line to:
> if (bus_type != V4L2_FWNODE_BUS_TYPE_PARALLEL), and then change the DTS
> file?

We could possibly use V4L2_FWNODE_BUS_TYPE_PARALLEL (5) for MIPI DPI
(although it's not a very accurate match, so a different type may be
better, this should be discussed), but V4L2_FWNODE_BUS_TYPE_CCP2 (1) is
definitely not appropriate for DSI. For that we need a new type, and I
don't think it should be rushed in v5.17.

> > > +		pdata->is_dpi = 0;
> > > +
> > > +	pdata->mipi_lanes = mipi_lanes;
> > > +	if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> > > +		pdata->mipi_lanes = MAX_LANES_SUPPORT;
> > > +
> > > +	if (pdata->is_dpi)
> > > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> > > +	else
> > > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
> > >  
> > >  	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
> > >  	if (ret < 0) {
> > > @@ -1301,9 +1414,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");
> > >  
> > > -	return connector_status_connected;
> > > +	if (ctx->pdata.panel_bridge)
> > > +		return connector_status_connected;
> > > +
> > > +	return ctx->hpd_status ? connector_status_connected :
> > > +				     connector_status_disconnected;
> > >  }
> > >  
> > >  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> > > @@ -1332,7 +1449,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	|
> > > @@ -1460,6 +1577,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;
> > > @@ -1835,14 +1956,22 @@ 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);
> > >  
> > > -	ret = anx7625_attach_dsi(platform);
> > > -	if (ret) {
> > > -		DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > -		goto unregister_bridge;
> > > +	if (!platform->pdata.is_dpi) {
> > > +		ret = anx7625_attach_dsi(platform);
> > > +		if (ret) {
> > > +			DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > +			goto unregister_bridge;
> > > +		}
> > >  	}
> > >  
> > >  	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > index 6dcf64c703f9..3ef1d8f4e575 100644
> > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > @@ -141,12 +141,20 @@
> > >  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
> > >  
> > >  /******** END of I2C Address 0x72 *********/
> > > +
> > > +/***************************************************************/
> > > +/* Register definition of device address 0x7a */
> > > +#define DP_TX_SWING_REG_CNT		0x14
> > > +#define DP_TX_LANE0_SWING_REG0		0x00
> > > +#define DP_TX_LANE1_SWING_REG0		0x14
> > > +/******** END of I2C Address 0x7a *********/
> > > +
> > >  /***************************************************************/
> > >  /* Register definition of device address 0x7e */
> > >  
> > >  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
> > >  
> > > -#define FLASH_LOAD_STA 0x05
> > > +#define FLASH_LOAD_STA          0x05
> > >  #define FLASH_LOAD_STA_CHK	BIT(7)
> > >  
> > >  #define  XTAL_FRQ_SEL    0x3F
> > > @@ -349,12 +357,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 regulator_bulk_data supplies[3];
> > >  	struct drm_bridge *panel_bridge;
> > >  	int intp_irq;
> > > +	int is_dpi;
> > > +	int mipi_lanes;
> > > +	int dp_lane0_swing_reg_cnt;
> > > +	int lane0_reg_data[DP_TX_SWING_REG_CNT];
> > > +	int dp_lane1_swing_reg_cnt;
> > > +	int lane1_reg_data[DP_TX_SWING_REG_CNT];
> > >  	u32 low_power_mode;
> > >  	struct device_node *mipi_host_node;
> > >  };

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-07  3:30       ` Laurent Pinchart
@ 2022-03-07  4:32         ` Xin Ji
  2022-03-07  4:47           ` Laurent Pinchart
  0 siblings, 1 reply; 20+ messages in thread
From: Xin Ji @ 2022-03-07  4:32 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: a.hajda, narmstrong, dan.carpenter, robert.foss, jonas,
	jernej.skrabec, airlied, daniel, sam, pihsun, tzungbi, maxime,
	drinkcat, hsinyi, dri-devel, linux-kernel, bliang, qwen, robh+dt,
	devicetree

On Mon, Mar 07, 2022 at 05:30:09AM +0200, Laurent Pinchart wrote:
> Hello Xin,
> 
> On Mon, Mar 07, 2022 at 11:22:48AM +0800, Xin Ji wrote:
> > On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> > > Hello Xin,
> > > 
> > > (Question for Rob below, and I'm afraid this is urgent as we need to
> > > merge a fix in v5.17).
> > > 
> > > On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > > > The basic anx7625 driver only support MIPI DSI rx signal input.
> > > > This patch add MIPI DPI rx input configuration support, after apply
> > > > this patch, the driver can support DSI rx or DPI rx by adding
> > > > 'bus-type' in DT.
> > > > 
> > > > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > ---
> > > >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> > > >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> > > >  2 files changed, 205 insertions(+), 60 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > index f48e91134c20..f7c3386c8929 100644
> > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > @@ -32,6 +32,7 @@
> > > >  #include <drm/drm_print.h>
> > > >  #include <drm/drm_probe_helper.h>
> > > >  
> > > > +#include <media/v4l2-fwnode.h>
> > > >  #include <video/display_timing.h>
> > > >  
> > > >  #include "anx7625.h"
> > > > @@ -152,18 +153,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)
> > > > @@ -221,38 +222,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)
> > > >  {
> > > > @@ -431,7 +400,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 +
> > > > @@ -615,6 +584,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
> > > >  	return ret;
> > > >  }
> > > >  
> > > > +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> > > > +{
> > > > +	struct device *dev = &ctx->client->dev;
> > > > +	u16 freq = ctx->dt.pixelclock.min / 1000;
> > > > +	int ret;
> > > > +
> > > > +	/* configure pixel clock */
> > > > +	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > +				PIXEL_CLOCK_L, freq & 0xFF);
> > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > +				 PIXEL_CLOCK_H, (freq >> 8));
> > > > +
> > > > +	/* set DPI mode */
> > > > +	/* set to DPI PLL module sel */
> > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > +				 MIPI_DIGITAL_PLL_9, 0x20);
> > > > +	/* power down MIPI */
> > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > +				 MIPI_LANE_CTRL_10, 0x08);
> > > > +	/* enable DPI mode */
> > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > +				 MIPI_DIGITAL_PLL_18, 0x1C);
> > > > +	/* set first edge */
> > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> > > > +				 VIDEO_CONTROL_0, 0x06);
> > > > +	if (ret < 0)
> > > > +		DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> > > > +
> > > > +	return ret;
> > > > +}
> > > > +
> > > > +static int anx7625_dpi_config(struct anx7625_data *ctx)
> > > > +{
> > > > +	struct device *dev = &ctx->client->dev;
> > > > +	int ret;
> > > > +
> > > > +	DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> > > > +
> > > > +	/* DSC disable */
> > > > +	ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > +				R_DSC_CTRL_0, ~DSC_EN);
> > > > +	if (ret < 0) {
> > > > +		DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> > > > +		return ret;
> > > > +	}
> > > > +
> > > > +	ret = anx7625_config_bit_matrix(ctx);
> > > > +	if (ret < 0) {
> > > > +		DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> > > > +		return ret;
> > > > +	}
> > > > +
> > > > +	ret = anx7625_api_dpi_config(ctx);
> > > > +	if (ret < 0) {
> > > > +		DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> > > > +		return ret;
> > > > +	}
> > > > +
> > > > +	/* set MIPI RX EN */
> > > > +	ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > > > +			       AP_AV_STATUS, AP_MIPI_RX_EN);
> > > > +	/* clear mute flag */
> > > > +	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > +				 AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> > > > +	if (ret < 0)
> > > > +		DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> > > > +
> > > > +	return ret;
> > > > +}
> > > > +
> > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > >  {
> > > >  	int ret;
> > > > @@ -625,9 +664,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > >  		return;
> > > >  	}
> > > >  
> > > > -	anx7625_config_audio_input(ctx);
> > > > -
> > > > -	ret = anx7625_dsi_config(ctx);
> > > > +	if (ctx->pdata.is_dpi)
> > > > +		ret = anx7625_dpi_config(ctx);
> > > > +	else
> > > > +		ret = anx7625_dsi_config(ctx);
> > > >  
> > > >  	if (ret < 0)
> > > >  		DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> > > > @@ -1075,6 +1115,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
> > > >  		return;
> > > >  	}
> > > >  
> > > > +	ctx->hpd_status = 1;
> > > >  	ctx->hpd_high_cnt++;
> > > >  
> > > >  	/* Not support HDCP */
> > > > @@ -1084,8 +1125,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)
> > > > @@ -1104,6 +1147,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;
> > > > +
> > > >  	ret = readx_poll_timeout(anx7625_read_hpd_status_p0,
> > > >  				 ctx, val,
> > > >  				 ((val & HPD_STATUS) || (val < 0)),
> > > > @@ -1131,6 +1178,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;
> > > > @@ -1146,9 +1208,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)
> > > > @@ -1225,20 +1286,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
> > > >  	return IRQ_HANDLED;
> > > >  }
> > > >  
> > > > +static int anx7625_get_swing_setting(struct device *dev,
> > > > +				     struct anx7625_platform_data *pdata)
> > > > +{
> > > > +	int num_regs;
> > > > +
> > > > +	if (of_get_property(dev->of_node,
> > > > +			    "analogix,lane0-swing", &num_regs)) {
> > > > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > > > +			num_regs = DP_TX_SWING_REG_CNT;
> > > > +
> > > > +		pdata->dp_lane0_swing_reg_cnt = num_regs;
> > > > +		of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> > > > +					   pdata->lane0_reg_data, num_regs);
> > > > +	}
> > > > +
> > > > +	if (of_get_property(dev->of_node,
> > > > +			    "analogix,lane1-swing", &num_regs)) {
> > > > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > > > +			num_regs = DP_TX_SWING_REG_CNT;
> > > > +
> > > > +		pdata->dp_lane1_swing_reg_cnt = num_regs;
> > > > +		of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> > > > +					   pdata->lane1_reg_data, num_regs);
> > > > +	}
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > >  static int anx7625_parse_dt(struct device *dev,
> > > >  			    struct anx7625_platform_data *pdata)
> > > >  {
> > > > -	struct device_node *np = dev->of_node;
> > > > +	struct device_node *np = dev->of_node, *ep0;
> > > >  	struct drm_panel *panel;
> > > >  	int ret;
> > > > +	int bus_type, mipi_lanes;
> > > > +
> > > > +	anx7625_get_swing_setting(dev, pdata);
> > > >  
> > > > +	pdata->is_dpi = 1; /* default dpi mode */
> > > >  	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> > > >  	if (!pdata->mipi_host_node) {
> > > >  		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> > > >  		return -ENODEV;
> > > >  	}
> > > >  
> > > > -	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > > +	bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > > +	mipi_lanes = MAX_LANES_SUPPORT;
> > > > +	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > > +	if (ep0) {
> > > > +		if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > > +			bus_type = 0;
> > > > +
> > > > +		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > > +	}
> > > > +
> > > > +	if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> > > 
> > > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > > it's not an exact match.
> > > 
> > > This patch has landed in v5.17-rc1, along with the corresponding
> > > bindings. As DT bindings are an ABI, we should really fix this before
> > > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > > me (unless Rob disagrees).
> > > 
> > > It would seem best to revert this series and the corresponding bindings,
> > > and retry in v5.18.
> >
> > Hi, what about make a patch to change this line to:
> > if (bus_type != V4L2_FWNODE_BUS_TYPE_PARALLEL), and then change the DTS
> > file?
> 
> We could possibly use V4L2_FWNODE_BUS_TYPE_PARALLEL (5) for MIPI DPI
> (although it's not a very accurate match, so a different type may be
> better, this should be discussed), but V4L2_FWNODE_BUS_TYPE_CCP2 (1) is
> definitely not appropriate for DSI. For that we need a new type, and I
> don't think it should be rushed in v5.17.
Hi Laurent Pinchart, what should I do now? Do you mean upload a bug fix
patch after kernel defined a new type(DPI and DSI) in new kernel?

Thanks,
Xin

> 
> > > > +		pdata->is_dpi = 0;
> > > > +
> > > > +	pdata->mipi_lanes = mipi_lanes;
> > > > +	if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> > > > +		pdata->mipi_lanes = MAX_LANES_SUPPORT;
> > > > +
> > > > +	if (pdata->is_dpi)
> > > > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> > > > +	else
> > > > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
> > > >  
> > > >  	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
> > > >  	if (ret < 0) {
> > > > @@ -1301,9 +1414,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");
> > > >  
> > > > -	return connector_status_connected;
> > > > +	if (ctx->pdata.panel_bridge)
> > > > +		return connector_status_connected;
> > > > +
> > > > +	return ctx->hpd_status ? connector_status_connected :
> > > > +				     connector_status_disconnected;
> > > >  }
> > > >  
> > > >  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> > > > @@ -1332,7 +1449,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	|
> > > > @@ -1460,6 +1577,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;
> > > > @@ -1835,14 +1956,22 @@ 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);
> > > >  
> > > > -	ret = anx7625_attach_dsi(platform);
> > > > -	if (ret) {
> > > > -		DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > -		goto unregister_bridge;
> > > > +	if (!platform->pdata.is_dpi) {
> > > > +		ret = anx7625_attach_dsi(platform);
> > > > +		if (ret) {
> > > > +			DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > +			goto unregister_bridge;
> > > > +		}
> > > >  	}
> > > >  
> > > >  	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > index 6dcf64c703f9..3ef1d8f4e575 100644
> > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > @@ -141,12 +141,20 @@
> > > >  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
> > > >  
> > > >  /******** END of I2C Address 0x72 *********/
> > > > +
> > > > +/***************************************************************/
> > > > +/* Register definition of device address 0x7a */
> > > > +#define DP_TX_SWING_REG_CNT		0x14
> > > > +#define DP_TX_LANE0_SWING_REG0		0x00
> > > > +#define DP_TX_LANE1_SWING_REG0		0x14
> > > > +/******** END of I2C Address 0x7a *********/
> > > > +
> > > >  /***************************************************************/
> > > >  /* Register definition of device address 0x7e */
> > > >  
> > > >  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
> > > >  
> > > > -#define FLASH_LOAD_STA 0x05
> > > > +#define FLASH_LOAD_STA          0x05
> > > >  #define FLASH_LOAD_STA_CHK	BIT(7)
> > > >  
> > > >  #define  XTAL_FRQ_SEL    0x3F
> > > > @@ -349,12 +357,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 regulator_bulk_data supplies[3];
> > > >  	struct drm_bridge *panel_bridge;
> > > >  	int intp_irq;
> > > > +	int is_dpi;
> > > > +	int mipi_lanes;
> > > > +	int dp_lane0_swing_reg_cnt;
> > > > +	int lane0_reg_data[DP_TX_SWING_REG_CNT];
> > > > +	int dp_lane1_swing_reg_cnt;
> > > > +	int lane1_reg_data[DP_TX_SWING_REG_CNT];
> > > >  	u32 low_power_mode;
> > > >  	struct device_node *mipi_host_node;
> > > >  };
> 
> -- 
> Regards,
> 
> Laurent Pinchart

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-07  4:32         ` Xin Ji
@ 2022-03-07  4:47           ` Laurent Pinchart
  2022-03-07  5:09             ` Xin Ji
  0 siblings, 1 reply; 20+ messages in thread
From: Laurent Pinchart @ 2022-03-07  4:47 UTC (permalink / raw)
  To: Xin Ji
  Cc: a.hajda, narmstrong, dan.carpenter, robert.foss, jonas,
	jernej.skrabec, airlied, daniel, sam, pihsun, tzungbi, maxime,
	drinkcat, hsinyi, dri-devel, linux-kernel, bliang, qwen, robh+dt,
	devicetree

Hello Xin,

On Mon, Mar 07, 2022 at 12:32:49PM +0800, Xin Ji wrote:
> On Mon, Mar 07, 2022 at 05:30:09AM +0200, Laurent Pinchart wrote:
> > On Mon, Mar 07, 2022 at 11:22:48AM +0800, Xin Ji wrote:
> > > On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> > > > Hello Xin,
> > > > 
> > > > (Question for Rob below, and I'm afraid this is urgent as we need to
> > > > merge a fix in v5.17).
> > > > 
> > > > On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > > > > The basic anx7625 driver only support MIPI DSI rx signal input.
> > > > > This patch add MIPI DPI rx input configuration support, after apply
> > > > > this patch, the driver can support DSI rx or DPI rx by adding
> > > > > 'bus-type' in DT.
> > > > > 
> > > > > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > ---
> > > > >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> > > > >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> > > > >  2 files changed, 205 insertions(+), 60 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > index f48e91134c20..f7c3386c8929 100644
> > > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > @@ -32,6 +32,7 @@
> > > > >  #include <drm/drm_print.h>
> > > > >  #include <drm/drm_probe_helper.h>
> > > > >  
> > > > > +#include <media/v4l2-fwnode.h>
> > > > >  #include <video/display_timing.h>
> > > > >  
> > > > >  #include "anx7625.h"
> > > > > @@ -152,18 +153,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)
> > > > > @@ -221,38 +222,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)
> > > > >  {
> > > > > @@ -431,7 +400,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 +
> > > > > @@ -615,6 +584,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
> > > > >  	return ret;
> > > > >  }
> > > > >  
> > > > > +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> > > > > +{
> > > > > +	struct device *dev = &ctx->client->dev;
> > > > > +	u16 freq = ctx->dt.pixelclock.min / 1000;
> > > > > +	int ret;
> > > > > +
> > > > > +	/* configure pixel clock */
> > > > > +	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > > +				PIXEL_CLOCK_L, freq & 0xFF);
> > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > > +				 PIXEL_CLOCK_H, (freq >> 8));
> > > > > +
> > > > > +	/* set DPI mode */
> > > > > +	/* set to DPI PLL module sel */
> > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > +				 MIPI_DIGITAL_PLL_9, 0x20);
> > > > > +	/* power down MIPI */
> > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > +				 MIPI_LANE_CTRL_10, 0x08);
> > > > > +	/* enable DPI mode */
> > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > +				 MIPI_DIGITAL_PLL_18, 0x1C);
> > > > > +	/* set first edge */
> > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> > > > > +				 VIDEO_CONTROL_0, 0x06);
> > > > > +	if (ret < 0)
> > > > > +		DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> > > > > +
> > > > > +	return ret;
> > > > > +}
> > > > > +
> > > > > +static int anx7625_dpi_config(struct anx7625_data *ctx)
> > > > > +{
> > > > > +	struct device *dev = &ctx->client->dev;
> > > > > +	int ret;
> > > > > +
> > > > > +	DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> > > > > +
> > > > > +	/* DSC disable */
> > > > > +	ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > > +				R_DSC_CTRL_0, ~DSC_EN);
> > > > > +	if (ret < 0) {
> > > > > +		DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> > > > > +		return ret;
> > > > > +	}
> > > > > +
> > > > > +	ret = anx7625_config_bit_matrix(ctx);
> > > > > +	if (ret < 0) {
> > > > > +		DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> > > > > +		return ret;
> > > > > +	}
> > > > > +
> > > > > +	ret = anx7625_api_dpi_config(ctx);
> > > > > +	if (ret < 0) {
> > > > > +		DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> > > > > +		return ret;
> > > > > +	}
> > > > > +
> > > > > +	/* set MIPI RX EN */
> > > > > +	ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > > > > +			       AP_AV_STATUS, AP_MIPI_RX_EN);
> > > > > +	/* clear mute flag */
> > > > > +	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > > +				 AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> > > > > +	if (ret < 0)
> > > > > +		DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> > > > > +
> > > > > +	return ret;
> > > > > +}
> > > > > +
> > > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > >  {
> > > > >  	int ret;
> > > > > @@ -625,9 +664,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > >  		return;
> > > > >  	}
> > > > >  
> > > > > -	anx7625_config_audio_input(ctx);
> > > > > -
> > > > > -	ret = anx7625_dsi_config(ctx);
> > > > > +	if (ctx->pdata.is_dpi)
> > > > > +		ret = anx7625_dpi_config(ctx);
> > > > > +	else
> > > > > +		ret = anx7625_dsi_config(ctx);
> > > > >  
> > > > >  	if (ret < 0)
> > > > >  		DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> > > > > @@ -1075,6 +1115,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
> > > > >  		return;
> > > > >  	}
> > > > >  
> > > > > +	ctx->hpd_status = 1;
> > > > >  	ctx->hpd_high_cnt++;
> > > > >  
> > > > >  	/* Not support HDCP */
> > > > > @@ -1084,8 +1125,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)
> > > > > @@ -1104,6 +1147,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;
> > > > > +
> > > > >  	ret = readx_poll_timeout(anx7625_read_hpd_status_p0,
> > > > >  				 ctx, val,
> > > > >  				 ((val & HPD_STATUS) || (val < 0)),
> > > > > @@ -1131,6 +1178,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;
> > > > > @@ -1146,9 +1208,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)
> > > > > @@ -1225,20 +1286,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
> > > > >  	return IRQ_HANDLED;
> > > > >  }
> > > > >  
> > > > > +static int anx7625_get_swing_setting(struct device *dev,
> > > > > +				     struct anx7625_platform_data *pdata)
> > > > > +{
> > > > > +	int num_regs;
> > > > > +
> > > > > +	if (of_get_property(dev->of_node,
> > > > > +			    "analogix,lane0-swing", &num_regs)) {
> > > > > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > > > > +			num_regs = DP_TX_SWING_REG_CNT;
> > > > > +
> > > > > +		pdata->dp_lane0_swing_reg_cnt = num_regs;
> > > > > +		of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> > > > > +					   pdata->lane0_reg_data, num_regs);
> > > > > +	}
> > > > > +
> > > > > +	if (of_get_property(dev->of_node,
> > > > > +			    "analogix,lane1-swing", &num_regs)) {
> > > > > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > > > > +			num_regs = DP_TX_SWING_REG_CNT;
> > > > > +
> > > > > +		pdata->dp_lane1_swing_reg_cnt = num_regs;
> > > > > +		of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> > > > > +					   pdata->lane1_reg_data, num_regs);
> > > > > +	}
> > > > > +
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > >  static int anx7625_parse_dt(struct device *dev,
> > > > >  			    struct anx7625_platform_data *pdata)
> > > > >  {
> > > > > -	struct device_node *np = dev->of_node;
> > > > > +	struct device_node *np = dev->of_node, *ep0;
> > > > >  	struct drm_panel *panel;
> > > > >  	int ret;
> > > > > +	int bus_type, mipi_lanes;
> > > > > +
> > > > > +	anx7625_get_swing_setting(dev, pdata);
> > > > >  
> > > > > +	pdata->is_dpi = 1; /* default dpi mode */
> > > > >  	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> > > > >  	if (!pdata->mipi_host_node) {
> > > > >  		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> > > > >  		return -ENODEV;
> > > > >  	}
> > > > >  
> > > > > -	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > > > +	bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > > > +	mipi_lanes = MAX_LANES_SUPPORT;
> > > > > +	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > > > +	if (ep0) {
> > > > > +		if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > > > +			bus_type = 0;
> > > > > +
> > > > > +		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > > > +	}
> > > > > +
> > > > > +	if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> > > > 
> > > > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > > > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > > > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > > > it's not an exact match.
> > > > 
> > > > This patch has landed in v5.17-rc1, along with the corresponding
> > > > bindings. As DT bindings are an ABI, we should really fix this before
> > > > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > > > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > > > me (unless Rob disagrees).
> > > > 
> > > > It would seem best to revert this series and the corresponding bindings,
> > > > and retry in v5.18.
> > >
> > > Hi, what about make a patch to change this line to:
> > > if (bus_type != V4L2_FWNODE_BUS_TYPE_PARALLEL), and then change the DTS
> > > file?
> > 
> > We could possibly use V4L2_FWNODE_BUS_TYPE_PARALLEL (5) for MIPI DPI
> > (although it's not a very accurate match, so a different type may be
> > better, this should be discussed), but V4L2_FWNODE_BUS_TYPE_CCP2 (1) is
> > definitely not appropriate for DSI. For that we need a new type, and I
> > don't think it should be rushed in v5.17.
>
> Hi Laurent Pinchart, what should I do now? Do you mean upload a bug fix
> patch after kernel defined a new type(DPI and DSI) in new kernel?

I think fixing this properly requires defining at least a new bus type
for DSI. As this can't be done in v5.17, the best option seems to revert
this series now as a fix for v5?.17, and submit a new version for v5.18,
with a patch to add a DSI bus type.

Any opinion from Rob (Herring and Foss) ?

> > > > > +		pdata->is_dpi = 0;
> > > > > +
> > > > > +	pdata->mipi_lanes = mipi_lanes;
> > > > > +	if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> > > > > +		pdata->mipi_lanes = MAX_LANES_SUPPORT;
> > > > > +
> > > > > +	if (pdata->is_dpi)
> > > > > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> > > > > +	else
> > > > > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
> > > > >  
> > > > >  	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
> > > > >  	if (ret < 0) {
> > > > > @@ -1301,9 +1414,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");
> > > > >  
> > > > > -	return connector_status_connected;
> > > > > +	if (ctx->pdata.panel_bridge)
> > > > > +		return connector_status_connected;
> > > > > +
> > > > > +	return ctx->hpd_status ? connector_status_connected :
> > > > > +				     connector_status_disconnected;
> > > > >  }
> > > > >  
> > > > >  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> > > > > @@ -1332,7 +1449,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	|
> > > > > @@ -1460,6 +1577,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;
> > > > > @@ -1835,14 +1956,22 @@ 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);
> > > > >  
> > > > > -	ret = anx7625_attach_dsi(platform);
> > > > > -	if (ret) {
> > > > > -		DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > > -		goto unregister_bridge;
> > > > > +	if (!platform->pdata.is_dpi) {
> > > > > +		ret = anx7625_attach_dsi(platform);
> > > > > +		if (ret) {
> > > > > +			DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > > +			goto unregister_bridge;
> > > > > +		}
> > > > >  	}
> > > > >  
> > > > >  	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> > > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > index 6dcf64c703f9..3ef1d8f4e575 100644
> > > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > @@ -141,12 +141,20 @@
> > > > >  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
> > > > >  
> > > > >  /******** END of I2C Address 0x72 *********/
> > > > > +
> > > > > +/***************************************************************/
> > > > > +/* Register definition of device address 0x7a */
> > > > > +#define DP_TX_SWING_REG_CNT		0x14
> > > > > +#define DP_TX_LANE0_SWING_REG0		0x00
> > > > > +#define DP_TX_LANE1_SWING_REG0		0x14
> > > > > +/******** END of I2C Address 0x7a *********/
> > > > > +
> > > > >  /***************************************************************/
> > > > >  /* Register definition of device address 0x7e */
> > > > >  
> > > > >  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
> > > > >  
> > > > > -#define FLASH_LOAD_STA 0x05
> > > > > +#define FLASH_LOAD_STA          0x05
> > > > >  #define FLASH_LOAD_STA_CHK	BIT(7)
> > > > >  
> > > > >  #define  XTAL_FRQ_SEL    0x3F
> > > > > @@ -349,12 +357,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 regulator_bulk_data supplies[3];
> > > > >  	struct drm_bridge *panel_bridge;
> > > > >  	int intp_irq;
> > > > > +	int is_dpi;
> > > > > +	int mipi_lanes;
> > > > > +	int dp_lane0_swing_reg_cnt;
> > > > > +	int lane0_reg_data[DP_TX_SWING_REG_CNT];
> > > > > +	int dp_lane1_swing_reg_cnt;
> > > > > +	int lane1_reg_data[DP_TX_SWING_REG_CNT];
> > > > >  	u32 low_power_mode;
> > > > >  	struct device_node *mipi_host_node;
> > > > >  };

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-07  4:47           ` Laurent Pinchart
@ 2022-03-07  5:09             ` Xin Ji
  2022-03-07  5:17               ` Laurent Pinchart
  2022-03-07  5:17               ` Hsin-Yi Wang
  0 siblings, 2 replies; 20+ messages in thread
From: Xin Ji @ 2022-03-07  5:09 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: a.hajda, narmstrong, dan.carpenter, robert.foss, jonas,
	jernej.skrabec, airlied, daniel, sam, pihsun, tzungbi, maxime,
	drinkcat, hsinyi, dri-devel, linux-kernel, bliang, qwen, robh+dt,
	devicetree

On Mon, Mar 07, 2022 at 06:47:44AM +0200, Laurent Pinchart wrote:
> Hello Xin,
> 
> On Mon, Mar 07, 2022 at 12:32:49PM +0800, Xin Ji wrote:
> > On Mon, Mar 07, 2022 at 05:30:09AM +0200, Laurent Pinchart wrote:
> > > On Mon, Mar 07, 2022 at 11:22:48AM +0800, Xin Ji wrote:
> > > > On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> > > > > Hello Xin,
> > > > > 
> > > > > (Question for Rob below, and I'm afraid this is urgent as we need to
> > > > > merge a fix in v5.17).
> > > > > 
> > > > > On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > > > > > The basic anx7625 driver only support MIPI DSI rx signal input.
> > > > > > This patch add MIPI DPI rx input configuration support, after apply
> > > > > > this patch, the driver can support DSI rx or DPI rx by adding
> > > > > > 'bus-type' in DT.
> > > > > > 
> > > > > > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > > ---
> > > > > >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> > > > > >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> > > > > >  2 files changed, 205 insertions(+), 60 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > index f48e91134c20..f7c3386c8929 100644
> > > > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > @@ -32,6 +32,7 @@
> > > > > >  #include <drm/drm_print.h>
> > > > > >  #include <drm/drm_probe_helper.h>
> > > > > >  
> > > > > > +#include <media/v4l2-fwnode.h>
> > > > > >  #include <video/display_timing.h>
> > > > > >  
> > > > > >  #include "anx7625.h"
> > > > > > @@ -152,18 +153,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)
> > > > > > @@ -221,38 +222,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)
> > > > > >  {
> > > > > > @@ -431,7 +400,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 +
> > > > > > @@ -615,6 +584,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
> > > > > >  	return ret;
> > > > > >  }
> > > > > >  
> > > > > > +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> > > > > > +{
> > > > > > +	struct device *dev = &ctx->client->dev;
> > > > > > +	u16 freq = ctx->dt.pixelclock.min / 1000;
> > > > > > +	int ret;
> > > > > > +
> > > > > > +	/* configure pixel clock */
> > > > > > +	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > > > +				PIXEL_CLOCK_L, freq & 0xFF);
> > > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > > > +				 PIXEL_CLOCK_H, (freq >> 8));
> > > > > > +
> > > > > > +	/* set DPI mode */
> > > > > > +	/* set to DPI PLL module sel */
> > > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > +				 MIPI_DIGITAL_PLL_9, 0x20);
> > > > > > +	/* power down MIPI */
> > > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > +				 MIPI_LANE_CTRL_10, 0x08);
> > > > > > +	/* enable DPI mode */
> > > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > +				 MIPI_DIGITAL_PLL_18, 0x1C);
> > > > > > +	/* set first edge */
> > > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> > > > > > +				 VIDEO_CONTROL_0, 0x06);
> > > > > > +	if (ret < 0)
> > > > > > +		DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> > > > > > +
> > > > > > +	return ret;
> > > > > > +}
> > > > > > +
> > > > > > +static int anx7625_dpi_config(struct anx7625_data *ctx)
> > > > > > +{
> > > > > > +	struct device *dev = &ctx->client->dev;
> > > > > > +	int ret;
> > > > > > +
> > > > > > +	DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> > > > > > +
> > > > > > +	/* DSC disable */
> > > > > > +	ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > > > +				R_DSC_CTRL_0, ~DSC_EN);
> > > > > > +	if (ret < 0) {
> > > > > > +		DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> > > > > > +		return ret;
> > > > > > +	}
> > > > > > +
> > > > > > +	ret = anx7625_config_bit_matrix(ctx);
> > > > > > +	if (ret < 0) {
> > > > > > +		DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> > > > > > +		return ret;
> > > > > > +	}
> > > > > > +
> > > > > > +	ret = anx7625_api_dpi_config(ctx);
> > > > > > +	if (ret < 0) {
> > > > > > +		DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> > > > > > +		return ret;
> > > > > > +	}
> > > > > > +
> > > > > > +	/* set MIPI RX EN */
> > > > > > +	ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > > > > > +			       AP_AV_STATUS, AP_MIPI_RX_EN);
> > > > > > +	/* clear mute flag */
> > > > > > +	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > > > +				 AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> > > > > > +	if (ret < 0)
> > > > > > +		DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> > > > > > +
> > > > > > +	return ret;
> > > > > > +}
> > > > > > +
> > > > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > >  {
> > > > > >  	int ret;
> > > > > > @@ -625,9 +664,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > >  		return;
> > > > > >  	}
> > > > > >  
> > > > > > -	anx7625_config_audio_input(ctx);
> > > > > > -
> > > > > > -	ret = anx7625_dsi_config(ctx);
> > > > > > +	if (ctx->pdata.is_dpi)
> > > > > > +		ret = anx7625_dpi_config(ctx);
> > > > > > +	else
> > > > > > +		ret = anx7625_dsi_config(ctx);
> > > > > >  
> > > > > >  	if (ret < 0)
> > > > > >  		DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> > > > > > @@ -1075,6 +1115,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
> > > > > >  		return;
> > > > > >  	}
> > > > > >  
> > > > > > +	ctx->hpd_status = 1;
> > > > > >  	ctx->hpd_high_cnt++;
> > > > > >  
> > > > > >  	/* Not support HDCP */
> > > > > > @@ -1084,8 +1125,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)
> > > > > > @@ -1104,6 +1147,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;
> > > > > > +
> > > > > >  	ret = readx_poll_timeout(anx7625_read_hpd_status_p0,
> > > > > >  				 ctx, val,
> > > > > >  				 ((val & HPD_STATUS) || (val < 0)),
> > > > > > @@ -1131,6 +1178,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;
> > > > > > @@ -1146,9 +1208,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)
> > > > > > @@ -1225,20 +1286,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
> > > > > >  	return IRQ_HANDLED;
> > > > > >  }
> > > > > >  
> > > > > > +static int anx7625_get_swing_setting(struct device *dev,
> > > > > > +				     struct anx7625_platform_data *pdata)
> > > > > > +{
> > > > > > +	int num_regs;
> > > > > > +
> > > > > > +	if (of_get_property(dev->of_node,
> > > > > > +			    "analogix,lane0-swing", &num_regs)) {
> > > > > > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > > > > > +			num_regs = DP_TX_SWING_REG_CNT;
> > > > > > +
> > > > > > +		pdata->dp_lane0_swing_reg_cnt = num_regs;
> > > > > > +		of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> > > > > > +					   pdata->lane0_reg_data, num_regs);
> > > > > > +	}
> > > > > > +
> > > > > > +	if (of_get_property(dev->of_node,
> > > > > > +			    "analogix,lane1-swing", &num_regs)) {
> > > > > > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > > > > > +			num_regs = DP_TX_SWING_REG_CNT;
> > > > > > +
> > > > > > +		pdata->dp_lane1_swing_reg_cnt = num_regs;
> > > > > > +		of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> > > > > > +					   pdata->lane1_reg_data, num_regs);
> > > > > > +	}
> > > > > > +
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > > >  static int anx7625_parse_dt(struct device *dev,
> > > > > >  			    struct anx7625_platform_data *pdata)
> > > > > >  {
> > > > > > -	struct device_node *np = dev->of_node;
> > > > > > +	struct device_node *np = dev->of_node, *ep0;
> > > > > >  	struct drm_panel *panel;
> > > > > >  	int ret;
> > > > > > +	int bus_type, mipi_lanes;
> > > > > > +
> > > > > > +	anx7625_get_swing_setting(dev, pdata);
> > > > > >  
> > > > > > +	pdata->is_dpi = 1; /* default dpi mode */
> > > > > >  	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> > > > > >  	if (!pdata->mipi_host_node) {
> > > > > >  		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> > > > > >  		return -ENODEV;
> > > > > >  	}
> > > > > >  
> > > > > > -	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > > > > +	bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > > > > +	mipi_lanes = MAX_LANES_SUPPORT;
> > > > > > +	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > > > > +	if (ep0) {
> > > > > > +		if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > > > > +			bus_type = 0;
> > > > > > +
> > > > > > +		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > > > > +	}
> > > > > > +
> > > > > > +	if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> > > > > 
> > > > > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > > > > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > > > > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > > > > it's not an exact match.
> > > > > 
> > > > > This patch has landed in v5.17-rc1, along with the corresponding
> > > > > bindings. As DT bindings are an ABI, we should really fix this before
> > > > > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > > > > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > > > > me (unless Rob disagrees).
> > > > > 
> > > > > It would seem best to revert this series and the corresponding bindings,
> > > > > and retry in v5.18.
> > > >
> > > > Hi, what about make a patch to change this line to:
> > > > if (bus_type != V4L2_FWNODE_BUS_TYPE_PARALLEL), and then change the DTS
> > > > file?
> > > 
> > > We could possibly use V4L2_FWNODE_BUS_TYPE_PARALLEL (5) for MIPI DPI
> > > (although it's not a very accurate match, so a different type may be
> > > better, this should be discussed), but V4L2_FWNODE_BUS_TYPE_CCP2 (1) is
> > > definitely not appropriate for DSI. For that we need a new type, and I
> > > don't think it should be rushed in v5.17.
> >
> > Hi Laurent Pinchart, what should I do now? Do you mean upload a bug fix
> > patch after kernel defined a new type(DPI and DSI) in new kernel?
> 
> I think fixing this properly requires defining at least a new bus type
> for DSI. As this can't be done in v5.17, the best option seems to revert
> this series now as a fix for v5?.17, and submit a new version for v5.18,
> with a patch to add a DSI bus type.
> 
> Any opinion from Rob (Herring and Foss) ?
Hi all, the problem is Chromium OS product depends on this
patch and other patches(which is depends on this patch). It may have
some risk if redefine the 'bus-type' property for sold out Chromium PC.

Thanks,
Xin

> 
> > > > > > +		pdata->is_dpi = 0;
> > > > > > +
> > > > > > +	pdata->mipi_lanes = mipi_lanes;
> > > > > > +	if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> > > > > > +		pdata->mipi_lanes = MAX_LANES_SUPPORT;
> > > > > > +
> > > > > > +	if (pdata->is_dpi)
> > > > > > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> > > > > > +	else
> > > > > > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
> > > > > >  
> > > > > >  	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
> > > > > >  	if (ret < 0) {
> > > > > > @@ -1301,9 +1414,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");
> > > > > >  
> > > > > > -	return connector_status_connected;
> > > > > > +	if (ctx->pdata.panel_bridge)
> > > > > > +		return connector_status_connected;
> > > > > > +
> > > > > > +	return ctx->hpd_status ? connector_status_connected :
> > > > > > +				     connector_status_disconnected;
> > > > > >  }
> > > > > >  
> > > > > >  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> > > > > > @@ -1332,7 +1449,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	|
> > > > > > @@ -1460,6 +1577,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;
> > > > > > @@ -1835,14 +1956,22 @@ 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);
> > > > > >  
> > > > > > -	ret = anx7625_attach_dsi(platform);
> > > > > > -	if (ret) {
> > > > > > -		DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > > > -		goto unregister_bridge;
> > > > > > +	if (!platform->pdata.is_dpi) {
> > > > > > +		ret = anx7625_attach_dsi(platform);
> > > > > > +		if (ret) {
> > > > > > +			DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > > > +			goto unregister_bridge;
> > > > > > +		}
> > > > > >  	}
> > > > > >  
> > > > > >  	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> > > > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > index 6dcf64c703f9..3ef1d8f4e575 100644
> > > > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > @@ -141,12 +141,20 @@
> > > > > >  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
> > > > > >  
> > > > > >  /******** END of I2C Address 0x72 *********/
> > > > > > +
> > > > > > +/***************************************************************/
> > > > > > +/* Register definition of device address 0x7a */
> > > > > > +#define DP_TX_SWING_REG_CNT		0x14
> > > > > > +#define DP_TX_LANE0_SWING_REG0		0x00
> > > > > > +#define DP_TX_LANE1_SWING_REG0		0x14
> > > > > > +/******** END of I2C Address 0x7a *********/
> > > > > > +
> > > > > >  /***************************************************************/
> > > > > >  /* Register definition of device address 0x7e */
> > > > > >  
> > > > > >  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
> > > > > >  
> > > > > > -#define FLASH_LOAD_STA 0x05
> > > > > > +#define FLASH_LOAD_STA          0x05
> > > > > >  #define FLASH_LOAD_STA_CHK	BIT(7)
> > > > > >  
> > > > > >  #define  XTAL_FRQ_SEL    0x3F
> > > > > > @@ -349,12 +357,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 regulator_bulk_data supplies[3];
> > > > > >  	struct drm_bridge *panel_bridge;
> > > > > >  	int intp_irq;
> > > > > > +	int is_dpi;
> > > > > > +	int mipi_lanes;
> > > > > > +	int dp_lane0_swing_reg_cnt;
> > > > > > +	int lane0_reg_data[DP_TX_SWING_REG_CNT];
> > > > > > +	int dp_lane1_swing_reg_cnt;
> > > > > > +	int lane1_reg_data[DP_TX_SWING_REG_CNT];
> > > > > >  	u32 low_power_mode;
> > > > > >  	struct device_node *mipi_host_node;
> > > > > >  };
> 
> -- 
> Regards,
> 
> Laurent Pinchart

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-07  5:09             ` Xin Ji
@ 2022-03-07  5:17               ` Laurent Pinchart
  2022-03-07  5:17               ` Hsin-Yi Wang
  1 sibling, 0 replies; 20+ messages in thread
From: Laurent Pinchart @ 2022-03-07  5:17 UTC (permalink / raw)
  To: Xin Ji
  Cc: a.hajda, narmstrong, dan.carpenter, robert.foss, jonas,
	jernej.skrabec, airlied, daniel, sam, pihsun, tzungbi, maxime,
	drinkcat, hsinyi, dri-devel, linux-kernel, bliang, qwen, robh+dt,
	devicetree

Hello Xin,

On Mon, Mar 07, 2022 at 01:09:45PM +0800, Xin Ji wrote:
> On Mon, Mar 07, 2022 at 06:47:44AM +0200, Laurent Pinchart wrote:
> > On Mon, Mar 07, 2022 at 12:32:49PM +0800, Xin Ji wrote:
> > > On Mon, Mar 07, 2022 at 05:30:09AM +0200, Laurent Pinchart wrote:
> > > > On Mon, Mar 07, 2022 at 11:22:48AM +0800, Xin Ji wrote:
> > > > > On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> > > > > > Hello Xin,
> > > > > > 
> > > > > > (Question for Rob below, and I'm afraid this is urgent as we need to
> > > > > > merge a fix in v5.17).
> > > > > > 
> > > > > > On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > > > > > > The basic anx7625 driver only support MIPI DSI rx signal input.
> > > > > > > This patch add MIPI DPI rx input configuration support, after apply
> > > > > > > this patch, the driver can support DSI rx or DPI rx by adding
> > > > > > > 'bus-type' in DT.
> > > > > > > 
> > > > > > > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > > > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > > > ---
> > > > > > >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> > > > > > >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> > > > > > >  2 files changed, 205 insertions(+), 60 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > > index f48e91134c20..f7c3386c8929 100644
> > > > > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > > @@ -32,6 +32,7 @@
> > > > > > >  #include <drm/drm_print.h>
> > > > > > >  #include <drm/drm_probe_helper.h>
> > > > > > >  
> > > > > > > +#include <media/v4l2-fwnode.h>
> > > > > > >  #include <video/display_timing.h>
> > > > > > >  
> > > > > > >  #include "anx7625.h"
> > > > > > > @@ -152,18 +153,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)
> > > > > > > @@ -221,38 +222,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)
> > > > > > >  {
> > > > > > > @@ -431,7 +400,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 +
> > > > > > > @@ -615,6 +584,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
> > > > > > >  	return ret;
> > > > > > >  }
> > > > > > >  
> > > > > > > +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> > > > > > > +{
> > > > > > > +	struct device *dev = &ctx->client->dev;
> > > > > > > +	u16 freq = ctx->dt.pixelclock.min / 1000;
> > > > > > > +	int ret;
> > > > > > > +
> > > > > > > +	/* configure pixel clock */
> > > > > > > +	ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > > > > +				PIXEL_CLOCK_L, freq & 0xFF);
> > > > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > > > > +				 PIXEL_CLOCK_H, (freq >> 8));
> > > > > > > +
> > > > > > > +	/* set DPI mode */
> > > > > > > +	/* set to DPI PLL module sel */
> > > > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > > +				 MIPI_DIGITAL_PLL_9, 0x20);
> > > > > > > +	/* power down MIPI */
> > > > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > > +				 MIPI_LANE_CTRL_10, 0x08);
> > > > > > > +	/* enable DPI mode */
> > > > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > > +				 MIPI_DIGITAL_PLL_18, 0x1C);
> > > > > > > +	/* set first edge */
> > > > > > > +	ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> > > > > > > +				 VIDEO_CONTROL_0, 0x06);
> > > > > > > +	if (ret < 0)
> > > > > > > +		DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> > > > > > > +
> > > > > > > +	return ret;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static int anx7625_dpi_config(struct anx7625_data *ctx)
> > > > > > > +{
> > > > > > > +	struct device *dev = &ctx->client->dev;
> > > > > > > +	int ret;
> > > > > > > +
> > > > > > > +	DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> > > > > > > +
> > > > > > > +	/* DSC disable */
> > > > > > > +	ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > > > > +				R_DSC_CTRL_0, ~DSC_EN);
> > > > > > > +	if (ret < 0) {
> > > > > > > +		DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> > > > > > > +		return ret;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	ret = anx7625_config_bit_matrix(ctx);
> > > > > > > +	if (ret < 0) {
> > > > > > > +		DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> > > > > > > +		return ret;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	ret = anx7625_api_dpi_config(ctx);
> > > > > > > +	if (ret < 0) {
> > > > > > > +		DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> > > > > > > +		return ret;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	/* set MIPI RX EN */
> > > > > > > +	ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > > > > > > +			       AP_AV_STATUS, AP_MIPI_RX_EN);
> > > > > > > +	/* clear mute flag */
> > > > > > > +	ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > > > > +				 AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> > > > > > > +	if (ret < 0)
> > > > > > > +		DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> > > > > > > +
> > > > > > > +	return ret;
> > > > > > > +}
> > > > > > > +
> > > > > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > > >  {
> > > > > > >  	int ret;
> > > > > > > @@ -625,9 +664,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > > >  		return;
> > > > > > >  	}
> > > > > > >  
> > > > > > > -	anx7625_config_audio_input(ctx);
> > > > > > > -
> > > > > > > -	ret = anx7625_dsi_config(ctx);
> > > > > > > +	if (ctx->pdata.is_dpi)
> > > > > > > +		ret = anx7625_dpi_config(ctx);
> > > > > > > +	else
> > > > > > > +		ret = anx7625_dsi_config(ctx);
> > > > > > >  
> > > > > > >  	if (ret < 0)
> > > > > > >  		DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> > > > > > > @@ -1075,6 +1115,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
> > > > > > >  		return;
> > > > > > >  	}
> > > > > > >  
> > > > > > > +	ctx->hpd_status = 1;
> > > > > > >  	ctx->hpd_high_cnt++;
> > > > > > >  
> > > > > > >  	/* Not support HDCP */
> > > > > > > @@ -1084,8 +1125,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)
> > > > > > > @@ -1104,6 +1147,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;
> > > > > > > +
> > > > > > >  	ret = readx_poll_timeout(anx7625_read_hpd_status_p0,
> > > > > > >  				 ctx, val,
> > > > > > >  				 ((val & HPD_STATUS) || (val < 0)),
> > > > > > > @@ -1131,6 +1178,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;
> > > > > > > @@ -1146,9 +1208,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)
> > > > > > > @@ -1225,20 +1286,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
> > > > > > >  	return IRQ_HANDLED;
> > > > > > >  }
> > > > > > >  
> > > > > > > +static int anx7625_get_swing_setting(struct device *dev,
> > > > > > > +				     struct anx7625_platform_data *pdata)
> > > > > > > +{
> > > > > > > +	int num_regs;
> > > > > > > +
> > > > > > > +	if (of_get_property(dev->of_node,
> > > > > > > +			    "analogix,lane0-swing", &num_regs)) {
> > > > > > > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > > > > > > +			num_regs = DP_TX_SWING_REG_CNT;
> > > > > > > +
> > > > > > > +		pdata->dp_lane0_swing_reg_cnt = num_regs;
> > > > > > > +		of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> > > > > > > +					   pdata->lane0_reg_data, num_regs);
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	if (of_get_property(dev->of_node,
> > > > > > > +			    "analogix,lane1-swing", &num_regs)) {
> > > > > > > +		if (num_regs > DP_TX_SWING_REG_CNT)
> > > > > > > +			num_regs = DP_TX_SWING_REG_CNT;
> > > > > > > +
> > > > > > > +		pdata->dp_lane1_swing_reg_cnt = num_regs;
> > > > > > > +		of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> > > > > > > +					   pdata->lane1_reg_data, num_regs);
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > >  static int anx7625_parse_dt(struct device *dev,
> > > > > > >  			    struct anx7625_platform_data *pdata)
> > > > > > >  {
> > > > > > > -	struct device_node *np = dev->of_node;
> > > > > > > +	struct device_node *np = dev->of_node, *ep0;
> > > > > > >  	struct drm_panel *panel;
> > > > > > >  	int ret;
> > > > > > > +	int bus_type, mipi_lanes;
> > > > > > > +
> > > > > > > +	anx7625_get_swing_setting(dev, pdata);
> > > > > > >  
> > > > > > > +	pdata->is_dpi = 1; /* default dpi mode */
> > > > > > >  	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> > > > > > >  	if (!pdata->mipi_host_node) {
> > > > > > >  		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> > > > > > >  		return -ENODEV;
> > > > > > >  	}
> > > > > > >  
> > > > > > > -	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > > > > > +	bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > > > > > +	mipi_lanes = MAX_LANES_SUPPORT;
> > > > > > > +	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > > > > > +	if (ep0) {
> > > > > > > +		if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > > > > > +			bus_type = 0;
> > > > > > > +
> > > > > > > +		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> > > > > > 
> > > > > > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > > > > > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > > > > > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > > > > > it's not an exact match.
> > > > > > 
> > > > > > This patch has landed in v5.17-rc1, along with the corresponding
> > > > > > bindings. As DT bindings are an ABI, we should really fix this before
> > > > > > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > > > > > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > > > > > me (unless Rob disagrees).
> > > > > > 
> > > > > > It would seem best to revert this series and the corresponding bindings,
> > > > > > and retry in v5.18.
> > > > >
> > > > > Hi, what about make a patch to change this line to:
> > > > > if (bus_type != V4L2_FWNODE_BUS_TYPE_PARALLEL), and then change the DTS
> > > > > file?
> > > > 
> > > > We could possibly use V4L2_FWNODE_BUS_TYPE_PARALLEL (5) for MIPI DPI
> > > > (although it's not a very accurate match, so a different type may be
> > > > better, this should be discussed), but V4L2_FWNODE_BUS_TYPE_CCP2 (1) is
> > > > definitely not appropriate for DSI. For that we need a new type, and I
> > > > don't think it should be rushed in v5.17.
> > >
> > > Hi Laurent Pinchart, what should I do now? Do you mean upload a bug fix
> > > patch after kernel defined a new type(DPI and DSI) in new kernel?
> > 
> > I think fixing this properly requires defining at least a new bus type
> > for DSI. As this can't be done in v5.17, the best option seems to revert
> > this series now as a fix for v5?.17, and submit a new version for v5.18,
> > with a patch to add a DSI bus type.
> > 
> > Any opinion from Rob (Herring and Foss) ?
>
> Hi all, the problem is Chromium OS product depends on this
> patch and other patches(which is depends on this patch). It may have
> some risk if redefine the 'bus-type' property for sold out Chromium PC.

That's a common issue with DT bindings deployed in products before they
are mainlined (hence the reason why DT bindings should really go
mainline first). If the device tree for those devices can't be updated,
then Chrome OS can carry a downstream patch in their kernel.

> > > > > > > +		pdata->is_dpi = 0;
> > > > > > > +
> > > > > > > +	pdata->mipi_lanes = mipi_lanes;
> > > > > > > +	if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> > > > > > > +		pdata->mipi_lanes = MAX_LANES_SUPPORT;
> > > > > > > +
> > > > > > > +	if (pdata->is_dpi)
> > > > > > > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> > > > > > > +	else
> > > > > > > +		DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
> > > > > > >  
> > > > > > >  	ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
> > > > > > >  	if (ret < 0) {
> > > > > > > @@ -1301,9 +1414,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");
> > > > > > >  
> > > > > > > -	return connector_status_connected;
> > > > > > > +	if (ctx->pdata.panel_bridge)
> > > > > > > +		return connector_status_connected;
> > > > > > > +
> > > > > > > +	return ctx->hpd_status ? connector_status_connected :
> > > > > > > +				     connector_status_disconnected;
> > > > > > >  }
> > > > > > >  
> > > > > > >  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> > > > > > > @@ -1332,7 +1449,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	|
> > > > > > > @@ -1460,6 +1577,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;
> > > > > > > @@ -1835,14 +1956,22 @@ 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);
> > > > > > >  
> > > > > > > -	ret = anx7625_attach_dsi(platform);
> > > > > > > -	if (ret) {
> > > > > > > -		DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > > > > -		goto unregister_bridge;
> > > > > > > +	if (!platform->pdata.is_dpi) {
> > > > > > > +		ret = anx7625_attach_dsi(platform);
> > > > > > > +		if (ret) {
> > > > > > > +			DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > > > > +			goto unregister_bridge;
> > > > > > > +		}
> > > > > > >  	}
> > > > > > >  
> > > > > > >  	DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> > > > > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > > index 6dcf64c703f9..3ef1d8f4e575 100644
> > > > > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > > @@ -141,12 +141,20 @@
> > > > > > >  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
> > > > > > >  
> > > > > > >  /******** END of I2C Address 0x72 *********/
> > > > > > > +
> > > > > > > +/***************************************************************/
> > > > > > > +/* Register definition of device address 0x7a */
> > > > > > > +#define DP_TX_SWING_REG_CNT		0x14
> > > > > > > +#define DP_TX_LANE0_SWING_REG0		0x00
> > > > > > > +#define DP_TX_LANE1_SWING_REG0		0x14
> > > > > > > +/******** END of I2C Address 0x7a *********/
> > > > > > > +
> > > > > > >  /***************************************************************/
> > > > > > >  /* Register definition of device address 0x7e */
> > > > > > >  
> > > > > > >  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
> > > > > > >  
> > > > > > > -#define FLASH_LOAD_STA 0x05
> > > > > > > +#define FLASH_LOAD_STA          0x05
> > > > > > >  #define FLASH_LOAD_STA_CHK	BIT(7)
> > > > > > >  
> > > > > > >  #define  XTAL_FRQ_SEL    0x3F
> > > > > > > @@ -349,12 +357,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 regulator_bulk_data supplies[3];
> > > > > > >  	struct drm_bridge *panel_bridge;
> > > > > > >  	int intp_irq;
> > > > > > > +	int is_dpi;
> > > > > > > +	int mipi_lanes;
> > > > > > > +	int dp_lane0_swing_reg_cnt;
> > > > > > > +	int lane0_reg_data[DP_TX_SWING_REG_CNT];
> > > > > > > +	int dp_lane1_swing_reg_cnt;
> > > > > > > +	int lane1_reg_data[DP_TX_SWING_REG_CNT];
> > > > > > >  	u32 low_power_mode;
> > > > > > >  	struct device_node *mipi_host_node;
> > > > > > >  };

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-07  5:09             ` Xin Ji
  2022-03-07  5:17               ` Laurent Pinchart
@ 2022-03-07  5:17               ` Hsin-Yi Wang
  2022-03-07  5:35                 ` Xin Ji
  1 sibling, 1 reply; 20+ messages in thread
From: Hsin-Yi Wang @ 2022-03-07  5:17 UTC (permalink / raw)
  To: Xin Ji
  Cc: Laurent Pinchart, a.hajda, narmstrong, dan.carpenter,
	robert.foss, jonas, jernej.skrabec, airlied, daniel, sam, pihsun,
	tzungbi, maxime, drinkcat, dri-devel, linux-kernel, bliang, qwen,
	robh+dt, devicetree

On Mon, Mar 7, 2022 at 1:09 PM Xin Ji <xji@analogixsemi.com> wrote:
>
> On Mon, Mar 07, 2022 at 06:47:44AM +0200, Laurent Pinchart wrote:
> > Hello Xin,
> >
> > On Mon, Mar 07, 2022 at 12:32:49PM +0800, Xin Ji wrote:
> > > On Mon, Mar 07, 2022 at 05:30:09AM +0200, Laurent Pinchart wrote:
> > > > On Mon, Mar 07, 2022 at 11:22:48AM +0800, Xin Ji wrote:
> > > > > On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> > > > > > Hello Xin,
> > > > > >
> > > > > > (Question for Rob below, and I'm afraid this is urgent as we need to
> > > > > > merge a fix in v5.17).
> > > > > >
> > > > > > On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > > > > > > The basic anx7625 driver only support MIPI DSI rx signal input.
> > > > > > > This patch add MIPI DPI rx input configuration support, after apply
> > > > > > > this patch, the driver can support DSI rx or DPI rx by adding
> > > > > > > 'bus-type' in DT.
> > > > > > >
> > > > > > > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > > > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > > > ---
> > > > > > >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> > > > > > >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> > > > > > >  2 files changed, 205 insertions(+), 60 deletions(-)
> > > > > > >
> > > > > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > > index f48e91134c20..f7c3386c8929 100644
> > > > > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > > @@ -32,6 +32,7 @@
> > > > > > >  #include <drm/drm_print.h>
> > > > > > >  #include <drm/drm_probe_helper.h>
> > > > > > >
> > > > > > > +#include <media/v4l2-fwnode.h>
> > > > > > >  #include <video/display_timing.h>
> > > > > > >
> > > > > > >  #include "anx7625.h"
> > > > > > > @@ -152,18 +153,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)
> > > > > > > @@ -221,38 +222,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)
> > > > > > >  {
> > > > > > > @@ -431,7 +400,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 +
> > > > > > > @@ -615,6 +584,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
> > > > > > >     return ret;
> > > > > > >  }
> > > > > > >
> > > > > > > +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> > > > > > > +{
> > > > > > > +   struct device *dev = &ctx->client->dev;
> > > > > > > +   u16 freq = ctx->dt.pixelclock.min / 1000;
> > > > > > > +   int ret;
> > > > > > > +
> > > > > > > +   /* configure pixel clock */
> > > > > > > +   ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > > > > +                           PIXEL_CLOCK_L, freq & 0xFF);
> > > > > > > +   ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > > > > +                            PIXEL_CLOCK_H, (freq >> 8));
> > > > > > > +
> > > > > > > +   /* set DPI mode */
> > > > > > > +   /* set to DPI PLL module sel */
> > > > > > > +   ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > > +                            MIPI_DIGITAL_PLL_9, 0x20);
> > > > > > > +   /* power down MIPI */
> > > > > > > +   ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > > +                            MIPI_LANE_CTRL_10, 0x08);
> > > > > > > +   /* enable DPI mode */
> > > > > > > +   ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > > +                            MIPI_DIGITAL_PLL_18, 0x1C);
> > > > > > > +   /* set first edge */
> > > > > > > +   ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> > > > > > > +                            VIDEO_CONTROL_0, 0x06);
> > > > > > > +   if (ret < 0)
> > > > > > > +           DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> > > > > > > +
> > > > > > > +   return ret;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static int anx7625_dpi_config(struct anx7625_data *ctx)
> > > > > > > +{
> > > > > > > +   struct device *dev = &ctx->client->dev;
> > > > > > > +   int ret;
> > > > > > > +
> > > > > > > +   DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> > > > > > > +
> > > > > > > +   /* DSC disable */
> > > > > > > +   ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > > > > +                           R_DSC_CTRL_0, ~DSC_EN);
> > > > > > > +   if (ret < 0) {
> > > > > > > +           DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> > > > > > > +           return ret;
> > > > > > > +   }
> > > > > > > +
> > > > > > > +   ret = anx7625_config_bit_matrix(ctx);
> > > > > > > +   if (ret < 0) {
> > > > > > > +           DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> > > > > > > +           return ret;
> > > > > > > +   }
> > > > > > > +
> > > > > > > +   ret = anx7625_api_dpi_config(ctx);
> > > > > > > +   if (ret < 0) {
> > > > > > > +           DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> > > > > > > +           return ret;
> > > > > > > +   }
> > > > > > > +
> > > > > > > +   /* set MIPI RX EN */
> > > > > > > +   ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > > > > > > +                          AP_AV_STATUS, AP_MIPI_RX_EN);
> > > > > > > +   /* clear mute flag */
> > > > > > > +   ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > > > > +                            AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> > > > > > > +   if (ret < 0)
> > > > > > > +           DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> > > > > > > +
> > > > > > > +   return ret;
> > > > > > > +}
> > > > > > > +
> > > > > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > > >  {
> > > > > > >     int ret;
> > > > > > > @@ -625,9 +664,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > > >             return;
> > > > > > >     }
> > > > > > >
> > > > > > > -   anx7625_config_audio_input(ctx);
> > > > > > > -
> > > > > > > -   ret = anx7625_dsi_config(ctx);
> > > > > > > +   if (ctx->pdata.is_dpi)
> > > > > > > +           ret = anx7625_dpi_config(ctx);
> > > > > > > +   else
> > > > > > > +           ret = anx7625_dsi_config(ctx);
> > > > > > >
> > > > > > >     if (ret < 0)
> > > > > > >             DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> > > > > > > @@ -1075,6 +1115,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
> > > > > > >             return;
> > > > > > >     }
> > > > > > >
> > > > > > > +   ctx->hpd_status = 1;
> > > > > > >     ctx->hpd_high_cnt++;
> > > > > > >
> > > > > > >     /* Not support HDCP */
> > > > > > > @@ -1084,8 +1125,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)
> > > > > > > @@ -1104,6 +1147,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;
> > > > > > > +
> > > > > > >     ret = readx_poll_timeout(anx7625_read_hpd_status_p0,
> > > > > > >                              ctx, val,
> > > > > > >                              ((val & HPD_STATUS) || (val < 0)),
> > > > > > > @@ -1131,6 +1178,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;
> > > > > > > @@ -1146,9 +1208,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)
> > > > > > > @@ -1225,20 +1286,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
> > > > > > >     return IRQ_HANDLED;
> > > > > > >  }
> > > > > > >
> > > > > > > +static int anx7625_get_swing_setting(struct device *dev,
> > > > > > > +                                struct anx7625_platform_data *pdata)
> > > > > > > +{
> > > > > > > +   int num_regs;
> > > > > > > +
> > > > > > > +   if (of_get_property(dev->of_node,
> > > > > > > +                       "analogix,lane0-swing", &num_regs)) {
> > > > > > > +           if (num_regs > DP_TX_SWING_REG_CNT)
> > > > > > > +                   num_regs = DP_TX_SWING_REG_CNT;
> > > > > > > +
> > > > > > > +           pdata->dp_lane0_swing_reg_cnt = num_regs;
> > > > > > > +           of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> > > > > > > +                                      pdata->lane0_reg_data, num_regs);
> > > > > > > +   }
> > > > > > > +
> > > > > > > +   if (of_get_property(dev->of_node,
> > > > > > > +                       "analogix,lane1-swing", &num_regs)) {
> > > > > > > +           if (num_regs > DP_TX_SWING_REG_CNT)
> > > > > > > +                   num_regs = DP_TX_SWING_REG_CNT;
> > > > > > > +
> > > > > > > +           pdata->dp_lane1_swing_reg_cnt = num_regs;
> > > > > > > +           of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> > > > > > > +                                      pdata->lane1_reg_data, num_regs);
> > > > > > > +   }
> > > > > > > +
> > > > > > > +   return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > >  static int anx7625_parse_dt(struct device *dev,
> > > > > > >                         struct anx7625_platform_data *pdata)
> > > > > > >  {
> > > > > > > -   struct device_node *np = dev->of_node;
> > > > > > > +   struct device_node *np = dev->of_node, *ep0;
> > > > > > >     struct drm_panel *panel;
> > > > > > >     int ret;
> > > > > > > +   int bus_type, mipi_lanes;
> > > > > > > +
> > > > > > > +   anx7625_get_swing_setting(dev, pdata);
> > > > > > >
> > > > > > > +   pdata->is_dpi = 1; /* default dpi mode */
> > > > > > >     pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> > > > > > >     if (!pdata->mipi_host_node) {
> > > > > > >             DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> > > > > > >             return -ENODEV;
> > > > > > >     }
> > > > > > >
> > > > > > > -   DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > > > > > +   bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > > > > > +   mipi_lanes = MAX_LANES_SUPPORT;
> > > > > > > +   ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > > > > > +   if (ep0) {
> > > > > > > +           if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > > > > > +                   bus_type = 0;
> > > > > > > +
> > > > > > > +           mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > > > > > +   }
> > > > > > > +
> > > > > > > +   if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> > > > > >
> > > > > > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > > > > > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > > > > > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > > > > > it's not an exact match.
> > > > > >
> > > > > > This patch has landed in v5.17-rc1, along with the corresponding
> > > > > > bindings. As DT bindings are an ABI, we should really fix this before
> > > > > > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > > > > > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > > > > > me (unless Rob disagrees).
> > > > > >
> > > > > > It would seem best to revert this series and the corresponding bindings,
> > > > > > and retry in v5.18.
> > > > >
> > > > > Hi, what about make a patch to change this line to:
> > > > > if (bus_type != V4L2_FWNODE_BUS_TYPE_PARALLEL), and then change the DTS
> > > > > file?
> > > >
> > > > We could possibly use V4L2_FWNODE_BUS_TYPE_PARALLEL (5) for MIPI DPI
> > > > (although it's not a very accurate match, so a different type may be
> > > > better, this should be discussed), but V4L2_FWNODE_BUS_TYPE_CCP2 (1) is
> > > > definitely not appropriate for DSI. For that we need a new type, and I
> > > > don't think it should be rushed in v5.17.
> > >
> > > Hi Laurent Pinchart, what should I do now? Do you mean upload a bug fix
> > > patch after kernel defined a new type(DPI and DSI) in new kernel?
> >
> > I think fixing this properly requires defining at least a new bus type
> > for DSI. As this can't be done in v5.17, the best option seems to revert
> > this series now as a fix for v5?.17, and submit a new version for v5.18,
> > with a patch to add a DSI bus type.
> >
> > Any opinion from Rob (Herring and Foss) ?
> Hi all, the problem is Chromium OS product depends on this
> patch and other patches(which is depends on this patch). It may have
> some risk if redefine the 'bus-type' property for sold out Chromium PC.
>
hi Xin,

I think what Laurent meant was to revert the landed patch in v5.17
only. The patch wasn't landed in prior kernel versions (before v5.16),
so it won't break Chromium OS products. There are some patches in
drm-misc depending on this patch though.

> Thanks,
> Xin
>
> >
> > > > > > > +           pdata->is_dpi = 0;
> > > > > > > +
> > > > > > > +   pdata->mipi_lanes = mipi_lanes;
> > > > > > > +   if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> > > > > > > +           pdata->mipi_lanes = MAX_LANES_SUPPORT;
> > > > > > > +
> > > > > > > +   if (pdata->is_dpi)
> > > > > > > +           DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> > > > > > > +   else
> > > > > > > +           DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
> > > > > > >
> > > > > > >     ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
> > > > > > >     if (ret < 0) {
> > > > > > > @@ -1301,9 +1414,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");
> > > > > > >
> > > > > > > -   return connector_status_connected;
> > > > > > > +   if (ctx->pdata.panel_bridge)
> > > > > > > +           return connector_status_connected;
> > > > > > > +
> > > > > > > +   return ctx->hpd_status ? connector_status_connected :
> > > > > > > +                                connector_status_disconnected;
> > > > > > >  }
> > > > > > >
> > > > > > >  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> > > > > > > @@ -1332,7 +1449,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  |
> > > > > > > @@ -1460,6 +1577,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;
> > > > > > > @@ -1835,14 +1956,22 @@ 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);
> > > > > > >
> > > > > > > -   ret = anx7625_attach_dsi(platform);
> > > > > > > -   if (ret) {
> > > > > > > -           DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > > > > -           goto unregister_bridge;
> > > > > > > +   if (!platform->pdata.is_dpi) {
> > > > > > > +           ret = anx7625_attach_dsi(platform);
> > > > > > > +           if (ret) {
> > > > > > > +                   DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > > > > +                   goto unregister_bridge;
> > > > > > > +           }
> > > > > > >     }
> > > > > > >
> > > > > > >     DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> > > > > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > > index 6dcf64c703f9..3ef1d8f4e575 100644
> > > > > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > > @@ -141,12 +141,20 @@
> > > > > > >  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
> > > > > > >
> > > > > > >  /******** END of I2C Address 0x72 *********/
> > > > > > > +
> > > > > > > +/***************************************************************/
> > > > > > > +/* Register definition of device address 0x7a */
> > > > > > > +#define DP_TX_SWING_REG_CNT                0x14
> > > > > > > +#define DP_TX_LANE0_SWING_REG0             0x00
> > > > > > > +#define DP_TX_LANE1_SWING_REG0             0x14
> > > > > > > +/******** END of I2C Address 0x7a *********/
> > > > > > > +
> > > > > > >  /***************************************************************/
> > > > > > >  /* Register definition of device address 0x7e */
> > > > > > >
> > > > > > >  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
> > > > > > >
> > > > > > > -#define FLASH_LOAD_STA 0x05
> > > > > > > +#define FLASH_LOAD_STA          0x05
> > > > > > >  #define FLASH_LOAD_STA_CHK BIT(7)
> > > > > > >
> > > > > > >  #define  XTAL_FRQ_SEL    0x3F
> > > > > > > @@ -349,12 +357,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 regulator_bulk_data supplies[3];
> > > > > > >     struct drm_bridge *panel_bridge;
> > > > > > >     int intp_irq;
> > > > > > > +   int is_dpi;
> > > > > > > +   int mipi_lanes;
> > > > > > > +   int dp_lane0_swing_reg_cnt;
> > > > > > > +   int lane0_reg_data[DP_TX_SWING_REG_CNT];
> > > > > > > +   int dp_lane1_swing_reg_cnt;
> > > > > > > +   int lane1_reg_data[DP_TX_SWING_REG_CNT];
> > > > > > >     u32 low_power_mode;
> > > > > > >     struct device_node *mipi_host_node;
> > > > > > >  };
> >
> > --
> > Regards,
> >
> > Laurent Pinchart

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-07  5:17               ` Hsin-Yi Wang
@ 2022-03-07  5:35                 ` Xin Ji
  0 siblings, 0 replies; 20+ messages in thread
From: Xin Ji @ 2022-03-07  5:35 UTC (permalink / raw)
  To: Hsin-Yi Wang
  Cc: Laurent Pinchart, a.hajda, narmstrong, dan.carpenter,
	robert.foss, jonas, jernej.skrabec, airlied, daniel, sam, pihsun,
	tzungbi, maxime, drinkcat, dri-devel, linux-kernel, bliang, qwen,
	robh+dt, devicetree

On Mon, Mar 07, 2022 at 01:17:44PM +0800, Hsin-Yi Wang wrote:
> On Mon, Mar 7, 2022 at 1:09 PM Xin Ji <xji@analogixsemi.com> wrote:
> >
> > On Mon, Mar 07, 2022 at 06:47:44AM +0200, Laurent Pinchart wrote:
> > > Hello Xin,
> > >
> > > On Mon, Mar 07, 2022 at 12:32:49PM +0800, Xin Ji wrote:
> > > > On Mon, Mar 07, 2022 at 05:30:09AM +0200, Laurent Pinchart wrote:
> > > > > On Mon, Mar 07, 2022 at 11:22:48AM +0800, Xin Ji wrote:
> > > > > > On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> > > > > > > Hello Xin,
> > > > > > >
> > > > > > > (Question for Rob below, and I'm afraid this is urgent as we need to
> > > > > > > merge a fix in v5.17).
> > > > > > >
> > > > > > > On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > > > > > > > The basic anx7625 driver only support MIPI DSI rx signal input.
> > > > > > > > This patch add MIPI DPI rx input configuration support, after apply
> > > > > > > > this patch, the driver can support DSI rx or DPI rx by adding
> > > > > > > > 'bus-type' in DT.
> > > > > > > >
> > > > > > > > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > > > > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > > > > ---
> > > > > > > >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> > > > > > > >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> > > > > > > >  2 files changed, 205 insertions(+), 60 deletions(-)
> > > > > > > >
> > > > > > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > > > index f48e91134c20..f7c3386c8929 100644
> > > > > > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > > > > @@ -32,6 +32,7 @@
> > > > > > > >  #include <drm/drm_print.h>
> > > > > > > >  #include <drm/drm_probe_helper.h>
> > > > > > > >
> > > > > > > > +#include <media/v4l2-fwnode.h>
> > > > > > > >  #include <video/display_timing.h>
> > > > > > > >
> > > > > > > >  #include "anx7625.h"
> > > > > > > > @@ -152,18 +153,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)
> > > > > > > > @@ -221,38 +222,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)
> > > > > > > >  {
> > > > > > > > @@ -431,7 +400,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 +
> > > > > > > > @@ -615,6 +584,76 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
> > > > > > > >     return ret;
> > > > > > > >  }
> > > > > > > >
> > > > > > > > +static int anx7625_api_dpi_config(struct anx7625_data *ctx)
> > > > > > > > +{
> > > > > > > > +   struct device *dev = &ctx->client->dev;
> > > > > > > > +   u16 freq = ctx->dt.pixelclock.min / 1000;
> > > > > > > > +   int ret;
> > > > > > > > +
> > > > > > > > +   /* configure pixel clock */
> > > > > > > > +   ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > > > > > +                           PIXEL_CLOCK_L, freq & 0xFF);
> > > > > > > > +   ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > > > > > > > +                            PIXEL_CLOCK_H, (freq >> 8));
> > > > > > > > +
> > > > > > > > +   /* set DPI mode */
> > > > > > > > +   /* set to DPI PLL module sel */
> > > > > > > > +   ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > > > +                            MIPI_DIGITAL_PLL_9, 0x20);
> > > > > > > > +   /* power down MIPI */
> > > > > > > > +   ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > > > +                            MIPI_LANE_CTRL_10, 0x08);
> > > > > > > > +   /* enable DPI mode */
> > > > > > > > +   ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p1_client,
> > > > > > > > +                            MIPI_DIGITAL_PLL_18, 0x1C);
> > > > > > > > +   /* set first edge */
> > > > > > > > +   ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> > > > > > > > +                            VIDEO_CONTROL_0, 0x06);
> > > > > > > > +   if (ret < 0)
> > > > > > > > +           DRM_DEV_ERROR(dev, "IO error : dpi phy set failed.\n");
> > > > > > > > +
> > > > > > > > +   return ret;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static int anx7625_dpi_config(struct anx7625_data *ctx)
> > > > > > > > +{
> > > > > > > > +   struct device *dev = &ctx->client->dev;
> > > > > > > > +   int ret;
> > > > > > > > +
> > > > > > > > +   DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
> > > > > > > > +
> > > > > > > > +   /* DSC disable */
> > > > > > > > +   ret = anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > > > > > +                           R_DSC_CTRL_0, ~DSC_EN);
> > > > > > > > +   if (ret < 0) {
> > > > > > > > +           DRM_DEV_ERROR(dev, "IO error : disable dsc failed.\n");
> > > > > > > > +           return ret;
> > > > > > > > +   }
> > > > > > > > +
> > > > > > > > +   ret = anx7625_config_bit_matrix(ctx);
> > > > > > > > +   if (ret < 0) {
> > > > > > > > +           DRM_DEV_ERROR(dev, "config bit matrix failed.\n");
> > > > > > > > +           return ret;
> > > > > > > > +   }
> > > > > > > > +
> > > > > > > > +   ret = anx7625_api_dpi_config(ctx);
> > > > > > > > +   if (ret < 0) {
> > > > > > > > +           DRM_DEV_ERROR(dev, "mipi phy(dpi) setup failed.\n");
> > > > > > > > +           return ret;
> > > > > > > > +   }
> > > > > > > > +
> > > > > > > > +   /* set MIPI RX EN */
> > > > > > > > +   ret = anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > > > > > > > +                          AP_AV_STATUS, AP_MIPI_RX_EN);
> > > > > > > > +   /* clear mute flag */
> > > > > > > > +   ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > > > > > > > +                            AP_AV_STATUS, (u8)~AP_MIPI_MUTE);
> > > > > > > > +   if (ret < 0)
> > > > > > > > +           DRM_DEV_ERROR(dev, "IO error : enable mipi rx failed.\n");
> > > > > > > > +
> > > > > > > > +   return ret;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > >  static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > > > >  {
> > > > > > > >     int ret;
> > > > > > > > @@ -625,9 +664,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
> > > > > > > >             return;
> > > > > > > >     }
> > > > > > > >
> > > > > > > > -   anx7625_config_audio_input(ctx);
> > > > > > > > -
> > > > > > > > -   ret = anx7625_dsi_config(ctx);
> > > > > > > > +   if (ctx->pdata.is_dpi)
> > > > > > > > +           ret = anx7625_dpi_config(ctx);
> > > > > > > > +   else
> > > > > > > > +           ret = anx7625_dsi_config(ctx);
> > > > > > > >
> > > > > > > >     if (ret < 0)
> > > > > > > >             DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
> > > > > > > > @@ -1075,6 +1115,7 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx)
> > > > > > > >             return;
> > > > > > > >     }
> > > > > > > >
> > > > > > > > +   ctx->hpd_status = 1;
> > > > > > > >     ctx->hpd_high_cnt++;
> > > > > > > >
> > > > > > > >     /* Not support HDCP */
> > > > > > > > @@ -1084,8 +1125,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)
> > > > > > > > @@ -1104,6 +1147,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;
> > > > > > > > +
> > > > > > > >     ret = readx_poll_timeout(anx7625_read_hpd_status_p0,
> > > > > > > >                              ctx, val,
> > > > > > > >                              ((val & HPD_STATUS) || (val < 0)),
> > > > > > > > @@ -1131,6 +1178,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;
> > > > > > > > @@ -1146,9 +1208,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)
> > > > > > > > @@ -1225,20 +1286,72 @@ static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
> > > > > > > >     return IRQ_HANDLED;
> > > > > > > >  }
> > > > > > > >
> > > > > > > > +static int anx7625_get_swing_setting(struct device *dev,
> > > > > > > > +                                struct anx7625_platform_data *pdata)
> > > > > > > > +{
> > > > > > > > +   int num_regs;
> > > > > > > > +
> > > > > > > > +   if (of_get_property(dev->of_node,
> > > > > > > > +                       "analogix,lane0-swing", &num_regs)) {
> > > > > > > > +           if (num_regs > DP_TX_SWING_REG_CNT)
> > > > > > > > +                   num_regs = DP_TX_SWING_REG_CNT;
> > > > > > > > +
> > > > > > > > +           pdata->dp_lane0_swing_reg_cnt = num_regs;
> > > > > > > > +           of_property_read_u32_array(dev->of_node, "analogix,lane0-swing",
> > > > > > > > +                                      pdata->lane0_reg_data, num_regs);
> > > > > > > > +   }
> > > > > > > > +
> > > > > > > > +   if (of_get_property(dev->of_node,
> > > > > > > > +                       "analogix,lane1-swing", &num_regs)) {
> > > > > > > > +           if (num_regs > DP_TX_SWING_REG_CNT)
> > > > > > > > +                   num_regs = DP_TX_SWING_REG_CNT;
> > > > > > > > +
> > > > > > > > +           pdata->dp_lane1_swing_reg_cnt = num_regs;
> > > > > > > > +           of_property_read_u32_array(dev->of_node, "analogix,lane1-swing",
> > > > > > > > +                                      pdata->lane1_reg_data, num_regs);
> > > > > > > > +   }
> > > > > > > > +
> > > > > > > > +   return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > >  static int anx7625_parse_dt(struct device *dev,
> > > > > > > >                         struct anx7625_platform_data *pdata)
> > > > > > > >  {
> > > > > > > > -   struct device_node *np = dev->of_node;
> > > > > > > > +   struct device_node *np = dev->of_node, *ep0;
> > > > > > > >     struct drm_panel *panel;
> > > > > > > >     int ret;
> > > > > > > > +   int bus_type, mipi_lanes;
> > > > > > > > +
> > > > > > > > +   anx7625_get_swing_setting(dev, pdata);
> > > > > > > >
> > > > > > > > +   pdata->is_dpi = 1; /* default dpi mode */
> > > > > > > >     pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> > > > > > > >     if (!pdata->mipi_host_node) {
> > > > > > > >             DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> > > > > > > >             return -ENODEV;
> > > > > > > >     }
> > > > > > > >
> > > > > > > > -   DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > > > > > > +   bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > > > > > > +   mipi_lanes = MAX_LANES_SUPPORT;
> > > > > > > > +   ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > > > > > > +   if (ep0) {
> > > > > > > > +           if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > > > > > > +                   bus_type = 0;
> > > > > > > > +
> > > > > > > > +           mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > > > > > > +   }
> > > > > > > > +
> > > > > > > > +   if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> > > > > > >
> > > > > > > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > > > > > > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > > > > > > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > > > > > > it's not an exact match.
> > > > > > >
> > > > > > > This patch has landed in v5.17-rc1, along with the corresponding
> > > > > > > bindings. As DT bindings are an ABI, we should really fix this before
> > > > > > > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > > > > > > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > > > > > > me (unless Rob disagrees).
> > > > > > >
> > > > > > > It would seem best to revert this series and the corresponding bindings,
> > > > > > > and retry in v5.18.
> > > > > >
> > > > > > Hi, what about make a patch to change this line to:
> > > > > > if (bus_type != V4L2_FWNODE_BUS_TYPE_PARALLEL), and then change the DTS
> > > > > > file?
> > > > >
> > > > > We could possibly use V4L2_FWNODE_BUS_TYPE_PARALLEL (5) for MIPI DPI
> > > > > (although it's not a very accurate match, so a different type may be
> > > > > better, this should be discussed), but V4L2_FWNODE_BUS_TYPE_CCP2 (1) is
> > > > > definitely not appropriate for DSI. For that we need a new type, and I
> > > > > don't think it should be rushed in v5.17.
> > > >
> > > > Hi Laurent Pinchart, what should I do now? Do you mean upload a bug fix
> > > > patch after kernel defined a new type(DPI and DSI) in new kernel?
> > >
> > > I think fixing this properly requires defining at least a new bus type
> > > for DSI. As this can't be done in v5.17, the best option seems to revert
> > > this series now as a fix for v5?.17, and submit a new version for v5.18,
> > > with a patch to add a DSI bus type.
> > >
> > > Any opinion from Rob (Herring and Foss) ?
> > Hi all, the problem is Chromium OS product depends on this
> > patch and other patches(which is depends on this patch). It may have
> > some risk if redefine the 'bus-type' property for sold out Chromium PC.
> >
> hi Xin,
> 
> I think what Laurent meant was to revert the landed patch in v5.17
> only. The patch wasn't landed in prior kernel versions (before v5.16),
> so it won't break Chromium OS products. There are some patches in
> drm-misc depending on this patch though.
Hi Laurent Pinchart, Hsin-Yi, OK, thanks!
Xin
> 
> > Thanks,
> > Xin
> >
> > >
> > > > > > > > +           pdata->is_dpi = 0;
> > > > > > > > +
> > > > > > > > +   pdata->mipi_lanes = mipi_lanes;
> > > > > > > > +   if (pdata->mipi_lanes > MAX_LANES_SUPPORT || pdata->mipi_lanes <= 0)
> > > > > > > > +           pdata->mipi_lanes = MAX_LANES_SUPPORT;
> > > > > > > > +
> > > > > > > > +   if (pdata->is_dpi)
> > > > > > > > +           DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DPI host node.\n");
> > > > > > > > +   else
> > > > > > > > +           DRM_DEV_DEBUG_DRIVER(dev, "found MIPI DSI host node.\n");
> > > > > > > >
> > > > > > > >     ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
> > > > > > > >     if (ret < 0) {
> > > > > > > > @@ -1301,9 +1414,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");
> > > > > > > >
> > > > > > > > -   return connector_status_connected;
> > > > > > > > +   if (ctx->pdata.panel_bridge)
> > > > > > > > +           return connector_status_connected;
> > > > > > > > +
> > > > > > > > +   return ctx->hpd_status ? connector_status_connected :
> > > > > > > > +                                connector_status_disconnected;
> > > > > > > >  }
> > > > > > > >
> > > > > > > >  static int anx7625_attach_dsi(struct anx7625_data *ctx)
> > > > > > > > @@ -1332,7 +1449,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  |
> > > > > > > > @@ -1460,6 +1577,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;
> > > > > > > > @@ -1835,14 +1956,22 @@ 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);
> > > > > > > >
> > > > > > > > -   ret = anx7625_attach_dsi(platform);
> > > > > > > > -   if (ret) {
> > > > > > > > -           DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > > > > > -           goto unregister_bridge;
> > > > > > > > +   if (!platform->pdata.is_dpi) {
> > > > > > > > +           ret = anx7625_attach_dsi(platform);
> > > > > > > > +           if (ret) {
> > > > > > > > +                   DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
> > > > > > > > +                   goto unregister_bridge;
> > > > > > > > +           }
> > > > > > > >     }
> > > > > > > >
> > > > > > > >     DRM_DEV_DEBUG_DRIVER(dev, "probe done\n");
> > > > > > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > > > index 6dcf64c703f9..3ef1d8f4e575 100644
> > > > > > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
> > > > > > > > @@ -141,12 +141,20 @@
> > > > > > > >  #define  HORIZONTAL_BACK_PORCH_H      0x22  /* Bit[7:4] are reserved */
> > > > > > > >
> > > > > > > >  /******** END of I2C Address 0x72 *********/
> > > > > > > > +
> > > > > > > > +/***************************************************************/
> > > > > > > > +/* Register definition of device address 0x7a */
> > > > > > > > +#define DP_TX_SWING_REG_CNT                0x14
> > > > > > > > +#define DP_TX_LANE0_SWING_REG0             0x00
> > > > > > > > +#define DP_TX_LANE1_SWING_REG0             0x14
> > > > > > > > +/******** END of I2C Address 0x7a *********/
> > > > > > > > +
> > > > > > > >  /***************************************************************/
> > > > > > > >  /* Register definition of device address 0x7e */
> > > > > > > >
> > > > > > > >  #define  I2C_ADDR_7E_FLASH_CONTROLLER  0x7E
> > > > > > > >
> > > > > > > > -#define FLASH_LOAD_STA 0x05
> > > > > > > > +#define FLASH_LOAD_STA          0x05
> > > > > > > >  #define FLASH_LOAD_STA_CHK BIT(7)
> > > > > > > >
> > > > > > > >  #define  XTAL_FRQ_SEL    0x3F
> > > > > > > > @@ -349,12 +357,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 regulator_bulk_data supplies[3];
> > > > > > > >     struct drm_bridge *panel_bridge;
> > > > > > > >     int intp_irq;
> > > > > > > > +   int is_dpi;
> > > > > > > > +   int mipi_lanes;
> > > > > > > > +   int dp_lane0_swing_reg_cnt;
> > > > > > > > +   int lane0_reg_data[DP_TX_SWING_REG_CNT];
> > > > > > > > +   int dp_lane1_swing_reg_cnt;
> > > > > > > > +   int lane1_reg_data[DP_TX_SWING_REG_CNT];
> > > > > > > >     u32 low_power_mode;
> > > > > > > >     struct device_node *mipi_host_node;
> > > > > > > >  };
> > >
> > > --
> > > Regards,
> > >
> > > Laurent Pinchart

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-06 17:13   ` Laurent Pinchart
  2022-03-07  3:22     ` Xin Ji
@ 2022-03-07  6:12     ` Chen-Yu Tsai
  2022-03-07 15:49       ` Robert Foss
  1 sibling, 1 reply; 20+ messages in thread
From: Chen-Yu Tsai @ 2022-03-07  6:12 UTC (permalink / raw)
  To: Laurent Pinchart, Nícolas F. R. A. Prado
  Cc: Xin Ji, a.hajda, narmstrong, dan.carpenter, robert.foss, jonas,
	jernej.skrabec, airlied, daniel, sam, pihsun, tzungbi, maxime,
	drinkcat, hsinyi, dri-devel, linux-kernel, bliang, qwen, robh+dt,
	devicetree

On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> Hello Xin,
> 
> (Question for Rob below, and I'm afraid this is urgent as we need to
> merge a fix in v5.17).
> 
> On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > The basic anx7625 driver only support MIPI DSI rx signal input.
> > This patch add MIPI DPI rx input configuration support, after apply
> > this patch, the driver can support DSI rx or DPI rx by adding
> > 'bus-type' in DT.
> > 
> > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > ---
> >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> >  2 files changed, 205 insertions(+), 60 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > index f48e91134c20..f7c3386c8929 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c

[...]

> >  static int anx7625_parse_dt(struct device *dev,
> >  			    struct anx7625_platform_data *pdata)
> >  {
> > -	struct device_node *np = dev->of_node;
> > +	struct device_node *np = dev->of_node, *ep0;
> >  	struct drm_panel *panel;
> >  	int ret;
> > +	int bus_type, mipi_lanes;
> > +
> > +	anx7625_get_swing_setting(dev, pdata);
> >  
> > +	pdata->is_dpi = 1; /* default dpi mode */
> >  	pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> >  	if (!pdata->mipi_host_node) {
> >  		DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> >  		return -ENODEV;
> >  	}
> >  
> > -	DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > +	bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > +	mipi_lanes = MAX_LANES_SUPPORT;
> > +	ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > +	if (ep0) {
> > +		if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > +			bus_type = 0;
> > +
> > +		mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > +	}
> > +
> > +	if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> 
> This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> it's not an exact match.
> 
> This patch has landed in v5.17-rc1, along with the corresponding
> bindings. As DT bindings are an ABI, we should really fix this before
> v5.17 is released. There is no DSI bus types defined in DT, and adding
> one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> me (unless Rob disagrees).
> 
> It would seem best to revert this series and the corresponding bindings,
> and retry in v5.18.

There is a DT patch using this property that is already queued up for 5.17
in the soc tree:

https://lore.kernel.org/all/20220214200507.2500693-1-nfraprado@collabora.com/

merged here:

http://git.kernel.org/soc/soc/c/32568ae37596b529628ac09b875f4874e614f63f

We will need to revert that one as well.

ChenYu

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-07  6:12     ` Chen-Yu Tsai
@ 2022-03-07 15:49       ` Robert Foss
  2022-03-08 10:00         ` Robert Foss
  0 siblings, 1 reply; 20+ messages in thread
From: Robert Foss @ 2022-03-07 15:49 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Laurent Pinchart, Nícolas F. R. A. Prado, Xin Ji, a.hajda,
	narmstrong, dan.carpenter, jonas, jernej.skrabec, airlied,
	daniel, sam, pihsun, tzungbi, maxime, drinkcat, hsinyi,
	dri-devel, linux-kernel, bliang, qwen, robh+dt, devicetree

On Mon, 7 Mar 2022 at 07:12, Chen-Yu Tsai <wenst@chromium.org> wrote:
>
> On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> > Hello Xin,
> >
> > (Question for Rob below, and I'm afraid this is urgent as we need to
> > merge a fix in v5.17).
> >
> > On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > > The basic anx7625 driver only support MIPI DSI rx signal input.
> > > This patch add MIPI DPI rx input configuration support, after apply
> > > this patch, the driver can support DSI rx or DPI rx by adding
> > > 'bus-type' in DT.
> > >
> > > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > ---
> > >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> > >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> > >  2 files changed, 205 insertions(+), 60 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > index f48e91134c20..f7c3386c8929 100644
> > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
>
> [...]
>
> > >  static int anx7625_parse_dt(struct device *dev,
> > >                         struct anx7625_platform_data *pdata)
> > >  {
> > > -   struct device_node *np = dev->of_node;
> > > +   struct device_node *np = dev->of_node, *ep0;
> > >     struct drm_panel *panel;
> > >     int ret;
> > > +   int bus_type, mipi_lanes;
> > > +
> > > +   anx7625_get_swing_setting(dev, pdata);
> > >
> > > +   pdata->is_dpi = 1; /* default dpi mode */
> > >     pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> > >     if (!pdata->mipi_host_node) {
> > >             DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> > >             return -ENODEV;
> > >     }
> > >
> > > -   DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > +   bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > +   mipi_lanes = MAX_LANES_SUPPORT;
> > > +   ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > +   if (ep0) {
> > > +           if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > +                   bus_type = 0;
> > > +
> > > +           mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > +   }
> > > +
> > > +   if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> >
> > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > it's not an exact match.
> >
> > This patch has landed in v5.17-rc1, along with the corresponding
> > bindings. As DT bindings are an ABI, we should really fix this before
> > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > me (unless Rob disagrees).
> >
> > It would seem best to revert this series and the corresponding bindings,
> > and retry in v5.18.
>
> There is a DT patch using this property that is already queued up for 5.17
> in the soc tree:
>
> https://lore.kernel.org/all/20220214200507.2500693-1-nfraprado@collabora.com/
>
> merged here:
>
> http://git.kernel.org/soc/soc/c/32568ae37596b529628ac09b875f4874e614f63f
>
> We will need to revert that one as well.

I just submitted a series reverting the dt-binding change + the
related commit to "mt8183: jacuzzi".
Can I get a quick r-b/a-b in order to get this into v5.17.

https://lore.kernel.org/all/20220307154558.2505734-3-robert.foss@linaro.org/

>
> ChenYu

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-07 15:49       ` Robert Foss
@ 2022-03-08 10:00         ` Robert Foss
  2022-03-21 11:52           ` Xin Ji
  0 siblings, 1 reply; 20+ messages in thread
From: Robert Foss @ 2022-03-08 10:00 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Laurent Pinchart, Nícolas F. R. A. Prado, Xin Ji, a.hajda,
	narmstrong, dan.carpenter, jonas, jernej.skrabec, airlied,
	daniel, sam, pihsun, tzungbi, maxime, drinkcat, hsinyi,
	dri-devel, linux-kernel, bliang, qwen, robh+dt, devicetree

On Mon, 7 Mar 2022 at 16:49, Robert Foss <robert.foss@linaro.org> wrote:
>
> On Mon, 7 Mar 2022 at 07:12, Chen-Yu Tsai <wenst@chromium.org> wrote:
> >
> > On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> > > Hello Xin,
> > >
> > > (Question for Rob below, and I'm afraid this is urgent as we need to
> > > merge a fix in v5.17).
> > >
> > > On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > > > The basic anx7625 driver only support MIPI DSI rx signal input.
> > > > This patch add MIPI DPI rx input configuration support, after apply
> > > > this patch, the driver can support DSI rx or DPI rx by adding
> > > > 'bus-type' in DT.
> > > >
> > > > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > ---
> > > >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> > > >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> > > >  2 files changed, 205 insertions(+), 60 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > index f48e91134c20..f7c3386c8929 100644
> > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> >
> > [...]
> >
> > > >  static int anx7625_parse_dt(struct device *dev,
> > > >                         struct anx7625_platform_data *pdata)
> > > >  {
> > > > -   struct device_node *np = dev->of_node;
> > > > +   struct device_node *np = dev->of_node, *ep0;
> > > >     struct drm_panel *panel;
> > > >     int ret;
> > > > +   int bus_type, mipi_lanes;
> > > > +
> > > > +   anx7625_get_swing_setting(dev, pdata);
> > > >
> > > > +   pdata->is_dpi = 1; /* default dpi mode */
> > > >     pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> > > >     if (!pdata->mipi_host_node) {
> > > >             DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> > > >             return -ENODEV;
> > > >     }
> > > >
> > > > -   DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > > +   bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > > +   mipi_lanes = MAX_LANES_SUPPORT;
> > > > +   ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > > +   if (ep0) {
> > > > +           if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > > +                   bus_type = 0;
> > > > +
> > > > +           mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > > +   }
> > > > +
> > > > +   if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> > >
> > > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > > it's not an exact match.
> > >
> > > This patch has landed in v5.17-rc1, along with the corresponding
> > > bindings. As DT bindings are an ABI, we should really fix this before
> > > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > > me (unless Rob disagrees).
> > >
> > > It would seem best to revert this series and the corresponding bindings,
> > > and retry in v5.18.
> >
> > There is a DT patch using this property that is already queued up for 5.17
> > in the soc tree:
> >
> > https://lore.kernel.org/all/20220214200507.2500693-1-nfraprado@collabora.com/
> >
> > merged here:
> >
> > http://git.kernel.org/soc/soc/c/32568ae37596b529628ac09b875f4874e614f63f
> >
> > We will need to revert that one as well.
>
> I just submitted a series reverting the dt-binding change + the
> related commit to "mt8183: jacuzzi".
> Can I get a quick r-b/a-b in order to get this into v5.17.
>
> https://lore.kernel.org/all/20220307154558.2505734-3-robert.foss@linaro.org/
>

v2 of revert submitted.

https://lore.kernel.org/all/20220308094911.2680291-1-robert.foss@linaro.org/

Xin: Will you spin a series that adds DPI support and re-enables DPI
for anx7625? Additionally, "mt8183: jacuzzi" will have to have DPI
re-enabled.

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-08 10:00         ` Robert Foss
@ 2022-03-21 11:52           ` Xin Ji
  2022-03-28  9:54             ` Robert Foss
  0 siblings, 1 reply; 20+ messages in thread
From: Xin Ji @ 2022-03-21 11:52 UTC (permalink / raw)
  To: Robert Foss
  Cc: Laurent Pinchart, Nícolas F. R. A. Prado, Xin Ji, a.hajda,
	narmstrong, dan.carpenter, jonas, jernej.skrabec, airlied,
	daniel, sam, pihsun, tzungbi, maxime, drinkcat, hsinyi,
	dri-devel, linux-kernel, bliang, qwen, robh+dt, devicetree,
	Chen-Yu Tsai

On Tue, Mar 08, 2022 at 11:00:20AM +0100, Robert Foss wrote:
> On Mon, 7 Mar 2022 at 16:49, Robert Foss <robert.foss@linaro.org> wrote:
> >
> > On Mon, 7 Mar 2022 at 07:12, Chen-Yu Tsai <wenst@chromium.org> wrote:
> > >
> > > On Sun, Mar 06, 2022 at 07:13:30PM +0200, Laurent Pinchart wrote:
> > > > Hello Xin,
> > > >
> > > > (Question for Rob below, and I'm afraid this is urgent as we need to
> > > > merge a fix in v5.17).
> > > >
> > > > On Fri, Nov 05, 2021 at 11:19:03AM +0800, Xin Ji wrote:
> > > > > The basic anx7625 driver only support MIPI DSI rx signal input.
> > > > > This patch add MIPI DPI rx input configuration support, after apply
> > > > > this patch, the driver can support DSI rx or DPI rx by adding
> > > > > 'bus-type' in DT.
> > > > >
> > > > > Reviewed-by: Robert Foss <robert.foss@linaro.org>
> > > > > Signed-off-by: Xin Ji <xji@analogixsemi.com>
> > > > > ---
> > > > >  drivers/gpu/drm/bridge/analogix/anx7625.c | 247 ++++++++++++++++------
> > > > >  drivers/gpu/drm/bridge/analogix/anx7625.h |  18 +-
> > > > >  2 files changed, 205 insertions(+), 60 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > index f48e91134c20..f7c3386c8929 100644
> > > > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > >
> > > [...]
> > >
> > > > >  static int anx7625_parse_dt(struct device *dev,
> > > > >                         struct anx7625_platform_data *pdata)
> > > > >  {
> > > > > -   struct device_node *np = dev->of_node;
> > > > > +   struct device_node *np = dev->of_node, *ep0;
> > > > >     struct drm_panel *panel;
> > > > >     int ret;
> > > > > +   int bus_type, mipi_lanes;
> > > > > +
> > > > > +   anx7625_get_swing_setting(dev, pdata);
> > > > >
> > > > > +   pdata->is_dpi = 1; /* default dpi mode */
> > > > >     pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
> > > > >     if (!pdata->mipi_host_node) {
> > > > >             DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
> > > > >             return -ENODEV;
> > > > >     }
> > > > >
> > > > > -   DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > > > +   bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > > > +   mipi_lanes = MAX_LANES_SUPPORT;
> > > > > +   ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > > > +   if (ep0) {
> > > > > +           if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > > > +                   bus_type = 0;
> > > > > +
> > > > > +           mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > > > +   }
> > > > > +
> > > > > +   if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> > > >
> > > > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > > > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > > > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > > > it's not an exact match.
> > > >
> > > > This patch has landed in v5.17-rc1, along with the corresponding
> > > > bindings. As DT bindings are an ABI, we should really fix this before
> > > > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > > > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > > > me (unless Rob disagrees).
> > > >
> > > > It would seem best to revert this series and the corresponding bindings,
> > > > and retry in v5.18.
> > >
> > > There is a DT patch using this property that is already queued up for 5.17
> > > in the soc tree:
> > >
> > > https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20220214200507.2500693-1-nfraprado%40collabora.com%2F&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C69542695a9cd42cff5a508da00ea7baa%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637823304343387964%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=KbitBhnvGWfpHu6PNLUmrgdqcoZbXaA3hGwq9iAjQfI%3D&amp;reserved=0
> > >
> > > merged here:
> > >
> > > https://nam10.safelinks.protection.outlook.com/?url=http%3A%2F%2Fgit.kernel.org%2Fsoc%2Fsoc%2Fc%2F32568ae37596b529628ac09b875f4874e614f63f&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C69542695a9cd42cff5a508da00ea7baa%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637823304343387964%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=YJAs0IPxR0hrHpGR7K00itcTIF9cnz4L4ta%2B9ACQdSk%3D&amp;reserved=0
> > >
> > > We will need to revert that one as well.
> >
> > I just submitted a series reverting the dt-binding change + the
> > related commit to "mt8183: jacuzzi".
> > Can I get a quick r-b/a-b in order to get this into v5.17.
> >
> > https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20220307154558.2505734-3-robert.foss%40linaro.org%2F&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C69542695a9cd42cff5a508da00ea7baa%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637823304343387964%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=S5ScH2jid3ZRobvO%2Fl2nVgdOvFHNj1nWafTQYG3L9d0%3D&amp;reserved=0
> >
> 
> v2 of revert submitted.
> 
> https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20220308094911.2680291-1-robert.foss%40linaro.org%2F&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C69542695a9cd42cff5a508da00ea7baa%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637823304343387964%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=D6ulS16g4v4x0u23OtYRrSeitTqllWwDzPiT%2BxMcQQg%3D&amp;reserved=0
> 
> Xin: Will you spin a series that adds DPI support and re-enables DPI
> for anx7625? Additionally, "mt8183: jacuzzi" will have to have DPI
> re-enabled.
Hi Robert Foss, I'm little confused, do I need resend this serial or
send a patch based on currently define(V4L2_FWNODE_BUS_TYPE_PARALLEL)?

And use V4L2_FWNODE_BUS_TYPE_PARALLEL for DPI, other value for DSI
setup?

Thanks,
Xin

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-21 11:52           ` Xin Ji
@ 2022-03-28  9:54             ` Robert Foss
  2022-03-28 11:10               ` Xin Ji
  0 siblings, 1 reply; 20+ messages in thread
From: Robert Foss @ 2022-03-28  9:54 UTC (permalink / raw)
  To: Xin Ji
  Cc: Laurent Pinchart, Nícolas F. R. A. Prado, a.hajda,
	narmstrong, dan.carpenter, jonas, jernej.skrabec, airlied,
	daniel, sam, pihsun, tzungbi, maxime, drinkcat, hsinyi,
	dri-devel, linux-kernel, bliang, qwen, robh+dt, devicetree,
	Chen-Yu Tsai

> > > > > > -   DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > > > > +   bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > > > > +   mipi_lanes = MAX_LANES_SUPPORT;
> > > > > > +   ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > > > > +   if (ep0) {
> > > > > > +           if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > > > > +                   bus_type = 0;
> > > > > > +
> > > > > > +           mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > > > > +   }
> > > > > > +
> > > > > > +   if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> > > > >
> > > > > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > > > > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > > > > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > > > > it's not an exact match.
> > > > >
> > > > > This patch has landed in v5.17-rc1, along with the corresponding
> > > > > bindings. As DT bindings are an ABI, we should really fix this before
> > > > > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > > > > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > > > > me (unless Rob disagrees).
> > > > >
> > > > > It would seem best to revert this series and the corresponding bindings,
> > > > > and retry in v5.18.
> > > >
> > > > There is a DT patch using this property that is already queued up for 5.17
> > > > in the soc tree:
> > > >
> > > > https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20220214200507.2500693-1-nfraprado%40collabora.com%2F&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C69542695a9cd42cff5a508da00ea7baa%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637823304343387964%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=KbitBhnvGWfpHu6PNLUmrgdqcoZbXaA3hGwq9iAjQfI%3D&amp;reserved=0
> > > >
> > > > merged here:
> > > >
> > > > https://nam10.safelinks.protection.outlook.com/?url=http%3A%2F%2Fgit.kernel.org%2Fsoc%2Fsoc%2Fc%2F32568ae37596b529628ac09b875f4874e614f63f&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C69542695a9cd42cff5a508da00ea7baa%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637823304343387964%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=YJAs0IPxR0hrHpGR7K00itcTIF9cnz4L4ta%2B9ACQdSk%3D&amp;reserved=0
> > > >
> > > > We will need to revert that one as well.
> > >
> > > I just submitted a series reverting the dt-binding change + the
> > > related commit to "mt8183: jacuzzi".
> > > Can I get a quick r-b/a-b in order to get this into v5.17.
> > >
> > > https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20220307154558.2505734-3-robert.foss%40linaro.org%2F&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C69542695a9cd42cff5a508da00ea7baa%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637823304343387964%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=S5ScH2jid3ZRobvO%2Fl2nVgdOvFHNj1nWafTQYG3L9d0%3D&amp;reserved=0
> > >
> >
> > v2 of revert submitted.
> >
> > https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20220308094911.2680291-1-robert.foss%40linaro.org%2F&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C69542695a9cd42cff5a508da00ea7baa%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637823304343387964%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=D6ulS16g4v4x0u23OtYRrSeitTqllWwDzPiT%2BxMcQQg%3D&amp;reserved=0
> >
> > Xin: Will you spin a series that adds DPI support and re-enables DPI
> > for anx7625? Additionally, "mt8183: jacuzzi" will have to have DPI
> > re-enabled.
> Hi Robert Foss, I'm little confused, do I need resend this serial or
> send a patch based on currently define(V4L2_FWNODE_BUS_TYPE_PARALLEL)?
>
> And use V4L2_FWNODE_BUS_TYPE_PARALLEL for DPI, other value for DSI
> setup?

V4L2_FWNODE_BUS_TYPE_PARALLEL is not meant to be used for DPI, but
rather is used to represtent CPI. So another enum (something along the
lines of V4L2_FWNODE_BUS_TYPE_DPI) needs to be defined, and then this
series needs to use this new enum.

I'd like to see the following:
 - Introduction of V4L2_FWNODE_BUS_TYPE_DPI
 - Reworking this series to use V4L2_FWNODE_BUS_TYPE_DPI
 - Reworking "mt8183: jacuzzi" to use V4L2_FWNODE_BUS_TYPE_DPI

Does that make sense?


Rob.

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

* Re: [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature
  2022-03-28  9:54             ` Robert Foss
@ 2022-03-28 11:10               ` Xin Ji
  0 siblings, 0 replies; 20+ messages in thread
From: Xin Ji @ 2022-03-28 11:10 UTC (permalink / raw)
  To: Robert Foss
  Cc: Laurent Pinchart, Nícolas F. R. A. Prado, a.hajda,
	narmstrong, dan.carpenter, jonas, jernej.skrabec, airlied,
	daniel, sam, pihsun, tzungbi, maxime, drinkcat, hsinyi,
	dri-devel, linux-kernel, bliang, qwen, robh+dt, devicetree,
	Chen-Yu Tsai

On Mon, Mar 28, 2022 at 11:54:12AM +0200, Robert Foss wrote:
> > > > > > > -   DRM_DEV_DEBUG_DRIVER(dev, "found dsi host node.\n");
> > > > > > > +   bus_type = V4L2_FWNODE_BUS_TYPE_PARALLEL;
> > > > > > > +   mipi_lanes = MAX_LANES_SUPPORT;
> > > > > > > +   ep0 = of_graph_get_endpoint_by_regs(np, 0, 0);
> > > > > > > +   if (ep0) {
> > > > > > > +           if (of_property_read_u32(ep0, "bus-type", &bus_type))
> > > > > > > +                   bus_type = 0;
> > > > > > > +
> > > > > > > +           mipi_lanes = of_property_count_u32_elems(ep0, "data-lanes");
> > > > > > > +   }
> > > > > > > +
> > > > > > > +   if (bus_type == V4L2_FWNODE_BUS_TYPE_PARALLEL) /* bus type is Parallel(DSI) */
> > > > > >
> > > > > > This is not correct *at all*. V4L2_FWNODE_BUS_TYPE_PARALLEL has nothing
> > > > > > to do with DSI. DSI stands for Digital *Serial* Interface. If anything,
> > > > > > the V4L2_FWNODE_BUS_TYPE_PARALLEL type would map better to DPI, even if
> > > > > > it's not an exact match.
> > > > > >
> > > > > > This patch has landed in v5.17-rc1, along with the corresponding
> > > > > > bindings. As DT bindings are an ABI, we should really fix this before
> > > > > > v5.17 is released. There is no DSI bus types defined in DT, and adding
> > > > > > one as a fix so late in the v5.17-rc cycle seems a bit of a stretch to
> > > > > > me (unless Rob disagrees).
> > > > > >
> > > > > > It would seem best to revert this series and the corresponding bindings,
> > > > > > and retry in v5.18.
> > > > >
> > > > > There is a DT patch using this property that is already queued up for 5.17
> > > > > in the soc tree:
> > > > >
> > > > > https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20220214200507.2500693-1-nfraprado%40collabora.com%2F&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C450c5609d8c24e9a34fa08da10a0f126%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637840580680816692%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=bARYbwXq6IJGxn3UBp%2F75lZhoTpzmZkTQsN0yvs7Cgg%3D&amp;reserved=0
> > > > >
> > > > > merged here:
> > > > >
> > > > > https://nam10.safelinks.protection.outlook.com/?url=http%3A%2F%2Fgit.kernel.org%2Fsoc%2Fsoc%2Fc%2F32568ae37596b529628ac09b875f4874e614f63f&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C450c5609d8c24e9a34fa08da10a0f126%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637840580680816692%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=lt3Tp8DveE1RJ%2F1MqDzYdKtHDxIyqhBbur%2Fm4N432AI%3D&amp;reserved=0
> > > > >
> > > > > We will need to revert that one as well.
> > > >
> > > > I just submitted a series reverting the dt-binding change + the
> > > > related commit to "mt8183: jacuzzi".
> > > > Can I get a quick r-b/a-b in order to get this into v5.17.
> > > >
> > > > https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20220307154558.2505734-3-robert.foss%40linaro.org%2F&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C450c5609d8c24e9a34fa08da10a0f126%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637840580680816692%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=dgA%2BrQ3KBMPLoR5bwL5Wt2Vs6EuNy%2Fh9yfOftxeUXjM%3D&amp;reserved=0
> > > >
> > >
> > > v2 of revert submitted.
> > >
> > > https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Fall%2F20220308094911.2680291-1-robert.foss%40linaro.org%2F&amp;data=04%7C01%7Cxji%40analogixsemi.com%7C450c5609d8c24e9a34fa08da10a0f126%7Cb099b0b4f26c4cf59a0fd5be9acab205%7C0%7C0%7C637840580680816692%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=vIcCvXrwZs8XhXuoQ8On7vB9%2Bwrsov1DD5UBX%2B1G93Q%3D&amp;reserved=0
> > >
> > > Xin: Will you spin a series that adds DPI support and re-enables DPI
> > > for anx7625? Additionally, "mt8183: jacuzzi" will have to have DPI
> > > re-enabled.
> > Hi Robert Foss, I'm little confused, do I need resend this serial or
> > send a patch based on currently define(V4L2_FWNODE_BUS_TYPE_PARALLEL)?
> >
> > And use V4L2_FWNODE_BUS_TYPE_PARALLEL for DPI, other value for DSI
> > setup?
> 
> V4L2_FWNODE_BUS_TYPE_PARALLEL is not meant to be used for DPI, but
> rather is used to represtent CPI. So another enum (something along the
> lines of V4L2_FWNODE_BUS_TYPE_DPI) needs to be defined, and then this
> series needs to use this new enum.
> 
> I'd like to see the following:
>  - Introduction of V4L2_FWNODE_BUS_TYPE_DPI
>  - Reworking this series to use V4L2_FWNODE_BUS_TYPE_DPI
>  - Reworking "mt8183: jacuzzi" to use V4L2_FWNODE_BUS_TYPE_DPI
> 
> Does that make sense?
Hi Rob, OK, I'll prepare the patch for review.
Thanks,
Xin
> 
> 
> Rob.

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

* [PATCH v12 1/4] dt-bindings:drm/bridge:anx7625:add vendor define
@ 2021-11-04  3:34 Xin Ji
  0 siblings, 0 replies; 20+ messages in thread
From: Xin Ji @ 2021-11-04  3:34 UTC (permalink / raw)
  To: airlied, daniel, robh+dt, robert.foss, sam, drinkcat, hsinyi,
	thunder.leizhen, dri-devel, devicetree, linux-kernel
  Cc: Xin Ji, Rob Herring

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

The device which cannot pass DP tx PHY CTS caused by long PCB trace or
embedded MUX, adjusting ANX7625 PHY parameters can pass the CTS test. The
adjusting type include Pre-emphasis, Vp-p, Rterm(Resistor Termination)
and Rsel(Driven Strength). Each lane has maximum 20 registers for
these settings.

Signed-off-by: Xin Ji <xji@analogixsemi.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
 .../display/bridge/analogix,anx7625.yaml      | 65 ++++++++++++++++++-
 1 file changed, 63 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
index ab48ab2f4240..1d3e88daca04 100644
--- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
@@ -43,14 +43,70 @@ properties:
   vdd33-supply:
     description: Regulator that provides the supply 3.3V power.
 
+  analogix,lane0-swing:
+    $ref: /schemas/types.yaml#/definitions/uint8-array
+    minItems: 1
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane0 PHY.
+      Registers 0~9 are Swing0_Pre0, Swing1_Pre0, Swing2_Pre0,
+      Swing3_Pre0, Swing0_Pre1, Swing1_Pre1, Swing2_Pre1, Swing0_Pre2,
+      Swing1_Pre2, Swing0_Pre3, they are for [Boost control] and
+      [Swing control] setting.
+      Registers 0~9, bit 3:0 is [Boost control], these bits control
+      post cursor manual, increase the [Boost control] to increase
+      Pre-emphasis value.
+      Registers 0~9, bit 6:4 is [Swing control], these bits control
+      swing manual, increase [Swing control] setting to add Vp-p value
+      for each Swing, Pre.
+      Registers 10~19 are Swing0_Pre0, Swing1_Pre0, Swing2_Pre0,
+      Swing3_Pre0, Swing0_Pre1, Swing1_Pre1, Swing2_Pre1, Swing0_Pre2,
+      Swing1_Pre2, Swing0_Pre3, they are for [R select control] and
+      [R Termination control] setting.
+      Registers 10~19, bit 4:0 is [R select control], these bits are
+      compensation manual, increase it can enhance IO driven strength
+      and Vp-p.
+      Registers 10~19, bit 5:6 is [R termination control], these bits
+      adjust 50ohm impedance of DP tx termination. 00:55 ohm,
+      01:50 ohm(default), 10:45 ohm, 11:40 ohm.
+
+  analogix,lane1-swing:
+    $ref: /schemas/types.yaml#/definitions/uint8-array
+    minItems: 1
+    maxItems: 20
+    description:
+      an array of swing register setting for DP tx lane1 PHY.
+      DP TX lane1 swing register setting same with lane0
+      swing, please refer lane0-swing property description.
+
+  analogix,audio-enable:
+    type: boolean
+    description: let the driver enable audio HDMI codec function or not.
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
     properties:
       port@0:
-        $ref: /schemas/graph.yaml#/properties/port
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
         description:
-          Video port for MIPI DSI input.
+          MIPI DSI/DPI input.
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            type: object
+            additionalProperties: false
+
+            properties:
+              remote-endpoint: true
+
+              bus-type:
+                enum: [1, 5]
+                default: 1
+
+              data-lanes: true
 
       port@1:
         $ref: /schemas/graph.yaml#/properties/port
@@ -87,6 +143,9 @@ examples:
             vdd10-supply = <&pp1000_mipibrdg>;
             vdd18-supply = <&pp1800_mipibrdg>;
             vdd33-supply = <&pp3300_mipibrdg>;
+            analogix,audio-enable;
+            analogix,lane0-swing = /bits/ 8 <0x14 0x54 0x64 0x74>;
+            analogix,lane1-swing = /bits/ 8 <0x14 0x54 0x64 0x74>;
 
             ports {
                 #address-cells = <1>;
@@ -96,6 +155,8 @@ examples:
                     reg = <0>;
                     anx7625_in: endpoint {
                         remote-endpoint = <&mipi_dsi>;
+                        bus-type = <5>;
+                        data-lanes = <0 1 2 3>;
                     };
                 };
 
-- 
2.25.1


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

end of thread, other threads:[~2022-03-28 11:10 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-05  3:19 [PATCH v12 1/4] dt-bindings:drm/bridge:anx7625:add vendor define Xin Ji
2021-11-05  3:19 ` [PATCH v12 2/4] drm/bridge: anx7625: fix not correct return value Xin Ji
2021-11-05  3:19 ` [PATCH v12 3/4] drm/bridge: anx7625: add MIPI DPI input feature Xin Ji
2022-03-06 17:13   ` Laurent Pinchart
2022-03-07  3:22     ` Xin Ji
2022-03-07  3:30       ` Laurent Pinchart
2022-03-07  4:32         ` Xin Ji
2022-03-07  4:47           ` Laurent Pinchart
2022-03-07  5:09             ` Xin Ji
2022-03-07  5:17               ` Laurent Pinchart
2022-03-07  5:17               ` Hsin-Yi Wang
2022-03-07  5:35                 ` Xin Ji
2022-03-07  6:12     ` Chen-Yu Tsai
2022-03-07 15:49       ` Robert Foss
2022-03-08 10:00         ` Robert Foss
2022-03-21 11:52           ` Xin Ji
2022-03-28  9:54             ` Robert Foss
2022-03-28 11:10               ` Xin Ji
2021-11-05  3:19 ` [PATCH v12 4/4] drm/bridge: anx7625: add HDMI audio function Xin Ji
  -- strict thread matches above, loose matches on Subject: below --
2021-11-04  3:34 [PATCH v12 1/4] dt-bindings:drm/bridge:anx7625:add vendor define Xin Ji

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).