From: Jingoo Han <jg1.han@samsung.com>
To: linux-fbdev@vger.kernel.org
Subject: Re: [PATCH 1/4] video: mmp display subsystem
Date: Thu, 30 Aug 2012 01:37:17 +0000 [thread overview]
Message-ID: <001401cd864f$fd91edb0$f8b5c910$%han@samsung.com> (raw)
In-Reply-To: <1346234684-12532-1-git-send-email-zzhu3@marvell.com>
On Wednesday, August 29, 2012 7:05 PM Zhou Zhu wrote:
>
> Added mmp display subsystem to support Marvell MMP display controllers.
>
> This subsystem contains 4 parts:
> --fb folder
> --core.c
> --hw folder
> --panel folder
>
> 1. fb folder contains implementation of fb.
> fb get path and ovly from common interface and operates on these structures.
>
> 2. core.c provides common interface for a hardware abstraction.
> Major parts of this interface are:
> a) Path: path is a output device connected to a panel or HDMI TV.
> Main operations of the path is set/get timing/output color.
> fb operates output device through path structure.
> b) Ovly: Ovly is a buffer shown on the path.
> Ovly describes frame buffer and its source/destination size, offset, input
> color, buffer address, z-order, and so on.
> Each fb device maps to one ovly.
>
> 3. hw folder contains implementation of hardware operations defined by core.c.
> It registers paths for fb use.
>
> 4. panel folder contains implementation of panels.
> It's connected to path. Panel drivers would also regiester panels and linked
> to path when probe.
>
> Change-Id: I830e34af9aad3196c2db021b4fb90ceeafbf73d2
Please remove unnecessary 'Change-Id'.
> Signed-off-by: Zhou Zhu <zzhu3@marvell.com>
> Signed-off-by: Lisa Du <cldu@marvell.com>
> ---
> drivers/video/Kconfig | 1 +
> drivers/video/Makefile | 1 +
> drivers/video/mmp/Kconfig | 5 +
> drivers/video/mmp/Makefile | 1 +
> drivers/video/mmp/core.c | 217 +++++++++++++++++++++++++
> include/video/mmp_disp.h | 381 ++++++++++++++++++++++++++++++++++++++++++++
> 6 files changed, 606 insertions(+), 0 deletions(-)
> create mode 100644 drivers/video/mmp/Kconfig
> create mode 100644 drivers/video/mmp/Makefile
> create mode 100644 drivers/video/mmp/core.c
> create mode 100644 include/video/mmp_disp.h
>
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index 0217f74..b71a5c9 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -2447,6 +2447,7 @@ config FB_PUV3_UNIGFX
> source "drivers/video/omap/Kconfig"
> source "drivers/video/omap2/Kconfig"
> source "drivers/video/exynos/Kconfig"
> +source "drivers/video/mmp/Kconfig"
> source "drivers/video/backlight/Kconfig"
>
> if VT
> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> index ee8dafb..6b0ae31 100644
> --- a/drivers/video/Makefile
> +++ b/drivers/video/Makefile
> @@ -106,6 +106,7 @@ obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
> obj-$(CONFIG_FB_PXA) += pxafb.o
> obj-$(CONFIG_FB_PXA168) += pxa168fb.o
> obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o
> +obj-$(CONFIG_MMP_DISP) += mmp/
> obj-$(CONFIG_FB_W100) += w100fb.o
> obj-$(CONFIG_FB_TMIO) += tmiofb.o
> obj-$(CONFIG_FB_AU1100) += au1100fb.o
> diff --git a/drivers/video/mmp/Kconfig b/drivers/video/mmp/Kconfig
> new file mode 100644
> index 0000000..0554336
> --- /dev/null
> +++ b/drivers/video/mmp/Kconfig
> @@ -0,0 +1,5 @@
> +menuconfig MMP_DISP
> + tristate "Marvell MMP Display Subsystem support"
> + depends on CPU_PXA910 || CPU_MMP2 || CPU_MMP3 || CPU_PXA988
> + help
> + Marvell Display Subsystem support.
> diff --git a/drivers/video/mmp/Makefile b/drivers/video/mmp/Makefile
> new file mode 100644
> index 0000000..820eb10
> --- /dev/null
> +++ b/drivers/video/mmp/Makefile
> @@ -0,0 +1 @@
> +obj-y += core.o
> diff --git a/drivers/video/mmp/core.c b/drivers/video/mmp/core.c
> new file mode 100644
> index 0000000..b2e7433
> --- /dev/null
> +++ b/drivers/video/mmp/core.c
> @@ -0,0 +1,217 @@
> +/*
> + * linux/drivers/video/mmp/common.c
> + * This driver is a common framework for Marvell Display Controller
> + *
> + * Copyright (C) 2012 Marvell Technology Group Ltd.
> + * Authors: Zhou Zhu <zzhu3@marvell.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/export.h>
> +#include <video/mmp_disp.h>
> +
> +static struct mmp_ovly *path_get_ovly(struct mmp_path *path,
> + int ovly_id)
> +{
> + if (path && ovly_id < path->ovly_num)
> + return &path->ovlys[ovly_id];
> + return 0;
> +}
> +
> +static int path_check_status(struct mmp_path *path)
> +{
> + int i;
> + for (i = 0; i < path->ovly_num; i++)
> + if (path->ovlys[i].status)
> + return 1;
> +
> + return 0;
> +}
> +
> +/*
> + * Get modelist write pointer of modelist.
> + * It also returns modelist number
> + * this function fetches modelist from phy/panel:
> + * for HDMI/parallel or dsi to hdmi cases, get from phy
> + * or get from panel
> + */
> +static int path_get_modelist(struct mmp_path *path,
> + struct mmp_mode **modelist)
> +{
> + BUG_ON(!path || !modelist);
> +
> + if (path->panel && path->panel->get_modelist)
> + return path->panel->get_modelist(path->panel, modelist);
> +
> + return 0;
> +}
> +
> +#define list_find(_item, _list, _field, _name) \
> + do {\
> + int found = 0;\
> + list_for_each_entry(_item, &_list, node) {\
> + dev_dbg(_item->dev, "checking %s, target %s",\
> + _item->_field, _name);\
> + if (strcmp(_name, _item->_field) = 0) {\
> + found = 1;\
> + break;\
> + } \
> + } \
> + if (!found)\
> + _item = NULL;\
> + } while (0);
It makes checkpatch warning as below.
WARNING: do {} while (0) macros should not be semicolon terminated
Please remove semicolon as below.
} while (0)
> +
> +/*
> + * panel list is used to pair panel/path when path/panel registered
> + * path list is used for both buffer driver and platdriver
> + * plat driver do path register/unregister
> + * panel driver do panel register/unregister
> + * buffer driver get registered path
> + */
> +static LIST_HEAD(panel_list);
> +static LIST_HEAD(path_list);
> +static DEFINE_MUTEX(disp_lock);
> +
> +int mmp_register_panel(struct mmp_panel *panel)
> +{
> + struct mmp_path *path;
> +
> + mutex_lock(&disp_lock);
> +
> + /* add */
> + list_add_tail(&panel->node, &panel_list);
> +
> + /* try to register to path */
> + list_find(path, path_list, name, panel->plat_path_name);
> + if (path) {
> + dev_info(panel->dev, "register to path %s\n",
> + panel->plat_path_name);
> + path->panel = panel;
> + }
> +
> + mutex_unlock(&disp_lock);
> + return 1;
> +}
> +EXPORT_SYMBOL_GPL(mmp_register_panel);
> +
> +void mmp_unregister_panel(struct mmp_panel *panel)
> +{
> + mutex_lock(&disp_lock);
> + list_del(&panel->node);
> + mutex_unlock(&disp_lock);
> +}
> +EXPORT_SYMBOL_GPL(mmp_unregister_panel);
> +
> +struct mmp_path *mmp_get_path(const char *name)
> +{
> + struct mmp_path *path;
> +
> + mutex_lock(&disp_lock);
> + list_find(path, path_list, name, name);
> + mutex_unlock(&disp_lock);
> +
> + return path;
> +}
> +EXPORT_SYMBOL_GPL(mmp_get_path);
> +
> +struct mmp_path *mmp_register_path(struct mmp_path_info *info)
> +{
> + int i, size;
> + struct mmp_path *path = NULL;
> + struct mmp_panel *panel;
> +
> + size = sizeof(struct mmp_path)
> + + sizeof(struct mmp_ovly) * info->ovly_num;
> + path = kzalloc(size, GFP_KERNEL);
> + if (!path)
> + goto failed;
> +
> + /* path set */
> + path->ovlys = (void *)path + sizeof(struct mmp_path);
> + mutex_init(&path->access_ok);
> + path->dev = info->dev;
> + path->id = info->id;
> + path->name = info->name;
> + path->output_type = info->output_type;
> + path->ovly_num = info->ovly_num;
> + path->plat_data = info->plat_data;
> + path->ops.set_mode = info->set_mode;
> +
> + mutex_lock(&disp_lock);
> + /* get panel */
> + list_find(panel, panel_list, plat_path_name, info->name);
> + if (panel) {
> + dev_info(path->dev, "get panel %s\n", panel->name);
> + path->panel = panel;
> + }
> +
> + dev_info(path->dev, "register %s, ovly_num %d\n",
> + path->name, path->ovly_num);
> +
> + /* default op set: if already set by driver, never cover it */
> + if (!path->ops.check_status)
> + path->ops.check_status = path_check_status;
> + if (!path->ops.get_ovly)
> + path->ops.get_ovly = path_get_ovly;
> + if (!path->ops.get_modelist)
> + path->ops.get_modelist = path_get_modelist;
> +
> + /* step3: init ovlys */
> + for (i = 0; i < path->ovly_num; i++) {
> + path->ovlys[i].path = path;
> + path->ovlys[i].id = i;
> + mutex_init(&path->ovlys[i].access_ok);
> + path->ovlys[i].ops = info->ovly_ops;
> + }
> +
> + /* add to pathlist */
> + list_add_tail(&path->node, &path_list);
> +
> + mutex_unlock(&disp_lock);
> + return path;
> +
> +failed:
> + kfree(path);
> + mutex_unlock(&disp_lock);
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(mmp_register_path);
> +
> +void mmp_unregister_path(struct mmp_path *path)
> +{
> + int i;
> +
> + if (!path)
> + return;
> +
> + mutex_lock(&disp_lock);
> + /* del from pathlist */
> + list_del(&path->node);
> +
> + /* deinit ovlys */
> + for (i = 0; i < path->ovly_num; i++)
> + mutex_destroy(&path->ovlys[i].access_ok);
> +
> + mutex_destroy(&path->access_ok);
> +
> + kfree(path);
> + mutex_unlock(&disp_lock);
> +
> + dev_info(path->dev, "de-register %s\n", path->name);
> +}
> +EXPORT_SYMBOL_GPL(mmp_unregister_path);
> diff --git a/include/video/mmp_disp.h b/include/video/mmp_disp.h
> new file mode 100644
> index 0000000..e7318f9
> --- /dev/null
> +++ b/include/video/mmp_disp.h
> @@ -0,0 +1,381 @@
> +/*
> + * linux/include/video/mmp_disp.h
> + * Header file for Marvell MMP Display Controller
> + *
> + * Copyright (C) 2012 Marvell Technology Group Ltd.
> + * Authors: Zhou Zhu <zzhu3@marvell.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + */
> +
> +#ifndef _MMP_DISP_H_
> +#define _MMP_DISP_H_
> +#include <linux/kthread.h>
> +
> +enum {
> + PIXFMT_UYVY = 0,
> + PIXFMT_VYUY,
> + PIXFMT_YUYV,
> + PIXFMT_YUV422P,
> + PIXFMT_YVU422P,
> + PIXFMT_YUV420P,
> + PIXFMT_YVU420P,
> + PIXFMT_RGB565 = 0x100,
> + PIXFMT_BGR565,
> + PIXFMT_RGB1555,
> + PIXFMT_BGR1555,
> + PIXFMT_RGB888PACK,
> + PIXFMT_BGR888PACK,
> + PIXFMT_RGB888UNPACK,
> + PIXFMT_BGR888UNPACK,
> + PIXFMT_RGBA888,
> + PIXFMT_BGRA888,
> + PIXFMT_RGB666, /* for output usage */
> + PIXFMT_PSEUDOCOLOR = 0x200,
> +};
> +
> +static inline int pixfmt_to_stride(int pix_fmt)
> +{
> + switch (pix_fmt) {
> + case PIXFMT_RGB565:
> + case PIXFMT_BGR565:
> + case PIXFMT_RGB1555:
> + case PIXFMT_BGR1555:
> + case PIXFMT_UYVY:
> + case PIXFMT_VYUY:
> + case PIXFMT_YUYV:
> + return 2;
> + case PIXFMT_RGB888UNPACK:
> + case PIXFMT_BGR888UNPACK:
> + case PIXFMT_RGBA888:
> + case PIXFMT_BGRA888:
> + return 4;
> + case PIXFMT_RGB888PACK:
> + case PIXFMT_BGR888PACK:
> + return 3;
> + case PIXFMT_YUV422P:
> + case PIXFMT_YVU422P:
> + case PIXFMT_YUV420P:
> + case PIXFMT_YVU420P:
> + case PIXFMT_PSEUDOCOLOR:
> + return 1;
> + default:
> + return 0;
> + }
> +}
> +
> +/* parameters used by path/ovly */
> +/* ovly related para: win/addr */
> +struct mmp_win {
> + /* position/size of window */
> + u16 xsrc;
> + u16 ysrc;
> + u16 xdst;
> + u16 ydst;
> + u16 xpos;
> + u16 ypos;
> + u16 left_crop;
> + u16 right_crop;
> + u16 up_crop;
> + u16 bottom_crop;
> + int pix_fmt;
> +};
> +
> +struct mmp_addr {
> + /* phys address */
> + u32 phys[6];
> +};
> +
> +/* path related para: mode */
> +struct mmp_mode {
> + const char *name;
> + u32 refresh;
> + u32 xres;
> + u32 yres;
> + u32 left_margin;
> + u32 right_margin;
> + u32 upper_margin;
> + u32 lower_margin;
> + u32 hsync_len;
> + u32 vsync_len;
> + u32 hsync_invert;
> + u32 vsync_invert;
> + u32 invert_pixclock;
> + u32 pixclock_freq;
> + int pix_fmt_out;
> +};
> +
> +/* main structures */
> +struct mmp_path;
> +struct mmp_ovly;
> +struct mmp_panel;
> +
> +
Please remove unnecessary line.
> +/* status types */
> +enum {
> + mmp_OFF = 0,
> + mmp_ON,
> +};
> +
> +static inline const char *stat_name(int stat)
> +{
> + switch (stat) {
> + case mmp_OFF:
> + return "OFF";
> + case mmp_ON:
> + return "ON";
> + default:
> + return "UNKNOWNSTAT";
> + }
> +}
> +
> +struct mmp_ovly_ops {
> + /* should be provided by driver */
> + void (*set_fetch)(struct mmp_ovly *ovly, int fetch_id);
> + void (*set_onoff)(struct mmp_ovly *ovly, int status);
> + void (*set_win)(struct mmp_ovly *ovly, struct mmp_win *win);
> + int (*set_addr)(struct mmp_ovly *ovly, struct mmp_addr *addr);
> +};
> +
> +/* ovly describes a z-order indexed slot in each path. */
> +struct mmp_ovly {
> + int id;
> + const char *name;
> + struct mmp_path *path;
> +
> + /* ovly info: private data */
> + int dmafetch_id;
> + struct mmp_addr addr;
> + struct mmp_win win;
> +
> + /* state */
> + int open_count;
> + int status;
> + struct mutex access_ok;
> +
> + struct mmp_ovly_ops *ops;
> +};
> +
> +/* panel type */
> +enum {
> + PANELTYPE_Active = 0,
> + PANELTYPE_Smart,
> + PANELTYPE_TV,
> + PANELTYPE_DSI_CMD,
> + PANELTYPE_DSI_VIDEO,
> +};
> +
> +enum {
> + PANEL_CMDS_SPI,
> + PANEL_CMDS_DSI,
> +};
> +
> +/* commands for panel: commands and sleep time in ms */
> +struct mmp_panel_cmds {
> + u16 *cmds;
> + int cmds_num;
> + int sleep;
> +};
> +
> +struct mmp_spi_cfg {
> + u32 clk_cnt;
> + u32 rx_bits;
> + u32 tx_bits;
> + u32 wire_num;
> +};
> +
> +struct mmp_panel_cmd_sets {
> + int type;
> + struct mmp_panel_cmds *on_cmds;
> + int on_cmds_num;
> + struct mmp_panel_cmds *off_cmds;
> + int off_cmds_num;
> + void *config;
> +};
> +
> +struct mmp_panel {
> + /* use node to register to list */
> + struct list_head node;
> + const char *name;
> + /* path name used to connect to proper path configed */
> + const char *plat_path_name;
> + struct device *dev;
> + int panel_type;
> + int (*get_modelist)(struct mmp_panel *panel,
> + struct mmp_mode **modelist);
> + void (*set_mode)(struct mmp_panel *panel,
> + struct mmp_mode *mode);
> + void (*plat_set_onoff)(int status);
> + struct mmp_panel_cmd_sets *cmd_set;
> + /* todo: add query */
> +};
> +
> +struct mmp_path_ops {
> + int (*check_status)(struct mmp_path *path);
> + struct mmp_ovly *(*get_ovly)(struct mmp_path *path,
> + int ovly_id);
> + int (*get_modelist)(struct mmp_path *path,
> + struct mmp_mode **modelist);
> +
> + /* follow ops should be provided by driver */
> + void (*set_mode)(struct mmp_path *path, struct mmp_mode *mode);
> + void (*set_onoff)(struct mmp_path *path, int status);
> + /* todo: add query */
> +};
> +
> +/* path output types */
> +enum {
> + PATH_OUT_PARALLEL,
> + PATH_OUT_DSI,
> + PATH_OUT_HDMI,
> +};
> +
> +/* path is main part of mmp-disp */
> +struct mmp_path {
> + /* use node to register to list */
> + struct list_head node;
> +
> + /* init data */
> + struct device *dev;
> +
> + int id;
> + const char *name;
> + int output_type;
> + struct mmp_panel *panel;
> + void *plat_data;
> +
> + /* dynamic use */
> + struct mmp_mode mode;
> +
> + /* state */
> + int open_count;
> + int status;
> + struct mutex access_ok;
> +
> + struct mmp_path_ops ops;
> +
> + /* layers */
> + int ovly_num;
> + struct mmp_ovly *ovlys;
> +};
> +
> +extern struct mmp_path *mmp_get_path(const char *name);
> +static inline void mmp_path_set_mode(struct mmp_path *path,
> + struct mmp_mode *mode)
> +{
> + if (path)
> + path->ops.set_mode(path, mode);
> +}
> +static inline void mmp_path_set_onoff(struct mmp_path *path, int status)
> +{
> + if (path)
> + path->ops.set_onoff(path, status);
> +}
> +static inline int mmp_path_get_modelist(struct mmp_path *path,
> + struct mmp_mode **modelist)
> +{
> + if (path)
> + return path->ops.get_modelist(path, modelist);
> + return 0;
> +}
> +static inline struct mmp_ovly *mmp_path_get_ovly(
> + struct mmp_path *path, int ovly_id)
> +{
> + if (path)
> + return path->ops.get_ovly(path, ovly_id);
> + return NULL;
> +}
> +static inline void mmp_ovly_set_fetch(struct mmp_ovly *ovly,
> + int fetch_id)
> +{
> + if (ovly)
> + ovly->ops->set_fetch(ovly, fetch_id);
> +}
> +static inline void mmp_ovly_set_onoff(struct mmp_ovly *ovly, int status)
> +{
> + if (ovly)
> + ovly->ops->set_onoff(ovly, status);
> +}
> +static inline void mmp_ovly_set_win(struct mmp_ovly *ovly,
> + struct mmp_win *win)
> +{
> + if (ovly)
> + ovly->ops->set_win(ovly, win);
> +}
> +static inline int mmp_ovly_set_addr(struct mmp_ovly *ovly,
> + struct mmp_addr *addr)
> +{
> + if (ovly)
> + return ovly->ops->set_addr(ovly, addr);
> + return 0;
> +}
> +
> +/*
> + * driver data is set from each detailed ctrl driver for path usage
> + * it defined a common interface that plat driver need to implement
> + */
> +struct mmp_path_info {
> + /* driver data, set when registed*/
> + const char *name;
> + struct device *dev;
> + int id;
> + int output_type;
> + int ovly_num;
> + void (*set_mode)(struct mmp_path *path, struct mmp_mode *mode);
> + void (*set_onoff)(struct mmp_path *path, int status);
> + struct mmp_ovly_ops *ovly_ops;
> + void *plat_data;
> +};
> +
> +extern struct mmp_path *mmp_register_path(
> + struct mmp_path_info *info);
> +extern void mmp_unregister_path(struct mmp_path *path);
> +extern int mmp_register_panel(struct mmp_panel *panel);
> +extern void mmp_unregister_panel(struct mmp_panel *panel);
> +
> +/* defintions for platform data */
> +/* interface for buffer driver */
> +struct mmp_buffer_driver_mach_info {
> + const char *name;
> + const char *path_name;
> + int ovly_id;
> + int dmafetch_id;
> + int default_pixfmt;
> + u32 irq_mask;
> +};
> +
> +/* interface for controllers driver */
> +struct mmp_mach_path_config {
> + const char *name;
> + int ovly_num;
> + int output_type;
> + u32 path_config;
> + u32 link_config;
> +};
> +
> +struct mmp_mach_plat_info {
> + const char *name;
> + const char *clk_name;
> + int path_num;
> + struct mmp_mach_path_config *paths;
> +};
> +
> +/* interface for panel drivers */
> +struct mmp_mach_panel_info {
> + const char *name;
> + void (*plat_set_onoff)(int status);
> + const char *plat_path_name;
> +};
> +#endif /* _MMP_DISP_H_ */
> --
> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2012-08-30 1:37 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-29 10:04 [PATCH 1/4] video: mmp display subsystem Zhou Zhu
2012-08-30 1:37 ` Jingoo Han [this message]
2012-08-30 2:26 ` Zhou Zhu
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='001401cd864f$fd91edb0$f8b5c910$%han@samsung.com' \
--to=jg1.han@samsung.com \
--cc=linux-fbdev@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 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).