All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephane Viau <sviau@codeaurora.org>
To: dri-devel@lists.freedesktop.org
Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 4/4] drm/msm/mdp5: Make the intf connection in config module
Date: Tue,  3 Mar 2015 13:36:15 -0500	[thread overview]
Message-ID: <1425407775-7704-5-git-send-email-sviau@codeaurora.org> (raw)
In-Reply-To: <1425407775-7704-1-git-send-email-sviau@codeaurora.org>

Up until now, we assume that eDP is tight to intf_0 and HDMI to
intf_3. This information shall actually come from the mdp5_cfg
module since it can change from one chip to another.

Signed-off-by: Stephane Viau <sviau@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c |   8 +++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h |   4 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 111 ++++++++++++++++++--------------
 3 files changed, 74 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index 72c075a..8bee023 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -62,6 +62,10 @@ const struct mdp5_cfg_hw msm8x74_config = {
 		.count = 4,
 		.base = { 0x12500, 0x12700, 0x12900, 0x12b00 },
 	},
+	.intfs = {
+		[0] = INTF_eDP,
+		[3] = INTF_HDMI,
+	},
 	.max_clk = 200000000,
 };
 
@@ -111,6 +115,10 @@ const struct mdp5_cfg_hw apq8084_config = {
 		.count = 5,
 		.base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 },
 	},
+	.intfs = {
+		[0] = INTF_eDP,
+		[3] = INTF_HDMI,
+	},
 	.max_clk = 320000000,
 };
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
index be149b3..4e91f14 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
@@ -58,6 +58,8 @@ struct mdp5_smp_block {
 	int reserved[MAX_CLIENTS];	/* # of MMBs allocated per client */
 };
 
+#define MDP5_INTF_NUM_MAX	5
+
 struct mdp5_cfg_hw {
 	char  *name;
 
@@ -71,6 +73,8 @@ struct mdp5_cfg_hw {
 	struct mdp5_sub_block ad;
 	struct mdp5_sub_block intf;
 
+	u32 intfs[MDP5_INTF_NUM_MAX]; /* array of enum mdp5_intf_type */
+
 	uint32_t max_clk;
 };
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 390d9d2..8cec00e 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -161,6 +161,44 @@ int mdp5_enable(struct mdp5_kms *mdp5_kms)
 	return 0;
 }
 
+static int construct_encoder(struct mdp5_kms *mdp5_kms,
+		enum mdp5_intf_type intf_type, int intf_num)
+{
+	struct drm_device *dev = mdp5_kms->dev;
+	struct msm_drm_private *priv = dev->dev_private;
+	struct drm_encoder *encoder;
+	struct mdp5_interface intf = {
+			.num	= intf_num,
+			.type	= intf_type,
+			.mode	= MDP5_INTF_MODE_NONE,
+	};
+	int ret = 0;
+
+	encoder = mdp5_encoder_init(dev, &intf);
+	if (IS_ERR(encoder)) {
+		ret = PTR_ERR(encoder);
+		dev_err(dev->dev, "failed to construct encoder: %d\n", ret);
+		return ret;
+	}
+
+	encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
+	priv->encoders[priv->num_encoders++] = encoder;
+
+	if (intf_type == INTF_HDMI) {
+		ret = hdmi_modeset_init(priv->hdmi, dev, encoder);
+		if (ret)
+			dev_err(dev->dev, "failed to init HDMI: %d\n", ret);
+
+	} else if (intf_type == INTF_eDP) {
+		/* Construct bridge/connector for eDP: */
+		ret = msm_edp_modeset_init(priv->edp, dev, encoder);
+		if (ret)
+			dev_err(dev->dev, "failed to init eDP: %d\n", ret);
+	}
+
+	return ret;
+}
+
 static int modeset_init(struct mdp5_kms *mdp5_kms)
 {
 	static const enum mdp5_pipe crtcs[] = {
@@ -171,7 +209,6 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 	};
 	struct drm_device *dev = mdp5_kms->dev;
 	struct msm_drm_private *priv = dev->dev_private;
-	struct drm_encoder *encoder;
 	const struct mdp5_cfg_hw *hw_cfg;
 	int i, ret;
 
@@ -222,56 +259,29 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 		}
 	}
 
