All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marek Szyprowski <m.szyprowski@samsung.com>
To: dri-devel@lists.freedesktop.org, linux-samsung-soc@vger.kernel.org
Cc: Enrico Weigelt <enrico.weigelt@gr13.net>,
	Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>,
	Seung-Woo Kim <sw0312.kim@samsung.com>,
	Tobias Jakobi <tjakobi@math.uni-bielefeld.de>,
	Marek Szyprowski <m.szyprowski@samsung.com>
Subject: [RFC 2/2] drm/exynos: register rotator as fbproc instead of custom ipp framework
Date: Mon, 22 Aug 2016 11:44:35 +0200	[thread overview]
Message-ID: <1471859077-15679-3-git-send-email-m.szyprowski@samsung.com> (raw)
In-Reply-To: <1471859077-15679-1-git-send-email-m.szyprowski@samsung.com>

This is a quick conversion of Exynos DRM rotator driver from
Exynos IPP framework to generic DRM FBProc API to demonstrate how to use it
from the driver side.

Not-for-merge-yet: the code of the driver must be cleaned up first, because
its internals still depends on Exynos IPP structures.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/Kconfig              |   1 -
 drivers/gpu/drm/exynos/exynos_drm_drv.c     |   3 +-
 drivers/gpu/drm/exynos/exynos_drm_rotator.c | 353 +++++++++++++++-------------
 drivers/gpu/drm/exynos/exynos_drm_rotator.h |  19 --
 4 files changed, 194 insertions(+), 182 deletions(-)
 delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_rotator.h

diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 83f61c513b7e..6eebba9be797 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -109,7 +109,6 @@ config DRM_EXYNOS_FIMC
 
 config DRM_EXYNOS_ROTATOR
 	bool "Rotator"
