All of lore.kernel.org
 help / color / mirror / Atom feed
From: roy-cw.yeh <roy-cw.yeh@mediatek.com>
To: Rob Herring <robh+dt@kernel.org>,
	Matthias Brugger <matthias.bgg@gmail.com>,
	AngeloGioacchino Del Regno
	<angelogioacchino.delregno@collabora.com>,
	Chun-Kuang Hu <chunkuang.hu@kernel.org>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>,
	Fabien Parent <fparent@baylibre.com>,
	"Roy-CW . Yeh" <roy-cw.yeh@mediatek.com>,
	"jason-jh . lin" <jason-jh.lin@mediatek.com>,
	daoyuan huang <daoyuan.huang@mediatek.com>,
	 Ping-Hsun Wu <ping-hsun.wu@mediatek.com>,
	Moudy Ho <moudy.ho@mediatek.com>,
	"river . cheng" <river.cheng@mediatek.com>,
	Enric Balletbo i Serra <enric.balletbo@collabora.com>,
	Yongqiang Niu <yongqiang.niu@mediatek.com>,
	<devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<linux-media@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-mediatek@lists.infradead.org>
Subject: [PATCH v1 11/14] media: platform: mtk-mdp3: Revise frame change criteria
Date: Mon, 17 Jan 2022 13:52:51 +0800	[thread overview]
Message-ID: <20220117055254.9777-12-roy-cw.yeh@mediatek.com> (raw)
In-Reply-To: <20220117055254.9777-1-roy-cw.yeh@mediatek.com>

From: "Roy-CW.Yeh" <roy-cw.yeh@mediatek.com>

frame_change will trigger MDP SCP to re-calculate path and parameter.
MDP fails when it doesn't get correct parameters to process frame,
and it will activate by the following conditions:

1. first frame
2. Scenario changes (single/dual pipe)
3. input size changes
4. input format changes
5. output size changes (crop included)

Signed-off-by: Roy-CW.Yeh <roy-cw.yeh@mediatek.com>
---
 .../media/platform/mtk-mdp3/mtk-mdp3-core.h   |  2 ++
 .../media/platform/mtk-mdp3/mtk-mdp3-m2m.c    | 22 +++++++++++++++----
 .../media/platform/mtk-mdp3/mtk-mdp3-regs.c   | 19 ++++++++++++++++
 .../media/platform/mtk-mdp3/mtk-mdp3-regs.h   |  9 ++++++++
 4 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h
index 0fb932ad3560..0eb08ce69781 100644
--- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h
+++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h
@@ -11,6 +11,7 @@
 #include <media/v4l2-mem2mem.h>
 #include <linux/soc/mediatek/mtk-mmsys.h>
 #include <linux/soc/mediatek/mtk-mutex.h>
+#include "mtk-mdp3-regs.h"
 #include "mtk-mdp3-comp.h"
 #include "mtk-mdp3-vpu.h"
 