-	if (priv->hdmi) {
-		struct mdp5_interface intf = {
-				.num	= 3,
-				.type	= INTF_HDMI,
-				.mode	= MDP5_INTF_MODE_NONE,
-		};
-
-		/* Construct encoder for HDMI: */
-		encoder = mdp5_encoder_init(dev, &intf);
-		if (IS_ERR(encoder)) {
-			dev_err(dev->dev, "failed to construct encoder\n");
-			ret = PTR_ERR(encoder);
-			goto fail;
-		}
-
-		encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;;
-		priv->encoders[priv->num_encoders++] = encoder;
-
-		ret = hdmi_modeset_init(priv->hdmi, dev, encoder);
-		if (ret) {
-			dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret);
-			goto fail;
-		}
-	}
-
-	if (priv->edp) {
-		struct mdp5_interface intf = {
-				.num	= 0,
-				.type	= INTF_eDP,
-				.mode	= MDP5_INTF_MODE_NONE,
-		};
-
-		/* Construct encoder for eDP: */
-		encoder = mdp5_encoder_init(dev, &intf);
-		if (IS_ERR(encoder)) {
-			dev_err(dev->dev, "failed to construct eDP encoder\n");
-			ret = PTR_ERR(encoder);
-			goto fail;
+	/* Construct external display interfaces' encoders: */
+	for (i = 0; i < ARRAY_SIZE(hw_cfg->intfs); i++) {
+		enum mdp5_intf_type intf_type = hw_cfg->intfs[i];
+
+		switch (intf_type) {
+		case INTF_DISABLED:
+			break;
+		case INTF_eDP:
+			if (priv->edp)
+				ret = construct_encoder(mdp5_kms, INTF_eDP, i);
+			break;
+		case INTF_HDMI:
+			if (priv->hdmi)
+				ret = construct_encoder(mdp5_kms, INTF_HDMI, i);
+			break;
+		default:
+			dev_err(dev->dev, "unknown intf: %d\n", intf_type);
+			ret = -EINVAL;
+			break;
 		}
 
-		encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
-		priv->encoders[priv->num_encoders++] = encoder;
-
-		/* Construct bridge/connector for eDP: */
-		ret = msm_edp_modeset_init(priv->edp, dev, encoder);
-		if (ret) {
-			dev_err(dev->dev, "failed to initialize eDP: %d\n",
-									ret);
+		if (ret)
 			goto fail;
-		}
 	}
 
 	return 0;
@@ -415,8 +425,11 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
 	 * we don't disable):
 	 */
 	mdp5_enable(mdp5_kms);
-	for (i = 0; i < config->hw->intf.count; i++)
+	for (i = 0; i < MDP5_INTF_NUM_MAX; i++) {
+		if (MDP5_INTF_IS_VIRTUAL_DISPLAY(config->hw->intfs[i]))
+			continue;
 		mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(i), 0);
+	}
 	mdp5_disable(mdp5_kms);
 	mdelay(16);
 
-- 
Qualcomm Innovation Center, Inc.

The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project

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

WARNING: multiple messages have this Message-ID (diff)
From: Stephane Viau <sviau@codeaurora.org>
To: dri-devel@lists.freedesktop.org
Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org,
	robdclark@gmail.com, Stephane Viau <sviau@codeaurora.org>
Subject: [PATCH 4/4] drm/msm/mdp5: Make the intf connection in config module
Date: Tue,  3 Mar 2015 13:36:15 -0500	[thread overview]
Message-ID: <1425407775-7704-5-git-send-email-sviau@codeaurora.org> (raw)
In-Reply-To: <1425407775-7704-1-git-send-email-sviau@codeaurora.org>

Up until now, we assume that eDP is tight to intf_0 and HDMI to
intf_3. This information shall actually come from the mdp5_cfg
module since it can change from one chip to another.

Signed-off-by: Stephane Viau <sviau@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c |   8 +++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h |   4 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 111 ++++++++++++++++++--------------
 3 files changed, 74 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index 72c075a..8bee023 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -62,6 +62,10 @@ const struct mdp5_cfg_hw msm8x74_config = {
 		.count = 4,
 		.base = { 0x12500, 0x12700, 0x12900, 0x12b00 },
 	},
+	.intfs = {
+		[0] = INTF_eDP,
+		[3] = INTF_HDMI,
+	},
 	.max_clk = 200000000,
 };
 