-	depends on DRM_EXYNOS_IPP
 	help
 	  Choose this option if you want to use Exynos Rotator for DRM.
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 877d2efa28e2..f536a63531bb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -395,7 +395,7 @@ static const struct file_operations exynos_drm_driver_fops = {
 
 static struct drm_driver exynos_drm_driver = {
 	.driver_features	= DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
-				  | DRIVER_ATOMIC | DRIVER_RENDER,
+				  | DRIVER_ATOMIC | DRIVER_RENDER | DRIVER_FBPROC,
 	.load			= exynos_drm_load,
 	.unload			= exynos_drm_unload,
 	.open			= exynos_drm_open,
@@ -532,6 +532,7 @@ static struct exynos_drm_driver_info exynos_drm_drivers[] = {
 		DRV_PTR(fimc_driver, CONFIG_DRM_EXYNOS_FIMC),
 	}, {
 		DRV_PTR(rotator_driver, CONFIG_DRM_EXYNOS_ROTATOR),
+		DRM_COMPONENT_DRIVER
 	}, {
 		DRV_PTR(gsc_driver, CONFIG_DRM_EXYNOS_GSC),
 	}, {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index 404367a430b5..8ecd8db0649a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/component.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -21,8 +22,10 @@
 #include <drm/drmP.h>
 #include <drm/exynos_drm.h>
 #include "regs-rotator.h"
+#include "exynos_drm_fb.h"
 #include "exynos_drm_drv.h"
 #include "exynos_drm_ipp.h"
+#include "exynos_drm_iommu.h"
 
 /*
  * Rotator supports image crop/rotator and input/output DMA operations.
@@ -92,7 +95,9 @@ struct rot_limit_table {
  * @suspended: suspended state.
  */
 struct rot_context {
-	struct exynos_drm_ippdrv	ippdrv;
+	struct drm_fbproc fbproc;
+	struct drm_device *drm_dev;
+	struct device *dev;
 	struct resource	*regs_res;
 	void __iomem	*regs;
 	struct clk	*clock;
@@ -100,6 +105,10 @@ struct rot_context {
 	int	irq;
 	int	cur_buf_id[EXYNOS_DRM_OPS_MAX];
 	bool	suspended;
+	spinlock_t 		lock;
+	struct drm_fbproc_task	*task;
+	wait_queue_head_t	done_wq;
+	bool			done;
 };
 
 static void rotator_reg_set_irq(struct rot_context *rot, bool enable)
@@ -138,9 +147,6 @@ static enum rot_irq_status rotator_reg_get_irq_status(struct rot_context *rot)
 static irqreturn_t rotator_irq_handler(int irq, void *arg)
 {
 	struct rot_context *rot = arg;
-	struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv;
-	struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
-	struct drm_exynos_ipp_event_work *event_work = c_node->event_work;
 	enum rot_irq_status irq_status;
 	u32 val;
 
@@ -152,12 +158,14 @@ static irqreturn_t rotator_irq_handler(int irq, void *arg)
 	val |= ROT_STATUS_IRQ_PENDING((u32)irq_status);
 	rot_write(val, ROT_STATUS);
 
-	if (irq_status == ROT_IRQ_STATUS_COMPLETE) {
-		event_work->ippdrv = ippdrv;
-		event_work->buf_id[EXYNOS_DRM_OPS_DST] =
-			rot->cur_buf_id[EXYNOS_DRM_OPS_DST];
-		queue_work(ippdrv->event_workq, &event_work->work);
-	} else {
+	spin_lock(&rot->lock);
+	rot->task = NULL;
+	rot->done = true;
+	spin_unlock(&rot->lock);
+
+	wake_up(&rot->done_wq);
+
+	if (irq_status != ROT_IRQ_STATUS_COMPLETE) {
 		DRM_ERROR("the SFR is set illegally\n");
 	}
 
@@ -455,36 +463,6 @@ static int rotator_dst_set_addr(struct device *dev,
 	return 0;
 }
 
-static struct exynos_drm_ipp_ops rot_src_ops = {
-	.set_fmt	=	rotator_src_set_fmt,
-	.set_size	=	rotator_src_set_size,
-	.set_addr	=	rotator_src_set_addr,
-};
-
-static struct exynos_drm_ipp_ops rot_dst_ops = {
-	.set_transf	=	rotator_dst_set_transf,
-	.set_size	=	rotator_dst_set_size,
-	.set_addr	=	rotator_dst_set_addr,
-};
-
-static int rotator_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
-{
-	struct drm_exynos_ipp_prop_list *prop_list = &ippdrv->prop_list;
-
-	prop_list->version = 1;
-	prop_list->flip = (1 << EXYNOS_DRM_FLIP_VERTICAL) |
-				(1 << EXYNOS_DRM_FLIP_HORIZONTAL);
-	prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) |
-				(1 << EXYNOS_DRM_DEGREE_90) |
-				(1 << EXYNOS_DRM_DEGREE_180) |
-				(1 << EXYNOS_DRM_DEGREE_270);
-	prop_list->csc = 0;
-	prop_list->crop = 0;
-	prop_list->scale = 0;
-
-	return 0;
-}
-
 static inline bool rotator_check_drm_fmt(u32 fmt)
 {
 	switch (fmt) {
@@ -511,93 +489,6 @@ static inline bool rotator_check_drm_flip(enum drm_exynos_flip flip)
 	}
 }
 
-static int rotator_ippdrv_check_property(struct device *dev,
-		struct drm_exynos_ipp_property *property)
-{
-	struct drm_exynos_ipp_config *src_config =
-					&property->config[EXYNOS_DRM_OPS_SRC];
-	struct drm_exynos_ipp_config *dst_config =
-					&property->config[EXYNOS_DRM_OPS_DST];
-	struct drm_exynos_pos *src_pos = &src_config->pos;
-	struct drm_exynos_pos *dst_pos = &dst_config->pos;
-	struct drm_exynos_sz *src_sz = &src_config->sz;
-	struct drm_exynos_sz *dst_sz = &dst_config->sz;
-	bool swap = false;
-
-	/* Check format configuration */
-	if (src_config->fmt != dst_config->fmt) {
-		DRM_DEBUG_KMS("not support csc feature\n");
-		return -EINVAL;
-	}
-
-	if (!rotator_check_drm_fmt(dst_config->fmt)) {
-		DRM_DEBUG_KMS("invalid format\n");
-		return -EINVAL;
-	}
-
-	/* Check transform configuration */
-	if (src_config->degree != EXYNOS_DRM_DEGREE_0) {
-		DRM_DEBUG_KMS("not support source-side rotation\n");
-		return -EINVAL;
-	}
-
-	switch (dst_config->degree) {
-	case EXYNOS_DRM_DEGREE_90:
-	case EXYNOS_DRM_DEGREE_270:
-		swap = true;
-	case EXYNOS_DRM_DEGREE_0:
-	case EXYNOS_DRM_DEGREE_180:
-		/* No problem */
-		break;
-	default:
-		DRM_DEBUG_KMS("invalid degree\n");
-		return -EINVAL;
-	}
-
-	if (src_config->flip != EXYNOS_DRM_FLIP_NONE) {
-		DRM_DEBUG_KMS("not support source-side flip\n");
-		return -EINVAL;
-	}
-
-	if (!rotator_check_drm_flip(dst_config->flip)) {
-		DRM_DEBUG_KMS("invalid flip\n");
-		return -EINVAL;
-	}
-
-	/* Check size configuration */
-	if ((src_pos->x + src_pos->w > src_sz->hsize) ||
-		(src_pos->y + src_pos->h > src_sz->vsize)) {
-		DRM_DEBUG_KMS("out of source buffer bound\n");
-		return -EINVAL;
-	}
-
-	if (swap) {
-		if ((dst_pos->x + dst_pos->h > dst_sz->vsize) ||
-			(dst_pos->y + dst_pos->w > dst_sz->hsize)) {
-			DRM_DEBUG_KMS("out of destination buffer bound\n");
-			return -EINVAL;
-		}
-
-		if ((src_pos->w != dst_pos->h) || (src_pos->h != dst_pos->w)) {
-			DRM_DEBUG_KMS("not support scale feature\n");
-			return -EINVAL;
-		}
-	} else {
-		if ((dst_pos->x + dst_pos->w > dst_sz->hsize) ||
-			(dst_pos->y + dst_pos->h > dst_sz->vsize)) {
-			DRM_DEBUG_KMS("out of destination buffer bound\n");
-			return -EINVAL;
-		}
-
-		if ((src_pos->w != dst_pos->w) || (src_pos->h != dst_pos->h)) {
-			DRM_DEBUG_KMS("not support scale feature\n");
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
 static int rotator_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
 {
 	struct rot_context *rot = dev_get_drvdata(dev);
@@ -692,24 +583,184 @@ static const struct of_device_id exynos_rotator_match[] = {
 };
 MODULE_DEVICE_TABLE(of, exynos_rotator_match);
 
+static int rotator_get_exclusive_access(struct rot_context *rot,
+					struct drm_fbproc_task *task)
+{
+	unsigned long flags;
+	int got_access = false;
+	int ret = 0;
+
+try_again:
+	spin_lock_irqsave(&rot->lock, flags);
+	if (rot->task == NULL) {
+		rot->task = task;
+		got_access = true;
+	}
+	spin_unlock_irqrestore(&rot->lock, flags);
+
+	if (!got_access) {
+		ret = wait_event_interruptible(rot->done_wq, rot->done);
+		if (ret)
+			return ret;
+		goto try_again;
+	}
+	return ret;
+}
+
+static int rotator_commit(struct drm_fbproc *fbproc,
+			  struct drm_fbproc_task *task)
+{
+	struct rot_context *rot =
+			container_of(fbproc, struct rot_context, fbproc);
+	struct device *dev = rot->dev;
+	dma_addr_t src_dma = exynos_drm_fb_dma_addr(task->src_fb, 0);
+	dma_addr_t dst_dma = exynos_drm_fb_dma_addr(task->dst_fb, 0);
+	int r = task->rotation;
+	int w = task->src_w >> 16;
+	int h = task->src_h >> 16;
+	int sx = task->src_x >> 16;
+	int dx = task->dst_x >> 16;
+	int sy = task->src_y >> 16;
+	int dy = task->dst_y >> 16;
+	int sp = task->src_fb->pitches[0];
+	int dp = task->dst_fb->pitches[0];
+
+	struct drm_exynos_ipp_buf_info src_buf_info = { .base[0] = src_dma, };
+	struct drm_exynos_ipp_buf_info dst_buf_info = { .base[0] = dst_dma, };
+	struct drm_exynos_pos src_pos = { sx, sy, w, h, };
+	struct drm_exynos_pos dst_pos = { dx, dy, w, h, };
+	struct drm_exynos_sz src_sz = { sp/4, h+sy, };
+	struct drm_exynos_sz dst_sz = { dp/4, h+dy, };
+	int ret;
+	int rotation = 0, flip = 0;
+	bool swap;
+
+	if (r & DRM_ROTATE_180)
+		rotation = EXYNOS_DRM_DEGREE_180;
+	else if (r & DRM_ROTATE_90)
+		rotation = EXYNOS_DRM_DEGREE_90;
+	else if (r & DRM_ROTATE_270)
+		rotation = EXYNOS_DRM_DEGREE_270;
+
+	if (r & DRM_REFLECT_X)
+		flip |= EXYNOS_DRM_FLIP_HORIZONTAL;
+	if (r & DRM_REFLECT_Y)
+		flip |= EXYNOS_DRM_FLIP_VERTICAL;
+
+	ret = rotator_get_exclusive_access(rot, task);
+	if (ret < 0)
+		return ret;
+
+	pm_runtime_get_sync(dev);
+
+	dev_dbg(dev, "r %d w %d h %d sx %d sy %d sp %d dx %d dy %d pd %d\n",
+		r, w, h, sx, sy, sp, dx, dy, dp);
+	rot->done = 0;
+
+	ret = rotator_src_set_fmt(dev, DRM_FORMAT_XRGB8888);
+	if (ret)
+		printk("error setting rotator %d\n", __LINE__);
+	ret = rotator_src_set_size(dev, 0, &src_pos, &src_sz);
+	if (ret)
+		printk("error setting rotator %d\n", __LINE__);
+	ret = rotator_src_set_addr(dev, &src_buf_info, 0, IPP_BUF_ENQUEUE);
+	if (ret)
+		printk("error setting rotator %d\n", __LINE__);
+
+	ret = rotator_dst_set_transf(dev, rotation, flip, &swap);
+	if (ret)
+		printk("error setting rotator %d\n", __LINE__);
+
+	if (swap) {
+		swap(dst_pos.w, dst_pos.h);
+		dst_sz.vsize = w+dy;
+	}
+	ret = rotator_dst_set_size(dev, 0, &dst_pos, &dst_sz);
+	if (ret)
+		printk("error setting rotator %d\n", __LINE__);
+	ret = rotator_dst_set_addr(dev, &dst_buf_info, 0, IPP_BUF_ENQUEUE);
+	if (ret)
+		printk("error setting rotator %d\n", __LINE__);
+
+	rotator_ippdrv_start(dev, IPP_CMD_M2M);
+
+	wait_event(rot->done_wq, rot->done);
+
+	pm_runtime_put(dev);
+
+	return 0;
+}
+
+struct drm_fbproc_funcs fbproc_funcs = {
+	.commit = rotator_commit,
+};
+
+static const uint32_t rotator_formats[] = {
+	DRM_FORMAT_XRGB8888,
+};
+
+static int rotator_bind(struct device *dev, struct device *master, void *data)
+{
+	struct rot_context *rot = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+	struct drm_fbproc *fbproc = &rot->fbproc;
+	struct drm_property *prop;
+
+	rot->drm_dev = drm_dev;
+	drm_iommu_attach_device(drm_dev, dev);
+
+
+	drm_fbproc_init(drm_dev, fbproc, &fbproc_funcs,
+			   DRM_FBPROC_CAP_CROP | DRM_FBPROC_CAP_ROTATE,
+			   rotator_formats, ARRAY_SIZE(rotator_formats),
+			   rotator_formats, ARRAY_SIZE(rotator_formats),
+			   "rotator");
+
+	prop = drm_mode_create_rotation_property(drm_dev,
+			DRM_ROTATE_0 | DRM_ROTATE_90 | DRM_ROTATE_180 |
+			DRM_ROTATE_270 | DRM_REFLECT_X | DRM_REFLECT_Y);
+
+	fbproc->rotation_property = prop;
+	drm_object_attach_property(&fbproc->base, prop, DRM_ROTATE_0);
+
+	dev_info(dev, "The exynos rotator is probed successfully\n");
+
+	return 0;
+}
+
+static void rotator_unbind(struct device *dev, struct device *master,
+			void *data)
+{
+	struct rot_context *rot = dev_get_drvdata(dev);
+
+	drm_iommu_detach_device(rot->drm_dev, rot->dev);
+}
+
+static const struct component_ops rotator_component_ops = {
+	.bind	= rotator_bind,
+	.unbind = rotator_unbind,
+};
+
 static int rotator_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct rot_context *rot;
-	struct exynos_drm_ippdrv *ippdrv;
+	const struct of_device_id *match;
 	int ret;
 
-	if (!dev->of_node) {
-		dev_err(dev, "cannot find of_node.\n");
-		return -ENODEV;
-	}
-
 	rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL);
 	if (!rot)
 		return -ENOMEM;
 
-	rot->limit_tbl = (struct rot_limit_table *)
-				of_device_get_match_data(dev);
+	match = of_match_node(exynos_rotator_match, dev->of_node);
+	if (!match) {
+		dev_err(dev, "failed to match node\n");
+		return -ENODEV;
+	}
+
+	spin_lock_init(&rot->lock);
+	rot->limit_tbl = (struct rot_limit_table *)match->data;
+	rot->dev = dev;
 	rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	rot->regs = devm_ioremap_resource(dev, rot->regs_res);
 	if (IS_ERR(rot->regs))
@@ -721,6 +772,8 @@ static int rotator_probe(struct platform_device *pdev)
 		return rot->irq;
 	}
 
+	init_waitqueue_head(&rot->done_wq);
+
 	ret = devm_request_threaded_irq(dev, rot->irq, NULL,
 			rotator_irq_handler, IRQF_ONESHOT, "drm_rotator", rot);
 	if (ret < 0) {
@@ -734,31 +787,12 @@ static int rotator_probe(struct platform_device *pdev)
 		return PTR_ERR(rot->clock);
 	}
 
-	pm_runtime_enable(dev);
-
-	ippdrv = &rot->ippdrv;
-	ippdrv->dev = dev;
-	ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &rot_src_ops;
-	ippdrv->ops[EXYNOS_DRM_OPS_DST] = &rot_dst_ops;
-	ippdrv->check_property = rotator_ippdrv_check_property;
-	ippdrv->start = rotator_ippdrv_start;
-	ret = rotator_init_prop_list(ippdrv);
-	if (ret < 0) {
-		dev_err(dev, "failed to init property list.\n");
-		goto err_ippdrv_register;
-	}
-
-	DRM_DEBUG_KMS("ippdrv[%p]\n", ippdrv);
-
 	platform_set_drvdata(pdev, rot);
+	pm_runtime_enable(dev);
 
-	ret = exynos_drm_ippdrv_register(ippdrv);
-	if (ret < 0) {
-		dev_err(dev, "failed to register drm rotator device\n");
+	ret = component_add(dev, &rotator_component_ops);
+	if (ret)
 		goto err_ippdrv_register;
-	}
-
-	dev_info(dev, "The exynos rotator is probed successfully\n");
 
 	return 0;
 
@@ -770,11 +804,8 @@ err_ippdrv_register:
 static int rotator_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct rot_context *rot = dev_get_drvdata(dev);
-	struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv;
-
-	exynos_drm_ippdrv_unregister(ippdrv);
 
+	component_del(dev, &rotator_component_ops);
 	pm_runtime_disable(dev);
 
 	return 0;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.h b/drivers/gpu/drm/exynos/exynos_drm_rotator.h
deleted file mode 100644
index 71a0b4c0c1e8..000000000000
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *
- * Authors:
- *	YoungJun Cho <yj44.cho@samsung.com>
- *	Eunchul Kim <chulspro.kim@samsung.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.
- */
-
-#ifndef	_EXYNOS_DRM_ROTATOR_H_
-#define	_EXYNOS_DRM_ROTATOR_H_
-
-/* TODO */
-
-#endif
-- 
1.9.1

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

  parent reply	other threads:[~2016-08-22  9:44 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-22  9:44 [RFC 0/2] New feature: Framebuffer processors Marek Szyprowski
2016-08-22  9:44 ` [RFC 1/2] drm: add support for framebuffer processors Marek Szyprowski
2016-08-22  9:44 ` Marek Szyprowski [this message]
2016-08-22  9:44 ` [RFC libdrm] add support for framebuffer processor (fbproc) objects Marek Szyprowski
2016-08-22  9:44 ` [RFC code example] example code for testing fbproc drivers Marek Szyprowski
2016-08-22  9:59 ` [RFC 0/2] New feature: Framebuffer processors Christian König
2016-08-22 14:59   ` Daniel Vetter
2016-08-22 15:23   ` Rob Clark
2016-08-22 15:30     ` Benjamin Gaignard
2016-08-23  9:41     ` Daniel Stone
2016-08-24 11:44       ` Inki Dae
2016-08-24 11:57         ` Daniel Vetter
2016-08-25  8:06           ` Inki Dae
2016-08-25  8:42             ` Daniel Vetter
2016-08-25 11:45               ` Inki Dae
2016-08-25 12:14                 ` Daniel Vetter
2016-08-30  5:52                   ` Inki Dae
2016-08-22 10:07 ` Tobias Jakobi
2016-08-22 10:50   ` Marek Szyprowski
2016-08-22 11:38     ` Tobias Jakobi
2016-08-22 20:05 ` Dave Airlie

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=1471859077-15679-3-git-send-email-m.szyprowski@samsung.com \
    --to=m.szyprowski@samsung.com \
    --cc=b.zolnierkie@samsung.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=enrico.weigelt@gr13.net \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=sw0312.kim@samsung.com \
    --cc=tjakobi@math.uni-bielefeld.de \
    /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.