@@ -96,6 +97,7 @@ struct mdp_dev {
 	atomic_t				suspended;
 	atomic_t				job_count;
 	atomic_t				cmdq_count[MDP_CMDQ_NUM];
+	struct mdp_framechange_param		prev_image;
 };
 
 struct mdp_pipe_info {
diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c
index 72a1864d880c..9afe56882208 100644
--- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c
+++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c
@@ -77,6 +77,7 @@ static void mdp_m2m_worker(struct work_struct *work)
 	struct vb2_v4l2_buffer *src_vb, *dst_vb;
 	struct img_ipi_frameparam param = {0};
 	struct mdp_cmdq_param task = {0};
+	struct mdp_framechange_param cur_frame = {0};
 	enum vb2_buffer_state vb_state = VB2_BUF_STATE_ERROR;
 	int ret;
 
@@ -90,20 +91,33 @@ static void mdp_m2m_worker(struct work_struct *work)
 	param.type = ctx->curr_param.type;
 	param.num_inputs = 1;
 	param.num_outputs = 1;
-	param.frame_change = (ctx->frame_count[MDP_M2M_SRC] == 0);
 
 	frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 	src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
 	mdp_set_src_config(&param.inputs[0], frame, &src_vb->vb2_buf);
 	mdp_set_scenario(ctx->mdp_dev, &param, frame);
-	if (param.frame_change)
-		dev_info(&ctx->mdp_dev->pdev->dev,
-			 "MDP Scenario: %d\n", param.type);
 
 	frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 	dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
 	mdp_set_dst_config(&param.outputs[0], frame, &dst_vb->vb2_buf);
 
+	cur_frame.scenario = param.type;
+	cur_frame.frame_count = ctx->frame_count[MDP_M2M_SRC];
+	memcpy(&cur_frame.in, &param.inputs[0], sizeof(cur_frame.in));
+	memcpy(&cur_frame.out, &param.outputs[0], sizeof(cur_frame.out));
+
+	if (mdp_is_framechange(&ctx->mdp_dev->prev_image, &cur_frame)) {
+		memcpy(&ctx->mdp_dev->prev_image, &cur_frame,
+		       sizeof(struct mdp_framechange_param));
+		param.frame_change = true;
+	} else {
+		param.frame_change = false;
+	}
+
+	if (param.frame_change)
+		dev_dbg(&ctx->mdp_dev->pdev->dev,
+			"MDP Scenario: %d\n", param.type);
+
 	param.timestamp = src_vb->vb2_buf.timestamp;
 
 	ret = mdp_vpu_process(&ctx->vpu, &param);
diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c
index c0a7e3569853..ccd9c338ff49 100644
--- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c
+++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c
@@ -429,6 +429,25 @@ static u32 mdp_fmt_get_plane_size(const struct mdp_format *fmt,
 	return 0;
 }
 
+bool mdp_is_framechange(struct mdp_framechange_param *prev,
+			struct mdp_framechange_param *cur)
+{
+	if (cur->frame_count == 0 ||
+	    prev->scenario != cur->scenario ||
+	    prev->in.buffer.format.colorformat != cur->in.buffer.format.colorformat ||
+	    prev->in.buffer.format.width != cur->in.buffer.format.width ||
+	    prev->in.buffer.format.height != cur->in.buffer.format.height ||
+	    prev->out.buffer.format.width != cur->out.buffer.format.width ||
+	    prev->out.buffer.format.height != cur->out.buffer.format.height ||
+	    prev->out.crop.left != cur->out.crop.left ||
+	    prev->out.crop.top != cur->out.crop.top ||
+	    prev->out.crop.width != cur->out.crop.width ||
+	    prev->out.crop.height != cur->out.crop.height)
+		return true;
+
+	return false;
+}
+
 void mdp_set_scenario(struct mdp_dev *mdp,
 		      struct img_ipi_frameparam *param,
 		      struct mdp_frame *frame)
diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h
index 3547ce10948f..436d5c899bc5 100644
--- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h
+++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h
@@ -397,6 +397,13 @@ struct mdp_frameparam {
 	enum v4l2_quantization		quant;
 };
 
+struct mdp_framechange_param {
+	u8 scenario;
+	u32 frame_count;
+	struct img_input in;
+	struct img_output out;
+};
+
 int mdp_enum_fmt_mplane(struct v4l2_fmtdesc *f);
 const struct mdp_format *mdp_try_fmt_mplane(struct v4l2_format *f,
 					    struct mdp_frameparam *param,
@@ -408,6 +415,8 @@ int mdp_try_crop(struct mdp_m2m_ctx *ctx, struct v4l2_rect *r,
 int mdp_check_scaling_ratio(const struct v4l2_rect *crop,
 			    const struct v4l2_rect *compose, s32 rotation,
 	const struct mdp_limit *limit);
+bool mdp_is_framechange(struct mdp_framechange_param *prev,
+			struct mdp_framechange_param *cur);
 void mdp_set_scenario(struct mdp_dev *mdp,
 		      struct img_ipi_frameparam *param,
 		      struct mdp_frame *frame);
-- 
2.18.0


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

WARNING: multiple messages have this Message-ID (diff)
From: roy-cw.yeh <roy-cw.yeh@mediatek.com>
To: Rob Herring <robh+dt@kernel.org>,
	Matthias Brugger <matthias.bgg@gmail.com>,
	AngeloGioacchino Del Regno
	<angelogioacchino.delregno@collabora.com>,
	Chun-Kuang Hu <chunkuang.hu@kernel.org>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>,
	Fabien Parent <fparent@baylibre.com>,
	"Roy-CW . Yeh" <roy-cw.yeh@mediatek.com>,
	"jason-jh . lin" <jason-jh.lin@mediatek.com>,
	daoyuan huang <daoyuan.huang@mediatek.com>,
	 Ping-Hsun Wu <ping-hsun.wu@mediatek.com>,
	Moudy Ho <moudy.ho@mediatek.com>,
	"river . cheng" <river.cheng@mediatek.com>,
	Enric Balletbo i Serra <enric.balletbo@collabora.com>,
	Yongqiang Niu <yongqiang.niu@mediatek.com>,
	<devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<linux-media@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-mediatek@lists.infradead.org>
Subject: [PATCH v1 11/14] media: platform: mtk-mdp3: Revise frame change criteria
Date: Mon, 17 Jan 2022 13:52:51 +0800	[thread overview]
Message-ID: <20220117055254.9777-12-roy-cw.yeh@mediatek.com> (raw)
In-Reply-To: <20220117055254.9777-1-roy-cw.yeh@mediatek.com>

From: "Roy-CW.Yeh" <roy-cw.yeh@mediatek.com>

frame_change will trigger MDP SCP to re-calculate path and parameter.
MDP fails when it doesn't get correct parameters to process frame,
and it will activate by the following conditions:

1. first frame
2. Scenario changes (single/dual pipe)
3. input size changes
4. input format changes
5. output size changes (crop included)

Signed-off-by: Roy-CW.Yeh <roy-cw.yeh@mediatek.com>
---
 .../media/platform/mtk-mdp3/mtk-mdp3-core.h   |  2 ++
 .../media/platform/mtk-mdp3/mtk-mdp3-m2m.c    | 22 +++++++++++++++----
 .../media/platform/mtk-mdp3/mtk-mdp3-regs.c   | 19 ++++++++++++++++
 .../media/platform/mtk-mdp3/mtk-mdp3-regs.h   |  9 ++++++++
 4 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h
index 0fb932ad3560..0eb08ce69781 100644
--- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h
+++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-core.h
@@ -11,6 +11,7 @@
 #include <media/v4l2-mem2mem.h>
 #include <linux/soc/mediatek/mtk-mmsys.h>
 #include <linux/soc/mediatek/mtk-mutex.h>
+#include "mtk-mdp3-regs.h"
 #include "mtk-mdp3-comp.h"
 #include "mtk-mdp3-vpu.h"
 
@@ -96,6 +97,7 @@ struct mdp_dev {
 	atomic_t				suspended;
 	atomic_t				job_count;
 	atomic_t				cmdq_count[MDP_CMDQ_NUM];
+	struct mdp_framechange_param		prev_image;
 };
 
 struct mdp_pipe_info {
diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c
index 72a1864d880c..9afe56882208 100644
--- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c
+++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-m2m.c
@@ -77,6 +77,7 @@ static void mdp_m2m_worker(struct work_struct *work)
 	struct vb2_v4l2_buffer *src_vb, *dst_vb;
 	struct img_ipi_frameparam param = {0};
 	struct mdp_cmdq_param task = {0};
+	struct mdp_framechange_param cur_frame = {0};
 	enum vb2_buffer_state vb_state = VB2_BUF_STATE_ERROR;
 	int ret;
 
@@ -90,20 +91,33 @@ static void mdp_m2m_worker(struct work_struct *work)
 	param.type = ctx->curr_param.type;
 	param.num_inputs = 1;
 	param.num_outputs = 1;
-	param.frame_change = (ctx->frame_count[MDP_M2M_SRC] == 0);
 
 	frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 	src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
 	mdp_set_src_config(&param.inputs[0], frame, &src_vb->vb2_buf);
 	mdp_set_scenario(ctx->mdp_dev, &param, frame);
-	if (param.frame_change)
-		dev_info(&ctx->mdp_dev->pdev->dev,
-			 "MDP Scenario: %d\n", param.type);
 
 	frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 	dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
 	mdp_set_dst_config(&param.outputs[0], frame, &dst_vb->vb2_buf);
 
+	cur_frame.scenario = param.type;
+	cur_frame.frame_count = ctx->frame_count[MDP_M2M_SRC];
+	memcpy(&cur_frame.in, &param.inputs[0], sizeof(cur_frame.in));
+	memcpy(&cur_frame.out, &param.outputs[0], sizeof(cur_frame.out));
+
+	if (mdp_is_framechange(&ctx->mdp_dev->prev_image, &cur_frame)) {
+		memcpy(&ctx->mdp_dev->prev_image, &cur_frame,
+		       sizeof(struct mdp_framechange_param));
+		param.frame_change = true;
+	} else {
+		param.frame_change = false;
+	}
+
+	if (param.frame_change)
+		dev_dbg(&ctx->mdp_dev->pdev->dev,
+			"MDP Scenario: %d\n", param.type);
+
 	param.timestamp = src_vb->vb2_buf.timestamp;
 
 	ret = mdp_vpu_process(&ctx->vpu, &param);
diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c
index c0a7e3569853..ccd9c338ff49 100644
--- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c
+++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.c
@@ -429,6 +429,25 @@ static u32 mdp_fmt_get_plane_size(const struct mdp_format *fmt,
 	return 0;
 }
 
+bool mdp_is_framechange(struct mdp_framechange_param *prev,
+			struct mdp_framechange_param *cur)
+{
+	if (cur->frame_count == 0 ||
+	    prev->scenario != cur->scenario ||
+	    prev->in.buffer.format.colorformat != cur->in.buffer.format.colorformat ||
+	    prev->in.buffer.format.width != cur->in.buffer.format.width ||
+	    prev->in.buffer.format.height != cur->in.buffer.format.height ||
+	    prev->out.buffer.format.width != cur->out.buffer.format.width ||
+	    prev->out.buffer.format.height != cur->out.buffer.format.height ||
+	    prev->out.crop.left != cur->out.crop.left ||
+	    prev->out.crop.top != cur->out.crop.top ||
+	    prev->out.crop.width != cur->out.crop.width ||
+	    prev->out.crop.height != cur->out.crop.height)
+		return true;
+
+	return false;
+}
+
 void mdp_set_scenario(struct mdp_dev *mdp,
 		      struct img_ipi_frameparam *param,
 		      struct mdp_frame *frame)
diff --git a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h
index 3547ce10948f..436d5c899bc5 100644
--- a/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h
+++ b/drivers/media/platform/mtk-mdp3/mtk-mdp3-regs.h
@@ -397,6 +397,13 @@ struct mdp_frameparam {
 	enum v4l2_quantization		quant;
 };
 
+struct mdp_framechange_param {
+	u8 scenario;
+	u32 frame_count;
+	struct img_input in;
+	struct img_output out;
+};
+
 int mdp_enum_fmt_mplane(struct v4l2_fmtdesc *f);
 const struct mdp_format *mdp_try_fmt_mplane(struct v4l2_format *f,
 					    struct mdp_frameparam *param,
@@ -408,6 +415,8 @@ int mdp_try_crop(struct mdp_m2m_ctx *ctx, struct v4l2_rect *r,
 int mdp_check_scaling_ratio(const struct v4l2_rect *crop,
 			    const struct v4l2_rect *compose, s32 rotation,
 	const struct mdp_limit *limit);
+bool mdp_is_framechange(struct mdp_framechange_param *prev,
+			struct mdp_framechange_param *cur);
 void mdp_set_scenario(struct mdp_dev *mdp,
 		      struct img_ipi_frameparam *param,
 		      struct mdp_frame *frame);
-- 
2.18.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2022-01-17  5:53 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-17  5:52 [PATCH v1 00/14] Add mdp support for mt8195 roy-cw.yeh
2022-01-17  5:52 ` roy-cw.yeh
2022-01-17  5:52 ` [PATCH v1 01/14] soc: mediatek: mmsys: expand MDP enum for chip independence architecture roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-01-17  5:52 ` [PATCH v1 02/14] soc: mediatek: mutex: expand parameter for mdp mutex function roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-03-18  9:23   ` CK Hu
2022-03-18  9:23     ` CK Hu
2022-01-17  5:52 ` [PATCH v1 03/14] soc: mediatek: mmsys: support mt8195 vppsys0/1 roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-03-18  8:58   ` CK Hu
2022-03-18  8:58     ` CK Hu
2022-01-17  5:52 ` [PATCH v1 04/14] soc: mediatek: mutex: " roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-01-17  5:52 ` [PATCH v1 05/14] media: platform: mtk-mdp3: add chip independence architecture roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-01-17  5:52 ` [PATCH v1 06/14] media: platform: mtk-mdp3: Modify mtk-img-ipi.h for MT8195 SCP roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-01-27 15:02   ` AngeloGioacchino Del Regno
2022-01-27 15:02     ` AngeloGioacchino Del Regno
2022-01-27 15:02     ` AngeloGioacchino Del Regno
2022-01-17  5:52 ` [PATCH v1 07/14] media: platform: mtk-mdp3: Add platform configuration for MT8195 roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-01-17  5:52 ` [PATCH v1 08/14] media: platform: mtk-mdp3: Add engine setting " roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-01-17  5:52 ` [PATCH v1 09/14] media: platform: mtk-mdp3: Add support MT8195 roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-01-17  5:52 ` [PATCH v1 10/14] media: platform: mtk-mdp3: Add dual pipe feature support roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-01-17  5:52 ` roy-cw.yeh [this message]
2022-01-17  5:52   ` [PATCH v1 11/14] media: platform: mtk-mdp3: Revise frame change criteria roy-cw.yeh
2022-01-17  5:52 ` [PATCH v1 12/14] media: platform: mtk-mdp3: Reconfigure shared memory roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-01-17  5:52 ` [PATCH v1 13/14] arm64: dts: mt8195: add mdp3 node roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-01-17  5:52 ` [PATCH v1 14/14] dt-bindings: media: mediatek: mdp3: add yaml for new modules added in mt8195 roy-cw.yeh
2022-01-17  5:52   ` roy-cw.yeh
2022-01-21 21:06   ` Rob Herring
2022-01-21 21:06     ` Rob Herring

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=20220117055254.9777-12-roy-cw.yeh@mediatek.com \
    --to=roy-cw.yeh@mediatek.com \
    --cc=angelogioacchino.delregno@collabora.com \
    --cc=chunkuang.hu@kernel.org \
    --cc=daoyuan.huang@mediatek.com \
    --cc=devicetree@vger.kernel.org \
    --cc=enric.balletbo@collabora.com \
    --cc=fparent@baylibre.com \
    --cc=jason-jh.lin@mediatek.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=matthias.bgg@gmail.com \
    --cc=mchehab@kernel.org \
    --cc=moudy.ho@mediatek.com \
    --cc=ping-hsun.wu@mediatek.com \
    --cc=river.cheng@mediatek.com \
    --cc=robh+dt@kernel.org \
    --cc=yongqiang.niu@mediatek.com \
    /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.