@@ -111,6 +115,10 @@ const struct mdp5_cfg_hw apq8084_config = {
 		.count = 5,
 		.base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 },
 	},
+	.intfs = {
+		[0] = INTF_eDP,
+		[3] = INTF_HDMI,
+	},
 	.max_clk = 320000000,
 };
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
index be149b3..4e91f14 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
@@ -58,6 +58,8 @@ struct mdp5_smp_block {
 	int reserved[MAX_CLIENTS];	/* # of MMBs allocated per client */
 };
 
+#define MDP5_INTF_NUM_MAX	5
+
 struct mdp5_cfg_hw {
 	char  *name;
 
@@ -71,6 +73,8 @@ struct mdp5_cfg_hw {
 	struct mdp5_sub_block ad;
 	struct mdp5_sub_block intf;
 
+	u32 intfs[MDP5_INTF_NUM_MAX]; /* array of enum mdp5_intf_type */
+
 	uint32_t max_clk;
 };
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 390d9d2..8cec00e 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -161,6 +161,44 @@ int mdp5_enable(struct mdp5_kms *mdp5_kms)
 	return 0;
 }
 
+static int construct_encoder(struct mdp5_kms *mdp5_kms,
+		enum mdp5_intf_type intf_type, int intf_num)
+{
+	struct drm_device *dev = mdp5_kms->dev;
+	struct msm_drm_private *priv = dev->dev_private;
+	struct drm_encoder *encoder;
+	struct mdp5_interface intf = {
+			.num	= intf_num,
+			.type	= intf_type,
+			.mode	= MDP5_INTF_MODE_NONE,
+	};
+	int ret = 0;
+
+	encoder = mdp5_encoder_init(dev, &intf);
+	if (IS_ERR(encoder)) {
+		ret = PTR_ERR(encoder);
+		dev_err(dev->dev, "failed to construct encoder: %d\n", ret);
+		return ret;
+	}
+
+	encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
+	priv->encoders[priv->num_encoders++] = encoder;
+
+	if (intf_type == INTF_HDMI) {
+		ret = hdmi_modeset_init(priv->hdmi, dev, encoder);
+		if (ret)
+			dev_err(dev->dev, "failed to init HDMI: %d\n", ret);
+
+	} else if (intf_type == INTF_eDP) {
+		/* Construct bridge/connector for eDP: */
+		ret = msm_edp_modeset_init(priv->edp, dev, encoder);
+		if (ret)
+			dev_err(dev->dev, "failed to init eDP: %d\n", ret);
+	}
+
+	return ret;
+}
+
 static int modeset_init(struct mdp5_kms *mdp5_kms)
 {
 	static const enum mdp5_pipe crtcs[] = {
@@ -171,7 +209,6 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 	};
 	struct drm_device *dev = mdp5_kms->dev;
 	struct msm_drm_private *priv = dev->dev_private;
-	struct drm_encoder *encoder;
 	const struct mdp5_cfg_hw *hw_cfg;
 	int i, ret;
 
@@ -222,56 +259,29 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 		}
 	}
 
-	if (priv->hdmi) {
-		struct mdp5_interface intf = {
-				.num	= 3,
-				.type	= INTF_HDMI,
-				.mode	= MDP5_INTF_MODE_NONE,
-		};
-
-		/* Construct encoder for HDMI: */
-		encoder = mdp5_encoder_init(dev, &intf);
-		if (IS_ERR(encoder)) {
-			dev_err(dev->dev, "failed to construct encoder\n");
-			ret = PTR_ERR(encoder);
-			goto fail;
-		}
-
-		encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;;
-		priv->encoders[priv->num_encoders++] = encoder;
-
-		ret = hdmi_modeset_init(priv->hdmi, dev, encoder);
-		if (ret) {
-			dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret);
-			goto fail;
-		}
-	}
-
-	if (priv->edp) {
-		struct mdp5_interface intf = {
-				.num	= 0,
-				.type	= INTF_eDP,
-				.mode	= MDP5_INTF_MODE_NONE,
-		};
-
-		/* Construct encoder for eDP: */
-		encoder = mdp5_encoder_init(dev, &intf);
-		if (IS_ERR(encoder)) {
-			dev_err(dev->dev, "failed to construct eDP encoder\n");
-			ret = PTR_ERR(encoder);
-			goto fail;
+	/* Construct external display interfaces' encoders: */
+	for (i = 0; i < ARRAY_SIZE(hw_cfg->intfs); i++) {
+		enum mdp5_intf_type intf_type = hw_cfg->intfs[i];
+
+		switch (intf_type) {
+		case INTF_DISABLED:
+			break;
+		case INTF_eDP:
+			if (priv->edp)
+				ret = construct_encoder(mdp5_kms, INTF_eDP, i);
+			break;
+		case INTF_HDMI:
+			if (priv->hdmi)
+				ret = construct_encoder(mdp5_kms, INTF_HDMI, i);
+			break;
+		default:
+			dev_err(dev->dev, "unknown intf: %d\n", intf_type);
+			ret = -EINVAL;
+			break;
 		}
 
-		encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
-		priv->encoders[priv->num_encoders++] = encoder;
-
-		/* Construct bridge/connector for eDP: */
-		ret = msm_edp_modeset_init(priv->edp, dev, encoder);
-		if (ret) {
-			dev_err(dev->dev, "failed to initialize eDP: %d\n",
-									ret);
+		if (ret)
 			goto fail;
-		}
 	}
 
 	return 0;
@@ -415,8 +425,11 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
 	 * we don't disable):
 	 */
 	mdp5_enable(mdp5_kms);
-	for (i = 0; i < config->hw->intf.count; i++)
+	for (i = 0; i < MDP5_INTF_NUM_MAX; i++) {
+		if (MDP5_INTF_IS_VIRTUAL_DISPLAY(config->hw->intfs[i]))
+			continue;
 		mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(i), 0);
+	}
 	mdp5_disable(mdp5_kms);
 	mdelay(16);
 
-- 
Qualcomm Innovation Center, Inc.

The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project


  parent reply	other threads:[~2015-03-03 18:36 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-03 18:36 [PATCH 0/4] drm/msm: preparation for WB/DSI connectors Stephane Viau
2015-03-03 18:36 ` [PATCH 1/4] drm/msm/mdp5: Update generated header files Stephane Viau
2015-03-03 18:36   ` Stephane Viau
2015-03-03 18:37   ` [PATCH] rnndb: Prepare for more interfaces support (WB, DSI) Stephane Viau
2015-03-03 18:37     ` Stephane Viau
2015-03-03 18:36 ` [PATCH 2/4] drm/msm/mdp5: Enhance operation mode for pipeline configuration Stephane Viau
2015-03-03 18:36   ` Stephane Viau
2015-03-04  6:22   ` Archit Taneja
2015-03-04  6:22     ` Archit Taneja
2015-03-03 18:36 ` [PATCH 3/4] drm/msm/mdp5: Add START signal to kick off certain pipelines Stephane Viau
2015-03-03 18:36   ` Stephane Viau
2015-03-03 18:36 ` Stephane Viau [this message]
2015-03-03 18:36   ` [PATCH 4/4] drm/msm/mdp5: Make the intf connection in config module Stephane Viau
2015-03-04  6:13   ` Archit Taneja
2015-03-04  6:13     ` Archit Taneja
2015-03-04 15:44     ` "Stéphane Viau"
2015-03-04 15:44       ` "Stéphane Viau"
2015-03-05  4:03       ` Archit Taneja
2015-03-05 14:59 ` [PATCH v2 0/4] drm/msm: preparation for WB/DSI connectors Stephane Viau
2015-03-05 14:59   ` [PATCH v2 1/4] drm/msm/mdp5: Update generated header files Stephane Viau
2015-03-05 14:59     ` Stephane Viau
2015-03-05 14:59   ` [PATCH v2 2/4] drm/msm/mdp5: Enhance operation mode for pipeline configuration Stephane Viau
2015-03-05 14:59     ` Stephane Viau
2015-03-05 14:59   ` [PATCH v2 3/4] drm/msm/mdp5: Add START signal to kick off certain pipelines Stephane Viau
2015-03-05 14:59   ` [PATCH v2 4/4] drm/msm/mdp5: Make the intf connection in config module Stephane Viau
2015-03-05 14:59     ` Stephane Viau
2015-03-09 13:11 ` [PATCH 0/5] drm/msm: Add display configuration for msm8x16 Stephane Viau
2015-03-09 13:11   ` [PATCH 1/5] drm/msm/mdp5: Update headers (introduce MDP5 domain) Stephane Viau
2015-03-09 13:11   ` [PATCH 2/5] drm/msm/mdp5: Separate MDP5 domain from MDSS domain Stephane Viau
2015-03-09 13:11   ` [PATCH 3/5] drm/msm/mdp5: Update headers (remove enum mdp5_client_id) Stephane Viau
2015-03-09 13:11   ` [PATCH 4/5] drm/msm/mdp5: Get SMP client list from mdp5_cfg Stephane Viau
2015-03-09 13:11   ` [PATCH 5/5] drm/msm/mdp5: Add hardware configuration for msm8x16 Stephane Viau
2015-03-12  9:04     ` Archit Taneja
2015-03-12  9:04       ` Archit Taneja
2015-03-13 19:45       ` "Stéphane Viau"
2015-03-13 19:49         ` [PATCH v3 0/4] drm/msm: preparation for WB/DSI connectors Stephane Viau
2015-03-13 19:49           ` [PATCH v3 1/4] drm/msm/mdp5: Update generated header files Stephane Viau
2015-03-13 19:49             ` Stephane Viau
2015-03-13 19:49           ` [PATCH v3 2/4] drm/msm/mdp5: Enhance operation mode for pipeline configuration Stephane Viau
2015-03-13 19:49           ` [PATCH v3 3/4] drm/msm/mdp5: Add START signal to kick off certain pipelines Stephane Viau
2015-03-13 19:49             ` Stephane Viau
2015-03-23 10:50             ` Archit Taneja
2015-03-23 10:50               ` Archit Taneja
2015-03-23 22:10               ` "Stéphane Viau"
2015-03-23 22:10                 ` "Stéphane Viau"
2015-03-24  4:47                 ` Archit Taneja
2015-03-13 19:49           ` [PATCH v3 4/4] drm/msm/mdp5: Make the intf connection in config module Stephane Viau
2015-03-13 19:49             ` Stephane Viau
2015-03-16  5:03         ` [PATCH 5/5] drm/msm/mdp5: Add hardware configuration for msm8x16 Archit Taneja
2015-03-16  5:03           ` Archit Taneja
2015-03-09 13:12   ` [PATCH 1/2] rnndb: Separate MDP5 domain from MDSS domain Stephane Viau
2015-03-09 13:12     ` [PATCH 2/2] rnndb: Do not use enum mdp5_client_id to configure SMP Stephane Viau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1425407775-7704-5-git-send-email-sviau@codeaurora.org \
    --to=sviau@codeaurora.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.