All of lore.kernel.org
 help / color / mirror / Atom feed
* [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework
@ 2022-03-16  9:37 Suraj Kandpal
  2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework Suraj Kandpal
                   ` (10 more replies)
  0 siblings, 11 replies; 24+ messages in thread
From: Suraj Kandpal @ 2022-03-16  9:37 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

A patch series was floated in the drm mailing list which aimed to change
the drm_connector and drm_encoder fields to pointer in the
drm_connector_writeback structure, this received a huge pushback from
the community but since i915 expects each connector present in the
drm_device list to be a intel_connector but drm_writeback framework
forces us to use a drm_connector which is not embedded in
intel_connector the current drm_writeback framework becomes very
unfeasible to us as it would mean a lot of checks at a lot of places
to take into account the above issue. One of the solutions is to
make our own writeback pipeline bypassing one provided by drm
which is what these patches do.

Suraj Kandpal (3):
  drm/i915: Creating writeback pipeline to bypass drm_writeback
    framework
  drm/i915: Define WD trancoder for i915
  drm/i915: Enabling WD Transcoder

 drivers/gpu/drm/i915/Makefile                 |   2 +
 drivers/gpu/drm/i915/display/intel_acpi.c     |   1 +
 drivers/gpu/drm/i915/display/intel_display.c  |  85 +-
 drivers/gpu/drm/i915/display/intel_display.h  |  15 +
 .../drm/i915/display/intel_display_types.h    |  21 +
 drivers/gpu/drm/i915/display/intel_dpll.c     |   3 +
 drivers/gpu/drm/i915/display/intel_opregion.c |   3 +
 .../gpu/drm/i915/display/intel_wb_connector.c | 296 ++++++
 .../gpu/drm/i915/display/intel_wb_connector.h |  99 ++
 drivers/gpu/drm/i915/display/intel_wd.c       | 996 ++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_wd.h       |  82 ++
 drivers/gpu/drm/i915/i915_drv.h               |   5 +
 drivers/gpu/drm/i915/i915_irq.c               |   8 +-
 drivers/gpu/drm/i915/i915_pci.c               |   7 +-
 drivers/gpu/drm/i915/i915_reg.h               | 139 +++
 15 files changed, 1759 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_wd.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_wd.h

-- 
2.35.1


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

* [Intel-gfx] [RFC PATCH 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework
  2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
@ 2022-03-16  9:37 ` Suraj Kandpal
  2022-03-16 14:25   ` kernel test robot
  2022-03-18  4:18   ` [Intel-gfx] [RFC PATCH v2 " Suraj Kandpal
  2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 2/3] drm/i915: Define WD trancoder for i915 Suraj Kandpal
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 24+ messages in thread
From: Suraj Kandpal @ 2022-03-16  9:37 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Changes to create a i915 private pipeline to enable the WD transcoder
without relying on the current drm_writeback framework.

Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 .../gpu/drm/i915/display/intel_wb_connector.c | 296 ++++++++++++++++++
 .../gpu/drm/i915/display/intel_wb_connector.h |  99 ++++++
 drivers/gpu/drm/i915/i915_drv.h               |   3 +
 4 files changed, 399 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 1a771ee5b1d0..087bd9d1b397 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -286,6 +286,7 @@ i915-y += \
 	display/intel_tv.o \
 	display/intel_vdsc.o \
 	display/intel_vrr.o \
+	display/intel_wb_connector.o\
 	display/vlv_dsi.o \
 	display/vlv_dsi_pll.o
 
diff --git a/drivers/gpu/drm/i915/display/intel_wb_connector.c b/drivers/gpu/drm/i915/display/intel_wb_connector.c
new file mode 100644
index 000000000000..526b3e7530e0
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wb_connector.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright © 2022 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Suraj Kandpal <suraj.kandpal@intel.com>
+ *	Arun Murthy <arun.r.murthy@intel.com>
+ *
+ */
+
+
+#include <linux/dma-fence.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_property.h>
+
+#include "i915_drv.h"
+#include "intel_wb_connector.h"
+#include "intel_display_types.h"
+
+#define fence_to_wb_connector(x) container_of(x->lock, \
+					      struct intel_writeback_connector, \
+					      fence_lock)
+
+static const char *intel_writeback_fence_get_driver_name(struct dma_fence *fence)
+{
+	struct intel_writeback_connector *wb_connector =
+		fence_to_wb_connector(fence);
+
+	return wb_connector->base->dev->driver->name;
+}
+
+static const char *
+intel_writeback_fence_get_timeline_name(struct dma_fence *fence)
+{
+	struct intel_writeback_connector *wb_connector =
+		fence_to_wb_connector(fence);
+
+	return wb_connector->timeline_name;
+}
+
+static bool intel_writeback_fence_enable_signaling(struct dma_fence *fence)
+{
+	return true;
+}
+
+static const struct dma_fence_ops intel_writeback_fence_ops = {
+	.get_driver_name = intel_writeback_fence_get_driver_name,
+	.get_timeline_name = intel_writeback_fence_get_timeline_name,
+	.enable_signaling = intel_writeback_fence_enable_signaling,
+};
+
+static int intel_create_writeback_properties(struct drm_device *dev)
+{
+	struct drm_property *prop;
+	struct drm_i915_private *i915 = to_i915(dev);
+
+	if (!i915->wb_fb_id_property) {
+		prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+						"WRITEBACK_FB_ID",
+						DRM_MODE_OBJECT_FB);
+		if (!prop)
+			return -ENOMEM;
+		i915->wb_fb_id_property = prop;
+	}
+
+	if (!i915->wb_pixel_formats_property) {
+		prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
+					DRM_MODE_PROP_ATOMIC |
+					DRM_MODE_PROP_IMMUTABLE,
+					"WRITEBACK_PIXEL_FORMATS", 0);
+		if (!prop)
+			return -ENOMEM;
+		i915->wb_pixel_formats_property = prop;
+	}
+
+	if (!i915->wb_out_fence_ptr_property) {
+		prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+						"WRITEBACK_OUT_FENCE_PTR", 0,
+						U64_MAX);
+		if (!prop)
+			return -ENOMEM;
+		i915->wb_out_fence_ptr_property = prop;
+	}
+
+	return 0;
+}
+
+static const struct drm_encoder_funcs intel_writeback_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int intel_writeback_connector_init(struct drm_device *dev,
+				 struct intel_writeback_connector *wb_connector,
+				 const struct drm_connector_funcs *con_funcs,
+				 const struct drm_encoder_helper_funcs *enc_helper_funcs,
+				 const u32 *formats, int n_formats)
+{
+	struct drm_property_blob *blob;
+	struct drm_i915_private *i915 = to_i915(dev);
+	struct drm_connector *connector = wb_connector->base;
+	int ret;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	ret = intel_create_writeback_properties(dev);
+
+	if (ret != 0)
+		return ret;
+
+	blob = drm_property_create_blob(dev, n_formats * sizeof(*formats),
+					formats);
+	if (IS_ERR(blob))
+		return PTR_ERR(blob);
+
+	drm_encoder_helper_add(wb_connector->encoder, enc_helper_funcs);
+	ret = drm_encoder_init(dev, wb_connector->encoder,
+			&intel_writeback_encoder_funcs,
+			DRM_MODE_ENCODER_VIRTUAL, NULL);
+	if (ret)
+		goto fail;
+
+	connector->interlace_allowed = 0;
+
+	ret = drm_connector_init(dev, connector, con_funcs,
+				DRM_MODE_CONNECTOR_WRITEBACK);
+	if (ret)
+		goto connector_fail;
+
+	ret = drm_connector_attach_encoder(connector,
+					wb_connector->encoder);
+	if (ret)
+		goto attach_fail;
+
+	INIT_LIST_HEAD(&wb_connector->job_queue);
+	spin_lock_init(&wb_connector->job_lock);
+
+	wb_connector->fence_context = dma_fence_context_alloc(1);
+	spin_lock_init(&wb_connector->fence_lock);
+	snprintf(wb_connector->timeline_name,
+		sizeof(wb_connector->timeline_name),
+		"CONNECTOR:%d-%s", connector->base.id, connector->name);
+
+	drm_object_attach_property(&connector->base,
+				i915->wb_out_fence_ptr_property, 0);
+
+	drm_object_attach_property(&connector->base,
+				i915->wb_fb_id_property, 0);
+
+	drm_object_attach_property(&connector->base,
+				i915->wb_pixel_formats_property,
+				blob->base.id);
+	wb_connector->pixel_formats_blob_ptr = blob;
+
+	return 0;
+
+attach_fail:
+	drm_connector_cleanup(connector);
+connector_fail:
+	drm_encoder_cleanup(wb_connector->encoder);
+fail:
+	drm_property_blob_put(blob);
+	return ret;
+}
+
+void intel_writeback_queue_job(struct intel_writeback_connector *wb_connector,
+		struct drm_connector_state *conn_state)
+{
+	struct intel_writeback_job *wb_job;
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
+	unsigned long flags;
+
+	wb_job = intel_conn_state->job;
+	intel_conn_state->job = NULL;
+
+	spin_lock_irqsave(&wb_connector->job_lock, flags);
+	list_add_tail(&wb_job->list_entry, &wb_connector->job_queue);
+	spin_unlock_irqrestore(&wb_connector->job_lock, flags);
+}
+
+int intel_writeback_set_fb(struct drm_connector_state *conn_state,
+			 struct drm_framebuffer *fb)
+{
+	struct intel_connector *intel_connector = to_intel_connector(conn_state->connector);
+	struct intel_writeback_connector *wb_connector = &intel_connector->wb_conn;
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
+	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
+
+	if (!intel_conn_state->job) {
+		intel_conn_state->job =
+			kzalloc(sizeof(*intel_conn_state->job), GFP_KERNEL);
+		if (!intel_conn_state->job)
+			return -ENOMEM;
+
+		intel_conn_state->job->connector = wb_connector;
+	}
+
+	drm_framebuffer_assign(&intel_conn_state->job->fb, fb);
+	return 0;
+}
+
+void intel_writeback_cleanup_job(struct intel_writeback_job *job)
+{
+	if (job->fb)
+		drm_framebuffer_put(job->fb);
+
+	if (job->out_fence)
+		dma_fence_put(job->out_fence);
+
+	kfree(job);
+}
+
+void cleanup_work(struct work_struct *work)
+{
+	struct intel_writeback_job *job = container_of(work,
+						struct intel_writeback_job,
+						cleanup_work);
+
+	intel_writeback_cleanup_job(job);
+}
+
+void
+intel_writeback_signal_completion(struct intel_writeback_connector *wb_connector,
+				int status)
+{
+	unsigned long flags;
+	struct intel_writeback_job *job;
+	struct dma_fence *out_fence;
+
+	spin_lock_irqsave(&wb_connector->job_lock, flags);
+	job = list_first_entry_or_null(&wb_connector->job_queue,
+					struct intel_writeback_job,
+					list_entry);
+	if (job)
+		list_del(&job->list_entry);
+
+	spin_unlock_irqrestore(&wb_connector->job_lock, flags);
+
+	if (WARN_ON(!job))
+		return;
+
+	out_fence = job->out_fence;
+	if (out_fence) {
+		if (status)
+			dma_fence_set_error(out_fence, status);
+		dma_fence_signal(out_fence);
+		dma_fence_put(out_fence);
+		job->out_fence = NULL;
+	}
+
+	INIT_WORK(&job->cleanup_work, cleanup_work);
+	queue_work(system_long_wq, &job->cleanup_work);
+}
+
+struct dma_fence *
+intel_writeback_get_out_fence(struct intel_writeback_connector *wb_connector)
+{
+	struct dma_fence *fence;
+
+	if (WARN_ON(wb_connector->base->connector_type !=
+		DRM_MODE_CONNECTOR_WRITEBACK))
+		return NULL;
+
+	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+	if (!fence)
+		return NULL;
+
+	dma_fence_init(fence, &intel_writeback_fence_ops,
+		&wb_connector->fence_lock, wb_connector->fence_context,
+		++wb_connector->fence_seqno);
+
+	return fence;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_wb_connector.h b/drivers/gpu/drm/i915/display/intel_wb_connector.h
new file mode 100644
index 000000000000..71142457b7c1
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wb_connector.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Copyright © 2022 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Suraj Kandpal <suraj.kandpal@intel.com>
+ *	Arun Murthy <arun.r.murthy@intel.com>
+ *
+ */
+
+#ifndef __INTEL_WB_CONNECTOR_H__
+#define __INTEL_WB_CONNECTOR_H__
+
+#include <drm/drm_connector.h>
+#include <drm/drm_encoder.h>
+#include <linux/workqueue.h>
+#include "intel_display.h"
+
+/**
+ * struct intel_writeback_connector - Intel writeback connector
+ * to get a idea of each individual variable please look at
+ * documentation in drm_writeback.h we emulate the same structure
+ * ditto for intel_writeback_job structure.
+ */
+struct intel_writeback_connector {
+	struct drm_connector *base;
+	struct drm_encoder *encoder;
+	struct drm_property_blob *pixel_formats_blob_ptr;
+	spinlock_t job_lock;
+	struct list_head job_queue;
+	unsigned int fence_context;
+	spinlock_t fence_lock;
+	unsigned long fence_seqno;
+	char timeline_name[32];
+};
+
+/**
+ * struct intel_writeback_job - DRM writeback job
+ */
+struct intel_writeback_job {
+	struct intel_writeback_connector *connector;
+	bool *prepared;
+	struct work_struct cleanup_work;
+	struct list_head list_entry;
+	struct drm_framebuffer *fb;
+	struct dma_fence *out_fence;
+	void *priv;
+};
+
+int intel_writeback_connector_init(struct drm_device *dev,
+			struct intel_writeback_connector *wb_connector,
+			const struct drm_connector_funcs *con_funcs,
+			const struct drm_encoder_helper_funcs *enc_helper_funcs,
+			const u32 *formats, int n_formats);
+
+int intel_writeback_set_fb(struct drm_connector_state *conn_state,
+			struct drm_framebuffer *fb);
+
+int intel_writeback_prepare_job(struct intel_writeback_job *job);
+
+void intel_writeback_queue_job(struct intel_writeback_connector *wb_connector,
+			struct drm_connector_state *conn_state);
+
+void intel_writeback_cleanup_job(struct intel_writeback_job *job);
+
+void
+intel_writeback_signal_completion(struct intel_writeback_connector *wb_connector,
+			int status);
+
+struct dma_fence *
+intel_writeback_get_out_fence(struct intel_writeback_connector *wb_connector);
+struct intel_wb_connector *intel_wb_connector_alloc(void);
+void intel_wb_connector_free(struct intel_wb_connector *connector);
+void intel_wb_connector_destroy(struct drm_connector *connector);
+bool intel_wb_connector_get_hw_state(struct intel_wb_connector *connector);
+enum pipe intel_wb_connector_get_pipe(struct intel_wb_connector *connector);
+void intel_wb_connector_attach_encoder(struct intel_wb_connector *connector,
+					struct intel_encoder *encoder);
+
+#endif /* __INTEL_WB_CONNECTOR_H__ */
+
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 26df561a4e94..9a86ee88089e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -678,6 +678,9 @@ struct drm_i915_private {
 
 	struct drm_property *broadcast_rgb_property;
 	struct drm_property *force_audio_property;
+	struct drm_property *wb_fb_id_property;
+	struct drm_property *wb_out_fence_ptr_property;
+	struct drm_property *wb_pixel_formats_property;
 
 	u32 fdi_rx_config;
 
-- 
2.35.1


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

* [Intel-gfx] [RFC PATCH 2/3] drm/i915: Define WD trancoder for i915
  2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
  2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework Suraj Kandpal
@ 2022-03-16  9:37 ` Suraj Kandpal
  2022-03-18  4:20   ` [Intel-gfx] [RFC PATCH v2 " Suraj Kandpal
  2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 3/3] drm/i915: Enabling WD Transcoder Suraj Kandpal
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Suraj Kandpal @ 2022-03-16  9:37 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Adding WD Types, WD transcoder to enum list and WD Transcoder offsets

Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.h       | 6 ++++++
 drivers/gpu/drm/i915/display/intel_display_types.h | 1 +
 drivers/gpu/drm/i915/i915_reg.h                    | 2 ++
 3 files changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 8513703086b7..8c93a5de8e07 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -119,6 +119,8 @@ enum transcoder {
 	TRANSCODER_DSI_1,
 	TRANSCODER_DSI_A = TRANSCODER_DSI_0,	/* legacy DSI */
 	TRANSCODER_DSI_C = TRANSCODER_DSI_1,	/* legacy DSI */
+	TRANSCODER_WD_0,
+	TRANSCODER_WD_1,
 
 	I915_MAX_TRANSCODERS
 };
@@ -140,6 +142,10 @@ static inline const char *transcoder_name(enum transcoder transcoder)
 		return "DSI A";
 	case TRANSCODER_DSI_C:
 		return "DSI C";
+	case TRANSCODER_WD_0:
+		return "WD 0";
+	case TRANSCODER_WD_1:
+		return "WD 1";
 	default:
 		return "<invalid>";
 	}
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index d84e82f3eab9..dbd8b79bdf88 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -78,6 +78,7 @@ enum intel_output_type {
 	INTEL_OUTPUT_DSI = 9,
 	INTEL_OUTPUT_DDI = 10,
 	INTEL_OUTPUT_DP_MST = 11,
+	INTEL_OUTPUT_WD = 12,
 };
 
 enum hdmi_force_audio {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ddbc7a685a50..6396afd77209 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2023,6 +2023,8 @@
 #define TRANSCODER_EDP_OFFSET 0x6f000
 #define TRANSCODER_DSI0_OFFSET	0x6b000
 #define TRANSCODER_DSI1_OFFSET	0x6b800
+#define TRANSCODER_WD0_OFFSET	0x6e000
+#define TRANSCODER_WD1_OFFSET	0x6e800
 
 #define HTOTAL(trans)		_MMIO_TRANS2(trans, _HTOTAL_A)
 #define HBLANK(trans)		_MMIO_TRANS2(trans, _HBLANK_A)
-- 
2.35.1


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

* [Intel-gfx] [RFC PATCH 3/3] drm/i915: Enabling WD Transcoder
  2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
  2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework Suraj Kandpal
  2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 2/3] drm/i915: Define WD trancoder for i915 Suraj Kandpal
@ 2022-03-16  9:37 ` Suraj Kandpal
  2022-03-18  4:21   ` [Intel-gfx] [RFC PATCH v2 " Suraj Kandpal
  2022-03-16  9:51 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915 writeback private framework Patchwork
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Suraj Kandpal @ 2022-03-16  9:37 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Adding support for writeback transcoder to start capturing frames using
interrupt mechanism

Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 drivers/gpu/drm/i915/display/intel_acpi.c     |   1 +
 drivers/gpu/drm/i915/display/intel_display.c  |  85 +-
 drivers/gpu/drm/i915/display/intel_display.h  |   9 +
 .../drm/i915/display/intel_display_types.h    |  20 +
 drivers/gpu/drm/i915/display/intel_dpll.c     |   3 +
 drivers/gpu/drm/i915/display/intel_opregion.c |   3 +
 drivers/gpu/drm/i915/display/intel_wd.c       | 996 ++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_wd.h       |  82 ++
 drivers/gpu/drm/i915/i915_drv.h               |   2 +
 drivers/gpu/drm/i915/i915_irq.c               |   8 +-
 drivers/gpu/drm/i915/i915_pci.c               |   7 +-
 drivers/gpu/drm/i915/i915_reg.h               | 137 +++
 13 files changed, 1351 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_wd.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_wd.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 087bd9d1b397..5ee32513a945 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -287,6 +287,7 @@ i915-y += \
 	display/intel_vdsc.o \
 	display/intel_vrr.o \
 	display/intel_wb_connector.o\
+	display/intel_wd.o\
 	display/vlv_dsi.o \
 	display/vlv_dsi_pll.o
 
diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c
index e78430001f07..ae08db164f73 100644
--- a/drivers/gpu/drm/i915/display/intel_acpi.c
+++ b/drivers/gpu/drm/i915/display/intel_acpi.c
@@ -247,6 +247,7 @@ static u32 acpi_display_type(struct intel_connector *connector)
 	case DRM_MODE_CONNECTOR_LVDS:
 	case DRM_MODE_CONNECTOR_eDP:
 	case DRM_MODE_CONNECTOR_DSI:
+	case DRM_MODE_CONNECTOR_WRITEBACK:
 		display_type = ACPI_DISPLAY_TYPE_INTERNAL_DIGITAL;
 		break;
 	case DRM_MODE_CONNECTOR_Unknown:
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index eb49973621f0..72a6faa9045b 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -111,6 +111,7 @@
 #include "intel_sprite.h"
 #include "intel_tc.h"
 #include "intel_vga.h"
+#include "intel_wd.h"
 #include "i9xx_plane.h"
 #include "skl_scaler.h"
 #include "skl_universal_plane.h"
@@ -1544,6 +1545,72 @@ static void intel_encoders_update_complete(struct intel_atomic_state *state)
 	}
 }
 
+static void intel_queue_writeback_job(struct intel_atomic_state *state,
+		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)
+{
+	struct drm_connector_state *new_conn_state;
+	struct drm_connector *connector;
+	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
+	struct intel_wd *intel_wd;
+	struct intel_connector *intel_connector;
+	struct intel_digital_connector_state *intel_conn_state;
+	struct intel_encoder *encoder;
+	int i;
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (intel_wd->wd_crtc != intel_crtc)
+			return;
+
+	}
+
+	for_each_new_connector_in_state(&state->base, connector, new_conn_state,
+					i) {
+		intel_conn_state = to_intel_digital_connector_state(new_conn_state);
+		if (!intel_conn_state->job)
+			continue;
+		intel_connector = to_intel_connector(connector);
+		intel_writeback_queue_job(&intel_connector->wb_conn, new_conn_state);
+		drm_dbg_kms(&i915->drm, "queueing writeback job\n");
+	}
+}
+
+static void intel_find_writeback_connector(struct intel_atomic_state *state,
+		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)
+{
+	struct drm_connector_state *new_conn_state;
+	struct drm_connector *connector;
+	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
+	struct intel_wd *intel_wd;
+	struct intel_encoder *encoder;
+	int i;
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (intel_wd->wd_crtc != intel_crtc)
+			return;
+
+	}
+
+	for_each_new_connector_in_state(&state->base, connector, new_conn_state,
+					i) {
+		struct intel_connector *intel_connector;
+
+		intel_connector = to_intel_connector(connector);
+		drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]: status: %s\n",
+				connector->base.id, connector->name,
+				drm_get_connector_status_name(connector->status));
+		encoder = intel_connector_primary_encoder(intel_connector);
+		if (encoder->type == INTEL_OUTPUT_WD) {
+			drm_dbg_kms(&i915->drm, "encoder intel_output_wd found\n");
+			intel_wd_enable_capture(encoder, crtc_state, new_conn_state);
+		}
+	}
+
+}
+
 static void intel_encoders_pre_pll_enable(struct intel_atomic_state *state,
 					  struct intel_crtc *crtc)
 {
@@ -1944,7 +2011,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
 		bdw_set_pipemisc(new_crtc_state);
 
 	if (!intel_crtc_is_bigjoiner_slave(new_crtc_state) &&
-	    !transcoder_is_dsi(cpu_transcoder))
+	    !transcoder_is_dsi(cpu_transcoder) &&
+	    !transcoder_is_wd(cpu_transcoder))
 		hsw_configure_cpu_transcoder(new_crtc_state);
 
 	crtc->active = true;
@@ -2632,6 +2700,9 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,
 	if (connector->get_hw_state(connector)) {
 		struct intel_encoder *encoder = intel_attached_encoder(connector);
 
+		if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+			return;
+
 		I915_STATE_WARN(!crtc_state,
 			 "connector enabled without attached crtc\n");
 
@@ -5233,6 +5304,7 @@ static const char * const output_type_str[] = {
 	OUTPUT_TYPE(DSI),
 	OUTPUT_TYPE(DDI),
 	OUTPUT_TYPE(DP_MST),
+	OUTPUT_TYPE(WD),
 };
 
 #undef OUTPUT_TYPE
@@ -8577,6 +8649,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 		}
 	}
 
+	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+		intel_wd_set_vblank_event(crtc, new_crtc_state);
+	}
+
 	intel_encoders_update_prepare(state);
 
 	intel_dbuf_pre_plane_update(state);
@@ -8662,6 +8738,12 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 
 	intel_sagv_post_plane_update(state);
 
+	intel_wd_prepare_out_fence(dev, &state->base);
+	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+		intel_queue_writeback_job(state, crtc, new_crtc_state);
+		intel_find_writeback_connector(state, crtc, new_crtc_state);
+	}
+
 	drm_atomic_helper_commit_hw_done(&state->base);
 
 	if (state->modeset) {
@@ -8966,6 +9048,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
 		intel_ddi_init(dev_priv, PORT_TC1);
 		intel_ddi_init(dev_priv, PORT_TC2);
 	} else if (DISPLAY_VER(dev_priv) >= 12) {
+		intel_wd_init(dev_priv, TRANSCODER_WD_0);
 		intel_ddi_init(dev_priv, PORT_A);
 		intel_ddi_init(dev_priv, PORT_B);
 		intel_ddi_init(dev_priv, PORT_TC1);
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 8c93a5de8e07..27237d36a888 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -156,6 +156,11 @@ static inline bool transcoder_is_dsi(enum transcoder transcoder)
 	return transcoder == TRANSCODER_DSI_A || transcoder == TRANSCODER_DSI_C;
 }
 
+static inline bool transcoder_is_wd(enum transcoder transcoder)
+{
+	return transcoder == TRANSCODER_WD_0 || transcoder == TRANSCODER_WD_1;
+}
+
 /*
  * Global legacy plane identifier. Valid only for primary/sprite
  * planes on pre-g4x, and only for primary planes on g4x-bdw.
@@ -467,6 +472,10 @@ enum hpd_pin {
 	for_each_intel_encoder((dev), (intel_encoder)) \
 		for_each_if(intel_encoder_can_psr(intel_encoder))
 
+#define for_each_intel_encoder_with_wd(dev, intel_encoder)	\
+	for_each_intel_encoder(dev, intel_encoder)		\
+		for_each_if(intel_encoder_is_wd(intel_encoder))
+
 #define for_each_intel_connector_iter(intel_connector, iter) \
 	while ((intel_connector = to_intel_connector(drm_connector_list_iter_next(iter))))
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index dbd8b79bdf88..66539b3ff90b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -52,6 +52,7 @@
 #include "intel_display_power.h"
 #include "intel_dpll_mgr.h"
 #include "intel_pm_types.h"
+#include "intel_wb_connector.h"
 
 struct drm_printer;
 struct __intel_global_objs_state;
@@ -538,11 +539,14 @@ struct intel_connector {
 	struct work_struct modeset_retry_work;
 
 	struct intel_hdcp hdcp;
+
+	struct intel_writeback_connector wb_conn;
 };
 
 struct intel_digital_connector_state {
 	struct drm_connector_state base;
 
+	struct intel_writeback_job *job;
 	enum hdmi_force_audio force_audio;
 	int broadcast_rgb;
 };
@@ -1231,6 +1235,9 @@ struct intel_crtc_state {
 
 	/* for loading single buffered registers during vblank */
 	struct drm_vblank_work vblank_work;
+
+	/*contains the writeback job for the intel_writeback_connector*/
+	struct intel_writeback_job *writeback_job;
 };
 
 enum intel_pipe_crc_source {
@@ -1289,6 +1296,11 @@ struct intel_crtc {
 	bool cpu_fifo_underrun_disabled;
 	bool pch_fifo_underrun_disabled;
 
+	struct {
+		struct drm_pending_vblank_event *e;
+		atomic_t work_busy;
+		wait_queue_head_t wd_wait;
+	} wd;
 	/* per-pipe watermark state */
 	struct {
 		/* watermarks currently being used  */
@@ -1416,6 +1428,7 @@ struct cxsr_latency {
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
 #define to_intel_crtc_state(x) container_of(x, struct intel_crtc_state, uapi)
 #define to_intel_connector(x) container_of(x, struct intel_connector, base)
+#define to_intel_wb_connector(x) container_of(x, struct intel_wb_connector, base)
 #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 #define to_intel_plane(x) container_of(x, struct intel_plane, base)
@@ -1847,6 +1860,13 @@ static inline bool intel_encoder_is_dp(struct intel_encoder *encoder)
 	}
 }
 
+static inline bool intel_encoder_is_wd(struct intel_encoder *encoder)
+{
+	if (encoder->type == INTEL_OUTPUT_WD)
+		return true;
+	return false;
+}
+
 static inline struct intel_lspcon *
 enc_to_intel_lspcon(struct intel_encoder *encoder)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c
index 95b9d327ed4d..dfea17f5f99d 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll.c
@@ -939,6 +939,9 @@ static int hsw_crtc_compute_clock(struct intel_crtc_state *crtc_state)
 	if (IS_DG2(dev_priv))
 		return intel_mpllb_calc_state(crtc_state, encoder);
 
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_WD))
+		return 0;
+
 	if (DISPLAY_VER(dev_priv) < 11 &&
 	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
 		return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c
index f31e8c3f8ce0..b7a0ac9bad05 100644
--- a/drivers/gpu/drm/i915/display/intel_opregion.c
+++ b/drivers/gpu/drm/i915/display/intel_opregion.c
@@ -370,6 +370,9 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
 	if (ret)
 		return ret;
 
+	if (intel_encoder->type == INTEL_OUTPUT_WD)
+		return 0;
+
 	if (intel_encoder->type == INTEL_OUTPUT_DSI)
 		port = 0;
 	else
diff --git a/drivers/gpu/drm/i915/display/intel_wd.c b/drivers/gpu/drm/i915/display/intel_wd.c
new file mode 100644
index 000000000000..351476438cfe
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wd.c
@@ -0,0 +1,996 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Suraj Kandpal <suraj.kandpal@intel.com>
+ *	Arun Murthy <arun.r.murthy@intel.com>
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
+
+#include "intel_atomic.h"
+#include "intel_connector.h"
+#include "intel_wd.h"
+#include "intel_fb_pin.h"
+#include "intel_de.h"
+#include "intel_wb_connector.h"
+
+enum {
+	WD_CAPTURE_4_PIX,
+	WD_CAPTURE_2_PIX,
+} wd_capture_format;
+
+static struct intel_writeback_job
+*intel_get_writeback_job_from_queue(struct intel_wd *intel_wd)
+{
+	struct intel_writeback_job *job;
+	struct drm_i915_private *i915 = to_i915(intel_wd->base.base.dev);
+	struct intel_writeback_connector *wb_conn =
+		&intel_wd->attached_connector->wb_conn;
+	unsigned long flags;
+
+	spin_lock_irqsave(&wb_conn->job_lock, flags);
+	job = list_first_entry_or_null(&wb_conn->job_queue,
+			struct intel_writeback_job,
+			list_entry);
+	spin_unlock_irqrestore(&wb_conn->job_lock, flags);
+	if (job == NULL) {
+		drm_dbg_kms(&i915->drm, "job queue is empty\n");
+		return NULL;
+	}
+
+	return job;
+}
+
+void print_connectors(struct drm_i915_private *i915)
+{
+	struct drm_connector *connector;
+	struct drm_connector_list_iter conn_iter;
+	struct intel_connector *intel_connector;
+
+	drm_modeset_lock_all(&i915->drm);
+	drm_connector_list_iter_begin(&i915->drm, &conn_iter);
+	drm_for_each_connector_iter(connector, &conn_iter) {
+		intel_connector = to_intel_connector(connector);
+		drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]: status: %s\n",
+			connector->base.id, connector->name,
+			drm_get_connector_status_name(connector->status));
+	}
+	drm_connector_list_iter_end(&conn_iter);
+	drm_modeset_unlock_all(&i915->drm);
+}
+
+/*Check with Spec*/
+static const u32 wb_fmts[] = {
+		DRM_FORMAT_YUV444,
+		DRM_FORMAT_XYUV8888,
+		DRM_FORMAT_XBGR8888,
+		DRM_FORMAT_XRGB8888,
+		DRM_FORMAT_Y410,
+		DRM_FORMAT_YUV422,
+		DRM_FORMAT_XBGR2101010,
+		DRM_FORMAT_RGB565,
+
+};
+
+static int intel_wd_get_format(int pixel_format)
+{
+	int wd_format = -EINVAL;
+
+	switch (pixel_format) {
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_XYUV8888:
+	case DRM_FORMAT_YUV444:
+		wd_format = WD_CAPTURE_4_PIX;
+		break;
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_RGB565:
+		wd_format = WD_CAPTURE_2_PIX;
+		break;
+	default:
+		DRM_ERROR("unsupported pixel format %x!\n",
+			pixel_format);
+	}
+
+	return wd_format;
+}
+
+static int intel_wd_verify_pix_format(int format)
+{
+	const struct drm_format_info *info = drm_format_info(format);
+	int pix_format = info->format;
+	int i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(wb_fmts); i++)
+		if (pix_format == wb_fmts[i])
+			return 0;
+
+	return 1;
+}
+
+static u32 intel_wd_get_stride(const struct intel_crtc_state *crtc_state,
+			int format)
+{
+	const struct drm_format_info *info = drm_format_info(format);
+	int wd_format;
+	int hactive, pixel_size;
+
+	wd_format = intel_wd_get_format(info->format);
+
+	switch (wd_format) {
+	case WD_CAPTURE_4_PIX:
+		pixel_size = 4;
+		break;
+	case WD_CAPTURE_2_PIX:
+		pixel_size = 2;
+		break;
+	default:
+		pixel_size = 1;
+		break;
+	}
+
+	hactive = crtc_state->hw.adjusted_mode.crtc_hdisplay;
+
+	return DIV_ROUND_UP(hactive * pixel_size, 64);
+}
+
+static int intel_wd_pin_fb(struct intel_wd *intel_wd,
+			struct drm_framebuffer *fb)
+{
+	const struct i915_ggtt_view view = {
+		.type = I915_GGTT_VIEW_NORMAL,
+		};
+	struct i915_vma *vma;
+
+	vma = intel_pin_and_fence_fb_obj(fb, false, &view, false,
+			&intel_wd->flags);
+
+	if (IS_ERR(vma))
+		return PTR_ERR(vma);
+
+	intel_wd->vma = vma;
+	return 0;
+}
+
+static void intel_configure_slicing_strategy(struct drm_i915_private *i915,
+		struct intel_wd *intel_wd, u32 *tmp)
+{
+	*tmp &= ~WD_STRAT_MASK;
+	if (intel_wd->slicing_strategy == 1)
+		*tmp |= WD_SLICING_STRAT_1_1;
+	else if (intel_wd->slicing_strategy == 2)
+		*tmp |= WD_SLICING_STRAT_2_1;
+	else if (intel_wd->slicing_strategy == 3)
+		*tmp |= WD_SLICING_STRAT_4_1;
+	else if (intel_wd->slicing_strategy == 4)
+		*tmp |= WD_SLICING_STRAT_8_1;
+
+	intel_de_write(i915, WD_STREAMCAP_CTL(intel_wd->trans),
+			*tmp);
+
+}
+
+static enum drm_mode_status
+intel_wd_mode_valid(struct drm_connector *connector,
+		struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static int intel_wd_get_modes(struct drm_connector *connector)
+{
+	return 0;
+}
+
+static void intel_wd_get_config(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_crtc *intel_crtc =
+		to_intel_crtc(pipe_config->uapi.crtc);
+
+	drm_dbg_kms(&i915->drm, "\n");
+	if (intel_crtc) {
+		memcpy(pipe_config, intel_crtc->config,
+			sizeof(*pipe_config));
+		pipe_config->output_types |= BIT(INTEL_OUTPUT_WD);
+		drm_dbg_kms(&i915->drm, "crtc found\n");
+	}
+
+}
+
+static int intel_wd_compute_config(struct intel_encoder *encoder,
+			struct intel_crtc_state *pipe_config,
+			struct drm_connector_state *conn_state)
+{
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
+	struct intel_writeback_job *job;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	job = intel_get_writeback_job_from_queue(intel_wd);
+	if (job || intel_conn_state->job) {
+		intel_wd->wd_crtc = to_intel_crtc(pipe_config->uapi.crtc);
+		return 0;
+	}
+	drm_dbg_kms(&i915->drm, "No writebackjob in queue\n");
+
+	return 0;
+}
+
+static void intel_wd_get_power_domains(struct intel_encoder *encoder,
+			struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	intel_wakeref_t wakeref;
+
+	wakeref = intel_display_power_get(i915,
+				encoder->power_domain);
+
+	intel_wd->io_wakeref[0] = wakeref;
+	drm_dbg_kms(&i915->drm, "\n");
+}
+
+static bool intel_wd_get_hw_state(struct intel_encoder *encoder,
+		enum pipe *pipe)
+{
+	bool ret = false;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	struct intel_crtc *wd_crtc = intel_wd->wd_crtc;
+	intel_wakeref_t wakeref;
+	u32 tmp;
+
+	if (wd_crtc)
+		return false;
+
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+				encoder->power_domain);
+	drm_dbg_kms(encoder->base.dev, "power enabled : %s\n",
+			!wakeref ? "false":"true");
+
+	if (!wakeref)
+		return false;
+
+	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+	ret = tmp & WD_TRANS_ACTIVE;
+	drm_dbg_kms(encoder->base.dev, "trancoder enabled: %s\n",
+			ret ? "true":"false");
+	if (ret) {
+		*pipe = wd_crtc->pipe;
+		drm_dbg_kms(encoder->base.dev, "pipe selected is %d\n",
+			wd_crtc->pipe);
+	}
+	return true;
+}
+
+static int intel_wd_encoder_atomic_check(struct drm_encoder *encoder,
+				    struct drm_crtc_state *crtc_st,
+				    struct drm_connector_state *conn_st)
+{
+	/* Check for the format and buffers and property validity */
+	struct drm_framebuffer *fb;
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_st);
+	struct intel_writeback_job *job = intel_conn_state->job;
+	struct drm_i915_private *i915 = to_i915(encoder->dev);
+	const struct drm_display_mode *mode = &crtc_st->mode;
+	int ret;
+
+	drm_dbg_kms(&i915->drm, "\n");
+
+	if (!job) {
+		drm_dbg_kms(&i915->drm, "No writeback job created returning\n");
+		return -EINVAL;
+	}
+
+	fb = job->fb;
+
+	if (!fb) {
+		drm_dbg_kms(&i915->drm, "Invalid framebuffer\n");
+		return -EINVAL;
+	}
+
+	if (fb->width != mode->hdisplay || fb->height != mode->vdisplay) {
+		drm_dbg_kms(&i915->drm, "Invalid framebuffer size %ux%u\n",
+				fb->width, fb->height);
+		return -EINVAL;
+	}
+
+	ret = intel_wd_verify_pix_format(fb->format->format);
+
+	if (ret) {
+		drm_dbg_kms(&i915->drm, "Unsupported framebuffer format %08x\n",
+				fb->format->format);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+static const struct drm_encoder_helper_funcs wd_encoder_helper_funcs = {
+	.atomic_check = intel_wd_encoder_atomic_check,
+};
+
+static void intel_wd_connector_destroy(struct drm_connector *connector)
+{
+	drm_dbg_kms(connector->dev, "\n");
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+static enum drm_connector_status
+intel_wb_connector_detect(struct drm_connector *connector, bool force)
+{
+	drm_dbg_kms(connector->dev, "Writeback connector connected\n");
+	return connector_status_connected;
+}
+
+static int intel_atomic_set_writeback_fb_for_connector(
+		struct drm_connector_state *conn_state,
+		struct drm_framebuffer *fb)
+{
+	int ret;
+	struct drm_connector *conn = conn_state->connector;
+
+	ret = intel_writeback_set_fb(conn_state, fb);
+	if (ret < 0)
+		return ret;
+
+	if (fb)
+		drm_dbg_atomic(conn->dev,
+			"Set [FB:%d] for connector state %p\n",
+			fb->base.id, conn_state);
+	else
+		drm_dbg_atomic(conn->dev,
+			"Set [NOFB] for connector state %p\n",
+			conn_state);
+
+	return 0;
+}
+
+static int set_out_fence_for_connector(struct drm_atomic_state *state,
+					struct drm_connector *connector,
+					s32 __user *fence_ptr)
+{
+	unsigned int index = drm_connector_index(connector);
+
+	if (!fence_ptr)
+		return 0;
+
+	if (put_user(-1, fence_ptr))
+		return -EFAULT;
+
+	state->connectors[index].out_fence_ptr = fence_ptr;
+
+	return 0;
+}
+
+struct drm_mode_object *__intel_object_find(struct drm_device *dev,
+					       uint32_t id, uint32_t type)
+{
+	struct drm_mode_object *obj = NULL;
+
+	mutex_lock(&dev->mode_config.idr_mutex);
+	obj = idr_find(&dev->mode_config.object_idr, id);
+	if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
+		obj = NULL;
+	if (obj && obj->id != id)
+		obj = NULL;
+	if (obj && obj->free_cb) {
+		if (!kref_get_unless_zero(&obj->refcount))
+			obj = NULL;
+	}
+	mutex_unlock(&dev->mode_config.idr_mutex);
+
+	return obj;
+}
+
+struct drm_framebuffer *intel_wb_framebuffer_lookup(struct drm_device *dev,
+					       uint32_t id)
+{
+	struct drm_mode_object *obj;
+	struct drm_framebuffer *fb = NULL;
+
+	obj = __intel_object_find(dev, id, DRM_MODE_OBJECT_FB);
+	if (obj)
+		fb = obj_to_fb(obj);
+	return fb;
+}
+
+static s32 __user *intel_get_out_fence_for_connector(struct drm_atomic_state *state,
+					       struct drm_connector *connector)
+{
+	unsigned int index = drm_connector_index(connector);
+	s32 __user *fence_ptr;
+
+	fence_ptr = state->connectors[index].out_fence_ptr;
+	state->connectors[index].out_fence_ptr = NULL;
+
+	return fence_ptr;
+}
+
+static int intel_setup_out_fence(struct intel_out_fence_state *fence_state,
+			   struct dma_fence *fence)
+{
+
+	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
+	if (fence_state->fd < 0)
+		return fence_state->fd;
+
+	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
+		return -EFAULT;
+
+	fence_state->sync_file = sync_file_create(fence);
+	if (!fence_state->sync_file)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int intel_wd_prepare_out_fence(struct drm_device *dev,
+				struct drm_atomic_state *state)
+{
+	struct drm_connector *conn;
+	struct drm_connector_state *conn_state;
+	int i, ret;
+
+	drm_dbg_kms(dev, "\n");
+
+	for_each_new_connector_in_state(state, conn, conn_state, i) {
+		struct intel_writeback_connector *wb_conn;
+		struct intel_connector *intel_conn =
+			to_intel_connector(conn);
+		struct dma_fence *fence;
+		struct intel_wd *intel_wd;
+		struct intel_digital_connector_state *intel_conn_state =
+			to_intel_digital_connector_state(conn_state);
+		s32 __user *fence_ptr;
+
+		if (conn->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
+			continue;
+
+		if (!intel_conn_state->job)
+			continue;
+
+		intel_wd = enc_to_intel_wd(intel_conn->encoder);
+		fence_ptr = intel_get_out_fence_for_connector(state, conn);
+		if (!fence_ptr)
+			continue;
+
+		intel_wd->fence_state->out_fence_ptr = fence_ptr;
+
+		wb_conn = &intel_conn->wb_conn;
+		fence = intel_writeback_get_out_fence(wb_conn);
+		if (!fence)
+			return -ENOMEM;
+
+		ret = intel_setup_out_fence(intel_wd->fence_state, fence);
+		if (ret) {
+			dma_fence_put(fence);
+			return ret;
+		}
+
+		intel_conn_state->job->out_fence = fence;
+	}
+
+	return 0;
+}
+
+void intel_wd_complete_signaling(struct intel_wd *intel_wd)
+{
+	struct intel_out_fence_state *fence_state;
+
+	fence_state = intel_wd->fence_state;
+	fd_install(fence_state->fd,
+		fence_state->sync_file->file);
+
+}
+
+static int intel_set_writeback_property(struct drm_connector *connector,
+	struct drm_connector_state *state, struct drm_property *property,
+	uint64_t val)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *i915 = to_i915(dev);
+
+	if (property == i915->wb_fb_id_property) {
+		struct drm_framebuffer *fb;
+		int ret;
+
+		fb = intel_wb_framebuffer_lookup(dev, val);
+		ret = intel_atomic_set_writeback_fb_for_connector(state, fb);
+		if (fb)
+			drm_framebuffer_put(fb);
+		return ret;
+	} else if (property == i915->wb_out_fence_ptr_property) {
+		s32 __user *fence_ptr = u64_to_user_ptr(val);
+
+		return set_out_fence_for_connector(state->state, connector,
+						fence_ptr);
+	} else {
+		drm_dbg_atomic(connector->dev,
+			"[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
+			connector->base.id, connector->name,
+			property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+
+}
+
+static int intel_get_writeback_property(struct drm_connector *connector,
+	const struct drm_connector_state *state, struct drm_property *property,
+	uint64_t *val)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *i915 = to_i915(dev);
+
+	if (property == i915->wb_fb_id_property)
+		*val = 0;
+	else if (property == i915->wb_out_fence_ptr_property)
+		*val = 0;
+	else {
+		drm_dbg_atomic(&i915->drm,
+				"Unknown property [PROP:%d:%s]\n",
+				property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct drm_connector_funcs wd_connector_funcs = {
+	.detect = intel_wb_connector_detect,
+	.reset = drm_atomic_helper_connector_reset,
+	.destroy = intel_wd_connector_destroy,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+	.atomic_set_property = intel_set_writeback_property,
+	.atomic_get_property = intel_get_writeback_property,
+	.atomic_duplicate_state = intel_digital_connector_duplicate_state,
+};
+
+static const struct drm_connector_helper_funcs wd_connector_helper_funcs = {
+	.get_modes = intel_wd_get_modes,
+	.mode_valid = intel_wd_mode_valid,
+};
+
+static bool intel_fastset_dis(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config)
+{
+	pipe_config->uapi.mode_changed = true;
+	drm_dbg_kms(encoder->base.dev, "\n");
+	return false;
+}
+
+void intel_wd_init(struct drm_i915_private *i915, enum transcoder trans)
+{
+	struct intel_wd *intel_wd;
+	struct intel_encoder *encoder;
+	struct intel_out_fence_state *fence_state;
+	struct intel_connector *intel_connector;
+	struct intel_writeback_connector *wb_conn;
+	int n_formats = ARRAY_SIZE(wb_fmts);
+	int err;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	intel_wd = kzalloc(sizeof(*intel_wd), GFP_KERNEL);
+	if (!intel_wd)
+		return;
+
+	intel_connector = intel_connector_alloc();
+	if (!intel_connector) {
+		kfree(intel_wd);
+		return;
+	}
+
+	fence_state = kzalloc(sizeof(*fence_state), GFP_KERNEL);
+	if (!intel_wd) {
+		kfree(intel_wd);
+		kfree(intel_connector);
+		return;
+	}
+
+	wb_conn = &intel_connector->wb_conn;
+	wb_conn->base = &intel_connector->base;
+	wb_conn->encoder = &intel_wd->base.base;
+
+	encoder = &intel_wd->base;
+	intel_wd->attached_connector = intel_connector;
+	intel_wd->fence_state = fence_state;
+	intel_wd->trans = trans;
+	intel_wd->triggered_cap_mode = 1;
+	intel_wd->frame_num = 1;
+	intel_wd->slicing_strategy = 1;
+	encoder->get_config = intel_wd_get_config;
+	encoder->compute_config = intel_wd_compute_config;
+	encoder->get_hw_state = intel_wd_get_hw_state;
+	encoder->type = INTEL_OUTPUT_WD;
+	encoder->cloneable = 0;
+	encoder->pipe_mask = ~0;
+	encoder->power_domain = POWER_DOMAIN_TRANSCODER_B;
+	encoder->get_power_domains = intel_wd_get_power_domains;
+	encoder->initial_fastset_check = intel_fastset_dis;
+	intel_connector->get_hw_state =
+		intel_connector_get_hw_state;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	err = intel_writeback_connector_init(&i915->drm, wb_conn,
+		&wd_connector_funcs,
+		&wd_encoder_helper_funcs,
+		wb_fmts, n_formats);
+
+	if (err != 0) {
+		drm_dbg_kms(&i915->drm,
+		"intel_writeback_connector_init: Failed: %d\n",
+			err);
+		goto cleanup;
+	}
+
+	drm_connector_helper_add(wb_conn->base, &wd_connector_helper_funcs);
+	intel_connector_attach_encoder(intel_connector, encoder);
+	wb_conn->base->status = connector_status_connected;
+	return;
+
+cleanup:
+	kfree(intel_wd);
+	intel_connector_free(intel_connector);
+}
+
+void intel_wd_writeback_complete(struct intel_wd *intel_wd,
+	struct intel_writeback_job *job, int status)
+{
+	struct intel_writeback_connector *wb_conn =
+		&intel_wd->attached_connector->wb_conn;
+	intel_writeback_signal_completion(wb_conn, status);
+	intel_wd_complete_signaling(intel_wd);
+}
+
+int intel_wd_setup_transcoder(struct intel_wd *intel_wd,
+		struct intel_crtc_state *pipe_config,
+		struct intel_writeback_job *job)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
+	enum pipe pipe = intel_crtc->pipe;
+	struct drm_framebuffer *fb;
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+	struct drm_gem_object *wd_fb_obj;
+	int ret;
+	u32 stride, tmp;
+	u16 hactive, vactive;
+
+	fb = job->fb;
+	wd_fb_obj = fb->obj[0];
+	if (!wd_fb_obj) {
+		drm_dbg_kms(&dev_priv->drm, "No framebuffer gem object created\n");
+		return -1;
+	}
+	ret = intel_wd_pin_fb(intel_wd, fb);
+	drm_WARN_ON(&dev_priv->drm, ret != 0);
+
+	/*Write stride and surface registers in that particular order*/
+	stride = intel_wd_get_stride(pipe_config, fb->format->format);
+
+	tmp = intel_de_read(dev_priv, WD_STRIDE(intel_wd->trans));
+	tmp &= ~WD_STRIDE_MASK;
+	tmp |= (stride << WD_STRIDE_SHIFT);
+
+	intel_de_write(dev_priv, WD_STRIDE(intel_wd->trans), tmp);
+
+	tmp = intel_de_read(dev_priv, WD_SURF(intel_wd->trans));
+	drm_dbg_kms(&dev_priv->drm, "%d is the surface address\n", tmp);
+
+	intel_de_write(dev_priv, WD_SURF(intel_wd->trans),
+			i915_ggtt_offset(intel_wd->vma));
+
+	tmp = intel_de_read_fw(dev_priv, WD_IIR(intel_wd->trans));
+	intel_de_write_fw(dev_priv, WD_IIR(intel_wd->trans), tmp);
+
+	tmp = ~(WD_GTT_FAULT_INT|WD_WRITE_COMPLETE_INT|WD_FRAME_COMPLETE_INT|
+			WD_VBLANK_INT|WD_OVERRUN_INT|WD_CAPTURING_INT);
+	intel_de_write_fw(dev_priv, WD_IMR(intel_wd->trans), tmp);
+
+	if (intel_wd->stream_cap) {
+		tmp = intel_de_read(dev_priv,
+				WD_STREAMCAP_CTL(intel_wd->trans));
+		tmp |= WD_STREAM_CAP_MODE_EN;
+		intel_configure_slicing_strategy(dev_priv, intel_wd, &tmp);
+	}
+
+	hactive = pipe_config->uapi.mode.hdisplay;
+	vactive = pipe_config->uapi.mode.vdisplay;
+
+	drm_dbg_kms(&dev_priv->drm, "hactive : %d, vactive: %d\n", hactive, vactive);
+
+	tmp = intel_de_read(dev_priv, HTOTAL(intel_wd->trans));
+	drm_dbg_kms(&dev_priv->drm, "hactive_reg : %d\n", tmp);
+	tmp = intel_de_read(dev_priv, VTOTAL(intel_wd->trans));
+	drm_dbg_kms(&dev_priv->drm, "vactive_reg : %d\n", tmp);
+	/* minimum hactive as per bspec: 64 pixels*/
+	if (hactive < 64)
+		drm_err(&dev_priv->drm, "hactive is less then 64 pixels\n");
+
+	intel_de_write(dev_priv, HTOTAL(intel_wd->trans), hactive - 1);
+	intel_de_write(dev_priv, VTOTAL(intel_wd->trans), vactive - 1);
+
+	tmp = intel_de_read(dev_priv, WD_TRANS_FUNC_CTL(intel_wd->trans));
+	/* select pixel format */
+	tmp &= ~WD_PIX_FMT_MASK;
+
+	switch (fb->format->format) {
+	default:
+	fallthrough;
+	case DRM_FORMAT_YUYV:
+		tmp |= WD_PIX_FMT_YUYV;
+		break;
+	case DRM_FORMAT_XYUV8888:
+		tmp |= WD_PIX_FMT_XYUV8888;
+		break;
+	case DRM_FORMAT_XBGR8888:
+		tmp |= WD_PIX_FMT_XBGR8888;
+		break;
+	case DRM_FORMAT_Y410:
+		tmp |= WD_PIX_FMT_Y410;
+		break;
+	case DRM_FORMAT_YUV422:
+		tmp |= WD_PIX_FMT_YUV422;
+		break;
+	case DRM_FORMAT_XBGR2101010:
+		tmp |= WD_PIX_FMT_XBGR2101010;
+		break;
+	case DRM_FORMAT_RGB565:
+		tmp |= WD_PIX_FMT_RGB565;
+		break;
+	}
+
+	if (intel_wd->triggered_cap_mode)
+		tmp |= WD_TRIGGERED_CAP_MODE_ENABLE;
+
+	if (intel_wd->stream_cap)
+		tmp |= WD_CTL_POINTER_DTDH;
+
+	/*select input pipe*/
+	tmp &= ~WD_INPUT_SELECT_MASK;
+	drm_dbg_kms(&dev_priv->drm, "Selected pipe is %d\n", pipe);
+	switch (pipe) {
+	default:
+		fallthrough;
+	case PIPE_A:
+		tmp |= WD_INPUT_PIPE_A;
+		break;
+	case PIPE_B:
+		tmp |= WD_INPUT_PIPE_B;
+		break;
+	case PIPE_C:
+		tmp |= WD_INPUT_PIPE_C;
+		break;
+	case PIPE_D:
+		tmp |= WD_INPUT_PIPE_D;
+		break;
+	}
+
+	/* enable DDI buffer */
+	if (!(tmp & TRANS_WD_FUNC_ENABLE))
+		tmp |= TRANS_WD_FUNC_ENABLE;
+
+	intel_de_write(dev_priv, WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);
+
+	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+	ret = tmp & WD_TRANS_ACTIVE;
+	drm_dbg_kms(&dev_priv->drm, "Trancoder enabled: %s\n", ret ? "true":"false");
+
+	if (!ret) {
+		/*enable the transcoder	*/
+		tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+		tmp |= WD_TRANS_ENABLE;
+		intel_de_write(dev_priv, PIPECONF(intel_wd->trans), tmp);
+
+		/* wait for transcoder to be enabled */
+		if (intel_de_wait_for_set(dev_priv, PIPECONF(intel_wd->trans),
+				WD_TRANS_ACTIVE, 10))
+			drm_err(&dev_priv->drm, "WD transcoder not enabled\n");
+	}
+
+	return 0;
+}
+
+static void intel_wd_disable_capture(struct intel_wd *intel_wd)
+{
+	struct drm_i915_private *dev_priv = to_i915(intel_wd->base.base.dev);
+	u32 tmp;
+
+	intel_de_write_fw(dev_priv, WD_IMR(intel_wd->trans), 0xFF);
+	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+	tmp &= WD_TRANS_DISABLE;
+	intel_de_write(dev_priv, PIPECONF(intel_wd->trans), tmp);
+
+	drm_dbg_kms(&dev_priv->drm, "WD Trans_Conf value after disable = 0x%08x\n",
+		intel_de_read(dev_priv, PIPECONF(intel_wd->trans)));
+	tmp = intel_de_read(dev_priv, WD_TRANS_FUNC_CTL(intel_wd->trans));
+	tmp |= ~TRANS_WD_FUNC_ENABLE;
+}
+
+int intel_wd_capture(struct intel_wd *intel_wd,
+		struct intel_crtc_state *pipe_config,
+		struct intel_writeback_job *job)
+{
+	u32 tmp;
+	struct drm_i915_private *i915 = to_i915(intel_wd->base.base.dev);
+	int ret = 0, status = 0;
+	struct intel_crtc *wd_crtc = intel_wd->wd_crtc;
+	unsigned long flags;
+
+	drm_dbg_kms(&i915->drm, "\n");
+
+	if (!job->out_fence)
+		drm_dbg_kms(&i915->drm, "Not able to get out_fence for job\n");
+
+	ret = intel_wd_setup_transcoder(intel_wd, pipe_config, job);
+
+	if (ret < 0) {
+		drm_dbg_kms(&i915->drm,
+		"wd transcoder setup not completed aborting capture\n");
+		return -1;
+	}
+
+	if (wd_crtc == NULL) {
+		DRM_ERROR("CRTC not attached\n");
+		return -1;
+	}
+
+	tmp = intel_de_read_fw(i915,
+			WD_TRANS_FUNC_CTL(intel_wd->trans));
+	tmp |= START_TRIGGER_FRAME;
+	tmp &= ~WD_FRAME_NUMBER_MASK;
+	tmp |= intel_wd->frame_num;
+	intel_de_write_fw(i915,
+			WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);
+
+	if (!intel_de_wait_for_set(i915, WD_IIR(intel_wd->trans),
+				WD_FRAME_COMPLETE_INT, 100)){
+		drm_dbg_kms(&i915->drm, "frame captured\n");
+		tmp = intel_de_read(i915, WD_IIR(intel_wd->trans));
+		drm_dbg_kms(&i915->drm, "iir value : %d\n", tmp);
+		status = 0;
+	} else {
+		drm_dbg_kms(&i915->drm, "frame not captured triggering stop frame\n");
+		tmp = intel_de_read(i915,
+				WD_TRANS_FUNC_CTL(intel_wd->trans));
+		tmp |= STOP_TRIGGER_FRAME;
+		intel_de_write(i915,
+				WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);
+		status = -1;
+	}
+
+	intel_de_write(i915, WD_IIR(intel_wd->trans), tmp);
+	intel_wd_writeback_complete(intel_wd, job, status);
+	if (intel_get_writeback_job_from_queue(intel_wd) == NULL)
+		intel_wd_disable_capture(intel_wd);
+	if (wd_crtc->wd.e) {
+		spin_lock_irqsave(&i915->drm.event_lock, flags);
+		drm_dbg_kms(&i915->drm, "send %p\n", wd_crtc->wd.e);
+		drm_crtc_send_vblank_event(&wd_crtc->base,
+					wd_crtc->wd.e);
+		spin_unlock_irqrestore(&i915->drm.event_lock, flags);
+		wd_crtc->wd.e = NULL;
+	} else {
+		DRM_ERROR("Event NULL! %p, %p\n", &i915->drm,
+			wd_crtc);
+	}
+	return 0;
+
+}
+
+void intel_wd_enable_capture(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config,
+		struct drm_connector_state *conn_state)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	struct intel_writeback_job *job;
+
+	drm_dbg_kms(&i915->drm, "\n");
+
+	job = intel_get_writeback_job_from_queue(intel_wd);
+	if (job == NULL) {
+		drm_dbg_kms(&i915->drm,
+			"job queue is empty not capturing any frame\n");
+		return;
+	}
+
+	intel_wd_capture(intel_wd, pipe_config, job);
+	intel_wd->frame_num += 1;
+
+}
+
+void intel_wd_set_vblank_event(struct intel_crtc *intel_crtc,
+			struct intel_crtc_state *intel_crtc_state)
+{
+	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
+	struct drm_crtc_state *state = &intel_crtc_state->uapi;
+	struct intel_encoder *encoder;
+	struct intel_wd *intel_wd;
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (!intel_wd->wd_crtc) {
+			drm_dbg_kms(&i915->drm, "wd crtc not found\n");
+			return;
+		}
+	}
+
+	if (intel_crtc == intel_wd->wd_crtc) {
+		intel_crtc->wd.e = state->event;
+		state->event = NULL;
+		if (intel_crtc->wd.e)
+			drm_dbg_kms(&i915->drm, "WD event:%p\n",
+				intel_crtc->wd.e);
+		else
+			drm_dbg_kms(&i915->drm, "WD no event\n");
+	}
+}
+
+void intel_wd_handle_isr(struct drm_i915_private *i915)
+{
+	u32 iir_value = 0;
+	struct intel_encoder *encoder;
+	struct intel_wd *intel_wd;
+
+	iir_value = intel_de_read(i915, WD_IIR(TRANSCODER_WD_0));
+	drm_dbg_kms(&i915->drm, "\n");
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (!intel_wd->wd_crtc) {
+			DRM_ERROR("NO CRTC attached with WD\n");
+			goto clear_iir;
+		}
+	}
+
+	if (iir_value & WD_VBLANK_INT)
+		drm_dbg_kms(&i915->drm, "vblank interrupt for wd transcoder\n");
+	if (iir_value & WD_WRITE_COMPLETE_INT)
+		drm_dbg_kms(&i915->drm,
+		"wd write complete interrupt encountered\n");
+	else
+		DRM_INFO("iir: %x\n", iir_value);
+	if (iir_value & WD_FRAME_COMPLETE_INT) {
+		drm_dbg_kms(&i915->drm,
+			"frame complete interrupt for wd transcoder\n");
+		return;
+	}
+clear_iir:
+	intel_de_write(i915, WD_IIR(TRANSCODER_WD_0), iir_value);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_wd.h b/drivers/gpu/drm/i915/display/intel_wd.h
new file mode 100644
index 000000000000..2309afa23bb8
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wd.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author :
+ *	Suraj Kandpal<suraj.kandpal@intel.com>
+ *	Arun Murthy<arun.r.murthy@intel.com>
+ */
+
+#ifndef _INTEL_WD_H
+#define _INTEL_WD_H
+
+#include <drm/drm_crtc.h>
+#include <linux/sync_file.h>
+
+#include "intel_display_types.h"
+
+#define I915_MAX_WD_TANSCODERS 2
+
+struct intel_out_fence_state {
+	s32 __user *out_fence_ptr;
+	struct sync_file *sync_file;
+	int fd;
+};
+
+struct intel_wd {
+	struct intel_encoder base;
+	struct intel_crtc *wd_crtc;
+	struct intel_out_fence_state *fence_state;
+	intel_wakeref_t io_wakeref[I915_MAX_WD_TANSCODERS];
+	struct intel_connector *attached_connector;
+	enum transcoder trans;
+	struct i915_vma *vma;
+	unsigned long flags;
+	struct intel_writeback_job *job;
+	int triggered_cap_mode;
+	int frame_num;
+	bool stream_cap;
+	bool start_capture;
+	int slicing_strategy;
+};
+
+struct intel_wd_clk_vals {
+	u32 cdclk;
+	u16 link_m;
+	u16 link_n;
+};
+
+extern struct sync_file *sync_file_create(struct dma_fence *fence);
+static inline struct intel_wd *enc_to_intel_wd(struct intel_encoder *encoder)
+{
+	return container_of(&encoder->base, struct intel_wd, base.base);
+}
+void intel_wd_init(struct drm_i915_private *dev_priv, enum transcoder trans);
+void intel_wd_enable_capture(struct intel_encoder *encoder,
+				struct intel_crtc_state *pipe_config,
+				struct drm_connector_state *conn_state);
+void intel_wd_handle_isr(struct drm_i915_private *dev_priv);
+void intel_wd_set_vblank_event(struct intel_crtc *crtc,
+				struct intel_crtc_state *state);
+int intel_wd_prepare_out_fence(struct drm_device *dev,
+				struct drm_atomic_state *state);
+void intel_wd_complete_signaling(struct intel_wd *intel_wd);
+#endif/* _INTEL_WD_H */
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9a86ee88089e..b7e92a18125c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -38,6 +38,8 @@
 #include <linux/pm_qos.h>
 
 #include <drm/drm_connector.h>
+#include <drm/drm_writeback.h>
+#include <drm/i915_mei_hdcp_interface.h>
 #include <drm/ttm/ttm_device.h>
 
 #include "display/intel_bios.h"
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 73cebc6aa650..95a6a8f7a911 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -42,6 +42,7 @@
 #include "display/intel_hotplug.h"
 #include "display/intel_lpe_audio.h"
 #include "display/intel_psr.h"
+#include "display/intel_wd.h"
 
 #include "gt/intel_breadcrumbs.h"
 #include "gt/intel_gt.h"
@@ -2342,6 +2343,11 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
 		found = true;
 	}
 
+	if (iir & GEN8_DE_MISC_WD0) {
+		intel_wd_handle_isr(dev_priv);
+		found = true;
+	}
+
 	if (iir & GEN8_DE_EDP_PSR) {
 		struct intel_encoder *encoder;
 		u32 psr_iir;
@@ -3767,7 +3773,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
 	u32 de_pipe_enables;
 	u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
 	u32 de_port_enables;
-	u32 de_misc_masked = GEN8_DE_EDP_PSR;
+	u32 de_misc_masked = GEN8_DE_EDP_PSR | GEN8_DE_MISC_WD0;
 	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
 	enum pipe pipe;
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 67b89769f577..a524e0f030b6 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -853,7 +853,8 @@ static const struct intel_device_info jsl_info = {
 	.display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \
 	.display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | \
-		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \
+		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1)| \
+		BIT(TRANSCODER_WD_0), \
 	.pipe_offsets = { \
 		[TRANSCODER_A] = PIPE_A_OFFSET, \
 		[TRANSCODER_B] = PIPE_B_OFFSET, \
@@ -861,6 +862,8 @@ static const struct intel_device_info jsl_info = {
 		[TRANSCODER_D] = PIPE_D_OFFSET, \
 		[TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \
 		[TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \
+		[TRANSCODER_WD_0] = PIPE_WD0_OFFSET, \
+		[TRANSCODER_WD_1] = PIPE_WD1_OFFSET, \
 	}, \
 	.trans_offsets = { \
 		[TRANSCODER_A] = TRANSCODER_A_OFFSET, \
@@ -869,6 +872,8 @@ static const struct intel_device_info jsl_info = {
 		[TRANSCODER_D] = TRANSCODER_D_OFFSET, \
 		[TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \
 		[TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
+		[TRANSCODER_WD_0] = TRANSCODER_WD0_OFFSET, \
+		[TRANSCODER_WD_1] = TRANSCODER_WD1_OFFSET, \
 	}, \
 	TGL_CURSOR_OFFSETS, \
 	.has_global_mocs = 1, \
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 6396afd77209..abc41e7de0b5 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3797,6 +3797,11 @@
 #define PIPE_DSI0_OFFSET	0x7b000
 #define PIPE_DSI1_OFFSET	0x7b800
 
+/* WD 0 and 1 */
+#define PIPE_WD0_OFFSET		0x7e000
+#define PIPE_WD1_OFFSET		0x7d000
+
+
 #define PIPECONF(pipe)		_MMIO_PIPE2(pipe, _PIPEACONF)
 #define PIPEDSL(pipe)		_MMIO_PIPE2(pipe, _PIPEADSL)
 #define PIPEFRAME(pipe)		_MMIO_PIPE2(pipe, _PIPEAFRAMEHIGH)
@@ -4461,6 +4466,10 @@
 #define _PIPEDSI0CONF		0x7b008
 #define _PIPEDSI1CONF		0x7b808
 
+/* WD 0 and 1 */
+#define _PIPEWD0CONF		0x7e008
+#define _PIPEWD1CONF		0x7d008
+
 /* Sprite A control */
 #define _DVSACNTR		0x72180
 #define   DVS_ENABLE			REG_BIT(31)
@@ -5707,6 +5716,7 @@
 #define GEN8_DE_MISC_IER _MMIO(0x4446c)
 #define  GEN8_DE_MISC_GSE		(1 << 27)
 #define  GEN8_DE_EDP_PSR		(1 << 19)
+#define  GEN8_DE_MISC_WD0		(1 << 23)
 
 #define GEN8_PCU_ISR _MMIO(0x444e0)
 #define GEN8_PCU_IMR _MMIO(0x444e4)
@@ -8847,6 +8857,133 @@ enum skl_power_gate {
 #define   DSB_ENABLE			(1 << 31)
 #define   DSB_STATUS			(1 << 0)
 
+#define TGL_ROOT_DEVICE_ID		0x9A00
+#define TGL_ROOT_DEVICE_MASK		0xFF00
+#define TGL_ROOT_DEVICE_SKU_MASK	0xF
+#define TGL_ROOT_DEVICE_SKU_ULX		0x2
+#define TGL_ROOT_DEVICE_SKU_ULT		0x4
+
+/* Gen12 WD */
+#define _MMIO_WD(tc, wd0, wd1)		_MMIO_TRANS((tc) - TRANSCODER_WD_0, \
+							wd0, wd1)
+
+#define WD_TRANS_ENABLE			(1 << 31)
+#define WD_TRANS_DISABLE		0
+#define WD_TRANS_ACTIVE			(1 << 30)
+
+/* WD transcoder control */
+#define _WD_TRANS_FUNC_CTL_0		0x6e400
+#define _WD_TRANS_FUNC_CTL_1		0x6ec00
+#define WD_TRANS_FUNC_CTL(tc)		_MMIO_WD(tc,\
+					_WD_TRANS_FUNC_CTL_0,\
+					_WD_TRANS_FUNC_CTL_1)
+
+#define TRANS_WD_FUNC_ENABLE		(1 << 31)
+#define WD_TRIGGERED_CAP_MODE_ENABLE	(1 << 30)
+#define START_TRIGGER_FRAME		(1 << 29)
+#define STOP_TRIGGER_FRAME		(1 << 28)
+#define WD_CTL_POINTER_ETEH		(0 << 18)
+#define WD_CTL_POINTER_ETDH		(1 << 18)
+#define WD_CTL_POINTER_DTDH		(2 << 18)
+#define WD_INPUT_SELECT_MASK		(7 << 12)
+#define WD_INPUT_PIPE_A			(0 << 12)
+#define WD_INPUT_PIPE_B			(5 << 12)
+#define WD_INPUT_PIPE_C			(6 << 12)
+#define WD_INPUT_PIPE_D			(7 << 12)
+
+#define WD_PIX_FMT_MASK			(0x3 << 20)
+#define WD_PIX_FMT_YUYV			(0x1 << 20)
+#define WD_PIX_FMT_XYUV8888		(0x2 << 20)
+#define WD_PIX_FMT_XBGR8888		(0x3 << 20)
+#define WD_PIX_FMT_Y410			(0x4 << 20)
+#define WD_PIX_FMT_YUV422		(0x5 << 20)
+#define WD_PIX_FMT_XBGR2101010		(0x6 << 20)
+#define WD_PIX_FMT_RGB565		(0x7 << 20)
+
+#define WD_FRAME_NUMBER_MASK		15
+
+#define _WD_STRIDE_0			0x6e510
+#define _WD_STRIDE_1			0x6ed10
+#define WD_STRIDE(tc)			_MMIO_WD(tc,\
+					_WD_STRIDE_0,\
+					_WD_STRIDE_1)
+#define WD_STRIDE_SHIFT			6
+#define WD_STRIDE_MASK			(0x3ff << WD_STRIDE_SHIFT)
+
+#define _WD_STREAMCAP_CTL0		0x6e590
+#define _WD_STREAMCAP_CTL1		0x6ed90
+#define WD_STREAMCAP_CTL(tc)		_MMIO_WD(tc,\
+					_WD_STREAMCAP_CTL0,\
+					_WD_STREAMCAP_CTL1)
+
+#define WD_STREAM_CAP_MODE_EN		(1 << 31)
+#define WD_STRAT_MASK			(3 << 24)
+#define WD_SLICING_STRAT_1_1		(0 << 24)
+#define WD_SLICING_STRAT_2_1		(1 << 24)
+#define WD_SLICING_STRAT_4_1		(2 << 24)
+#define WD_SLICING_STRAT_8_1		(3 << 24)
+#define WD_STREAM_OVERRUN_STATUS	1
+
+#define _WD_SURF_0			0x6e514
+#define _WD_SURF_1			0x6ed14
+#define WD_SURF(tc)			_MMIO_WD(tc,\
+					_WD_SURF_0,\
+					_WD_SURF_1)
+
+#define _WD_IMR_0			0x6e560
+#define _WD_IMR_1			0x6ed60
+#define WD_IMR(tc)			_MMIO_WD(tc,\
+					_WD_IMR_0,\
+					_WD_IMR_1)
+#define WD_FRAME_COMPLETE_INT		(1 << 7)
+#define WD_GTT_FAULT_INT		(1 << 6)
+#define WD_VBLANK_INT			(1 << 5)
+#define WD_OVERRUN_INT			(1 << 4)
+#define WD_CAPTURING_INT		(1 << 3)
+#define WD_WRITE_COMPLETE_INT		(1 << 2)
+
+#define _WD_IIR_0			0x6e564
+#define _WD_IIR_1			0x6ed64
+#define WD_IIR(tc)			_MMIO_WD(tc,\
+					_WD_IIR_0,\
+					_WD_IIR_1)
+
+#define _WD_FRAME_STATUS_0		0x6e56b
+#define _WD_FRAME_STATUS_1		0x6ed6b
+#define WD_FRAME_STATUS(tc)		_MMIO_WD(tc,\
+					_WD_FRAME_STATUS_0,\
+					_WD_FRAME_STATUS_1)
+
+#define WD_FRAME_COMPLETE		(1 << 31)
+#define WD_STATE_IDLE			(0 << 24)
+#define WD_STATE_CAPSTART		(1 << 24)
+#define WD_STATE_FRAME_START		(2 << 24)
+#define WD_STATE_CAPACITIVE		(3 << 24)
+#define WD_STATE_TG_DONE		(4 << 24)
+#define WD_STATE_WDX_DONE		(5 << 24)
+#define WD_STATE_QUICK_CAP		(6 << 24)
+
+#define _WD_27_M_0			0x6e524
+#define _WD_27_M_1			0x6ed24
+#define WD_27_M(tc)			_MMIO_WD(tc,\
+					_WD_27_M_0,\
+					_WD_27_M_1)
+
+#define _WD_27_N_0			0x6e528
+
+//Address looks wrong in bspec:
+#define _WD_27_N_1			0x6ec28
+#define WD_27_N(tc)			_MMIO_WD(tc,\
+					_WD_27_N_0,\
+					_WD_27_N_1)
+
+#define _WD_TAIL_CFG_0			0x6e520
+#define _WD_TAIL_CFG_1			0x6ed20
+
+#define WD_TAIL_CFG(tc)			_MMIO_WD(tc,\
+					_WD_TAIL_CFG_0,\
+					_WD_TAIL_CFG_1)
+
 #define CLKREQ_POLICY			_MMIO(0x101038)
 #define  CLKREQ_POLICY_MEM_UP_OVRD	REG_BIT(1)
 
-- 
2.35.1


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

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915 writeback private framework
  2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
                   ` (2 preceding siblings ...)
  2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 3/3] drm/i915: Enabling WD Transcoder Suraj Kandpal
@ 2022-03-16  9:51 ` Patchwork
  2022-03-16  9:52 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2022-03-16  9:51 UTC (permalink / raw)
  To: Suraj Kandpal; +Cc: intel-gfx

== Series Details ==

Series: i915 writeback private framework
URL   : https://patchwork.freedesktop.org/series/101425/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
91a1acb1ae9e drm/i915: Creating writeback pipeline to bypass drm_writeback framework
-:25: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#25: 
new file mode 100644

-:59: CHECK:LINE_SPACING: Please don't use multiple blank lines
#59: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:30:
+
+

-:72: CHECK:MACRO_ARG_PRECEDENCE: Macro argument 'x' may be better as '(x)' to avoid precedence issues
#72: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:43:
+#define fence_to_wb_connector(x) container_of(x->lock, \
+					      struct intel_writeback_connector, \
+					      fence_lock)

-:111: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#111: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:82:
+		prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+						"WRITEBACK_FB_ID",

-:130: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#130: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:101:
+		prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+						"WRITEBACK_OUT_FENCE_PTR", 0,

-:145: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#145: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:116:
+int intel_writeback_connector_init(struct drm_device *dev,
+				 struct intel_writeback_connector *wb_connector,

-:168: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#168: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:139:
+	ret = drm_encoder_init(dev, wb_connector->encoder,
+			&intel_writeback_encoder_funcs,

-:176: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#176: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:147:
+	ret = drm_connector_init(dev, connector, con_funcs,
+				DRM_MODE_CONNECTOR_WRITEBACK);

-:181: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#181: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:152:
+	ret = drm_connector_attach_encoder(connector,
+					wb_connector->encoder);

-:191: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#191: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:162:
+	snprintf(wb_connector->timeline_name,
+		sizeof(wb_connector->timeline_name),

-:195: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#195: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:166:
+	drm_object_attach_property(&connector->base,
+				i915->wb_out_fence_ptr_property, 0);

-:198: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#198: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:169:
+	drm_object_attach_property(&connector->base,
+				i915->wb_fb_id_property, 0);

-:201: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#201: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:172:
+	drm_object_attach_property(&connector->base,
+				i915->wb_pixel_formats_property,

-:217: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#217: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:188:
+void intel_writeback_queue_job(struct intel_writeback_connector *wb_connector,
+		struct drm_connector_state *conn_state)

-:233: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#233: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:204:
+int intel_writeback_set_fb(struct drm_connector_state *conn_state,
+			 struct drm_framebuffer *fb)

-:276: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#276: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:247:
+intel_writeback_signal_completion(struct intel_writeback_connector *wb_connector,
+				int status)

-:284: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#284: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:255:
+	job = list_first_entry_or_null(&wb_connector->job_queue,
+					struct intel_writeback_job,

-:321: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#321: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:292:
+	dma_fence_init(fence, &intel_writeback_fence_ops,
+		&wb_connector->fence_lock, wb_connector->fence_context,

-:378: CHECK:UNCOMMENTED_DEFINITION: spinlock_t definition without comment
#378: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:47:
+	spinlock_t job_lock;

-:381: CHECK:UNCOMMENTED_DEFINITION: spinlock_t definition without comment
#381: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:50:
+	spinlock_t fence_lock;

-:400: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#400: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:69:
+int intel_writeback_connector_init(struct drm_device *dev,
+			struct intel_writeback_connector *wb_connector,

-:406: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#406: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:75:
+int intel_writeback_set_fb(struct drm_connector_state *conn_state,
+			struct drm_framebuffer *fb);

-:411: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#411: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:80:
+void intel_writeback_queue_job(struct intel_writeback_connector *wb_connector,
+			struct drm_connector_state *conn_state);

-:417: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#417: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:86:
+intel_writeback_signal_completion(struct intel_writeback_connector *wb_connector,
+			int status);

-:427: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#427: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:96:
+void intel_wb_connector_attach_encoder(struct intel_wb_connector *connector,
+					struct intel_encoder *encoder);

total: 0 errors, 1 warnings, 24 checks, 411 lines checked
7d4110d6e4d1 drm/i915: Define WD trancoder for i915
fcaf50c2dbca drm/i915: Enabling WD Transcoder
-:52: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#52: FILE: drivers/gpu/drm/i915/display/intel_display.c:1549:
+static void intel_queue_writeback_job(struct intel_atomic_state *state,
+		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)

-:69: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#69: FILE: drivers/gpu/drm/i915/display/intel_display.c:1566:
+
+	}

-:83: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#83: FILE: drivers/gpu/drm/i915/display/intel_display.c:1580:
+static void intel_find_writeback_connector(struct intel_atomic_state *state,
+		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)

-:98: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#98: FILE: drivers/gpu/drm/i915/display/intel_display.c:1595:
+
+	}

-:106: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#106: FILE: drivers/gpu/drm/i915/display/intel_display.c:1603:
+		drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]: status: %s\n",
+				connector->base.id, connector->name,

-:115: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#115: FILE: drivers/gpu/drm/i915/display/intel_display.c:1612:
+
+}

-:200: ERROR:COMPLEX_MACRO: Macros with complex values should be enclosed in parentheses
#200: FILE: drivers/gpu/drm/i915/display/intel_display.h:475:
+#define for_each_intel_encoder_with_wd(dev, intel_encoder)	\
+	for_each_intel_encoder(dev, intel_encoder)		\
+		for_each_if(intel_encoder_is_wd(intel_encoder))

-:200: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'intel_encoder' - possible side-effects?
#200: FILE: drivers/gpu/drm/i915/display/intel_display.h:475:
+#define for_each_intel_encoder_with_wd(dev, intel_encoder)	\
+	for_each_intel_encoder(dev, intel_encoder)		\
+		for_each_if(intel_encoder_is_wd(intel_encoder))

-:307: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#307: 
new file mode 100644

-:367: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#367: FILE: drivers/gpu/drm/i915/display/intel_wd.c:56:
+	job = list_first_entry_or_null(&wb_conn->job_queue,
+			struct intel_writeback_job,

-:370: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "!job"
#370: FILE: drivers/gpu/drm/i915/display/intel_wd.c:59:
+	if (job == NULL) {

-:389: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#389: FILE: drivers/gpu/drm/i915/display/intel_wd.c:78:
+		drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]: status: %s\n",
+			connector->base.id, connector->name,

-:427: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#427: FILE: drivers/gpu/drm/i915/display/intel_wd.c:116:
+		DRM_ERROR("unsupported pixel format %x!\n",
+			pixel_format);

-:447: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#447: FILE: drivers/gpu/drm/i915/display/intel_wd.c:136:
+static u32 intel_wd_get_stride(const struct intel_crtc_state *crtc_state,
+			int format)

-:473: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#473: FILE: drivers/gpu/drm/i915/display/intel_wd.c:162:
+static int intel_wd_pin_fb(struct intel_wd *intel_wd,
+			struct drm_framebuffer *fb)

-:481: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#481: FILE: drivers/gpu/drm/i915/display/intel_wd.c:170:
+	vma = intel_pin_and_fence_fb_obj(fb, false, &view, false,
+			&intel_wd->flags);

-:491: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#491: FILE: drivers/gpu/drm/i915/display/intel_wd.c:180:
+static void intel_configure_slicing_strategy(struct drm_i915_private *i915,
+		struct intel_wd *intel_wd, u32 *tmp)

-:504: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#504: FILE: drivers/gpu/drm/i915/display/intel_wd.c:193:
+	intel_de_write(i915, WD_STREAMCAP_CTL(intel_wd->trans),
+			*tmp);

-:506: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#506: FILE: drivers/gpu/drm/i915/display/intel_wd.c:195:
+
+}

-:510: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#510: FILE: drivers/gpu/drm/i915/display/intel_wd.c:199:
+intel_wd_mode_valid(struct drm_connector *connector,
+		struct drm_display_mode *mode)

-:521: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#521: FILE: drivers/gpu/drm/i915/display/intel_wd.c:210:
+static void intel_wd_get_config(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config)

-:530: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#530: FILE: drivers/gpu/drm/i915/display/intel_wd.c:219:
+		memcpy(pipe_config, intel_crtc->config,
+			sizeof(*pipe_config));

-:535: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#535: FILE: drivers/gpu/drm/i915/display/intel_wd.c:224:
+
+}

-:538: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#538: FILE: drivers/gpu/drm/i915/display/intel_wd.c:227:
+static int intel_wd_compute_config(struct intel_encoder *encoder,
+			struct intel_crtc_state *pipe_config,

-:559: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#559: FILE: drivers/gpu/drm/i915/display/intel_wd.c:248:
+static void intel_wd_get_power_domains(struct intel_encoder *encoder,
+			struct intel_crtc_state *crtc_state)

-:566: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#566: FILE: drivers/gpu/drm/i915/display/intel_wd.c:255:
+	wakeref = intel_display_power_get(i915,
+				encoder->power_domain);

-:573: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#573: FILE: drivers/gpu/drm/i915/display/intel_wd.c:262:
+static bool intel_wd_get_hw_state(struct intel_encoder *encoder,
+		enum pipe *pipe)

-:586: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#586: FILE: drivers/gpu/drm/i915/display/intel_wd.c:275:
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+				encoder->power_domain);

-:588: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#588: FILE: drivers/gpu/drm/i915/display/intel_wd.c:277:
+	drm_dbg_kms(encoder->base.dev, "power enabled : %s\n",
+			!wakeref ? "false":"true");

-:588: CHECK:SPACING: spaces required around that ':' (ctx:VxV)
#588: FILE: drivers/gpu/drm/i915/display/intel_wd.c:277:
+			!wakeref ? "false":"true");
 			                  ^

-:596: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#596: FILE: drivers/gpu/drm/i915/display/intel_wd.c:285:
+	drm_dbg_kms(encoder->base.dev, "trancoder enabled: %s\n",
+			ret ? "true":"false");

-:596: CHECK:SPACING: spaces required around that ':' (ctx:VxV)
#596: FILE: drivers/gpu/drm/i915/display/intel_wd.c:285:
+			ret ? "true":"false");
 			            ^

-:600: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#600: FILE: drivers/gpu/drm/i915/display/intel_wd.c:289:
+		drm_dbg_kms(encoder->base.dev, "pipe selected is %d\n",
+			wd_crtc->pipe);

-:606: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#606: FILE: drivers/gpu/drm/i915/display/intel_wd.c:295:
+static int intel_wd_encoder_atomic_check(struct drm_encoder *encoder,
+				    struct drm_crtc_state *crtc_st,

-:634: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#634: FILE: drivers/gpu/drm/i915/display/intel_wd.c:323:
+		drm_dbg_kms(&i915->drm, "Invalid framebuffer size %ux%u\n",
+				fb->width, fb->height);

-:642: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#642: FILE: drivers/gpu/drm/i915/display/intel_wd.c:331:
+		drm_dbg_kms(&i915->drm, "Unsupported framebuffer format %08x\n",
+				fb->format->format);

-:649: CHECK:LINE_SPACING: Please don't use multiple blank lines
#649: FILE: drivers/gpu/drm/i915/display/intel_wd.c:338:
+
+

-:668: CHECK:OPEN_ENDED_LINE: Lines should not end with a '('
#668: FILE: drivers/gpu/drm/i915/display/intel_wd.c:357:
+static int intel_atomic_set_writeback_fb_for_connector(

-:681: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#681: FILE: drivers/gpu/drm/i915/display/intel_wd.c:370:
+		drm_dbg_atomic(conn->dev,
+			"Set [FB:%d] for connector state %p\n",

-:685: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#685: FILE: drivers/gpu/drm/i915/display/intel_wd.c:374:
+		drm_dbg_atomic(conn->dev,
+			"Set [NOFB] for connector state %p\n",

-:692: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#692: FILE: drivers/gpu/drm/i915/display/intel_wd.c:381:
+static int set_out_fence_for_connector(struct drm_atomic_state *state,
+					struct drm_connector *connector,

-:709: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#709: FILE: drivers/gpu/drm/i915/display/intel_wd.c:398:
+struct drm_mode_object *__intel_object_find(struct drm_device *dev,
+					       uint32_t id, uint32_t type)

-:709: CHECK:PREFER_KERNEL_TYPES: Prefer kernel type 'u32' over 'uint32_t'
#709: FILE: drivers/gpu/drm/i915/display/intel_wd.c:398:
+					       uint32_t id, uint32_t type)

-:729: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#729: FILE: drivers/gpu/drm/i915/display/intel_wd.c:418:
+struct drm_framebuffer *intel_wb_framebuffer_lookup(struct drm_device *dev,
+					       uint32_t id)

-:741: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#741: FILE: drivers/gpu/drm/i915/display/intel_wd.c:430:
+static s32 __user *intel_get_out_fence_for_connector(struct drm_atomic_state *state,
+					       struct drm_connector *connector)

-:753: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#753: FILE: drivers/gpu/drm/i915/display/intel_wd.c:442:
+static int intel_setup_out_fence(struct intel_out_fence_state *fence_state,
+			   struct dma_fence *fence)

-:755: CHECK:BRACES: Blank lines aren't necessary after an open brace '{'
#755: FILE: drivers/gpu/drm/i915/display/intel_wd.c:444:
+{
+

-:771: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#771: FILE: drivers/gpu/drm/i915/display/intel_wd.c:460:
+int intel_wd_prepare_out_fence(struct drm_device *dev,
+				struct drm_atomic_state *state)

-:825: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#825: FILE: drivers/gpu/drm/i915/display/intel_wd.c:514:
+	fd_install(fence_state->fd,
+		fence_state->sync_file->file);

-:827: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#827: FILE: drivers/gpu/drm/i915/display/intel_wd.c:516:
+
+}

-:830: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#830: FILE: drivers/gpu/drm/i915/display/intel_wd.c:519:
+static int intel_set_writeback_property(struct drm_connector *connector,
+	struct drm_connector_state *state, struct drm_property *property,

-:852: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#852: FILE: drivers/gpu/drm/i915/display/intel_wd.c:541:
+		drm_dbg_atomic(connector->dev,
+			"[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",

-:860: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#860: FILE: drivers/gpu/drm/i915/display/intel_wd.c:549:
+
+}

-:863: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#863: FILE: drivers/gpu/drm/i915/display/intel_wd.c:552:
+static int intel_get_writeback_property(struct drm_connector *connector,
+	const struct drm_connector_state *state, struct drm_property *property,

-:869: CHECK:BRACES: braces {} should be used on all arms of this statement
#869: FILE: drivers/gpu/drm/i915/display/intel_wd.c:558:
+	if (property == i915->wb_fb_id_property)
[...]
+	else if (property == i915->wb_out_fence_ptr_property)
[...]
+	else {
[...]

-:873: CHECK:BRACES: Unbalanced braces around else statement
#873: FILE: drivers/gpu/drm/i915/display/intel_wd.c:562:
+	else {

-:875: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#875: FILE: drivers/gpu/drm/i915/display/intel_wd.c:564:
+		drm_dbg_atomic(&i915->drm,
+				"Unknown property [PROP:%d:%s]\n",

-:900: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#900: FILE: drivers/gpu/drm/i915/display/intel_wd.c:589:
+static bool intel_fastset_dis(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config)

-:960: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#960: FILE: drivers/gpu/drm/i915/display/intel_wd.c:649:
+	err = intel_writeback_connector_init(&i915->drm, wb_conn,
+		&wd_connector_funcs,

-:966: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#966: FILE: drivers/gpu/drm/i915/display/intel_wd.c:655:
+		drm_dbg_kms(&i915->drm,
+		"intel_writeback_connector_init: Failed: %d\n",

-:982: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#982: FILE: drivers/gpu/drm/i915/display/intel_wd.c:671:
+void intel_wd_writeback_complete(struct intel_wd *intel_wd,
+	struct intel_writeback_job *job, int status)

-:991: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#991: FILE: drivers/gpu/drm/i915/display/intel_wd.c:680:
+int intel_wd_setup_transcoder(struct intel_wd *intel_wd,
+		struct intel_crtc_state *pipe_config,

-:1025: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1025: FILE: drivers/gpu/drm/i915/display/intel_wd.c:714:
+	intel_de_write(dev_priv, WD_SURF(intel_wd->trans),
+			i915_ggtt_offset(intel_wd->vma));

-:1030: CHECK:SPACING: spaces preferred around that '|' (ctx:VxV)
#1030: FILE: drivers/gpu/drm/i915/display/intel_wd.c:719:
+	tmp = ~(WD_GTT_FAULT_INT|WD_WRITE_COMPLETE_INT|WD_FRAME_COMPLETE_INT|
 	                        ^

-:1030: CHECK:SPACING: spaces preferred around that '|' (ctx:VxV)
#1030: FILE: drivers/gpu/drm/i915/display/intel_wd.c:719:
+	tmp = ~(WD_GTT_FAULT_INT|WD_WRITE_COMPLETE_INT|WD_FRAME_COMPLETE_INT|
 	                                              ^

-:1030: CHECK:SPACING: space preferred before that '|' (ctx:VxE)
#1030: FILE: drivers/gpu/drm/i915/display/intel_wd.c:719:
+	tmp = ~(WD_GTT_FAULT_INT|WD_WRITE_COMPLETE_INT|WD_FRAME_COMPLETE_INT|
 	                                                                    ^

-:1031: CHECK:SPACING: spaces preferred around that '|' (ctx:VxV)
#1031: FILE: drivers/gpu/drm/i915/display/intel_wd.c:720:
+			WD_VBLANK_INT|WD_OVERRUN_INT|WD_CAPTURING_INT);
 			             ^

-:1031: CHECK:SPACING: spaces preferred around that '|' (ctx:VxV)
#1031: FILE: drivers/gpu/drm/i915/display/intel_wd.c:720:
+			WD_VBLANK_INT|WD_OVERRUN_INT|WD_CAPTURING_INT);
 			                            ^

-:1036: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1036: FILE: drivers/gpu/drm/i915/display/intel_wd.c:725:
+		tmp = intel_de_read(dev_priv,
+				WD_STREAMCAP_CTL(intel_wd->trans));

-:1121: CHECK:SPACING: spaces required around that ':' (ctx:VxV)
#1121: FILE: drivers/gpu/drm/i915/display/intel_wd.c:810:
+	drm_dbg_kms(&dev_priv->drm, "Trancoder enabled: %s\n", ret ? "true":"false");
 	                                                                   ^

-:1131: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1131: FILE: drivers/gpu/drm/i915/display/intel_wd.c:820:
+		if (intel_de_wait_for_set(dev_priv, PIPECONF(intel_wd->trans),
+				WD_TRANS_ACTIVE, 10))

-:1149: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1149: FILE: drivers/gpu/drm/i915/display/intel_wd.c:838:
+	drm_dbg_kms(&dev_priv->drm, "WD Trans_Conf value after disable = 0x%08x\n",
+		intel_de_read(dev_priv, PIPECONF(intel_wd->trans)));

-:1155: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1155: FILE: drivers/gpu/drm/i915/display/intel_wd.c:844:
+int intel_wd_capture(struct intel_wd *intel_wd,
+		struct intel_crtc_state *pipe_config,

-:1173: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1173: FILE: drivers/gpu/drm/i915/display/intel_wd.c:862:
+		drm_dbg_kms(&i915->drm,
+		"wd transcoder setup not completed aborting capture\n");

-:1177: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "!wd_crtc"
#1177: FILE: drivers/gpu/drm/i915/display/intel_wd.c:866:
+	if (wd_crtc == NULL) {

-:1183: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1183: FILE: drivers/gpu/drm/i915/display/intel_wd.c:872:
+	tmp = intel_de_read_fw(i915,
+			WD_TRANS_FUNC_CTL(intel_wd->trans));

-:1188: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1188: FILE: drivers/gpu/drm/i915/display/intel_wd.c:877:
+	intel_de_write_fw(i915,
+			WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);

-:1191: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1191: FILE: drivers/gpu/drm/i915/display/intel_wd.c:880:
+	if (!intel_de_wait_for_set(i915, WD_IIR(intel_wd->trans),
+				WD_FRAME_COMPLETE_INT, 100)){

-:1199: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1199: FILE: drivers/gpu/drm/i915/display/intel_wd.c:888:
+		tmp = intel_de_read(i915,
+				WD_TRANS_FUNC_CTL(intel_wd->trans));

-:1202: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1202: FILE: drivers/gpu/drm/i915/display/intel_wd.c:891:
+		intel_de_write(i915,
+				WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);

-:1208: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "!intel_get_writeback_job_from_queue"
#1208: FILE: drivers/gpu/drm/i915/display/intel_wd.c:897:
+	if (intel_get_writeback_job_from_queue(intel_wd) == NULL)

-:1214: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1214: FILE: drivers/gpu/drm/i915/display/intel_wd.c:903:
+		drm_crtc_send_vblank_event(&wd_crtc->base,
+					wd_crtc->wd.e);

-:1219: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1219: FILE: drivers/gpu/drm/i915/display/intel_wd.c:908:
+		DRM_ERROR("Event NULL! %p, %p\n", &i915->drm,
+			wd_crtc);

-:1223: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#1223: FILE: drivers/gpu/drm/i915/display/intel_wd.c:912:
+
+}

-:1226: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1226: FILE: drivers/gpu/drm/i915/display/intel_wd.c:915:
+void intel_wd_enable_capture(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config,

-:1236: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "!job"
#1236: FILE: drivers/gpu/drm/i915/display/intel_wd.c:925:
+	if (job == NULL) {

-:1238: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1238: FILE: drivers/gpu/drm/i915/display/intel_wd.c:927:
+		drm_dbg_kms(&i915->drm,
+			"job queue is empty not capturing any frame\n");

-:1245: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#1245: FILE: drivers/gpu/drm/i915/display/intel_wd.c:934:
+
+}

-:1248: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1248: FILE: drivers/gpu/drm/i915/display/intel_wd.c:937:
+void intel_wd_set_vblank_event(struct intel_crtc *intel_crtc,
+			struct intel_crtc_state *intel_crtc_state)

-:1269: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1269: FILE: drivers/gpu/drm/i915/display/intel_wd.c:958:
+			drm_dbg_kms(&i915->drm, "WD event:%p\n",
+				intel_crtc->wd.e);

-:1297: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1297: FILE: drivers/gpu/drm/i915/display/intel_wd.c:986:
+		drm_dbg_kms(&i915->drm,
+		"wd write complete interrupt encountered\n");

-:1302: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1302: FILE: drivers/gpu/drm/i915/display/intel_wd.c:991:
+		drm_dbg_kms(&i915->drm,
+			"frame complete interrupt for wd transcoder\n");

-:1380: CHECK:AVOID_EXTERNS: extern prototypes should be avoided in .h files
#1380: FILE: drivers/gpu/drm/i915/display/intel_wd.h:67:
+extern struct sync_file *sync_file_create(struct dma_fence *fence);

-:1385: CHECK:LINE_SPACING: Please use a blank line after function/struct/union/enum declarations
#1385: FILE: drivers/gpu/drm/i915/display/intel_wd.h:72:
+}
+void intel_wd_init(struct drm_i915_private *dev_priv, enum transcoder trans);

-:1387: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1387: FILE: drivers/gpu/drm/i915/display/intel_wd.h:74:
+void intel_wd_enable_capture(struct intel_encoder *encoder,
+				struct intel_crtc_state *pipe_config,

-:1391: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1391: FILE: drivers/gpu/drm/i915/display/intel_wd.h:78:
+void intel_wd_set_vblank_event(struct intel_crtc *crtc,
+				struct intel_crtc_state *state);

-:1393: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1393: FILE: drivers/gpu/drm/i915/display/intel_wd.h:80:
+int intel_wd_prepare_out_fence(struct drm_device *dev,
+				struct drm_atomic_state *state);

-:1451: CHECK:SPACING: spaces preferred around that '|' (ctx:VxE)
#1451: FILE: drivers/gpu/drm/i915/i915_pci.c:856:
+		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1)| \
 		                                             ^

-:1486: CHECK:LINE_SPACING: Please don't use multiple blank lines
#1486: FILE: drivers/gpu/drm/i915/i915_reg.h:3804:
+
+

total: 1 errors, 1 warnings, 97 checks, 1545 lines checked



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

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for i915 writeback private framework
  2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
                   ` (3 preceding siblings ...)
  2022-03-16  9:51 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915 writeback private framework Patchwork
@ 2022-03-16  9:52 ` Patchwork
  2022-03-16 10:07 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2022-03-16  9:52 UTC (permalink / raw)
  To: Suraj Kandpal; +Cc: intel-gfx

== Series Details ==

Series: i915 writeback private framework
URL   : https://patchwork.freedesktop.org/series/101425/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.



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

* [Intel-gfx] ✗ Fi.CI.BAT: failure for i915 writeback private framework
  2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
                   ` (4 preceding siblings ...)
  2022-03-16  9:52 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
@ 2022-03-16 10:07 ` Patchwork
  2022-03-17  8:39 ` [Intel-gfx] [RFC PATCH v2 0/3] " Suraj Kandpal
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2022-03-16 10:07 UTC (permalink / raw)
  To: Suraj Kandpal; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 8675 bytes --]

== Series Details ==

Series: i915 writeback private framework
URL   : https://patchwork.freedesktop.org/series/101425/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_11368 -> Patchwork_22583
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_22583 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_22583, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/index.html

Participating hosts (45 -> 39)
------------------------------

  Additional (1): bat-adls-5 
  Missing    (7): fi-kbl-soraka fi-hsw-4200u bat-dg2-8 fi-bsw-cyan fi-ctg-p8600 fi-pnv-d510 fi-bdw-samus 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_22583:

### IGT changes ###

#### Possible regressions ####

  * igt@runner@aborted:
    - fi-bwr-2160:        NOTRUN -> [FAIL][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-bwr-2160/igt@runner@aborted.html

  
#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@runner@aborted:
    - {fi-rkl-11600}:     NOTRUN -> [FAIL][2]
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-rkl-11600/igt@runner@aborted.html
    - {bat-jsl-2}:        NOTRUN -> [FAIL][3]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/bat-jsl-2/igt@runner@aborted.html
    - {fi-jsl-1}:         NOTRUN -> [FAIL][4]
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-jsl-1/igt@runner@aborted.html
    - {bat-jsl-1}:        NOTRUN -> [FAIL][5]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/bat-jsl-1/igt@runner@aborted.html
    - {fi-ehl-2}:         NOTRUN -> [FAIL][6]
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-ehl-2/igt@runner@aborted.html

  
Known issues
------------

  Here are the changes found in Patchwork_22583 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@runner@aborted:
    - fi-snb-2600:        NOTRUN -> [FAIL][7] ([i915#2426])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-snb-2600/igt@runner@aborted.html
    - fi-ilk-650:         NOTRUN -> [FAIL][8] ([i915#2426])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-ilk-650/igt@runner@aborted.html
    - fi-kbl-x1275:       NOTRUN -> [FAIL][9] ([i915#2426])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-kbl-x1275/igt@runner@aborted.html
    - fi-bsw-kefka:       NOTRUN -> [FAIL][10] ([i915#3690])
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-bsw-kefka/igt@runner@aborted.html
    - fi-bdw-gvtdvm:      NOTRUN -> [FAIL][11] ([i915#2426])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-bdw-gvtdvm/igt@runner@aborted.html
    - fi-cfl-8700k:       NOTRUN -> [FAIL][12] ([i915#2426])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-cfl-8700k/igt@runner@aborted.html
    - fi-cfl-8109u:       NOTRUN -> [FAIL][13] ([i915#2426])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-cfl-8109u/igt@runner@aborted.html
    - fi-glk-dsi:         NOTRUN -> [FAIL][14] ([i915#2426] / [k.org#202321])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-glk-dsi/igt@runner@aborted.html
    - fi-bsw-nick:        NOTRUN -> [FAIL][15] ([i915#3690])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-bsw-nick/igt@runner@aborted.html
    - fi-kbl-8809g:       NOTRUN -> [FAIL][16] ([i915#2426])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-kbl-8809g/igt@runner@aborted.html
    - fi-snb-2520m:       NOTRUN -> [FAIL][17] ([i915#2426])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-snb-2520m/igt@runner@aborted.html
    - fi-bdw-5557u:       NOTRUN -> [FAIL][18] ([i915#2426])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-bdw-5557u/igt@runner@aborted.html
    - fi-hsw-4770:        NOTRUN -> [FAIL][19] ([i915#5317])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-hsw-4770/igt@runner@aborted.html
    - fi-kbl-7500u:       NOTRUN -> [FAIL][20] ([i915#2426])
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-kbl-7500u/igt@runner@aborted.html
    - fi-kbl-guc:         NOTRUN -> [FAIL][21] ([i915#2426])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-kbl-guc/igt@runner@aborted.html
    - fi-rkl-guc:         NOTRUN -> [FAIL][22] ([i915#2426])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-rkl-guc/igt@runner@aborted.html
    - fi-ivb-3770:        NOTRUN -> [FAIL][23] ([i915#2426])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-ivb-3770/igt@runner@aborted.html
    - fi-bxt-dsi:         NOTRUN -> [FAIL][24] ([i915#2426])
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-bxt-dsi/igt@runner@aborted.html
    - fi-tgl-1115g4:      NOTRUN -> [FAIL][25] ([i915#5257])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-tgl-1115g4/igt@runner@aborted.html
    - fi-elk-e7500:       NOTRUN -> [FAIL][26] ([i915#2426])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-elk-e7500/igt@runner@aborted.html
    - fi-cfl-guc:         NOTRUN -> [FAIL][27] ([i915#2426])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-cfl-guc/igt@runner@aborted.html
    - fi-glk-j4005:       NOTRUN -> [FAIL][28] ([i915#2426] / [k.org#202321])
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-glk-j4005/igt@runner@aborted.html
    - fi-kbl-7567u:       NOTRUN -> [FAIL][29] ([i915#2426])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-kbl-7567u/igt@runner@aborted.html
    - fi-skl-guc:         NOTRUN -> [FAIL][30] ([i915#2426])
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-skl-guc/igt@runner@aborted.html
    - fi-skl-6700k2:      NOTRUN -> [FAIL][31] ([i915#2426])
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-skl-6700k2/igt@runner@aborted.html
    - fi-bsw-n3050:       NOTRUN -> [FAIL][32] ([i915#3690])
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-bsw-n3050/igt@runner@aborted.html
    - fi-blb-e6850:       NOTRUN -> [FAIL][33] ([i915#2403] / [i915#2426])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-blb-e6850/igt@runner@aborted.html

  
#### Warnings ####

  * igt@runner@aborted:
    - fi-apl-guc:         [FAIL][34] ([i915#2426] / [i915#4312]) -> [FAIL][35] ([i915#2426])
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11368/fi-apl-guc/igt@runner@aborted.html
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/fi-apl-guc/igt@runner@aborted.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [i915#2403]: https://gitlab.freedesktop.org/drm/intel/issues/2403
  [i915#2426]: https://gitlab.freedesktop.org/drm/intel/issues/2426
  [i915#3690]: https://gitlab.freedesktop.org/drm/intel/issues/3690
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4897]: https://gitlab.freedesktop.org/drm/intel/issues/4897
  [i915#5169]: https://gitlab.freedesktop.org/drm/intel/issues/5169
  [i915#5257]: https://gitlab.freedesktop.org/drm/intel/issues/5257
  [i915#5269]: https://gitlab.freedesktop.org/drm/intel/issues/5269
  [i915#5317]: https://gitlab.freedesktop.org/drm/intel/issues/5317
  [k.org#202321]: https://bugzilla.kernel.org/show_bug.cgi?id=202321


Build changes
-------------

  * Linux: CI_DRM_11368 -> Patchwork_22583

  CI-20190529: 20190529
  CI_DRM_11368: 66b3d1ac616565206cddf4327ca7c102b651b032 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6382: a6a5a178cb1cbe0dab8d8d092a4aee932ccb93cc @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_22583: fcaf50c2dbca5c75e4bcfd0f9a4386be28d174c7 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

fcaf50c2dbca drm/i915: Enabling WD Transcoder
7d4110d6e4d1 drm/i915: Define WD trancoder for i915
91a1acb1ae9e drm/i915: Creating writeback pipeline to bypass drm_writeback framework

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22583/index.html

[-- Attachment #2: Type: text/html, Size: 11330 bytes --]

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

* Re: [Intel-gfx] [RFC PATCH 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework
  2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework Suraj Kandpal
@ 2022-03-16 14:25   ` kernel test robot
  2022-03-18  4:18   ` [Intel-gfx] [RFC PATCH v2 " Suraj Kandpal
  1 sibling, 0 replies; 24+ messages in thread
From: kernel test robot @ 2022-03-16 14:25 UTC (permalink / raw)
  To: Suraj Kandpal; +Cc: llvm, kbuild-all

Hi Suraj,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on drm-intel/for-linux-next]
[also build test WARNING on drm-tip/drm-tip v5.17-rc8 next-20220315]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Suraj-Kandpal/i915-writeback-private-framework/20220316-174317
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-randconfig-a013 (https://download.01.org/0day-ci/archive/20220316/202203162207.xVTqzi0V-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project a6ec1e3d798f8eab43fb3a91028c6ab04e115fcb)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/5683a14535c9ba3bfd04906488c10a89e0fedacd
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Suraj-Kandpal/i915-writeback-private-framework/20220316-174317
        git checkout 5683a14535c9ba3bfd04906488c10a89e0fedacd
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/gpu/drm/i915/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/i915/display/intel_wb_connector.c:195:29: error: no member named 'job' in 'struct intel_digital_connector_state'
           wb_job = intel_conn_state->job;
                    ~~~~~~~~~~~~~~~~  ^
   drivers/gpu/drm/i915/display/intel_wb_connector.c:196:20: error: no member named 'job' in 'struct intel_digital_connector_state'
           intel_conn_state->job = NULL;
           ~~~~~~~~~~~~~~~~  ^
   drivers/gpu/drm/i915/display/intel_wb_connector.c:207:69: error: no member named 'wb_conn' in 'struct intel_connector'
           struct intel_writeback_connector *wb_connector = &intel_connector->wb_conn;
                                                             ~~~~~~~~~~~~~~~  ^
   drivers/gpu/drm/i915/display/intel_wb_connector.c:212:25: error: no member named 'job' in 'struct intel_digital_connector_state'
           if (!intel_conn_state->job) {
                ~~~~~~~~~~~~~~~~  ^
   drivers/gpu/drm/i915/display/intel_wb_connector.c:213:21: error: no member named 'job' in 'struct intel_digital_connector_state'
                   intel_conn_state->job =
                   ~~~~~~~~~~~~~~~~  ^
   drivers/gpu/drm/i915/display/intel_wb_connector.c:214:38: error: no member named 'job' in 'struct intel_digital_connector_state'
                           kzalloc(sizeof(*intel_conn_state->job), GFP_KERNEL);
                                           ~~~~~~~~~~~~~~~~  ^
   drivers/gpu/drm/i915/display/intel_wb_connector.c:215:26: error: no member named 'job' in 'struct intel_digital_connector_state'
                   if (!intel_conn_state->job)
                        ~~~~~~~~~~~~~~~~  ^
   drivers/gpu/drm/i915/display/intel_wb_connector.c:218:21: error: no member named 'job' in 'struct intel_digital_connector_state'
                   intel_conn_state->job->connector = wb_connector;
                   ~~~~~~~~~~~~~~~~  ^
   drivers/gpu/drm/i915/display/intel_wb_connector.c:221:44: error: no member named 'job' in 'struct intel_digital_connector_state'
           drm_framebuffer_assign(&intel_conn_state->job->fb, fb);
                                   ~~~~~~~~~~~~~~~~  ^
>> drivers/gpu/drm/i915/display/intel_wb_connector.c:236:6: warning: no previous prototype for function 'cleanup_work' [-Wmissing-prototypes]
   void cleanup_work(struct work_struct *work)
        ^
   drivers/gpu/drm/i915/display/intel_wb_connector.c:236:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void cleanup_work(struct work_struct *work)
   ^
   static 
   1 warning and 9 errors generated.


vim +/cleanup_work +236 drivers/gpu/drm/i915/display/intel_wb_connector.c

   202	
   203	int intel_writeback_set_fb(struct drm_connector_state *conn_state,
   204				 struct drm_framebuffer *fb)
   205	{
   206		struct intel_connector *intel_connector = to_intel_connector(conn_state->connector);
   207		struct intel_writeback_connector *wb_connector = &intel_connector->wb_conn;
   208		struct intel_digital_connector_state *intel_conn_state =
   209			to_intel_digital_connector_state(conn_state);
   210		WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
   211	
   212		if (!intel_conn_state->job) {
   213			intel_conn_state->job =
   214				kzalloc(sizeof(*intel_conn_state->job), GFP_KERNEL);
 > 215			if (!intel_conn_state->job)
   216				return -ENOMEM;
   217	
   218			intel_conn_state->job->connector = wb_connector;
   219		}
   220	
   221		drm_framebuffer_assign(&intel_conn_state->job->fb, fb);
   222		return 0;
   223	}
   224	
   225	void intel_writeback_cleanup_job(struct intel_writeback_job *job)
   226	{
   227		if (job->fb)
   228			drm_framebuffer_put(job->fb);
   229	
   230		if (job->out_fence)
   231			dma_fence_put(job->out_fence);
   232	
   233		kfree(job);
   234	}
   235	
 > 236	void cleanup_work(struct work_struct *work)
   237	{
   238		struct intel_writeback_job *job = container_of(work,
   239							struct intel_writeback_job,
   240							cleanup_work);
   241	
   242		intel_writeback_cleanup_job(job);
   243	}
   244	

---
0-DAY CI Kernel Test Service
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

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

* [Intel-gfx] [RFC PATCH v2 0/3] i915 writeback private framework
  2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
                   ` (5 preceding siblings ...)
  2022-03-16 10:07 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
@ 2022-03-17  8:39 ` Suraj Kandpal
  2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework Suraj Kandpal
                     ` (3 more replies)
  2022-03-18  4:48 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915 writeback private framework (rev4) Patchwork
                   ` (3 subsequent siblings)
  10 siblings, 4 replies; 24+ messages in thread
From: Suraj Kandpal @ 2022-03-17  8:39 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

A patch series was floated in the drm mailing list which aimed to change
the drm_connector and drm_encoder fields to pointer in the
drm_connector_writeback structure, this received a huge pushback from
the community but since i915 expects each connector present in the
drm_device list to be a intel_connector but drm_writeback framework
forces us to use a drm_connector which is not embedded in
intel_connector the current drm_writeback framework becomes very
unfeasible to us as it would mean a lot of checks at a lot of places
to take into account the above issue. One of the solutions is to
make our own writeback pipeline bypassing one provided by drm
which is what these patches do.

-----
Version 2:
adding fixes to avoid regression in previous gen and some basic
checkpatch changes.

Suraj Kandpal (3):
  drm/i915: Creating writeback pipeline to bypass drm_writeback
    framework
  drm/i915: Define WD trancoder for i915
  drm/i915: Enabling WD Transcoder

 drivers/gpu/drm/i915/Makefile                 |   2 +
 drivers/gpu/drm/i915/display/intel_acpi.c     |   1 +
 drivers/gpu/drm/i915/display/intel_display.c  |  89 +-
 drivers/gpu/drm/i915/display/intel_display.h  |  15 +
 .../drm/i915/display/intel_display_types.h    |  18 +
 drivers/gpu/drm/i915/display/intel_dpll.c     |   3 +
 drivers/gpu/drm/i915/display/intel_opregion.c |   3 +
 .../gpu/drm/i915/display/intel_wb_connector.c | 296 ++++++
 .../gpu/drm/i915/display/intel_wb_connector.h |  99 ++
 drivers/gpu/drm/i915/display/intel_wd.c       | 978 ++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_wd.h       |  82 ++
 drivers/gpu/drm/i915/i915_drv.h               |   5 +
 drivers/gpu/drm/i915/i915_irq.c               |   8 +-
 drivers/gpu/drm/i915/i915_pci.c               |   7 +-
 drivers/gpu/drm/i915/i915_reg.h               | 139 +++
 15 files changed, 1742 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_wd.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_wd.h

-- 
2.35.1


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

* [Intel-gfx] [RFC PATCH v2 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework
  2022-03-17  8:39 ` [Intel-gfx] [RFC PATCH v2 0/3] " Suraj Kandpal
@ 2022-03-17  8:39   ` Suraj Kandpal
  2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 2/3] drm/i915: Define WD trancoder for i915 Suraj Kandpal
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 24+ messages in thread
From: Suraj Kandpal @ 2022-03-17  8:39 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Changes to create a i915 private pipeline to enable the WD transcoder
without relying on the current drm_writeback framework.

Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 .../drm/i915/display/intel_display_types.h    |   4 +
 .../gpu/drm/i915/display/intel_wb_connector.c | 296 ++++++++++++++++++
 .../gpu/drm/i915/display/intel_wb_connector.h |  99 ++++++
 drivers/gpu/drm/i915/i915_drv.h               |   3 +
 5 files changed, 403 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 1a771ee5b1d0..087bd9d1b397 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -286,6 +286,7 @@ i915-y += \
 	display/intel_tv.o \
 	display/intel_vdsc.o \
 	display/intel_vrr.o \
+	display/intel_wb_connector.o\
 	display/vlv_dsi.o \
 	display/vlv_dsi_pll.o
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index d84e82f3eab9..7a96ecba73c0 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -52,6 +52,7 @@
 #include "intel_display_power.h"
 #include "intel_dpll_mgr.h"
 #include "intel_pm_types.h"
+#include "intel_wb_connector.h"
 
 struct drm_printer;
 struct __intel_global_objs_state;
@@ -537,11 +538,14 @@ struct intel_connector {
 	struct work_struct modeset_retry_work;
 
 	struct intel_hdcp hdcp;
+
+	struct intel_writeback_connector wb_conn;
 };
 
 struct intel_digital_connector_state {
 	struct drm_connector_state base;
 
+	struct intel_writeback_job *job;
 	enum hdmi_force_audio force_audio;
 	int broadcast_rgb;
 };
diff --git a/drivers/gpu/drm/i915/display/intel_wb_connector.c b/drivers/gpu/drm/i915/display/intel_wb_connector.c
new file mode 100644
index 000000000000..65f4abef53d0
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wb_connector.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright © 2022 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Suraj Kandpal <suraj.kandpal@intel.com>
+ *	Arun Murthy <arun.r.murthy@intel.com>
+ *
+ */
+
+
+#include <linux/dma-fence.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_property.h>
+
+#include "i915_drv.h"
+#include "intel_wb_connector.h"
+#include "intel_display_types.h"
+
+#define fence_to_wb_connector(x) container_of(x->lock, \
+					      struct intel_writeback_connector, \
+					      fence_lock)
+
+static const char *intel_writeback_fence_get_driver_name(struct dma_fence *fence)
+{
+	struct intel_writeback_connector *wb_connector =
+		fence_to_wb_connector(fence);
+
+	return wb_connector->base->dev->driver->name;
+}
+
+static const char *
+intel_writeback_fence_get_timeline_name(struct dma_fence *fence)
+{
+	struct intel_writeback_connector *wb_connector =
+		fence_to_wb_connector(fence);
+
+	return wb_connector->timeline_name;
+}
+
+static bool intel_writeback_fence_enable_signaling(struct dma_fence *fence)
+{
+	return true;
+}
+
+static const struct dma_fence_ops intel_writeback_fence_ops = {
+	.get_driver_name = intel_writeback_fence_get_driver_name,
+	.get_timeline_name = intel_writeback_fence_get_timeline_name,
+	.enable_signaling = intel_writeback_fence_enable_signaling,
+};
+
+static int intel_create_writeback_properties(struct drm_device *dev)
+{
+	struct drm_property *prop;
+	struct drm_i915_private *i915 = to_i915(dev);
+
+	if (!i915->wb_fb_id_property) {
+		prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+						"WRITEBACK_FB_ID",
+						DRM_MODE_OBJECT_FB);
+		if (!prop)
+			return -ENOMEM;
+		i915->wb_fb_id_property = prop;
+	}
+
+	if (!i915->wb_pixel_formats_property) {
+		prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
+					DRM_MODE_PROP_ATOMIC |
+					DRM_MODE_PROP_IMMUTABLE,
+					"WRITEBACK_PIXEL_FORMATS", 0);
+		if (!prop)
+			return -ENOMEM;
+		i915->wb_pixel_formats_property = prop;
+	}
+
+	if (!i915->wb_out_fence_ptr_property) {
+		prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+						"WRITEBACK_OUT_FENCE_PTR", 0,
+						U64_MAX);
+		if (!prop)
+			return -ENOMEM;
+		i915->wb_out_fence_ptr_property = prop;
+	}
+
+	return 0;
+}
+
+static const struct drm_encoder_funcs intel_writeback_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int intel_writeback_connector_init(struct drm_device *dev,
+				 struct intel_writeback_connector *wb_connector,
+				 const struct drm_connector_funcs *con_funcs,
+				 const struct drm_encoder_helper_funcs *enc_helper_funcs,
+				 const u32 *formats, int n_formats)
+{
+	struct drm_property_blob *blob;
+	struct drm_i915_private *i915 = to_i915(dev);
+	struct drm_connector *connector = wb_connector->base;
+	int ret;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	ret = intel_create_writeback_properties(dev);
+
+	if (ret != 0)
+		return ret;
+
+	blob = drm_property_create_blob(dev, n_formats * sizeof(*formats),
+					formats);
+	if (IS_ERR(blob))
+		return PTR_ERR(blob);
+
+	drm_encoder_helper_add(wb_connector->encoder, enc_helper_funcs);
+	ret = drm_encoder_init(dev, wb_connector->encoder,
+			&intel_writeback_encoder_funcs,
+			DRM_MODE_ENCODER_VIRTUAL, NULL);
+	if (ret)
+		goto fail;
+
+	connector->interlace_allowed = 0;
+
+	ret = drm_connector_init(dev, connector, con_funcs,
+				DRM_MODE_CONNECTOR_WRITEBACK);
+	if (ret)
+		goto connector_fail;
+
+	ret = drm_connector_attach_encoder(connector,
+					wb_connector->encoder);
+	if (ret)
+		goto attach_fail;
+
+	INIT_LIST_HEAD(&wb_connector->job_queue);
+	spin_lock_init(&wb_connector->job_lock);
+
+	wb_connector->fence_context = dma_fence_context_alloc(1);
+	spin_lock_init(&wb_connector->fence_lock);
+	snprintf(wb_connector->timeline_name,
+		sizeof(wb_connector->timeline_name),
+		"CONNECTOR:%d-%s", connector->base.id, connector->name);
+
+	drm_object_attach_property(&connector->base,
+				i915->wb_out_fence_ptr_property, 0);
+
+	drm_object_attach_property(&connector->base,
+				i915->wb_fb_id_property, 0);
+
+	drm_object_attach_property(&connector->base,
+				i915->wb_pixel_formats_property,
+				blob->base.id);
+	wb_connector->pixel_formats_blob_ptr = blob;
+
+	return 0;
+
+attach_fail:
+	drm_connector_cleanup(connector);
+connector_fail:
+	drm_encoder_cleanup(wb_connector->encoder);
+fail:
+	drm_property_blob_put(blob);
+	return ret;
+}
+
+void intel_writeback_queue_job(struct intel_writeback_connector *wb_connector,
+		struct drm_connector_state *conn_state)
+{
+	struct intel_writeback_job *wb_job;
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
+	unsigned long flags;
+
+	wb_job = intel_conn_state->job;
+	intel_conn_state->job = NULL;
+
+	spin_lock_irqsave(&wb_connector->job_lock, flags);
+	list_add_tail(&wb_job->list_entry, &wb_connector->job_queue);
+	spin_unlock_irqrestore(&wb_connector->job_lock, flags);
+}
+
+int intel_writeback_set_fb(struct drm_connector_state *conn_state,
+			 struct drm_framebuffer *fb)
+{
+	struct intel_connector *intel_connector = to_intel_connector(conn_state->connector);
+	struct intel_writeback_connector *wb_connector = &intel_connector->wb_conn;
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
+	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
+
+	if (!intel_conn_state->job) {
+		intel_conn_state->job =
+			kzalloc(sizeof(*intel_conn_state->job), GFP_KERNEL);
+		if (!intel_conn_state->job)
+			return -ENOMEM;
+
+		intel_conn_state->job->connector = wb_connector;
+	}
+
+	drm_framebuffer_assign(&intel_conn_state->job->fb, fb);
+	return 0;
+}
+
+void intel_writeback_cleanup_job(struct intel_writeback_job *job)
+{
+	if (job->fb)
+		drm_framebuffer_put(job->fb);
+
+	if (job->out_fence)
+		dma_fence_put(job->out_fence);
+
+	kfree(job);
+}
+
+static void cleanup_work(struct work_struct *work)
+{
+	struct intel_writeback_job *job = container_of(work,
+						struct intel_writeback_job,
+						cleanup_work);
+
+	intel_writeback_cleanup_job(job);
+}
+
+void
+intel_writeback_signal_completion(struct intel_writeback_connector *wb_connector,
+				int status)
+{
+	unsigned long flags;
+	struct intel_writeback_job *job;
+	struct dma_fence *out_fence;
+
+	spin_lock_irqsave(&wb_connector->job_lock, flags);
+	job = list_first_entry_or_null(&wb_connector->job_queue,
+					struct intel_writeback_job,
+					list_entry);
+	if (job)
+		list_del(&job->list_entry);
+
+	spin_unlock_irqrestore(&wb_connector->job_lock, flags);
+
+	if (WARN_ON(!job))
+		return;
+
+	out_fence = job->out_fence;
+	if (out_fence) {
+		if (status)
+			dma_fence_set_error(out_fence, status);
+		dma_fence_signal(out_fence);
+		dma_fence_put(out_fence);
+		job->out_fence = NULL;
+	}
+
+	INIT_WORK(&job->cleanup_work, cleanup_work);
+	queue_work(system_long_wq, &job->cleanup_work);
+}
+
+struct dma_fence *
+intel_writeback_get_out_fence(struct intel_writeback_connector *wb_connector)
+{
+	struct dma_fence *fence;
+
+	if (WARN_ON(wb_connector->base->connector_type !=
+		DRM_MODE_CONNECTOR_WRITEBACK))
+		return NULL;
+
+	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+	if (!fence)
+		return NULL;
+
+	dma_fence_init(fence, &intel_writeback_fence_ops,
+		&wb_connector->fence_lock, wb_connector->fence_context,
+		++wb_connector->fence_seqno);
+
+	return fence;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_wb_connector.h b/drivers/gpu/drm/i915/display/intel_wb_connector.h
new file mode 100644
index 000000000000..71142457b7c1
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wb_connector.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Copyright © 2022 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Suraj Kandpal <suraj.kandpal@intel.com>
+ *	Arun Murthy <arun.r.murthy@intel.com>
+ *
+ */
+
+#ifndef __INTEL_WB_CONNECTOR_H__
+#define __INTEL_WB_CONNECTOR_H__
+
+#include <drm/drm_connector.h>
+#include <drm/drm_encoder.h>
+#include <linux/workqueue.h>
+#include "intel_display.h"
+
+/**
+ * struct intel_writeback_connector - Intel writeback connector
+ * to get a idea of each individual variable please look at
+ * documentation in drm_writeback.h we emulate the same structure
+ * ditto for intel_writeback_job structure.
+ */
+struct intel_writeback_connector {
+	struct drm_connector *base;
+	struct drm_encoder *encoder;
+	struct drm_property_blob *pixel_formats_blob_ptr;
+	spinlock_t job_lock;
+	struct list_head job_queue;
+	unsigned int fence_context;
+	spinlock_t fence_lock;
+	unsigned long fence_seqno;
+	char timeline_name[32];
+};
+
+/**
+ * struct intel_writeback_job - DRM writeback job
+ */
+struct intel_writeback_job {
+	struct intel_writeback_connector *connector;
+	bool *prepared;
+	struct work_struct cleanup_work;
+	struct list_head list_entry;
+	struct drm_framebuffer *fb;
+	struct dma_fence *out_fence;
+	void *priv;
+};
+
+int intel_writeback_connector_init(struct drm_device *dev,
+			struct intel_writeback_connector *wb_connector,
+			const struct drm_connector_funcs *con_funcs,
+			const struct drm_encoder_helper_funcs *enc_helper_funcs,
+			const u32 *formats, int n_formats);
+
+int intel_writeback_set_fb(struct drm_connector_state *conn_state,
+			struct drm_framebuffer *fb);
+
+int intel_writeback_prepare_job(struct intel_writeback_job *job);
+
+void intel_writeback_queue_job(struct intel_writeback_connector *wb_connector,
+			struct drm_connector_state *conn_state);
+
+void intel_writeback_cleanup_job(struct intel_writeback_job *job);
+
+void
+intel_writeback_signal_completion(struct intel_writeback_connector *wb_connector,
+			int status);
+
+struct dma_fence *
+intel_writeback_get_out_fence(struct intel_writeback_connector *wb_connector);
+struct intel_wb_connector *intel_wb_connector_alloc(void);
+void intel_wb_connector_free(struct intel_wb_connector *connector);
+void intel_wb_connector_destroy(struct drm_connector *connector);
+bool intel_wb_connector_get_hw_state(struct intel_wb_connector *connector);
+enum pipe intel_wb_connector_get_pipe(struct intel_wb_connector *connector);
+void intel_wb_connector_attach_encoder(struct intel_wb_connector *connector,
+					struct intel_encoder *encoder);
+
+#endif /* __INTEL_WB_CONNECTOR_H__ */
+
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 26df561a4e94..9a86ee88089e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -678,6 +678,9 @@ struct drm_i915_private {
 
 	struct drm_property *broadcast_rgb_property;
 	struct drm_property *force_audio_property;
+	struct drm_property *wb_fb_id_property;
+	struct drm_property *wb_out_fence_ptr_property;
+	struct drm_property *wb_pixel_formats_property;
 
 	u32 fdi_rx_config;
 
-- 
2.35.1


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

* [Intel-gfx] [RFC PATCH v2 2/3] drm/i915: Define WD trancoder for i915
  2022-03-17  8:39 ` [Intel-gfx] [RFC PATCH v2 0/3] " Suraj Kandpal
  2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework Suraj Kandpal
@ 2022-03-17  8:39   ` Suraj Kandpal
  2022-04-06  5:00     ` Kandpal, Suraj
  2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 3/3] drm/i915: Enabling WD Transcoder Suraj Kandpal
  2022-04-06  4:56   ` [Intel-gfx] [RFC PATCH v2 0/3] i915 writeback private framework Kandpal, Suraj
  3 siblings, 1 reply; 24+ messages in thread
From: Suraj Kandpal @ 2022-03-17  8:39 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Adding WD Types, WD transcoder to enum list and WD Transcoder offsets

Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.h       | 6 ++++++
 drivers/gpu/drm/i915/display/intel_display_types.h | 1 +
 drivers/gpu/drm/i915/i915_reg.h                    | 2 ++
 3 files changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 8513703086b7..8c93a5de8e07 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -119,6 +119,8 @@ enum transcoder {
 	TRANSCODER_DSI_1,
 	TRANSCODER_DSI_A = TRANSCODER_DSI_0,	/* legacy DSI */
 	TRANSCODER_DSI_C = TRANSCODER_DSI_1,	/* legacy DSI */
+	TRANSCODER_WD_0,
+	TRANSCODER_WD_1,
 
 	I915_MAX_TRANSCODERS
 };
@@ -140,6 +142,10 @@ static inline const char *transcoder_name(enum transcoder transcoder)
 		return "DSI A";
 	case TRANSCODER_DSI_C:
 		return "DSI C";
+	case TRANSCODER_WD_0:
+		return "WD 0";
+	case TRANSCODER_WD_1:
+		return "WD 1";
 	default:
 		return "<invalid>";
 	}
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 7a96ecba73c0..dcb4ad43cf88 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -79,6 +79,7 @@ enum intel_output_type {
 	INTEL_OUTPUT_DSI = 9,
 	INTEL_OUTPUT_DDI = 10,
 	INTEL_OUTPUT_DP_MST = 11,
+	INTEL_OUTPUT_WD = 12,
 };
 
 enum hdmi_force_audio {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ddbc7a685a50..6396afd77209 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2023,6 +2023,8 @@
 #define TRANSCODER_EDP_OFFSET 0x6f000
 #define TRANSCODER_DSI0_OFFSET	0x6b000
 #define TRANSCODER_DSI1_OFFSET	0x6b800
+#define TRANSCODER_WD0_OFFSET	0x6e000
+#define TRANSCODER_WD1_OFFSET	0x6e800
 
 #define HTOTAL(trans)		_MMIO_TRANS2(trans, _HTOTAL_A)
 #define HBLANK(trans)		_MMIO_TRANS2(trans, _HBLANK_A)
-- 
2.35.1


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

* [Intel-gfx] [RFC PATCH v2 3/3] drm/i915: Enabling WD Transcoder
  2022-03-17  8:39 ` [Intel-gfx] [RFC PATCH v2 0/3] " Suraj Kandpal
  2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework Suraj Kandpal
  2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 2/3] drm/i915: Define WD trancoder for i915 Suraj Kandpal
@ 2022-03-17  8:39   ` Suraj Kandpal
  2022-04-06  4:58     ` Kandpal, Suraj
  2022-04-06  4:56   ` [Intel-gfx] [RFC PATCH v2 0/3] i915 writeback private framework Kandpal, Suraj
  3 siblings, 1 reply; 24+ messages in thread
From: Suraj Kandpal @ 2022-03-17  8:39 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Adding support for writeback transcoder to start capturing frames using
interrupt mechanism

Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 drivers/gpu/drm/i915/display/intel_acpi.c     |   1 +
 drivers/gpu/drm/i915/display/intel_display.c  |  89 +-
 drivers/gpu/drm/i915/display/intel_display.h  |   9 +
 .../drm/i915/display/intel_display_types.h    |  13 +
 drivers/gpu/drm/i915/display/intel_dpll.c     |   3 +
 drivers/gpu/drm/i915/display/intel_opregion.c |   3 +
 drivers/gpu/drm/i915/display/intel_wd.c       | 978 ++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_wd.h       |  82 ++
 drivers/gpu/drm/i915/i915_drv.h               |   2 +
 drivers/gpu/drm/i915/i915_irq.c               |   8 +-
 drivers/gpu/drm/i915/i915_pci.c               |   7 +-
 drivers/gpu/drm/i915/i915_reg.h               | 137 +++
 13 files changed, 1330 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_wd.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_wd.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 087bd9d1b397..5ee32513a945 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -287,6 +287,7 @@ i915-y += \
 	display/intel_vdsc.o \
 	display/intel_vrr.o \
 	display/intel_wb_connector.o\
+	display/intel_wd.o\
 	display/vlv_dsi.o \
 	display/vlv_dsi_pll.o
 
diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c
index e78430001f07..ae08db164f73 100644
--- a/drivers/gpu/drm/i915/display/intel_acpi.c
+++ b/drivers/gpu/drm/i915/display/intel_acpi.c
@@ -247,6 +247,7 @@ static u32 acpi_display_type(struct intel_connector *connector)
 	case DRM_MODE_CONNECTOR_LVDS:
 	case DRM_MODE_CONNECTOR_eDP:
 	case DRM_MODE_CONNECTOR_DSI:
+	case DRM_MODE_CONNECTOR_WRITEBACK:
 		display_type = ACPI_DISPLAY_TYPE_INTERNAL_DIGITAL;
 		break;
 	case DRM_MODE_CONNECTOR_Unknown:
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index eb49973621f0..6dedc7921f54 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -111,6 +111,7 @@
 #include "intel_sprite.h"
 #include "intel_tc.h"
 #include "intel_vga.h"
+#include "intel_wd.h"
 #include "i9xx_plane.h"
 #include "skl_scaler.h"
 #include "skl_universal_plane.h"
@@ -1544,6 +1545,72 @@ static void intel_encoders_update_complete(struct intel_atomic_state *state)
 	}
 }
 
+static void intel_queue_writeback_job(struct intel_atomic_state *state,
+		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)
+{
+	struct drm_connector_state *new_conn_state;
+	struct drm_connector *connector;
+	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
+	struct intel_wd *intel_wd;
+	struct intel_connector *intel_connector;
+	struct intel_digital_connector_state *intel_conn_state;
+	struct intel_encoder *encoder;
+	int i;
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (intel_wd->wd_crtc != intel_crtc)
+			return;
+
+	}
+
+	for_each_new_connector_in_state(&state->base, connector, new_conn_state,
+					i) {
+		intel_conn_state = to_intel_digital_connector_state(new_conn_state);
+		if (!intel_conn_state->job)
+			continue;
+		intel_connector = to_intel_connector(connector);
+		intel_writeback_queue_job(&intel_connector->wb_conn, new_conn_state);
+		drm_dbg_kms(&i915->drm, "queueing writeback job\n");
+	}
+}
+
+static void intel_find_writeback_connector(struct intel_atomic_state *state,
+		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)
+{
+	struct drm_connector_state *new_conn_state;
+	struct drm_connector *connector;
+	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
+	struct intel_wd *intel_wd;
+	struct intel_encoder *encoder;
+	int i;
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (intel_wd->wd_crtc != intel_crtc)
+			return;
+
+	}
+
+	for_each_new_connector_in_state(&state->base, connector, new_conn_state,
+					i) {
+		struct intel_connector *intel_connector;
+
+		intel_connector = to_intel_connector(connector);
+		drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]: status: %s\n",
+				connector->base.id, connector->name,
+				drm_get_connector_status_name(connector->status));
+		encoder = intel_connector_primary_encoder(intel_connector);
+		if (encoder->type == INTEL_OUTPUT_WD) {
+			drm_dbg_kms(&i915->drm, "encoder intel_output_wd found\n");
+			intel_wd_enable_capture(encoder, crtc_state, new_conn_state);
+		}
+	}
+
+}
+
 static void intel_encoders_pre_pll_enable(struct intel_atomic_state *state,
 					  struct intel_crtc *crtc)
 {
@@ -1944,7 +2011,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
 		bdw_set_pipemisc(new_crtc_state);
 
 	if (!intel_crtc_is_bigjoiner_slave(new_crtc_state) &&
-	    !transcoder_is_dsi(cpu_transcoder))
+	    !transcoder_is_dsi(cpu_transcoder) &&
+	    !transcoder_is_wd(cpu_transcoder))
 		hsw_configure_cpu_transcoder(new_crtc_state);
 
 	crtc->active = true;
@@ -2632,6 +2700,9 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,
 	if (connector->get_hw_state(connector)) {
 		struct intel_encoder *encoder = intel_attached_encoder(connector);
 
+		if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+			return;
+
 		I915_STATE_WARN(!crtc_state,
 			 "connector enabled without attached crtc\n");
 
@@ -5233,6 +5304,7 @@ static const char * const output_type_str[] = {
 	OUTPUT_TYPE(DSI),
 	OUTPUT_TYPE(DDI),
 	OUTPUT_TYPE(DP_MST),
+	OUTPUT_TYPE(WD),
 };
 
 #undef OUTPUT_TYPE
@@ -8577,6 +8649,12 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 		}
 	}
 
+	if (DISPLAY_VER(dev_priv) >= 12) {
+		for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+			intel_wd_set_vblank_event(crtc, new_crtc_state);
+		}
+	}
+
 	intel_encoders_update_prepare(state);
 
 	intel_dbuf_pre_plane_update(state);
@@ -8662,6 +8740,14 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 
 	intel_sagv_post_plane_update(state);
 
+	if (DISPLAY_VER(dev_priv) >= 12) {
+		intel_wd_prepare_out_fence(dev, &state->base);
+		for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+			intel_queue_writeback_job(state, crtc, new_crtc_state);
+			intel_find_writeback_connector(state, crtc, new_crtc_state);
+		}
+	}
+
 	drm_atomic_helper_commit_hw_done(&state->base);
 
 	if (state->modeset) {
@@ -8966,6 +9052,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
 		intel_ddi_init(dev_priv, PORT_TC1);
 		intel_ddi_init(dev_priv, PORT_TC2);
 	} else if (DISPLAY_VER(dev_priv) >= 12) {
+		intel_wd_init(dev_priv, TRANSCODER_WD_0);
 		intel_ddi_init(dev_priv, PORT_A);
 		intel_ddi_init(dev_priv, PORT_B);
 		intel_ddi_init(dev_priv, PORT_TC1);
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 8c93a5de8e07..27237d36a888 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -156,6 +156,11 @@ static inline bool transcoder_is_dsi(enum transcoder transcoder)
 	return transcoder == TRANSCODER_DSI_A || transcoder == TRANSCODER_DSI_C;
 }
 
+static inline bool transcoder_is_wd(enum transcoder transcoder)
+{
+	return transcoder == TRANSCODER_WD_0 || transcoder == TRANSCODER_WD_1;
+}
+
 /*
  * Global legacy plane identifier. Valid only for primary/sprite
  * planes on pre-g4x, and only for primary planes on g4x-bdw.
@@ -467,6 +472,10 @@ enum hpd_pin {
 	for_each_intel_encoder((dev), (intel_encoder)) \
 		for_each_if(intel_encoder_can_psr(intel_encoder))
 
+#define for_each_intel_encoder_with_wd(dev, intel_encoder)	\
+	for_each_intel_encoder(dev, intel_encoder)		\
+		for_each_if(intel_encoder_is_wd(intel_encoder))
+
 #define for_each_intel_connector_iter(intel_connector, iter) \
 	while ((intel_connector = to_intel_connector(drm_connector_list_iter_next(iter))))
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index dcb4ad43cf88..8522c348a73d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1293,6 +1293,11 @@ struct intel_crtc {
 	bool cpu_fifo_underrun_disabled;
 	bool pch_fifo_underrun_disabled;
 
+	struct {
+		struct drm_pending_vblank_event *e;
+		atomic_t work_busy;
+		wait_queue_head_t wd_wait;
+	} wd;
 	/* per-pipe watermark state */
 	struct {
 		/* watermarks currently being used  */
@@ -1420,6 +1425,7 @@ struct cxsr_latency {
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
 #define to_intel_crtc_state(x) container_of(x, struct intel_crtc_state, uapi)
 #define to_intel_connector(x) container_of(x, struct intel_connector, base)
+#define to_intel_wb_connector(x) container_of(x, struct intel_wb_connector, base)
 #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 #define to_intel_plane(x) container_of(x, struct intel_plane, base)
@@ -1851,6 +1857,13 @@ static inline bool intel_encoder_is_dp(struct intel_encoder *encoder)
 	}
 }
 
+static inline bool intel_encoder_is_wd(struct intel_encoder *encoder)
+{
+	if (encoder->type == INTEL_OUTPUT_WD)
+		return true;
+	return false;
+}
+
 static inline struct intel_lspcon *
 enc_to_intel_lspcon(struct intel_encoder *encoder)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c
index 95b9d327ed4d..dfea17f5f99d 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll.c
@@ -939,6 +939,9 @@ static int hsw_crtc_compute_clock(struct intel_crtc_state *crtc_state)
 	if (IS_DG2(dev_priv))
 		return intel_mpllb_calc_state(crtc_state, encoder);
 
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_WD))
+		return 0;
+
 	if (DISPLAY_VER(dev_priv) < 11 &&
 	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
 		return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c
index f31e8c3f8ce0..b7a0ac9bad05 100644
--- a/drivers/gpu/drm/i915/display/intel_opregion.c
+++ b/drivers/gpu/drm/i915/display/intel_opregion.c
@@ -370,6 +370,9 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
 	if (ret)
 		return ret;
 
+	if (intel_encoder->type == INTEL_OUTPUT_WD)
+		return 0;
+
 	if (intel_encoder->type == INTEL_OUTPUT_DSI)
 		port = 0;
 	else
diff --git a/drivers/gpu/drm/i915/display/intel_wd.c b/drivers/gpu/drm/i915/display/intel_wd.c
new file mode 100644
index 000000000000..a6c9350c3986
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wd.c
@@ -0,0 +1,978 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Suraj Kandpal <suraj.kandpal@intel.com>
+ *	Arun Murthy <arun.r.murthy@intel.com>
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
+
+#include "intel_atomic.h"
+#include "intel_connector.h"
+#include "intel_wd.h"
+#include "intel_fb_pin.h"
+#include "intel_de.h"
+#include "intel_wb_connector.h"
+
+enum {
+	WD_CAPTURE_4_PIX,
+	WD_CAPTURE_2_PIX,
+} wd_capture_format;
+
+static struct intel_writeback_job
+*intel_get_writeback_job_from_queue(struct intel_wd *intel_wd)
+{
+	struct intel_writeback_job *job;
+	struct drm_i915_private *i915 = to_i915(intel_wd->base.base.dev);
+	struct intel_writeback_connector *wb_conn =
+		&intel_wd->attached_connector->wb_conn;
+	unsigned long flags;
+
+	spin_lock_irqsave(&wb_conn->job_lock, flags);
+	job = list_first_entry_or_null(&wb_conn->job_queue,
+			struct intel_writeback_job,
+			list_entry);
+	spin_unlock_irqrestore(&wb_conn->job_lock, flags);
+	if (job == NULL) {
+		drm_dbg_kms(&i915->drm, "job queue is empty\n");
+		return NULL;
+	}
+
+	return job;
+}
+
+/*Check with Spec*/
+static const u32 wb_fmts[] = {
+		DRM_FORMAT_YUV444,
+		DRM_FORMAT_XYUV8888,
+		DRM_FORMAT_XBGR8888,
+		DRM_FORMAT_XRGB8888,
+		DRM_FORMAT_Y410,
+		DRM_FORMAT_YUV422,
+		DRM_FORMAT_XBGR2101010,
+		DRM_FORMAT_RGB565,
+
+};
+
+static int intel_wd_get_format(int pixel_format)
+{
+	int wd_format = -EINVAL;
+
+	switch (pixel_format) {
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_XYUV8888:
+	case DRM_FORMAT_YUV444:
+		wd_format = WD_CAPTURE_4_PIX;
+		break;
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_RGB565:
+		wd_format = WD_CAPTURE_2_PIX;
+		break;
+	default:
+		DRM_ERROR("unsupported pixel format %x!\n",
+			pixel_format);
+	}
+
+	return wd_format;
+}
+
+static int intel_wd_verify_pix_format(int format)
+{
+	const struct drm_format_info *info = drm_format_info(format);
+	int pix_format = info->format;
+	int i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(wb_fmts); i++)
+		if (pix_format == wb_fmts[i])
+			return 0;
+
+	return 1;
+}
+
+static u32 intel_wd_get_stride(const struct intel_crtc_state *crtc_state,
+			int format)
+{
+	const struct drm_format_info *info = drm_format_info(format);
+	int wd_format;
+	int hactive, pixel_size;
+
+	wd_format = intel_wd_get_format(info->format);
+
+	switch (wd_format) {
+	case WD_CAPTURE_4_PIX:
+		pixel_size = 4;
+		break;
+	case WD_CAPTURE_2_PIX:
+		pixel_size = 2;
+		break;
+	default:
+		pixel_size = 1;
+		break;
+	}
+
+	hactive = crtc_state->hw.adjusted_mode.crtc_hdisplay;
+
+	return DIV_ROUND_UP(hactive * pixel_size, 64);
+}
+
+static int intel_wd_pin_fb(struct intel_wd *intel_wd,
+			struct drm_framebuffer *fb)
+{
+	const struct i915_ggtt_view view = {
+		.type = I915_GGTT_VIEW_NORMAL,
+		};
+	struct i915_vma *vma;
+
+	vma = intel_pin_and_fence_fb_obj(fb, false, &view, false,
+			&intel_wd->flags);
+
+	if (IS_ERR(vma))
+		return PTR_ERR(vma);
+
+	intel_wd->vma = vma;
+	return 0;
+}
+
+static void intel_configure_slicing_strategy(struct drm_i915_private *i915,
+		struct intel_wd *intel_wd, u32 *tmp)
+{
+	*tmp &= ~WD_STRAT_MASK;
+	if (intel_wd->slicing_strategy == 1)
+		*tmp |= WD_SLICING_STRAT_1_1;
+	else if (intel_wd->slicing_strategy == 2)
+		*tmp |= WD_SLICING_STRAT_2_1;
+	else if (intel_wd->slicing_strategy == 3)
+		*tmp |= WD_SLICING_STRAT_4_1;
+	else if (intel_wd->slicing_strategy == 4)
+		*tmp |= WD_SLICING_STRAT_8_1;
+
+	intel_de_write(i915, WD_STREAMCAP_CTL(intel_wd->trans),
+			*tmp);
+
+}
+
+static enum drm_mode_status
+intel_wd_mode_valid(struct drm_connector *connector,
+		struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static int intel_wd_get_modes(struct drm_connector *connector)
+{
+	return 0;
+}
+
+static void intel_wd_get_config(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_crtc *intel_crtc =
+		to_intel_crtc(pipe_config->uapi.crtc);
+
+	drm_dbg_kms(&i915->drm, "\n");
+	if (intel_crtc) {
+		memcpy(pipe_config, intel_crtc->config,
+			sizeof(*pipe_config));
+		pipe_config->output_types |= BIT(INTEL_OUTPUT_WD);
+		drm_dbg_kms(&i915->drm, "crtc found\n");
+	}
+
+}
+
+static int intel_wd_compute_config(struct intel_encoder *encoder,
+			struct intel_crtc_state *pipe_config,
+			struct drm_connector_state *conn_state)
+{
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
+	struct intel_writeback_job *job;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	job = intel_get_writeback_job_from_queue(intel_wd);
+	if (job || intel_conn_state->job) {
+		intel_wd->wd_crtc = to_intel_crtc(pipe_config->uapi.crtc);
+		return 0;
+	}
+	drm_dbg_kms(&i915->drm, "No writebackjob in queue\n");
+
+	return 0;
+}
+
+static void intel_wd_get_power_domains(struct intel_encoder *encoder,
+			struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	intel_wakeref_t wakeref;
+
+	wakeref = intel_display_power_get(i915,
+				encoder->power_domain);
+
+	intel_wd->io_wakeref[0] = wakeref;
+	drm_dbg_kms(&i915->drm, "\n");
+}
+
+static bool intel_wd_get_hw_state(struct intel_encoder *encoder,
+		enum pipe *pipe)
+{
+	bool ret = false;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	struct intel_crtc *wd_crtc = intel_wd->wd_crtc;
+	intel_wakeref_t wakeref;
+	u32 tmp;
+
+	if (wd_crtc)
+		return false;
+
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+				encoder->power_domain);
+	drm_dbg_kms(encoder->base.dev, "power enabled : %s\n",
+			!wakeref ? "false":"true");
+
+	if (!wakeref)
+		return false;
+
+	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+	ret = tmp & WD_TRANS_ACTIVE;
+	drm_dbg_kms(encoder->base.dev, "trancoder enabled: %s\n",
+			ret ? "true":"false");
+	if (ret) {
+		*pipe = wd_crtc->pipe;
+		drm_dbg_kms(encoder->base.dev, "pipe selected is %d\n",
+			wd_crtc->pipe);
+	}
+	return true;
+}
+
+static int intel_wd_encoder_atomic_check(struct drm_encoder *encoder,
+				    struct drm_crtc_state *crtc_st,
+				    struct drm_connector_state *conn_st)
+{
+	/* Check for the format and buffers and property validity */
+	struct drm_framebuffer *fb;
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_st);
+	struct intel_writeback_job *job = intel_conn_state->job;
+	struct drm_i915_private *i915 = to_i915(encoder->dev);
+	const struct drm_display_mode *mode = &crtc_st->mode;
+	int ret;
+
+	drm_dbg_kms(&i915->drm, "\n");
+
+	if (!job) {
+		drm_dbg_kms(&i915->drm, "No writeback job created returning\n");
+		return -EINVAL;
+	}
+
+	fb = job->fb;
+
+	if (!fb) {
+		drm_dbg_kms(&i915->drm, "Invalid framebuffer\n");
+		return -EINVAL;
+	}
+
+	if (fb->width != mode->hdisplay || fb->height != mode->vdisplay) {
+		drm_dbg_kms(&i915->drm, "Invalid framebuffer size %ux%u\n",
+				fb->width, fb->height);
+		return -EINVAL;
+	}
+
+	ret = intel_wd_verify_pix_format(fb->format->format);
+
+	if (ret) {
+		drm_dbg_kms(&i915->drm, "Unsupported framebuffer format %08x\n",
+				fb->format->format);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+static const struct drm_encoder_helper_funcs wd_encoder_helper_funcs = {
+	.atomic_check = intel_wd_encoder_atomic_check,
+};
+
+static void intel_wd_connector_destroy(struct drm_connector *connector)
+{
+	drm_dbg_kms(connector->dev, "\n");
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+static enum drm_connector_status
+intel_wb_connector_detect(struct drm_connector *connector, bool force)
+{
+	drm_dbg_kms(connector->dev, "Writeback connector connected\n");
+	return connector_status_connected;
+}
+
+static int intel_atomic_set_writeback_fb_for_connector(
+		struct drm_connector_state *conn_state,
+		struct drm_framebuffer *fb)
+{
+	int ret;
+	struct drm_connector *conn = conn_state->connector;
+
+	ret = intel_writeback_set_fb(conn_state, fb);
+	if (ret < 0)
+		return ret;
+
+	if (fb)
+		drm_dbg_atomic(conn->dev,
+			"Set [FB:%d] for connector state %p\n",
+			fb->base.id, conn_state);
+	else
+		drm_dbg_atomic(conn->dev,
+			"Set [NOFB] for connector state %p\n",
+			conn_state);
+
+	return 0;
+}
+
+static int set_out_fence_for_connector(struct drm_atomic_state *state,
+					struct drm_connector *connector,
+					s32 __user *fence_ptr)
+{
+	unsigned int index = drm_connector_index(connector);
+
+	if (!fence_ptr)
+		return 0;
+
+	if (put_user(-1, fence_ptr))
+		return -EFAULT;
+
+	state->connectors[index].out_fence_ptr = fence_ptr;
+
+	return 0;
+}
+
+static struct drm_mode_object *__intel_object_find(struct drm_device *dev,
+					       uint32_t id, uint32_t type)
+{
+	struct drm_mode_object *obj = NULL;
+
+	mutex_lock(&dev->mode_config.idr_mutex);
+	obj = idr_find(&dev->mode_config.object_idr, id);
+	if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
+		obj = NULL;
+	if (obj && obj->id != id)
+		obj = NULL;
+	if (obj && obj->free_cb) {
+		if (!kref_get_unless_zero(&obj->refcount))
+			obj = NULL;
+	}
+	mutex_unlock(&dev->mode_config.idr_mutex);
+
+	return obj;
+}
+
+static struct drm_framebuffer *intel_wb_framebuffer_lookup(struct drm_device *dev,
+					       uint32_t id)
+{
+	struct drm_mode_object *obj;
+	struct drm_framebuffer *fb = NULL;
+
+	obj = __intel_object_find(dev, id, DRM_MODE_OBJECT_FB);
+	if (obj)
+		fb = obj_to_fb(obj);
+	return fb;
+}
+
+static s32 *intel_get_out_fence_for_connector(struct drm_atomic_state *state,
+					       struct drm_connector *connector)
+{
+	unsigned int index = drm_connector_index(connector);
+	s32 __user *fence_ptr;
+
+	fence_ptr = state->connectors[index].out_fence_ptr;
+	state->connectors[index].out_fence_ptr = NULL;
+
+	return fence_ptr;
+}
+
+static int intel_setup_out_fence(struct intel_out_fence_state *fence_state,
+			   struct dma_fence *fence)
+{
+
+	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
+	if (fence_state->fd < 0)
+		return fence_state->fd;
+
+	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
+		return -EFAULT;
+
+	fence_state->sync_file = sync_file_create(fence);
+	if (!fence_state->sync_file)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int intel_wd_prepare_out_fence(struct drm_device *dev,
+				struct drm_atomic_state *state)
+{
+	struct drm_connector *conn;
+	struct drm_connector_state *conn_state;
+	int i, ret;
+
+	drm_dbg_kms(dev, "\n");
+
+	for_each_new_connector_in_state(state, conn, conn_state, i) {
+		struct intel_writeback_connector *wb_conn;
+		struct intel_connector *intel_conn =
+			to_intel_connector(conn);
+		struct dma_fence *fence;
+		struct intel_wd *intel_wd;
+		struct intel_digital_connector_state *intel_conn_state =
+			to_intel_digital_connector_state(conn_state);
+		s32 __user *fence_ptr;
+
+		if (conn->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
+			continue;
+
+		if (!intel_conn_state->job)
+			continue;
+
+		intel_wd = enc_to_intel_wd(intel_conn->encoder);
+		fence_ptr = intel_get_out_fence_for_connector(state, conn);
+		if (!fence_ptr)
+			continue;
+
+		intel_wd->fence_state->out_fence_ptr = fence_ptr;
+
+		wb_conn = &intel_conn->wb_conn;
+		fence = intel_writeback_get_out_fence(wb_conn);
+		if (!fence)
+			return -ENOMEM;
+
+		ret = intel_setup_out_fence(intel_wd->fence_state, fence);
+		if (ret) {
+			dma_fence_put(fence);
+			return ret;
+		}
+
+		intel_conn_state->job->out_fence = fence;
+	}
+
+	return 0;
+}
+
+void intel_wd_complete_signaling(struct intel_wd *intel_wd)
+{
+	struct intel_out_fence_state *fence_state;
+
+	fence_state = intel_wd->fence_state;
+	fd_install(fence_state->fd,
+		fence_state->sync_file->file);
+
+}
+
+static int intel_set_writeback_property(struct drm_connector *connector,
+	struct drm_connector_state *state, struct drm_property *property,
+	uint64_t val)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *i915 = to_i915(dev);
+
+	if (property == i915->wb_fb_id_property) {
+		struct drm_framebuffer *fb;
+		int ret;
+
+		fb = intel_wb_framebuffer_lookup(dev, val);
+		ret = intel_atomic_set_writeback_fb_for_connector(state, fb);
+		if (fb)
+			drm_framebuffer_put(fb);
+		return ret;
+	} else if (property == i915->wb_out_fence_ptr_property) {
+		s32 __user *fence_ptr = u64_to_user_ptr(val);
+
+		return set_out_fence_for_connector(state->state, connector,
+						fence_ptr);
+	} else {
+		drm_dbg_atomic(connector->dev,
+			"[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
+			connector->base.id, connector->name,
+			property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+
+}
+
+static int intel_get_writeback_property(struct drm_connector *connector,
+	const struct drm_connector_state *state, struct drm_property *property,
+	uint64_t *val)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *i915 = to_i915(dev);
+
+	if (property == i915->wb_fb_id_property)
+		*val = 0;
+	else if (property == i915->wb_out_fence_ptr_property)
+		*val = 0;
+	else {
+		drm_dbg_atomic(&i915->drm,
+				"Unknown property [PROP:%d:%s]\n",
+				property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct drm_connector_funcs wd_connector_funcs = {
+	.detect = intel_wb_connector_detect,
+	.reset = drm_atomic_helper_connector_reset,
+	.destroy = intel_wd_connector_destroy,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+	.atomic_set_property = intel_set_writeback_property,
+	.atomic_get_property = intel_get_writeback_property,
+	.atomic_duplicate_state = intel_digital_connector_duplicate_state,
+};
+
+static const struct drm_connector_helper_funcs wd_connector_helper_funcs = {
+	.get_modes = intel_wd_get_modes,
+	.mode_valid = intel_wd_mode_valid,
+};
+
+static bool intel_fastset_dis(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config)
+{
+	pipe_config->uapi.mode_changed = true;
+	drm_dbg_kms(encoder->base.dev, "\n");
+	return false;
+}
+
+void intel_wd_init(struct drm_i915_private *i915, enum transcoder trans)
+{
+	struct intel_wd *intel_wd;
+	struct intel_encoder *encoder;
+	struct intel_out_fence_state *fence_state;
+	struct intel_connector *intel_connector;
+	struct intel_writeback_connector *wb_conn;
+	int n_formats = ARRAY_SIZE(wb_fmts);
+	int err;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	intel_wd = kzalloc(sizeof(*intel_wd), GFP_KERNEL);
+	if (!intel_wd)
+		return;
+
+	intel_connector = intel_connector_alloc();
+	if (!intel_connector) {
+		kfree(intel_wd);
+		return;
+	}
+
+	fence_state = kzalloc(sizeof(*fence_state), GFP_KERNEL);
+	if (!intel_wd) {
+		kfree(intel_wd);
+		kfree(intel_connector);
+		return;
+	}
+
+	wb_conn = &intel_connector->wb_conn;
+	wb_conn->base = &intel_connector->base;
+	wb_conn->encoder = &intel_wd->base.base;
+
+	encoder = &intel_wd->base;
+	intel_wd->attached_connector = intel_connector;
+	intel_wd->fence_state = fence_state;
+	intel_wd->trans = trans;
+	intel_wd->triggered_cap_mode = 1;
+	intel_wd->frame_num = 1;
+	intel_wd->slicing_strategy = 1;
+	encoder->get_config = intel_wd_get_config;
+	encoder->compute_config = intel_wd_compute_config;
+	encoder->get_hw_state = intel_wd_get_hw_state;
+	encoder->type = INTEL_OUTPUT_WD;
+	encoder->cloneable = 0;
+	encoder->pipe_mask = ~0;
+	encoder->power_domain = POWER_DOMAIN_TRANSCODER_B;
+	encoder->get_power_domains = intel_wd_get_power_domains;
+	encoder->initial_fastset_check = intel_fastset_dis;
+	intel_connector->get_hw_state =
+		intel_connector_get_hw_state;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	err = intel_writeback_connector_init(&i915->drm, wb_conn,
+		&wd_connector_funcs,
+		&wd_encoder_helper_funcs,
+		wb_fmts, n_formats);
+
+	if (err != 0) {
+		drm_dbg_kms(&i915->drm,
+		"intel_writeback_connector_init: Failed: %d\n",
+			err);
+		goto cleanup;
+	}
+
+	drm_connector_helper_add(wb_conn->base, &wd_connector_helper_funcs);
+	intel_connector_attach_encoder(intel_connector, encoder);
+	wb_conn->base->status = connector_status_connected;
+	return;
+
+cleanup:
+	kfree(intel_wd);
+	intel_connector_free(intel_connector);
+}
+
+static void intel_wd_writeback_complete(struct intel_wd *intel_wd,
+	struct intel_writeback_job *job, int status)
+{
+	struct intel_writeback_connector *wb_conn =
+		&intel_wd->attached_connector->wb_conn;
+	intel_writeback_signal_completion(wb_conn, status);
+	intel_wd_complete_signaling(intel_wd);
+}
+
+static int intel_wd_setup_transcoder(struct intel_wd *intel_wd,
+		struct intel_crtc_state *pipe_config,
+		struct intel_writeback_job *job)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
+	enum pipe pipe = intel_crtc->pipe;
+	struct drm_framebuffer *fb;
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+	struct drm_gem_object *wd_fb_obj;
+	int ret;
+	u32 stride, tmp;
+	u16 hactive, vactive;
+
+	fb = job->fb;
+	wd_fb_obj = fb->obj[0];
+	if (!wd_fb_obj) {
+		drm_dbg_kms(&dev_priv->drm, "No framebuffer gem object created\n");
+		return -1;
+	}
+	ret = intel_wd_pin_fb(intel_wd, fb);
+	drm_WARN_ON(&dev_priv->drm, ret != 0);
+
+	/*Write stride and surface registers in that particular order*/
+	stride = intel_wd_get_stride(pipe_config, fb->format->format);
+
+	tmp = intel_de_read(dev_priv, WD_STRIDE(intel_wd->trans));
+	tmp &= ~WD_STRIDE_MASK;
+	tmp |= (stride << WD_STRIDE_SHIFT);
+
+	intel_de_write(dev_priv, WD_STRIDE(intel_wd->trans), tmp);
+
+	tmp = intel_de_read(dev_priv, WD_SURF(intel_wd->trans));
+	drm_dbg_kms(&dev_priv->drm, "%d is the surface address\n", tmp);
+
+	intel_de_write(dev_priv, WD_SURF(intel_wd->trans),
+			i915_ggtt_offset(intel_wd->vma));
+
+	tmp = intel_de_read_fw(dev_priv, WD_IIR(intel_wd->trans));
+	intel_de_write_fw(dev_priv, WD_IIR(intel_wd->trans), tmp);
+
+	tmp = ~(WD_GTT_FAULT_INT|WD_WRITE_COMPLETE_INT|WD_FRAME_COMPLETE_INT|
+			WD_VBLANK_INT|WD_OVERRUN_INT|WD_CAPTURING_INT);
+	intel_de_write_fw(dev_priv, WD_IMR(intel_wd->trans), tmp);
+
+	if (intel_wd->stream_cap) {
+		tmp = intel_de_read(dev_priv,
+				WD_STREAMCAP_CTL(intel_wd->trans));
+		tmp |= WD_STREAM_CAP_MODE_EN;
+		intel_configure_slicing_strategy(dev_priv, intel_wd, &tmp);
+	}
+
+	hactive = pipe_config->uapi.mode.hdisplay;
+	vactive = pipe_config->uapi.mode.vdisplay;
+
+	drm_dbg_kms(&dev_priv->drm, "hactive : %d, vactive: %d\n", hactive, vactive);
+
+	tmp = intel_de_read(dev_priv, HTOTAL(intel_wd->trans));
+	drm_dbg_kms(&dev_priv->drm, "hactive_reg : %d\n", tmp);
+	tmp = intel_de_read(dev_priv, VTOTAL(intel_wd->trans));
+	drm_dbg_kms(&dev_priv->drm, "vactive_reg : %d\n", tmp);
+	/* minimum hactive as per bspec: 64 pixels*/
+	if (hactive < 64)
+		drm_err(&dev_priv->drm, "hactive is less then 64 pixels\n");
+
+	intel_de_write(dev_priv, HTOTAL(intel_wd->trans), hactive - 1);
+	intel_de_write(dev_priv, VTOTAL(intel_wd->trans), vactive - 1);
+
+	tmp = intel_de_read(dev_priv, WD_TRANS_FUNC_CTL(intel_wd->trans));
+	/* select pixel format */
+	tmp &= ~WD_PIX_FMT_MASK;
+
+	switch (fb->format->format) {
+	default:
+	fallthrough;
+	case DRM_FORMAT_YUYV:
+		tmp |= WD_PIX_FMT_YUYV;
+		break;
+	case DRM_FORMAT_XYUV8888:
+		tmp |= WD_PIX_FMT_XYUV8888;
+		break;
+	case DRM_FORMAT_XBGR8888:
+		tmp |= WD_PIX_FMT_XBGR8888;
+		break;
+	case DRM_FORMAT_Y410:
+		tmp |= WD_PIX_FMT_Y410;
+		break;
+	case DRM_FORMAT_YUV422:
+		tmp |= WD_PIX_FMT_YUV422;
+		break;
+	case DRM_FORMAT_XBGR2101010:
+		tmp |= WD_PIX_FMT_XBGR2101010;
+		break;
+	case DRM_FORMAT_RGB565:
+		tmp |= WD_PIX_FMT_RGB565;
+		break;
+	}
+
+	if (intel_wd->triggered_cap_mode)
+		tmp |= WD_TRIGGERED_CAP_MODE_ENABLE;
+
+	if (intel_wd->stream_cap)
+		tmp |= WD_CTL_POINTER_DTDH;
+
+	/*select input pipe*/
+	tmp &= ~WD_INPUT_SELECT_MASK;
+	drm_dbg_kms(&dev_priv->drm, "Selected pipe is %d\n", pipe);
+	switch (pipe) {
+	default:
+		fallthrough;
+	case PIPE_A:
+		tmp |= WD_INPUT_PIPE_A;
+		break;
+	case PIPE_B:
+		tmp |= WD_INPUT_PIPE_B;
+		break;
+	case PIPE_C:
+		tmp |= WD_INPUT_PIPE_C;
+		break;
+	case PIPE_D:
+		tmp |= WD_INPUT_PIPE_D;
+		break;
+	}
+
+	/* enable DDI buffer */
+	if (!(tmp & TRANS_WD_FUNC_ENABLE))
+		tmp |= TRANS_WD_FUNC_ENABLE;
+
+	intel_de_write(dev_priv, WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);
+
+	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+	ret = tmp & WD_TRANS_ACTIVE;
+	drm_dbg_kms(&dev_priv->drm, "Trancoder enabled: %s\n", ret ? "true":"false");
+
+	if (!ret) {
+		/*enable the transcoder	*/
+		tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+		tmp |= WD_TRANS_ENABLE;
+		intel_de_write(dev_priv, PIPECONF(intel_wd->trans), tmp);
+
+		/* wait for transcoder to be enabled */
+		if (intel_de_wait_for_set(dev_priv, PIPECONF(intel_wd->trans),
+				WD_TRANS_ACTIVE, 10))
+			drm_err(&dev_priv->drm, "WD transcoder not enabled\n");
+	}
+
+	return 0;
+}
+
+static void intel_wd_disable_capture(struct intel_wd *intel_wd)
+{
+	struct drm_i915_private *dev_priv = to_i915(intel_wd->base.base.dev);
+	u32 tmp;
+
+	intel_de_write_fw(dev_priv, WD_IMR(intel_wd->trans), 0xFF);
+	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+	tmp &= WD_TRANS_DISABLE;
+	intel_de_write(dev_priv, PIPECONF(intel_wd->trans), tmp);
+
+	drm_dbg_kms(&dev_priv->drm, "WD Trans_Conf value after disable = 0x%08x\n",
+		intel_de_read(dev_priv, PIPECONF(intel_wd->trans)));
+	tmp = intel_de_read(dev_priv, WD_TRANS_FUNC_CTL(intel_wd->trans));
+	tmp |= ~TRANS_WD_FUNC_ENABLE;
+}
+
+static int intel_wd_capture(struct intel_wd *intel_wd,
+		struct intel_crtc_state *pipe_config,
+		struct intel_writeback_job *job)
+{
+	u32 tmp;
+	struct drm_i915_private *i915 = to_i915(intel_wd->base.base.dev);
+	int ret = 0, status = 0;
+	struct intel_crtc *wd_crtc = intel_wd->wd_crtc;
+	unsigned long flags;
+
+	drm_dbg_kms(&i915->drm, "\n");
+
+	if (!job->out_fence)
+		drm_dbg_kms(&i915->drm, "Not able to get out_fence for job\n");
+
+	ret = intel_wd_setup_transcoder(intel_wd, pipe_config, job);
+
+	if (ret < 0) {
+		drm_dbg_kms(&i915->drm,
+		"wd transcoder setup not completed aborting capture\n");
+		return -1;
+	}
+
+	if (wd_crtc == NULL) {
+		DRM_ERROR("CRTC not attached\n");
+		return -1;
+	}
+
+	tmp = intel_de_read_fw(i915,
+			WD_TRANS_FUNC_CTL(intel_wd->trans));
+	tmp |= START_TRIGGER_FRAME;
+	tmp &= ~WD_FRAME_NUMBER_MASK;
+	tmp |= intel_wd->frame_num;
+	intel_de_write_fw(i915,
+			WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);
+
+	if (!intel_de_wait_for_set(i915, WD_IIR(intel_wd->trans),
+				WD_FRAME_COMPLETE_INT, 100)){
+		drm_dbg_kms(&i915->drm, "frame captured\n");
+		tmp = intel_de_read(i915, WD_IIR(intel_wd->trans));
+		drm_dbg_kms(&i915->drm, "iir value : %d\n", tmp);
+		status = 0;
+	} else {
+		drm_dbg_kms(&i915->drm, "frame not captured triggering stop frame\n");
+		tmp = intel_de_read(i915,
+				WD_TRANS_FUNC_CTL(intel_wd->trans));
+		tmp |= STOP_TRIGGER_FRAME;
+		intel_de_write(i915,
+				WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);
+		status = -1;
+	}
+
+	intel_de_write(i915, WD_IIR(intel_wd->trans), tmp);
+	intel_wd_writeback_complete(intel_wd, job, status);
+	if (intel_get_writeback_job_from_queue(intel_wd) == NULL)
+		intel_wd_disable_capture(intel_wd);
+	if (wd_crtc->wd.e) {
+		spin_lock_irqsave(&i915->drm.event_lock, flags);
+		drm_dbg_kms(&i915->drm, "send %p\n", wd_crtc->wd.e);
+		drm_crtc_send_vblank_event(&wd_crtc->base,
+					wd_crtc->wd.e);
+		spin_unlock_irqrestore(&i915->drm.event_lock, flags);
+		wd_crtc->wd.e = NULL;
+	} else {
+		DRM_ERROR("Event NULL! %p, %p\n", &i915->drm,
+			wd_crtc);
+	}
+	return 0;
+
+}
+
+void intel_wd_enable_capture(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config,
+		struct drm_connector_state *conn_state)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	struct intel_writeback_job *job;
+
+	drm_dbg_kms(&i915->drm, "\n");
+
+	job = intel_get_writeback_job_from_queue(intel_wd);
+	if (job == NULL) {
+		drm_dbg_kms(&i915->drm,
+			"job queue is empty not capturing any frame\n");
+		return;
+	}
+
+	intel_wd_capture(intel_wd, pipe_config, job);
+	intel_wd->frame_num += 1;
+
+}
+
+void intel_wd_set_vblank_event(struct intel_crtc *intel_crtc,
+			struct intel_crtc_state *intel_crtc_state)
+{
+	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
+	struct drm_crtc_state *state = &intel_crtc_state->uapi;
+	struct intel_encoder *encoder;
+	struct intel_wd *intel_wd;
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (!intel_wd->wd_crtc) {
+			drm_dbg_kms(&i915->drm, "wd crtc not found\n");
+			return;
+		}
+	}
+
+	if (intel_crtc == intel_wd->wd_crtc) {
+		intel_crtc->wd.e = state->event;
+		state->event = NULL;
+		if (intel_crtc->wd.e)
+			drm_dbg_kms(&i915->drm, "WD event:%p\n",
+				intel_crtc->wd.e);
+		else
+			drm_dbg_kms(&i915->drm, "WD no event\n");
+	}
+}
+
+void intel_wd_handle_isr(struct drm_i915_private *i915)
+{
+	u32 iir_value = 0;
+	struct intel_encoder *encoder;
+	struct intel_wd *intel_wd;
+
+	iir_value = intel_de_read(i915, WD_IIR(TRANSCODER_WD_0));
+	drm_dbg_kms(&i915->drm, "\n");
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (!intel_wd->wd_crtc) {
+			DRM_ERROR("NO CRTC attached with WD\n");
+			goto clear_iir;
+		}
+	}
+
+	if (iir_value & WD_VBLANK_INT)
+		drm_dbg_kms(&i915->drm, "vblank interrupt for wd transcoder\n");
+	if (iir_value & WD_WRITE_COMPLETE_INT)
+		drm_dbg_kms(&i915->drm,
+		"wd write complete interrupt encountered\n");
+	else
+		DRM_INFO("iir: %x\n", iir_value);
+	if (iir_value & WD_FRAME_COMPLETE_INT) {
+		drm_dbg_kms(&i915->drm,
+			"frame complete interrupt for wd transcoder\n");
+		return;
+	}
+clear_iir:
+	intel_de_write(i915, WD_IIR(TRANSCODER_WD_0), iir_value);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_wd.h b/drivers/gpu/drm/i915/display/intel_wd.h
new file mode 100644
index 000000000000..2309afa23bb8
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wd.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author :
+ *	Suraj Kandpal<suraj.kandpal@intel.com>
+ *	Arun Murthy<arun.r.murthy@intel.com>
+ */
+
+#ifndef _INTEL_WD_H
+#define _INTEL_WD_H
+
+#include <drm/drm_crtc.h>
+#include <linux/sync_file.h>
+
+#include "intel_display_types.h"
+
+#define I915_MAX_WD_TANSCODERS 2
+
+struct intel_out_fence_state {
+	s32 __user *out_fence_ptr;
+	struct sync_file *sync_file;
+	int fd;
+};
+
+struct intel_wd {
+	struct intel_encoder base;
+	struct intel_crtc *wd_crtc;
+	struct intel_out_fence_state *fence_state;
+	intel_wakeref_t io_wakeref[I915_MAX_WD_TANSCODERS];
+	struct intel_connector *attached_connector;
+	enum transcoder trans;
+	struct i915_vma *vma;
+	unsigned long flags;
+	struct intel_writeback_job *job;
+	int triggered_cap_mode;
+	int frame_num;
+	bool stream_cap;
+	bool start_capture;
+	int slicing_strategy;
+};
+
+struct intel_wd_clk_vals {
+	u32 cdclk;
+	u16 link_m;
+	u16 link_n;
+};
+
+extern struct sync_file *sync_file_create(struct dma_fence *fence);
+static inline struct intel_wd *enc_to_intel_wd(struct intel_encoder *encoder)
+{
+	return container_of(&encoder->base, struct intel_wd, base.base);
+}
+void intel_wd_init(struct drm_i915_private *dev_priv, enum transcoder trans);
+void intel_wd_enable_capture(struct intel_encoder *encoder,
+				struct intel_crtc_state *pipe_config,
+				struct drm_connector_state *conn_state);
+void intel_wd_handle_isr(struct drm_i915_private *dev_priv);
+void intel_wd_set_vblank_event(struct intel_crtc *crtc,
+				struct intel_crtc_state *state);
+int intel_wd_prepare_out_fence(struct drm_device *dev,
+				struct drm_atomic_state *state);
+void intel_wd_complete_signaling(struct intel_wd *intel_wd);
+#endif/* _INTEL_WD_H */
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9a86ee88089e..b7e92a18125c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -38,6 +38,8 @@
 #include <linux/pm_qos.h>
 
 #include <drm/drm_connector.h>
+#include <drm/drm_writeback.h>
+#include <drm/i915_mei_hdcp_interface.h>
 #include <drm/ttm/ttm_device.h>
 
 #include "display/intel_bios.h"
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 73cebc6aa650..95a6a8f7a911 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -42,6 +42,7 @@
 #include "display/intel_hotplug.h"
 #include "display/intel_lpe_audio.h"
 #include "display/intel_psr.h"
+#include "display/intel_wd.h"
 
 #include "gt/intel_breadcrumbs.h"
 #include "gt/intel_gt.h"
@@ -2342,6 +2343,11 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
 		found = true;
 	}
 
+	if (iir & GEN8_DE_MISC_WD0) {
+		intel_wd_handle_isr(dev_priv);
+		found = true;
+	}
+
 	if (iir & GEN8_DE_EDP_PSR) {
 		struct intel_encoder *encoder;
 		u32 psr_iir;
@@ -3767,7 +3773,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
 	u32 de_pipe_enables;
 	u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
 	u32 de_port_enables;
-	u32 de_misc_masked = GEN8_DE_EDP_PSR;
+	u32 de_misc_masked = GEN8_DE_EDP_PSR | GEN8_DE_MISC_WD0;
 	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
 	enum pipe pipe;
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 67b89769f577..a524e0f030b6 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -853,7 +853,8 @@ static const struct intel_device_info jsl_info = {
 	.display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \
 	.display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | \
-		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \
+		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1)| \
+		BIT(TRANSCODER_WD_0), \
 	.pipe_offsets = { \
 		[TRANSCODER_A] = PIPE_A_OFFSET, \
 		[TRANSCODER_B] = PIPE_B_OFFSET, \
@@ -861,6 +862,8 @@ static const struct intel_device_info jsl_info = {
 		[TRANSCODER_D] = PIPE_D_OFFSET, \
 		[TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \
 		[TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \
+		[TRANSCODER_WD_0] = PIPE_WD0_OFFSET, \
+		[TRANSCODER_WD_1] = PIPE_WD1_OFFSET, \
 	}, \
 	.trans_offsets = { \
 		[TRANSCODER_A] = TRANSCODER_A_OFFSET, \
@@ -869,6 +872,8 @@ static const struct intel_device_info jsl_info = {
 		[TRANSCODER_D] = TRANSCODER_D_OFFSET, \
 		[TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \
 		[TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
+		[TRANSCODER_WD_0] = TRANSCODER_WD0_OFFSET, \
+		[TRANSCODER_WD_1] = TRANSCODER_WD1_OFFSET, \
 	}, \
 	TGL_CURSOR_OFFSETS, \
 	.has_global_mocs = 1, \
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 6396afd77209..abc41e7de0b5 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3797,6 +3797,11 @@
 #define PIPE_DSI0_OFFSET	0x7b000
 #define PIPE_DSI1_OFFSET	0x7b800
 
+/* WD 0 and 1 */
+#define PIPE_WD0_OFFSET		0x7e000
+#define PIPE_WD1_OFFSET		0x7d000
+
+
 #define PIPECONF(pipe)		_MMIO_PIPE2(pipe, _PIPEACONF)
 #define PIPEDSL(pipe)		_MMIO_PIPE2(pipe, _PIPEADSL)
 #define PIPEFRAME(pipe)		_MMIO_PIPE2(pipe, _PIPEAFRAMEHIGH)
@@ -4461,6 +4466,10 @@
 #define _PIPEDSI0CONF		0x7b008
 #define _PIPEDSI1CONF		0x7b808
 
+/* WD 0 and 1 */
+#define _PIPEWD0CONF		0x7e008
+#define _PIPEWD1CONF		0x7d008
+
 /* Sprite A control */
 #define _DVSACNTR		0x72180
 #define   DVS_ENABLE			REG_BIT(31)
@@ -5707,6 +5716,7 @@
 #define GEN8_DE_MISC_IER _MMIO(0x4446c)
 #define  GEN8_DE_MISC_GSE		(1 << 27)
 #define  GEN8_DE_EDP_PSR		(1 << 19)
+#define  GEN8_DE_MISC_WD0		(1 << 23)
 
 #define GEN8_PCU_ISR _MMIO(0x444e0)
 #define GEN8_PCU_IMR _MMIO(0x444e4)
@@ -8847,6 +8857,133 @@ enum skl_power_gate {
 #define   DSB_ENABLE			(1 << 31)
 #define   DSB_STATUS			(1 << 0)
 
+#define TGL_ROOT_DEVICE_ID		0x9A00
+#define TGL_ROOT_DEVICE_MASK		0xFF00
+#define TGL_ROOT_DEVICE_SKU_MASK	0xF
+#define TGL_ROOT_DEVICE_SKU_ULX		0x2
+#define TGL_ROOT_DEVICE_SKU_ULT		0x4
+
+/* Gen12 WD */
+#define _MMIO_WD(tc, wd0, wd1)		_MMIO_TRANS((tc) - TRANSCODER_WD_0, \
+							wd0, wd1)
+
+#define WD_TRANS_ENABLE			(1 << 31)
+#define WD_TRANS_DISABLE		0
+#define WD_TRANS_ACTIVE			(1 << 30)
+
+/* WD transcoder control */
+#define _WD_TRANS_FUNC_CTL_0		0x6e400
+#define _WD_TRANS_FUNC_CTL_1		0x6ec00
+#define WD_TRANS_FUNC_CTL(tc)		_MMIO_WD(tc,\
+					_WD_TRANS_FUNC_CTL_0,\
+					_WD_TRANS_FUNC_CTL_1)
+
+#define TRANS_WD_FUNC_ENABLE		(1 << 31)
+#define WD_TRIGGERED_CAP_MODE_ENABLE	(1 << 30)
+#define START_TRIGGER_FRAME		(1 << 29)
+#define STOP_TRIGGER_FRAME		(1 << 28)
+#define WD_CTL_POINTER_ETEH		(0 << 18)
+#define WD_CTL_POINTER_ETDH		(1 << 18)
+#define WD_CTL_POINTER_DTDH		(2 << 18)
+#define WD_INPUT_SELECT_MASK		(7 << 12)
+#define WD_INPUT_PIPE_A			(0 << 12)
+#define WD_INPUT_PIPE_B			(5 << 12)
+#define WD_INPUT_PIPE_C			(6 << 12)
+#define WD_INPUT_PIPE_D			(7 << 12)
+
+#define WD_PIX_FMT_MASK			(0x3 << 20)
+#define WD_PIX_FMT_YUYV			(0x1 << 20)
+#define WD_PIX_FMT_XYUV8888		(0x2 << 20)
+#define WD_PIX_FMT_XBGR8888		(0x3 << 20)
+#define WD_PIX_FMT_Y410			(0x4 << 20)
+#define WD_PIX_FMT_YUV422		(0x5 << 20)
+#define WD_PIX_FMT_XBGR2101010		(0x6 << 20)
+#define WD_PIX_FMT_RGB565		(0x7 << 20)
+
+#define WD_FRAME_NUMBER_MASK		15
+
+#define _WD_STRIDE_0			0x6e510
+#define _WD_STRIDE_1			0x6ed10
+#define WD_STRIDE(tc)			_MMIO_WD(tc,\
+					_WD_STRIDE_0,\
+					_WD_STRIDE_1)
+#define WD_STRIDE_SHIFT			6
+#define WD_STRIDE_MASK			(0x3ff << WD_STRIDE_SHIFT)
+
+#define _WD_STREAMCAP_CTL0		0x6e590
+#define _WD_STREAMCAP_CTL1		0x6ed90
+#define WD_STREAMCAP_CTL(tc)		_MMIO_WD(tc,\
+					_WD_STREAMCAP_CTL0,\
+					_WD_STREAMCAP_CTL1)
+
+#define WD_STREAM_CAP_MODE_EN		(1 << 31)
+#define WD_STRAT_MASK			(3 << 24)
+#define WD_SLICING_STRAT_1_1		(0 << 24)
+#define WD_SLICING_STRAT_2_1		(1 << 24)
+#define WD_SLICING_STRAT_4_1		(2 << 24)
+#define WD_SLICING_STRAT_8_1		(3 << 24)
+#define WD_STREAM_OVERRUN_STATUS	1
+
+#define _WD_SURF_0			0x6e514
+#define _WD_SURF_1			0x6ed14
+#define WD_SURF(tc)			_MMIO_WD(tc,\
+					_WD_SURF_0,\
+					_WD_SURF_1)
+
+#define _WD_IMR_0			0x6e560
+#define _WD_IMR_1			0x6ed60
+#define WD_IMR(tc)			_MMIO_WD(tc,\
+					_WD_IMR_0,\
+					_WD_IMR_1)
+#define WD_FRAME_COMPLETE_INT		(1 << 7)
+#define WD_GTT_FAULT_INT		(1 << 6)
+#define WD_VBLANK_INT			(1 << 5)
+#define WD_OVERRUN_INT			(1 << 4)
+#define WD_CAPTURING_INT		(1 << 3)
+#define WD_WRITE_COMPLETE_INT		(1 << 2)
+
+#define _WD_IIR_0			0x6e564
+#define _WD_IIR_1			0x6ed64
+#define WD_IIR(tc)			_MMIO_WD(tc,\
+					_WD_IIR_0,\
+					_WD_IIR_1)
+
+#define _WD_FRAME_STATUS_0		0x6e56b
+#define _WD_FRAME_STATUS_1		0x6ed6b
+#define WD_FRAME_STATUS(tc)		_MMIO_WD(tc,\
+					_WD_FRAME_STATUS_0,\
+					_WD_FRAME_STATUS_1)
+
+#define WD_FRAME_COMPLETE		(1 << 31)
+#define WD_STATE_IDLE			(0 << 24)
+#define WD_STATE_CAPSTART		(1 << 24)
+#define WD_STATE_FRAME_START		(2 << 24)
+#define WD_STATE_CAPACITIVE		(3 << 24)
+#define WD_STATE_TG_DONE		(4 << 24)
+#define WD_STATE_WDX_DONE		(5 << 24)
+#define WD_STATE_QUICK_CAP		(6 << 24)
+
+#define _WD_27_M_0			0x6e524
+#define _WD_27_M_1			0x6ed24
+#define WD_27_M(tc)			_MMIO_WD(tc,\
+					_WD_27_M_0,\
+					_WD_27_M_1)
+
+#define _WD_27_N_0			0x6e528
+
+//Address looks wrong in bspec:
+#define _WD_27_N_1			0x6ec28
+#define WD_27_N(tc)			_MMIO_WD(tc,\
+					_WD_27_N_0,\
+					_WD_27_N_1)
+
+#define _WD_TAIL_CFG_0			0x6e520
+#define _WD_TAIL_CFG_1			0x6ed20
+
+#define WD_TAIL_CFG(tc)			_MMIO_WD(tc,\
+					_WD_TAIL_CFG_0,\
+					_WD_TAIL_CFG_1)
+
 #define CLKREQ_POLICY			_MMIO(0x101038)
 #define  CLKREQ_POLICY_MEM_UP_OVRD	REG_BIT(1)
 
-- 
2.35.1


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

* [Intel-gfx] [RFC PATCH v2 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework
  2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework Suraj Kandpal
  2022-03-16 14:25   ` kernel test robot
@ 2022-03-18  4:18   ` Suraj Kandpal
  2022-04-06  4:58     ` Kandpal, Suraj
  1 sibling, 1 reply; 24+ messages in thread
From: Suraj Kandpal @ 2022-03-18  4:18 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Changes to create a i915 private pipeline to enable the WD transcoder
without relying on the current drm_writeback framework.

Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 .../drm/i915/display/intel_display_types.h    |   4 +
 .../gpu/drm/i915/display/intel_wb_connector.c | 296 ++++++++++++++++++
 .../gpu/drm/i915/display/intel_wb_connector.h |  99 ++++++
 drivers/gpu/drm/i915/i915_drv.h               |   3 +
 5 files changed, 403 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 1a771ee5b1d0..087bd9d1b397 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -286,6 +286,7 @@ i915-y += \
 	display/intel_tv.o \
 	display/intel_vdsc.o \
 	display/intel_vrr.o \
+	display/intel_wb_connector.o\
 	display/vlv_dsi.o \
 	display/vlv_dsi_pll.o
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index d84e82f3eab9..7a96ecba73c0 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -52,6 +52,7 @@
 #include "intel_display_power.h"
 #include "intel_dpll_mgr.h"
 #include "intel_pm_types.h"
+#include "intel_wb_connector.h"
 
 struct drm_printer;
 struct __intel_global_objs_state;
@@ -537,11 +538,14 @@ struct intel_connector {
 	struct work_struct modeset_retry_work;
 
 	struct intel_hdcp hdcp;
+
+	struct intel_writeback_connector wb_conn;
 };
 
 struct intel_digital_connector_state {
 	struct drm_connector_state base;
 
+	struct intel_writeback_job *job;
 	enum hdmi_force_audio force_audio;
 	int broadcast_rgb;
 };
diff --git a/drivers/gpu/drm/i915/display/intel_wb_connector.c b/drivers/gpu/drm/i915/display/intel_wb_connector.c
new file mode 100644
index 000000000000..65f4abef53d0
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wb_connector.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright © 2022 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Suraj Kandpal <suraj.kandpal@intel.com>
+ *	Arun Murthy <arun.r.murthy@intel.com>
+ *
+ */
+
+
+#include <linux/dma-fence.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_property.h>
+
+#include "i915_drv.h"
+#include "intel_wb_connector.h"
+#include "intel_display_types.h"
+
+#define fence_to_wb_connector(x) container_of(x->lock, \
+					      struct intel_writeback_connector, \
+					      fence_lock)
+
+static const char *intel_writeback_fence_get_driver_name(struct dma_fence *fence)
+{
+	struct intel_writeback_connector *wb_connector =
+		fence_to_wb_connector(fence);
+
+	return wb_connector->base->dev->driver->name;
+}
+
+static const char *
+intel_writeback_fence_get_timeline_name(struct dma_fence *fence)
+{
+	struct intel_writeback_connector *wb_connector =
+		fence_to_wb_connector(fence);
+
+	return wb_connector->timeline_name;
+}
+
+static bool intel_writeback_fence_enable_signaling(struct dma_fence *fence)
+{
+	return true;
+}
+
+static const struct dma_fence_ops intel_writeback_fence_ops = {
+	.get_driver_name = intel_writeback_fence_get_driver_name,
+	.get_timeline_name = intel_writeback_fence_get_timeline_name,
+	.enable_signaling = intel_writeback_fence_enable_signaling,
+};
+
+static int intel_create_writeback_properties(struct drm_device *dev)
+{
+	struct drm_property *prop;
+	struct drm_i915_private *i915 = to_i915(dev);
+
+	if (!i915->wb_fb_id_property) {
+		prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+						"WRITEBACK_FB_ID",
+						DRM_MODE_OBJECT_FB);
+		if (!prop)
+			return -ENOMEM;
+		i915->wb_fb_id_property = prop;
+	}
+
+	if (!i915->wb_pixel_formats_property) {
+		prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
+					DRM_MODE_PROP_ATOMIC |
+					DRM_MODE_PROP_IMMUTABLE,
+					"WRITEBACK_PIXEL_FORMATS", 0);
+		if (!prop)
+			return -ENOMEM;
+		i915->wb_pixel_formats_property = prop;
+	}
+
+	if (!i915->wb_out_fence_ptr_property) {
+		prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+						"WRITEBACK_OUT_FENCE_PTR", 0,
+						U64_MAX);
+		if (!prop)
+			return -ENOMEM;
+		i915->wb_out_fence_ptr_property = prop;
+	}
+
+	return 0;
+}
+
+static const struct drm_encoder_funcs intel_writeback_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int intel_writeback_connector_init(struct drm_device *dev,
+				 struct intel_writeback_connector *wb_connector,
+				 const struct drm_connector_funcs *con_funcs,
+				 const struct drm_encoder_helper_funcs *enc_helper_funcs,
+				 const u32 *formats, int n_formats)
+{
+	struct drm_property_blob *blob;
+	struct drm_i915_private *i915 = to_i915(dev);
+	struct drm_connector *connector = wb_connector->base;
+	int ret;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	ret = intel_create_writeback_properties(dev);
+
+	if (ret != 0)
+		return ret;
+
+	blob = drm_property_create_blob(dev, n_formats * sizeof(*formats),
+					formats);
+	if (IS_ERR(blob))
+		return PTR_ERR(blob);
+
+	drm_encoder_helper_add(wb_connector->encoder, enc_helper_funcs);
+	ret = drm_encoder_init(dev, wb_connector->encoder,
+			&intel_writeback_encoder_funcs,
+			DRM_MODE_ENCODER_VIRTUAL, NULL);
+	if (ret)
+		goto fail;
+
+	connector->interlace_allowed = 0;
+
+	ret = drm_connector_init(dev, connector, con_funcs,
+				DRM_MODE_CONNECTOR_WRITEBACK);
+	if (ret)
+		goto connector_fail;
+
+	ret = drm_connector_attach_encoder(connector,
+					wb_connector->encoder);
+	if (ret)
+		goto attach_fail;
+
+	INIT_LIST_HEAD(&wb_connector->job_queue);
+	spin_lock_init(&wb_connector->job_lock);
+
+	wb_connector->fence_context = dma_fence_context_alloc(1);
+	spin_lock_init(&wb_connector->fence_lock);
+	snprintf(wb_connector->timeline_name,
+		sizeof(wb_connector->timeline_name),
+		"CONNECTOR:%d-%s", connector->base.id, connector->name);
+
+	drm_object_attach_property(&connector->base,
+				i915->wb_out_fence_ptr_property, 0);
+
+	drm_object_attach_property(&connector->base,
+				i915->wb_fb_id_property, 0);
+
+	drm_object_attach_property(&connector->base,
+				i915->wb_pixel_formats_property,
+				blob->base.id);
+	wb_connector->pixel_formats_blob_ptr = blob;
+
+	return 0;
+
+attach_fail:
+	drm_connector_cleanup(connector);
+connector_fail:
+	drm_encoder_cleanup(wb_connector->encoder);
+fail:
+	drm_property_blob_put(blob);
+	return ret;
+}
+
+void intel_writeback_queue_job(struct intel_writeback_connector *wb_connector,
+		struct drm_connector_state *conn_state)
+{
+	struct intel_writeback_job *wb_job;
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
+	unsigned long flags;
+
+	wb_job = intel_conn_state->job;
+	intel_conn_state->job = NULL;
+
+	spin_lock_irqsave(&wb_connector->job_lock, flags);
+	list_add_tail(&wb_job->list_entry, &wb_connector->job_queue);
+	spin_unlock_irqrestore(&wb_connector->job_lock, flags);
+}
+
+int intel_writeback_set_fb(struct drm_connector_state *conn_state,
+			 struct drm_framebuffer *fb)
+{
+	struct intel_connector *intel_connector = to_intel_connector(conn_state->connector);
+	struct intel_writeback_connector *wb_connector = &intel_connector->wb_conn;
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
+	WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
+
+	if (!intel_conn_state->job) {
+		intel_conn_state->job =
+			kzalloc(sizeof(*intel_conn_state->job), GFP_KERNEL);
+		if (!intel_conn_state->job)
+			return -ENOMEM;
+
+		intel_conn_state->job->connector = wb_connector;
+	}
+
+	drm_framebuffer_assign(&intel_conn_state->job->fb, fb);
+	return 0;
+}
+
+void intel_writeback_cleanup_job(struct intel_writeback_job *job)
+{
+	if (job->fb)
+		drm_framebuffer_put(job->fb);
+
+	if (job->out_fence)
+		dma_fence_put(job->out_fence);
+
+	kfree(job);
+}
+
+static void cleanup_work(struct work_struct *work)
+{
+	struct intel_writeback_job *job = container_of(work,
+						struct intel_writeback_job,
+						cleanup_work);
+
+	intel_writeback_cleanup_job(job);
+}
+
+void
+intel_writeback_signal_completion(struct intel_writeback_connector *wb_connector,
+				int status)
+{
+	unsigned long flags;
+	struct intel_writeback_job *job;
+	struct dma_fence *out_fence;
+
+	spin_lock_irqsave(&wb_connector->job_lock, flags);
+	job = list_first_entry_or_null(&wb_connector->job_queue,
+					struct intel_writeback_job,
+					list_entry);
+	if (job)
+		list_del(&job->list_entry);
+
+	spin_unlock_irqrestore(&wb_connector->job_lock, flags);
+
+	if (WARN_ON(!job))
+		return;
+
+	out_fence = job->out_fence;
+	if (out_fence) {
+		if (status)
+			dma_fence_set_error(out_fence, status);
+		dma_fence_signal(out_fence);
+		dma_fence_put(out_fence);
+		job->out_fence = NULL;
+	}
+
+	INIT_WORK(&job->cleanup_work, cleanup_work);
+	queue_work(system_long_wq, &job->cleanup_work);
+}
+
+struct dma_fence *
+intel_writeback_get_out_fence(struct intel_writeback_connector *wb_connector)
+{
+	struct dma_fence *fence;
+
+	if (WARN_ON(wb_connector->base->connector_type !=
+		DRM_MODE_CONNECTOR_WRITEBACK))
+		return NULL;
+
+	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+	if (!fence)
+		return NULL;
+
+	dma_fence_init(fence, &intel_writeback_fence_ops,
+		&wb_connector->fence_lock, wb_connector->fence_context,
+		++wb_connector->fence_seqno);
+
+	return fence;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_wb_connector.h b/drivers/gpu/drm/i915/display/intel_wb_connector.h
new file mode 100644
index 000000000000..71142457b7c1
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wb_connector.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Copyright © 2022 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Suraj Kandpal <suraj.kandpal@intel.com>
+ *	Arun Murthy <arun.r.murthy@intel.com>
+ *
+ */
+
+#ifndef __INTEL_WB_CONNECTOR_H__
+#define __INTEL_WB_CONNECTOR_H__
+
+#include <drm/drm_connector.h>
+#include <drm/drm_encoder.h>
+#include <linux/workqueue.h>
+#include "intel_display.h"
+
+/**
+ * struct intel_writeback_connector - Intel writeback connector
+ * to get a idea of each individual variable please look at
+ * documentation in drm_writeback.h we emulate the same structure
+ * ditto for intel_writeback_job structure.
+ */
+struct intel_writeback_connector {
+	struct drm_connector *base;
+	struct drm_encoder *encoder;
+	struct drm_property_blob *pixel_formats_blob_ptr;
+	spinlock_t job_lock;
+	struct list_head job_queue;
+	unsigned int fence_context;
+	spinlock_t fence_lock;
+	unsigned long fence_seqno;
+	char timeline_name[32];
+};
+
+/**
+ * struct intel_writeback_job - DRM writeback job
+ */
+struct intel_writeback_job {
+	struct intel_writeback_connector *connector;
+	bool *prepared;
+	struct work_struct cleanup_work;
+	struct list_head list_entry;
+	struct drm_framebuffer *fb;
+	struct dma_fence *out_fence;
+	void *priv;
+};
+
+int intel_writeback_connector_init(struct drm_device *dev,
+			struct intel_writeback_connector *wb_connector,
+			const struct drm_connector_funcs *con_funcs,
+			const struct drm_encoder_helper_funcs *enc_helper_funcs,
+			const u32 *formats, int n_formats);
+
+int intel_writeback_set_fb(struct drm_connector_state *conn_state,
+			struct drm_framebuffer *fb);
+
+int intel_writeback_prepare_job(struct intel_writeback_job *job);
+
+void intel_writeback_queue_job(struct intel_writeback_connector *wb_connector,
+			struct drm_connector_state *conn_state);
+
+void intel_writeback_cleanup_job(struct intel_writeback_job *job);
+
+void
+intel_writeback_signal_completion(struct intel_writeback_connector *wb_connector,
+			int status);
+
+struct dma_fence *
+intel_writeback_get_out_fence(struct intel_writeback_connector *wb_connector);
+struct intel_wb_connector *intel_wb_connector_alloc(void);
+void intel_wb_connector_free(struct intel_wb_connector *connector);
+void intel_wb_connector_destroy(struct drm_connector *connector);
+bool intel_wb_connector_get_hw_state(struct intel_wb_connector *connector);
+enum pipe intel_wb_connector_get_pipe(struct intel_wb_connector *connector);
+void intel_wb_connector_attach_encoder(struct intel_wb_connector *connector,
+					struct intel_encoder *encoder);
+
+#endif /* __INTEL_WB_CONNECTOR_H__ */
+
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 26df561a4e94..9a86ee88089e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -678,6 +678,9 @@ struct drm_i915_private {
 
 	struct drm_property *broadcast_rgb_property;
 	struct drm_property *force_audio_property;
+	struct drm_property *wb_fb_id_property;
+	struct drm_property *wb_out_fence_ptr_property;
+	struct drm_property *wb_pixel_formats_property;
 
 	u32 fdi_rx_config;
 
-- 
2.35.1


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

* [Intel-gfx] [RFC PATCH v2 2/3] drm/i915: Define WD trancoder for i915
  2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 2/3] drm/i915: Define WD trancoder for i915 Suraj Kandpal
@ 2022-03-18  4:20   ` Suraj Kandpal
  0 siblings, 0 replies; 24+ messages in thread
From: Suraj Kandpal @ 2022-03-18  4:20 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Adding WD Types, WD transcoder to enum list and WD Transcoder offsets

Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.h       | 6 ++++++
 drivers/gpu/drm/i915/display/intel_display_types.h | 1 +
 drivers/gpu/drm/i915/i915_reg.h                    | 2 ++
 3 files changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 8513703086b7..8c93a5de8e07 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -119,6 +119,8 @@ enum transcoder {
 	TRANSCODER_DSI_1,
 	TRANSCODER_DSI_A = TRANSCODER_DSI_0,	/* legacy DSI */
 	TRANSCODER_DSI_C = TRANSCODER_DSI_1,	/* legacy DSI */
+	TRANSCODER_WD_0,
+	TRANSCODER_WD_1,
 
 	I915_MAX_TRANSCODERS
 };
@@ -140,6 +142,10 @@ static inline const char *transcoder_name(enum transcoder transcoder)
 		return "DSI A";
 	case TRANSCODER_DSI_C:
 		return "DSI C";
+	case TRANSCODER_WD_0:
+		return "WD 0";
+	case TRANSCODER_WD_1:
+		return "WD 1";
 	default:
 		return "<invalid>";
 	}
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 7a96ecba73c0..dcb4ad43cf88 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -79,6 +79,7 @@ enum intel_output_type {
 	INTEL_OUTPUT_DSI = 9,
 	INTEL_OUTPUT_DDI = 10,
 	INTEL_OUTPUT_DP_MST = 11,
+	INTEL_OUTPUT_WD = 12,
 };
 
 enum hdmi_force_audio {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ddbc7a685a50..6396afd77209 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2023,6 +2023,8 @@
 #define TRANSCODER_EDP_OFFSET 0x6f000
 #define TRANSCODER_DSI0_OFFSET	0x6b000
 #define TRANSCODER_DSI1_OFFSET	0x6b800
+#define TRANSCODER_WD0_OFFSET	0x6e000
+#define TRANSCODER_WD1_OFFSET	0x6e800
 
 #define HTOTAL(trans)		_MMIO_TRANS2(trans, _HTOTAL_A)
 #define HBLANK(trans)		_MMIO_TRANS2(trans, _HBLANK_A)
-- 
2.35.1


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

* [Intel-gfx] [RFC PATCH v2 3/3] drm/i915: Enabling WD Transcoder
  2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 3/3] drm/i915: Enabling WD Transcoder Suraj Kandpal
@ 2022-03-18  4:21   ` Suraj Kandpal
  2022-03-25  5:35     ` Kandpal, Suraj
  0 siblings, 1 reply; 24+ messages in thread
From: Suraj Kandpal @ 2022-03-18  4:21 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Adding support for writeback transcoder to start capturing frames using
interrupt mechanism

Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |   1 +
 drivers/gpu/drm/i915/display/intel_acpi.c     |   1 +
 drivers/gpu/drm/i915/display/intel_display.c  |  89 +-
 drivers/gpu/drm/i915/display/intel_display.h  |   9 +
 .../drm/i915/display/intel_display_types.h    |  13 +
 drivers/gpu/drm/i915/display/intel_dpll.c     |   3 +
 drivers/gpu/drm/i915/display/intel_opregion.c |   3 +
 drivers/gpu/drm/i915/display/intel_wd.c       | 978 ++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_wd.h       |  82 ++
 drivers/gpu/drm/i915/i915_drv.h               |   2 +
 drivers/gpu/drm/i915/i915_irq.c               |   8 +-
 drivers/gpu/drm/i915/i915_pci.c               |   7 +-
 drivers/gpu/drm/i915/i915_reg.h               | 137 +++
 13 files changed, 1330 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_wd.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_wd.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 087bd9d1b397..5ee32513a945 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -287,6 +287,7 @@ i915-y += \
 	display/intel_vdsc.o \
 	display/intel_vrr.o \
 	display/intel_wb_connector.o\
+	display/intel_wd.o\
 	display/vlv_dsi.o \
 	display/vlv_dsi_pll.o
 
diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c
index e78430001f07..ae08db164f73 100644
--- a/drivers/gpu/drm/i915/display/intel_acpi.c
+++ b/drivers/gpu/drm/i915/display/intel_acpi.c
@@ -247,6 +247,7 @@ static u32 acpi_display_type(struct intel_connector *connector)
 	case DRM_MODE_CONNECTOR_LVDS:
 	case DRM_MODE_CONNECTOR_eDP:
 	case DRM_MODE_CONNECTOR_DSI:
+	case DRM_MODE_CONNECTOR_WRITEBACK:
 		display_type = ACPI_DISPLAY_TYPE_INTERNAL_DIGITAL;
 		break;
 	case DRM_MODE_CONNECTOR_Unknown:
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index eb49973621f0..6dedc7921f54 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -111,6 +111,7 @@
 #include "intel_sprite.h"
 #include "intel_tc.h"
 #include "intel_vga.h"
+#include "intel_wd.h"
 #include "i9xx_plane.h"
 #include "skl_scaler.h"
 #include "skl_universal_plane.h"
@@ -1544,6 +1545,72 @@ static void intel_encoders_update_complete(struct intel_atomic_state *state)
 	}
 }
 
+static void intel_queue_writeback_job(struct intel_atomic_state *state,
+		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)
+{
+	struct drm_connector_state *new_conn_state;
+	struct drm_connector *connector;
+	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
+	struct intel_wd *intel_wd;
+	struct intel_connector *intel_connector;
+	struct intel_digital_connector_state *intel_conn_state;
+	struct intel_encoder *encoder;
+	int i;
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (intel_wd->wd_crtc != intel_crtc)
+			return;
+
+	}
+
+	for_each_new_connector_in_state(&state->base, connector, new_conn_state,
+					i) {
+		intel_conn_state = to_intel_digital_connector_state(new_conn_state);
+		if (!intel_conn_state->job)
+			continue;
+		intel_connector = to_intel_connector(connector);
+		intel_writeback_queue_job(&intel_connector->wb_conn, new_conn_state);
+		drm_dbg_kms(&i915->drm, "queueing writeback job\n");
+	}
+}
+
+static void intel_find_writeback_connector(struct intel_atomic_state *state,
+		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)
+{
+	struct drm_connector_state *new_conn_state;
+	struct drm_connector *connector;
+	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
+	struct intel_wd *intel_wd;
+	struct intel_encoder *encoder;
+	int i;
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (intel_wd->wd_crtc != intel_crtc)
+			return;
+
+	}
+
+	for_each_new_connector_in_state(&state->base, connector, new_conn_state,
+					i) {
+		struct intel_connector *intel_connector;
+
+		intel_connector = to_intel_connector(connector);
+		drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]: status: %s\n",
+				connector->base.id, connector->name,
+				drm_get_connector_status_name(connector->status));
+		encoder = intel_connector_primary_encoder(intel_connector);
+		if (encoder->type == INTEL_OUTPUT_WD) {
+			drm_dbg_kms(&i915->drm, "encoder intel_output_wd found\n");
+			intel_wd_enable_capture(encoder, crtc_state, new_conn_state);
+		}
+	}
+
+}
+
 static void intel_encoders_pre_pll_enable(struct intel_atomic_state *state,
 					  struct intel_crtc *crtc)
 {
@@ -1944,7 +2011,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
 		bdw_set_pipemisc(new_crtc_state);
 
 	if (!intel_crtc_is_bigjoiner_slave(new_crtc_state) &&
-	    !transcoder_is_dsi(cpu_transcoder))
+	    !transcoder_is_dsi(cpu_transcoder) &&
+	    !transcoder_is_wd(cpu_transcoder))
 		hsw_configure_cpu_transcoder(new_crtc_state);
 
 	crtc->active = true;
@@ -2632,6 +2700,9 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,
 	if (connector->get_hw_state(connector)) {
 		struct intel_encoder *encoder = intel_attached_encoder(connector);
 
+		if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+			return;
+
 		I915_STATE_WARN(!crtc_state,
 			 "connector enabled without attached crtc\n");
 
@@ -5233,6 +5304,7 @@ static const char * const output_type_str[] = {
 	OUTPUT_TYPE(DSI),
 	OUTPUT_TYPE(DDI),
 	OUTPUT_TYPE(DP_MST),
+	OUTPUT_TYPE(WD),
 };
 
 #undef OUTPUT_TYPE
@@ -8577,6 +8649,12 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 		}
 	}
 
+	if (DISPLAY_VER(dev_priv) >= 12) {
+		for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+			intel_wd_set_vblank_event(crtc, new_crtc_state);
+		}
+	}
+
 	intel_encoders_update_prepare(state);
 
 	intel_dbuf_pre_plane_update(state);
@@ -8662,6 +8740,14 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 
 	intel_sagv_post_plane_update(state);
 
+	if (DISPLAY_VER(dev_priv) >= 12) {
+		intel_wd_prepare_out_fence(dev, &state->base);
+		for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+			intel_queue_writeback_job(state, crtc, new_crtc_state);
+			intel_find_writeback_connector(state, crtc, new_crtc_state);
+		}
+	}
+
 	drm_atomic_helper_commit_hw_done(&state->base);
 
 	if (state->modeset) {
@@ -8966,6 +9052,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
 		intel_ddi_init(dev_priv, PORT_TC1);
 		intel_ddi_init(dev_priv, PORT_TC2);
 	} else if (DISPLAY_VER(dev_priv) >= 12) {
+		intel_wd_init(dev_priv, TRANSCODER_WD_0);
 		intel_ddi_init(dev_priv, PORT_A);
 		intel_ddi_init(dev_priv, PORT_B);
 		intel_ddi_init(dev_priv, PORT_TC1);
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 8c93a5de8e07..27237d36a888 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -156,6 +156,11 @@ static inline bool transcoder_is_dsi(enum transcoder transcoder)
 	return transcoder == TRANSCODER_DSI_A || transcoder == TRANSCODER_DSI_C;
 }
 
+static inline bool transcoder_is_wd(enum transcoder transcoder)
+{
+	return transcoder == TRANSCODER_WD_0 || transcoder == TRANSCODER_WD_1;
+}
+
 /*
  * Global legacy plane identifier. Valid only for primary/sprite
  * planes on pre-g4x, and only for primary planes on g4x-bdw.
@@ -467,6 +472,10 @@ enum hpd_pin {
 	for_each_intel_encoder((dev), (intel_encoder)) \
 		for_each_if(intel_encoder_can_psr(intel_encoder))
 
+#define for_each_intel_encoder_with_wd(dev, intel_encoder)	\
+	for_each_intel_encoder(dev, intel_encoder)		\
+		for_each_if(intel_encoder_is_wd(intel_encoder))
+
 #define for_each_intel_connector_iter(intel_connector, iter) \
 	while ((intel_connector = to_intel_connector(drm_connector_list_iter_next(iter))))
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index dcb4ad43cf88..8522c348a73d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1293,6 +1293,11 @@ struct intel_crtc {
 	bool cpu_fifo_underrun_disabled;
 	bool pch_fifo_underrun_disabled;
 
+	struct {
+		struct drm_pending_vblank_event *e;
+		atomic_t work_busy;
+		wait_queue_head_t wd_wait;
+	} wd;
 	/* per-pipe watermark state */
 	struct {
 		/* watermarks currently being used  */
@@ -1420,6 +1425,7 @@ struct cxsr_latency {
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
 #define to_intel_crtc_state(x) container_of(x, struct intel_crtc_state, uapi)
 #define to_intel_connector(x) container_of(x, struct intel_connector, base)
+#define to_intel_wb_connector(x) container_of(x, struct intel_wb_connector, base)
 #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 #define to_intel_plane(x) container_of(x, struct intel_plane, base)
@@ -1851,6 +1857,13 @@ static inline bool intel_encoder_is_dp(struct intel_encoder *encoder)
 	}
 }
 
+static inline bool intel_encoder_is_wd(struct intel_encoder *encoder)
+{
+	if (encoder->type == INTEL_OUTPUT_WD)
+		return true;
+	return false;
+}
+
 static inline struct intel_lspcon *
 enc_to_intel_lspcon(struct intel_encoder *encoder)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c
index 95b9d327ed4d..dfea17f5f99d 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll.c
@@ -939,6 +939,9 @@ static int hsw_crtc_compute_clock(struct intel_crtc_state *crtc_state)
 	if (IS_DG2(dev_priv))
 		return intel_mpllb_calc_state(crtc_state, encoder);
 
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_WD))
+		return 0;
+
 	if (DISPLAY_VER(dev_priv) < 11 &&
 	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
 		return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c
index f31e8c3f8ce0..b7a0ac9bad05 100644
--- a/drivers/gpu/drm/i915/display/intel_opregion.c
+++ b/drivers/gpu/drm/i915/display/intel_opregion.c
@@ -370,6 +370,9 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
 	if (ret)
 		return ret;
 
+	if (intel_encoder->type == INTEL_OUTPUT_WD)
+		return 0;
+
 	if (intel_encoder->type == INTEL_OUTPUT_DSI)
 		port = 0;
 	else
diff --git a/drivers/gpu/drm/i915/display/intel_wd.c b/drivers/gpu/drm/i915/display/intel_wd.c
new file mode 100644
index 000000000000..a6c9350c3986
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wd.c
@@ -0,0 +1,978 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Suraj Kandpal <suraj.kandpal@intel.com>
+ *	Arun Murthy <arun.r.murthy@intel.com>
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
+
+#include "intel_atomic.h"
+#include "intel_connector.h"
+#include "intel_wd.h"
+#include "intel_fb_pin.h"
+#include "intel_de.h"
+#include "intel_wb_connector.h"
+
+enum {
+	WD_CAPTURE_4_PIX,
+	WD_CAPTURE_2_PIX,
+} wd_capture_format;
+
+static struct intel_writeback_job
+*intel_get_writeback_job_from_queue(struct intel_wd *intel_wd)
+{
+	struct intel_writeback_job *job;
+	struct drm_i915_private *i915 = to_i915(intel_wd->base.base.dev);
+	struct intel_writeback_connector *wb_conn =
+		&intel_wd->attached_connector->wb_conn;
+	unsigned long flags;
+
+	spin_lock_irqsave(&wb_conn->job_lock, flags);
+	job = list_first_entry_or_null(&wb_conn->job_queue,
+			struct intel_writeback_job,
+			list_entry);
+	spin_unlock_irqrestore(&wb_conn->job_lock, flags);
+	if (job == NULL) {
+		drm_dbg_kms(&i915->drm, "job queue is empty\n");
+		return NULL;
+	}
+
+	return job;
+}
+
+/*Check with Spec*/
+static const u32 wb_fmts[] = {
+		DRM_FORMAT_YUV444,
+		DRM_FORMAT_XYUV8888,
+		DRM_FORMAT_XBGR8888,
+		DRM_FORMAT_XRGB8888,
+		DRM_FORMAT_Y410,
+		DRM_FORMAT_YUV422,
+		DRM_FORMAT_XBGR2101010,
+		DRM_FORMAT_RGB565,
+
+};
+
+static int intel_wd_get_format(int pixel_format)
+{
+	int wd_format = -EINVAL;
+
+	switch (pixel_format) {
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_XYUV8888:
+	case DRM_FORMAT_YUV444:
+		wd_format = WD_CAPTURE_4_PIX;
+		break;
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_RGB565:
+		wd_format = WD_CAPTURE_2_PIX;
+		break;
+	default:
+		DRM_ERROR("unsupported pixel format %x!\n",
+			pixel_format);
+	}
+
+	return wd_format;
+}
+
+static int intel_wd_verify_pix_format(int format)
+{
+	const struct drm_format_info *info = drm_format_info(format);
+	int pix_format = info->format;
+	int i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(wb_fmts); i++)
+		if (pix_format == wb_fmts[i])
+			return 0;
+
+	return 1;
+}
+
+static u32 intel_wd_get_stride(const struct intel_crtc_state *crtc_state,
+			int format)
+{
+	const struct drm_format_info *info = drm_format_info(format);
+	int wd_format;
+	int hactive, pixel_size;
+
+	wd_format = intel_wd_get_format(info->format);
+
+	switch (wd_format) {
+	case WD_CAPTURE_4_PIX:
+		pixel_size = 4;
+		break;
+	case WD_CAPTURE_2_PIX:
+		pixel_size = 2;
+		break;
+	default:
+		pixel_size = 1;
+		break;
+	}
+
+	hactive = crtc_state->hw.adjusted_mode.crtc_hdisplay;
+
+	return DIV_ROUND_UP(hactive * pixel_size, 64);
+}
+
+static int intel_wd_pin_fb(struct intel_wd *intel_wd,
+			struct drm_framebuffer *fb)
+{
+	const struct i915_ggtt_view view = {
+		.type = I915_GGTT_VIEW_NORMAL,
+		};
+	struct i915_vma *vma;
+
+	vma = intel_pin_and_fence_fb_obj(fb, false, &view, false,
+			&intel_wd->flags);
+
+	if (IS_ERR(vma))
+		return PTR_ERR(vma);
+
+	intel_wd->vma = vma;
+	return 0;
+}
+
+static void intel_configure_slicing_strategy(struct drm_i915_private *i915,
+		struct intel_wd *intel_wd, u32 *tmp)
+{
+	*tmp &= ~WD_STRAT_MASK;
+	if (intel_wd->slicing_strategy == 1)
+		*tmp |= WD_SLICING_STRAT_1_1;
+	else if (intel_wd->slicing_strategy == 2)
+		*tmp |= WD_SLICING_STRAT_2_1;
+	else if (intel_wd->slicing_strategy == 3)
+		*tmp |= WD_SLICING_STRAT_4_1;
+	else if (intel_wd->slicing_strategy == 4)
+		*tmp |= WD_SLICING_STRAT_8_1;
+
+	intel_de_write(i915, WD_STREAMCAP_CTL(intel_wd->trans),
+			*tmp);
+
+}
+
+static enum drm_mode_status
+intel_wd_mode_valid(struct drm_connector *connector,
+		struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static int intel_wd_get_modes(struct drm_connector *connector)
+{
+	return 0;
+}
+
+static void intel_wd_get_config(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_crtc *intel_crtc =
+		to_intel_crtc(pipe_config->uapi.crtc);
+
+	drm_dbg_kms(&i915->drm, "\n");
+	if (intel_crtc) {
+		memcpy(pipe_config, intel_crtc->config,
+			sizeof(*pipe_config));
+		pipe_config->output_types |= BIT(INTEL_OUTPUT_WD);
+		drm_dbg_kms(&i915->drm, "crtc found\n");
+	}
+
+}
+
+static int intel_wd_compute_config(struct intel_encoder *encoder,
+			struct intel_crtc_state *pipe_config,
+			struct drm_connector_state *conn_state)
+{
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
+	struct intel_writeback_job *job;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	job = intel_get_writeback_job_from_queue(intel_wd);
+	if (job || intel_conn_state->job) {
+		intel_wd->wd_crtc = to_intel_crtc(pipe_config->uapi.crtc);
+		return 0;
+	}
+	drm_dbg_kms(&i915->drm, "No writebackjob in queue\n");
+
+	return 0;
+}
+
+static void intel_wd_get_power_domains(struct intel_encoder *encoder,
+			struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	intel_wakeref_t wakeref;
+
+	wakeref = intel_display_power_get(i915,
+				encoder->power_domain);
+
+	intel_wd->io_wakeref[0] = wakeref;
+	drm_dbg_kms(&i915->drm, "\n");
+}
+
+static bool intel_wd_get_hw_state(struct intel_encoder *encoder,
+		enum pipe *pipe)
+{
+	bool ret = false;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	struct intel_crtc *wd_crtc = intel_wd->wd_crtc;
+	intel_wakeref_t wakeref;
+	u32 tmp;
+
+	if (wd_crtc)
+		return false;
+
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+				encoder->power_domain);
+	drm_dbg_kms(encoder->base.dev, "power enabled : %s\n",
+			!wakeref ? "false":"true");
+
+	if (!wakeref)
+		return false;
+
+	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+	ret = tmp & WD_TRANS_ACTIVE;
+	drm_dbg_kms(encoder->base.dev, "trancoder enabled: %s\n",
+			ret ? "true":"false");
+	if (ret) {
+		*pipe = wd_crtc->pipe;
+		drm_dbg_kms(encoder->base.dev, "pipe selected is %d\n",
+			wd_crtc->pipe);
+	}
+	return true;
+}
+
+static int intel_wd_encoder_atomic_check(struct drm_encoder *encoder,
+				    struct drm_crtc_state *crtc_st,
+				    struct drm_connector_state *conn_st)
+{
+	/* Check for the format and buffers and property validity */
+	struct drm_framebuffer *fb;
+	struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_st);
+	struct intel_writeback_job *job = intel_conn_state->job;
+	struct drm_i915_private *i915 = to_i915(encoder->dev);
+	const struct drm_display_mode *mode = &crtc_st->mode;
+	int ret;
+
+	drm_dbg_kms(&i915->drm, "\n");
+
+	if (!job) {
+		drm_dbg_kms(&i915->drm, "No writeback job created returning\n");
+		return -EINVAL;
+	}
+
+	fb = job->fb;
+
+	if (!fb) {
+		drm_dbg_kms(&i915->drm, "Invalid framebuffer\n");
+		return -EINVAL;
+	}
+
+	if (fb->width != mode->hdisplay || fb->height != mode->vdisplay) {
+		drm_dbg_kms(&i915->drm, "Invalid framebuffer size %ux%u\n",
+				fb->width, fb->height);
+		return -EINVAL;
+	}
+
+	ret = intel_wd_verify_pix_format(fb->format->format);
+
+	if (ret) {
+		drm_dbg_kms(&i915->drm, "Unsupported framebuffer format %08x\n",
+				fb->format->format);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+static const struct drm_encoder_helper_funcs wd_encoder_helper_funcs = {
+	.atomic_check = intel_wd_encoder_atomic_check,
+};
+
+static void intel_wd_connector_destroy(struct drm_connector *connector)
+{
+	drm_dbg_kms(connector->dev, "\n");
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+static enum drm_connector_status
+intel_wb_connector_detect(struct drm_connector *connector, bool force)
+{
+	drm_dbg_kms(connector->dev, "Writeback connector connected\n");
+	return connector_status_connected;
+}
+
+static int intel_atomic_set_writeback_fb_for_connector(
+		struct drm_connector_state *conn_state,
+		struct drm_framebuffer *fb)
+{
+	int ret;
+	struct drm_connector *conn = conn_state->connector;
+
+	ret = intel_writeback_set_fb(conn_state, fb);
+	if (ret < 0)
+		return ret;
+
+	if (fb)
+		drm_dbg_atomic(conn->dev,
+			"Set [FB:%d] for connector state %p\n",
+			fb->base.id, conn_state);
+	else
+		drm_dbg_atomic(conn->dev,
+			"Set [NOFB] for connector state %p\n",
+			conn_state);
+
+	return 0;
+}
+
+static int set_out_fence_for_connector(struct drm_atomic_state *state,
+					struct drm_connector *connector,
+					s32 __user *fence_ptr)
+{
+	unsigned int index = drm_connector_index(connector);
+
+	if (!fence_ptr)
+		return 0;
+
+	if (put_user(-1, fence_ptr))
+		return -EFAULT;
+
+	state->connectors[index].out_fence_ptr = fence_ptr;
+
+	return 0;
+}
+
+static struct drm_mode_object *__intel_object_find(struct drm_device *dev,
+					       uint32_t id, uint32_t type)
+{
+	struct drm_mode_object *obj = NULL;
+
+	mutex_lock(&dev->mode_config.idr_mutex);
+	obj = idr_find(&dev->mode_config.object_idr, id);
+	if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
+		obj = NULL;
+	if (obj && obj->id != id)
+		obj = NULL;
+	if (obj && obj->free_cb) {
+		if (!kref_get_unless_zero(&obj->refcount))
+			obj = NULL;
+	}
+	mutex_unlock(&dev->mode_config.idr_mutex);
+
+	return obj;
+}
+
+static struct drm_framebuffer *intel_wb_framebuffer_lookup(struct drm_device *dev,
+					       uint32_t id)
+{
+	struct drm_mode_object *obj;
+	struct drm_framebuffer *fb = NULL;
+
+	obj = __intel_object_find(dev, id, DRM_MODE_OBJECT_FB);
+	if (obj)
+		fb = obj_to_fb(obj);
+	return fb;
+}
+
+static s32 *intel_get_out_fence_for_connector(struct drm_atomic_state *state,
+					       struct drm_connector *connector)
+{
+	unsigned int index = drm_connector_index(connector);
+	s32 __user *fence_ptr;
+
+	fence_ptr = state->connectors[index].out_fence_ptr;
+	state->connectors[index].out_fence_ptr = NULL;
+
+	return fence_ptr;
+}
+
+static int intel_setup_out_fence(struct intel_out_fence_state *fence_state,
+			   struct dma_fence *fence)
+{
+
+	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
+	if (fence_state->fd < 0)
+		return fence_state->fd;
+
+	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
+		return -EFAULT;
+
+	fence_state->sync_file = sync_file_create(fence);
+	if (!fence_state->sync_file)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int intel_wd_prepare_out_fence(struct drm_device *dev,
+				struct drm_atomic_state *state)
+{
+	struct drm_connector *conn;
+	struct drm_connector_state *conn_state;
+	int i, ret;
+
+	drm_dbg_kms(dev, "\n");
+
+	for_each_new_connector_in_state(state, conn, conn_state, i) {
+		struct intel_writeback_connector *wb_conn;
+		struct intel_connector *intel_conn =
+			to_intel_connector(conn);
+		struct dma_fence *fence;
+		struct intel_wd *intel_wd;
+		struct intel_digital_connector_state *intel_conn_state =
+			to_intel_digital_connector_state(conn_state);
+		s32 __user *fence_ptr;
+
+		if (conn->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
+			continue;
+
+		if (!intel_conn_state->job)
+			continue;
+
+		intel_wd = enc_to_intel_wd(intel_conn->encoder);
+		fence_ptr = intel_get_out_fence_for_connector(state, conn);
+		if (!fence_ptr)
+			continue;
+
+		intel_wd->fence_state->out_fence_ptr = fence_ptr;
+
+		wb_conn = &intel_conn->wb_conn;
+		fence = intel_writeback_get_out_fence(wb_conn);
+		if (!fence)
+			return -ENOMEM;
+
+		ret = intel_setup_out_fence(intel_wd->fence_state, fence);
+		if (ret) {
+			dma_fence_put(fence);
+			return ret;
+		}
+
+		intel_conn_state->job->out_fence = fence;
+	}
+
+	return 0;
+}
+
+void intel_wd_complete_signaling(struct intel_wd *intel_wd)
+{
+	struct intel_out_fence_state *fence_state;
+
+	fence_state = intel_wd->fence_state;
+	fd_install(fence_state->fd,
+		fence_state->sync_file->file);
+
+}
+
+static int intel_set_writeback_property(struct drm_connector *connector,
+	struct drm_connector_state *state, struct drm_property *property,
+	uint64_t val)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *i915 = to_i915(dev);
+
+	if (property == i915->wb_fb_id_property) {
+		struct drm_framebuffer *fb;
+		int ret;
+
+		fb = intel_wb_framebuffer_lookup(dev, val);
+		ret = intel_atomic_set_writeback_fb_for_connector(state, fb);
+		if (fb)
+			drm_framebuffer_put(fb);
+		return ret;
+	} else if (property == i915->wb_out_fence_ptr_property) {
+		s32 __user *fence_ptr = u64_to_user_ptr(val);
+
+		return set_out_fence_for_connector(state->state, connector,
+						fence_ptr);
+	} else {
+		drm_dbg_atomic(connector->dev,
+			"[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",
+			connector->base.id, connector->name,
+			property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+
+}
+
+static int intel_get_writeback_property(struct drm_connector *connector,
+	const struct drm_connector_state *state, struct drm_property *property,
+	uint64_t *val)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *i915 = to_i915(dev);
+
+	if (property == i915->wb_fb_id_property)
+		*val = 0;
+	else if (property == i915->wb_out_fence_ptr_property)
+		*val = 0;
+	else {
+		drm_dbg_atomic(&i915->drm,
+				"Unknown property [PROP:%d:%s]\n",
+				property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct drm_connector_funcs wd_connector_funcs = {
+	.detect = intel_wb_connector_detect,
+	.reset = drm_atomic_helper_connector_reset,
+	.destroy = intel_wd_connector_destroy,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+	.atomic_set_property = intel_set_writeback_property,
+	.atomic_get_property = intel_get_writeback_property,
+	.atomic_duplicate_state = intel_digital_connector_duplicate_state,
+};
+
+static const struct drm_connector_helper_funcs wd_connector_helper_funcs = {
+	.get_modes = intel_wd_get_modes,
+	.mode_valid = intel_wd_mode_valid,
+};
+
+static bool intel_fastset_dis(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config)
+{
+	pipe_config->uapi.mode_changed = true;
+	drm_dbg_kms(encoder->base.dev, "\n");
+	return false;
+}
+
+void intel_wd_init(struct drm_i915_private *i915, enum transcoder trans)
+{
+	struct intel_wd *intel_wd;
+	struct intel_encoder *encoder;
+	struct intel_out_fence_state *fence_state;
+	struct intel_connector *intel_connector;
+	struct intel_writeback_connector *wb_conn;
+	int n_formats = ARRAY_SIZE(wb_fmts);
+	int err;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	intel_wd = kzalloc(sizeof(*intel_wd), GFP_KERNEL);
+	if (!intel_wd)
+		return;
+
+	intel_connector = intel_connector_alloc();
+	if (!intel_connector) {
+		kfree(intel_wd);
+		return;
+	}
+
+	fence_state = kzalloc(sizeof(*fence_state), GFP_KERNEL);
+	if (!intel_wd) {
+		kfree(intel_wd);
+		kfree(intel_connector);
+		return;
+	}
+
+	wb_conn = &intel_connector->wb_conn;
+	wb_conn->base = &intel_connector->base;
+	wb_conn->encoder = &intel_wd->base.base;
+
+	encoder = &intel_wd->base;
+	intel_wd->attached_connector = intel_connector;
+	intel_wd->fence_state = fence_state;
+	intel_wd->trans = trans;
+	intel_wd->triggered_cap_mode = 1;
+	intel_wd->frame_num = 1;
+	intel_wd->slicing_strategy = 1;
+	encoder->get_config = intel_wd_get_config;
+	encoder->compute_config = intel_wd_compute_config;
+	encoder->get_hw_state = intel_wd_get_hw_state;
+	encoder->type = INTEL_OUTPUT_WD;
+	encoder->cloneable = 0;
+	encoder->pipe_mask = ~0;
+	encoder->power_domain = POWER_DOMAIN_TRANSCODER_B;
+	encoder->get_power_domains = intel_wd_get_power_domains;
+	encoder->initial_fastset_check = intel_fastset_dis;
+	intel_connector->get_hw_state =
+		intel_connector_get_hw_state;
+
+	drm_dbg_kms(&i915->drm, "\n");
+	err = intel_writeback_connector_init(&i915->drm, wb_conn,
+		&wd_connector_funcs,
+		&wd_encoder_helper_funcs,
+		wb_fmts, n_formats);
+
+	if (err != 0) {
+		drm_dbg_kms(&i915->drm,
+		"intel_writeback_connector_init: Failed: %d\n",
+			err);
+		goto cleanup;
+	}
+
+	drm_connector_helper_add(wb_conn->base, &wd_connector_helper_funcs);
+	intel_connector_attach_encoder(intel_connector, encoder);
+	wb_conn->base->status = connector_status_connected;
+	return;
+
+cleanup:
+	kfree(intel_wd);
+	intel_connector_free(intel_connector);
+}
+
+static void intel_wd_writeback_complete(struct intel_wd *intel_wd,
+	struct intel_writeback_job *job, int status)
+{
+	struct intel_writeback_connector *wb_conn =
+		&intel_wd->attached_connector->wb_conn;
+	intel_writeback_signal_completion(wb_conn, status);
+	intel_wd_complete_signaling(intel_wd);
+}
+
+static int intel_wd_setup_transcoder(struct intel_wd *intel_wd,
+		struct intel_crtc_state *pipe_config,
+		struct intel_writeback_job *job)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
+	enum pipe pipe = intel_crtc->pipe;
+	struct drm_framebuffer *fb;
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+	struct drm_gem_object *wd_fb_obj;
+	int ret;
+	u32 stride, tmp;
+	u16 hactive, vactive;
+
+	fb = job->fb;
+	wd_fb_obj = fb->obj[0];
+	if (!wd_fb_obj) {
+		drm_dbg_kms(&dev_priv->drm, "No framebuffer gem object created\n");
+		return -1;
+	}
+	ret = intel_wd_pin_fb(intel_wd, fb);
+	drm_WARN_ON(&dev_priv->drm, ret != 0);
+
+	/*Write stride and surface registers in that particular order*/
+	stride = intel_wd_get_stride(pipe_config, fb->format->format);
+
+	tmp = intel_de_read(dev_priv, WD_STRIDE(intel_wd->trans));
+	tmp &= ~WD_STRIDE_MASK;
+	tmp |= (stride << WD_STRIDE_SHIFT);
+
+	intel_de_write(dev_priv, WD_STRIDE(intel_wd->trans), tmp);
+
+	tmp = intel_de_read(dev_priv, WD_SURF(intel_wd->trans));
+	drm_dbg_kms(&dev_priv->drm, "%d is the surface address\n", tmp);
+
+	intel_de_write(dev_priv, WD_SURF(intel_wd->trans),
+			i915_ggtt_offset(intel_wd->vma));
+
+	tmp = intel_de_read_fw(dev_priv, WD_IIR(intel_wd->trans));
+	intel_de_write_fw(dev_priv, WD_IIR(intel_wd->trans), tmp);
+
+	tmp = ~(WD_GTT_FAULT_INT|WD_WRITE_COMPLETE_INT|WD_FRAME_COMPLETE_INT|
+			WD_VBLANK_INT|WD_OVERRUN_INT|WD_CAPTURING_INT);
+	intel_de_write_fw(dev_priv, WD_IMR(intel_wd->trans), tmp);
+
+	if (intel_wd->stream_cap) {
+		tmp = intel_de_read(dev_priv,
+				WD_STREAMCAP_CTL(intel_wd->trans));
+		tmp |= WD_STREAM_CAP_MODE_EN;
+		intel_configure_slicing_strategy(dev_priv, intel_wd, &tmp);
+	}
+
+	hactive = pipe_config->uapi.mode.hdisplay;
+	vactive = pipe_config->uapi.mode.vdisplay;
+
+	drm_dbg_kms(&dev_priv->drm, "hactive : %d, vactive: %d\n", hactive, vactive);
+
+	tmp = intel_de_read(dev_priv, HTOTAL(intel_wd->trans));
+	drm_dbg_kms(&dev_priv->drm, "hactive_reg : %d\n", tmp);
+	tmp = intel_de_read(dev_priv, VTOTAL(intel_wd->trans));
+	drm_dbg_kms(&dev_priv->drm, "vactive_reg : %d\n", tmp);
+	/* minimum hactive as per bspec: 64 pixels*/
+	if (hactive < 64)
+		drm_err(&dev_priv->drm, "hactive is less then 64 pixels\n");
+
+	intel_de_write(dev_priv, HTOTAL(intel_wd->trans), hactive - 1);
+	intel_de_write(dev_priv, VTOTAL(intel_wd->trans), vactive - 1);
+
+	tmp = intel_de_read(dev_priv, WD_TRANS_FUNC_CTL(intel_wd->trans));
+	/* select pixel format */
+	tmp &= ~WD_PIX_FMT_MASK;
+
+	switch (fb->format->format) {
+	default:
+	fallthrough;
+	case DRM_FORMAT_YUYV:
+		tmp |= WD_PIX_FMT_YUYV;
+		break;
+	case DRM_FORMAT_XYUV8888:
+		tmp |= WD_PIX_FMT_XYUV8888;
+		break;
+	case DRM_FORMAT_XBGR8888:
+		tmp |= WD_PIX_FMT_XBGR8888;
+		break;
+	case DRM_FORMAT_Y410:
+		tmp |= WD_PIX_FMT_Y410;
+		break;
+	case DRM_FORMAT_YUV422:
+		tmp |= WD_PIX_FMT_YUV422;
+		break;
+	case DRM_FORMAT_XBGR2101010:
+		tmp |= WD_PIX_FMT_XBGR2101010;
+		break;
+	case DRM_FORMAT_RGB565:
+		tmp |= WD_PIX_FMT_RGB565;
+		break;
+	}
+
+	if (intel_wd->triggered_cap_mode)
+		tmp |= WD_TRIGGERED_CAP_MODE_ENABLE;
+
+	if (intel_wd->stream_cap)
+		tmp |= WD_CTL_POINTER_DTDH;
+
+	/*select input pipe*/
+	tmp &= ~WD_INPUT_SELECT_MASK;
+	drm_dbg_kms(&dev_priv->drm, "Selected pipe is %d\n", pipe);
+	switch (pipe) {
+	default:
+		fallthrough;
+	case PIPE_A:
+		tmp |= WD_INPUT_PIPE_A;
+		break;
+	case PIPE_B:
+		tmp |= WD_INPUT_PIPE_B;
+		break;
+	case PIPE_C:
+		tmp |= WD_INPUT_PIPE_C;
+		break;
+	case PIPE_D:
+		tmp |= WD_INPUT_PIPE_D;
+		break;
+	}
+
+	/* enable DDI buffer */
+	if (!(tmp & TRANS_WD_FUNC_ENABLE))
+		tmp |= TRANS_WD_FUNC_ENABLE;
+
+	intel_de_write(dev_priv, WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);
+
+	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+	ret = tmp & WD_TRANS_ACTIVE;
+	drm_dbg_kms(&dev_priv->drm, "Trancoder enabled: %s\n", ret ? "true":"false");
+
+	if (!ret) {
+		/*enable the transcoder	*/
+		tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+		tmp |= WD_TRANS_ENABLE;
+		intel_de_write(dev_priv, PIPECONF(intel_wd->trans), tmp);
+
+		/* wait for transcoder to be enabled */
+		if (intel_de_wait_for_set(dev_priv, PIPECONF(intel_wd->trans),
+				WD_TRANS_ACTIVE, 10))
+			drm_err(&dev_priv->drm, "WD transcoder not enabled\n");
+	}
+
+	return 0;
+}
+
+static void intel_wd_disable_capture(struct intel_wd *intel_wd)
+{
+	struct drm_i915_private *dev_priv = to_i915(intel_wd->base.base.dev);
+	u32 tmp;
+
+	intel_de_write_fw(dev_priv, WD_IMR(intel_wd->trans), 0xFF);
+	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
+	tmp &= WD_TRANS_DISABLE;
+	intel_de_write(dev_priv, PIPECONF(intel_wd->trans), tmp);
+
+	drm_dbg_kms(&dev_priv->drm, "WD Trans_Conf value after disable = 0x%08x\n",
+		intel_de_read(dev_priv, PIPECONF(intel_wd->trans)));
+	tmp = intel_de_read(dev_priv, WD_TRANS_FUNC_CTL(intel_wd->trans));
+	tmp |= ~TRANS_WD_FUNC_ENABLE;
+}
+
+static int intel_wd_capture(struct intel_wd *intel_wd,
+		struct intel_crtc_state *pipe_config,
+		struct intel_writeback_job *job)
+{
+	u32 tmp;
+	struct drm_i915_private *i915 = to_i915(intel_wd->base.base.dev);
+	int ret = 0, status = 0;
+	struct intel_crtc *wd_crtc = intel_wd->wd_crtc;
+	unsigned long flags;
+
+	drm_dbg_kms(&i915->drm, "\n");
+
+	if (!job->out_fence)
+		drm_dbg_kms(&i915->drm, "Not able to get out_fence for job\n");
+
+	ret = intel_wd_setup_transcoder(intel_wd, pipe_config, job);
+
+	if (ret < 0) {
+		drm_dbg_kms(&i915->drm,
+		"wd transcoder setup not completed aborting capture\n");
+		return -1;
+	}
+
+	if (wd_crtc == NULL) {
+		DRM_ERROR("CRTC not attached\n");
+		return -1;
+	}
+
+	tmp = intel_de_read_fw(i915,
+			WD_TRANS_FUNC_CTL(intel_wd->trans));
+	tmp |= START_TRIGGER_FRAME;
+	tmp &= ~WD_FRAME_NUMBER_MASK;
+	tmp |= intel_wd->frame_num;
+	intel_de_write_fw(i915,
+			WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);
+
+	if (!intel_de_wait_for_set(i915, WD_IIR(intel_wd->trans),
+				WD_FRAME_COMPLETE_INT, 100)){
+		drm_dbg_kms(&i915->drm, "frame captured\n");
+		tmp = intel_de_read(i915, WD_IIR(intel_wd->trans));
+		drm_dbg_kms(&i915->drm, "iir value : %d\n", tmp);
+		status = 0;
+	} else {
+		drm_dbg_kms(&i915->drm, "frame not captured triggering stop frame\n");
+		tmp = intel_de_read(i915,
+				WD_TRANS_FUNC_CTL(intel_wd->trans));
+		tmp |= STOP_TRIGGER_FRAME;
+		intel_de_write(i915,
+				WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);
+		status = -1;
+	}
+
+	intel_de_write(i915, WD_IIR(intel_wd->trans), tmp);
+	intel_wd_writeback_complete(intel_wd, job, status);
+	if (intel_get_writeback_job_from_queue(intel_wd) == NULL)
+		intel_wd_disable_capture(intel_wd);
+	if (wd_crtc->wd.e) {
+		spin_lock_irqsave(&i915->drm.event_lock, flags);
+		drm_dbg_kms(&i915->drm, "send %p\n", wd_crtc->wd.e);
+		drm_crtc_send_vblank_event(&wd_crtc->base,
+					wd_crtc->wd.e);
+		spin_unlock_irqrestore(&i915->drm.event_lock, flags);
+		wd_crtc->wd.e = NULL;
+	} else {
+		DRM_ERROR("Event NULL! %p, %p\n", &i915->drm,
+			wd_crtc);
+	}
+	return 0;
+
+}
+
+void intel_wd_enable_capture(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config,
+		struct drm_connector_state *conn_state)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
+	struct intel_writeback_job *job;
+
+	drm_dbg_kms(&i915->drm, "\n");
+
+	job = intel_get_writeback_job_from_queue(intel_wd);
+	if (job == NULL) {
+		drm_dbg_kms(&i915->drm,
+			"job queue is empty not capturing any frame\n");
+		return;
+	}
+
+	intel_wd_capture(intel_wd, pipe_config, job);
+	intel_wd->frame_num += 1;
+
+}
+
+void intel_wd_set_vblank_event(struct intel_crtc *intel_crtc,
+			struct intel_crtc_state *intel_crtc_state)
+{
+	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
+	struct drm_crtc_state *state = &intel_crtc_state->uapi;
+	struct intel_encoder *encoder;
+	struct intel_wd *intel_wd;
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (!intel_wd->wd_crtc) {
+			drm_dbg_kms(&i915->drm, "wd crtc not found\n");
+			return;
+		}
+	}
+
+	if (intel_crtc == intel_wd->wd_crtc) {
+		intel_crtc->wd.e = state->event;
+		state->event = NULL;
+		if (intel_crtc->wd.e)
+			drm_dbg_kms(&i915->drm, "WD event:%p\n",
+				intel_crtc->wd.e);
+		else
+			drm_dbg_kms(&i915->drm, "WD no event\n");
+	}
+}
+
+void intel_wd_handle_isr(struct drm_i915_private *i915)
+{
+	u32 iir_value = 0;
+	struct intel_encoder *encoder;
+	struct intel_wd *intel_wd;
+
+	iir_value = intel_de_read(i915, WD_IIR(TRANSCODER_WD_0));
+	drm_dbg_kms(&i915->drm, "\n");
+
+	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
+		intel_wd = enc_to_intel_wd(encoder);
+
+		if (!intel_wd->wd_crtc) {
+			DRM_ERROR("NO CRTC attached with WD\n");
+			goto clear_iir;
+		}
+	}
+
+	if (iir_value & WD_VBLANK_INT)
+		drm_dbg_kms(&i915->drm, "vblank interrupt for wd transcoder\n");
+	if (iir_value & WD_WRITE_COMPLETE_INT)
+		drm_dbg_kms(&i915->drm,
+		"wd write complete interrupt encountered\n");
+	else
+		DRM_INFO("iir: %x\n", iir_value);
+	if (iir_value & WD_FRAME_COMPLETE_INT) {
+		drm_dbg_kms(&i915->drm,
+			"frame complete interrupt for wd transcoder\n");
+		return;
+	}
+clear_iir:
+	intel_de_write(i915, WD_IIR(TRANSCODER_WD_0), iir_value);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_wd.h b/drivers/gpu/drm/i915/display/intel_wd.h
new file mode 100644
index 000000000000..2309afa23bb8
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_wd.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author :
+ *	Suraj Kandpal<suraj.kandpal@intel.com>
+ *	Arun Murthy<arun.r.murthy@intel.com>
+ */
+
+#ifndef _INTEL_WD_H
+#define _INTEL_WD_H
+
+#include <drm/drm_crtc.h>
+#include <linux/sync_file.h>
+
+#include "intel_display_types.h"
+
+#define I915_MAX_WD_TANSCODERS 2
+
+struct intel_out_fence_state {
+	s32 __user *out_fence_ptr;
+	struct sync_file *sync_file;
+	int fd;
+};
+
+struct intel_wd {
+	struct intel_encoder base;
+	struct intel_crtc *wd_crtc;
+	struct intel_out_fence_state *fence_state;
+	intel_wakeref_t io_wakeref[I915_MAX_WD_TANSCODERS];
+	struct intel_connector *attached_connector;
+	enum transcoder trans;
+	struct i915_vma *vma;
+	unsigned long flags;
+	struct intel_writeback_job *job;
+	int triggered_cap_mode;
+	int frame_num;
+	bool stream_cap;
+	bool start_capture;
+	int slicing_strategy;
+};
+
+struct intel_wd_clk_vals {
+	u32 cdclk;
+	u16 link_m;
+	u16 link_n;
+};
+
+extern struct sync_file *sync_file_create(struct dma_fence *fence);
+static inline struct intel_wd *enc_to_intel_wd(struct intel_encoder *encoder)
+{
+	return container_of(&encoder->base, struct intel_wd, base.base);
+}
+void intel_wd_init(struct drm_i915_private *dev_priv, enum transcoder trans);
+void intel_wd_enable_capture(struct intel_encoder *encoder,
+				struct intel_crtc_state *pipe_config,
+				struct drm_connector_state *conn_state);
+void intel_wd_handle_isr(struct drm_i915_private *dev_priv);
+void intel_wd_set_vblank_event(struct intel_crtc *crtc,
+				struct intel_crtc_state *state);
+int intel_wd_prepare_out_fence(struct drm_device *dev,
+				struct drm_atomic_state *state);
+void intel_wd_complete_signaling(struct intel_wd *intel_wd);
+#endif/* _INTEL_WD_H */
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9a86ee88089e..b7e92a18125c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -38,6 +38,8 @@
 #include <linux/pm_qos.h>
 
 #include <drm/drm_connector.h>
+#include <drm/drm_writeback.h>
+#include <drm/i915_mei_hdcp_interface.h>
 #include <drm/ttm/ttm_device.h>
 
 #include "display/intel_bios.h"
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 73cebc6aa650..95a6a8f7a911 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -42,6 +42,7 @@
 #include "display/intel_hotplug.h"
 #include "display/intel_lpe_audio.h"
 #include "display/intel_psr.h"
+#include "display/intel_wd.h"
 
 #include "gt/intel_breadcrumbs.h"
 #include "gt/intel_gt.h"
@@ -2342,6 +2343,11 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
 		found = true;
 	}
 
+	if (iir & GEN8_DE_MISC_WD0) {
+		intel_wd_handle_isr(dev_priv);
+		found = true;
+	}
+
 	if (iir & GEN8_DE_EDP_PSR) {
 		struct intel_encoder *encoder;
 		u32 psr_iir;
@@ -3767,7 +3773,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
 	u32 de_pipe_enables;
 	u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
 	u32 de_port_enables;
-	u32 de_misc_masked = GEN8_DE_EDP_PSR;
+	u32 de_misc_masked = GEN8_DE_EDP_PSR | GEN8_DE_MISC_WD0;
 	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
 	enum pipe pipe;
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 67b89769f577..a524e0f030b6 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -853,7 +853,8 @@ static const struct intel_device_info jsl_info = {
 	.display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \
 	.display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | \
-		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \
+		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1)| \
+		BIT(TRANSCODER_WD_0), \
 	.pipe_offsets = { \
 		[TRANSCODER_A] = PIPE_A_OFFSET, \
 		[TRANSCODER_B] = PIPE_B_OFFSET, \
@@ -861,6 +862,8 @@ static const struct intel_device_info jsl_info = {
 		[TRANSCODER_D] = PIPE_D_OFFSET, \
 		[TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \
 		[TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \
+		[TRANSCODER_WD_0] = PIPE_WD0_OFFSET, \
+		[TRANSCODER_WD_1] = PIPE_WD1_OFFSET, \
 	}, \
 	.trans_offsets = { \
 		[TRANSCODER_A] = TRANSCODER_A_OFFSET, \
@@ -869,6 +872,8 @@ static const struct intel_device_info jsl_info = {
 		[TRANSCODER_D] = TRANSCODER_D_OFFSET, \
 		[TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \
 		[TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
+		[TRANSCODER_WD_0] = TRANSCODER_WD0_OFFSET, \
+		[TRANSCODER_WD_1] = TRANSCODER_WD1_OFFSET, \
 	}, \
 	TGL_CURSOR_OFFSETS, \
 	.has_global_mocs = 1, \
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 6396afd77209..abc41e7de0b5 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3797,6 +3797,11 @@
 #define PIPE_DSI0_OFFSET	0x7b000
 #define PIPE_DSI1_OFFSET	0x7b800
 
+/* WD 0 and 1 */
+#define PIPE_WD0_OFFSET		0x7e000
+#define PIPE_WD1_OFFSET		0x7d000
+
+
 #define PIPECONF(pipe)		_MMIO_PIPE2(pipe, _PIPEACONF)
 #define PIPEDSL(pipe)		_MMIO_PIPE2(pipe, _PIPEADSL)
 #define PIPEFRAME(pipe)		_MMIO_PIPE2(pipe, _PIPEAFRAMEHIGH)
@@ -4461,6 +4466,10 @@
 #define _PIPEDSI0CONF		0x7b008
 #define _PIPEDSI1CONF		0x7b808
 
+/* WD 0 and 1 */
+#define _PIPEWD0CONF		0x7e008
+#define _PIPEWD1CONF		0x7d008
+
 /* Sprite A control */
 #define _DVSACNTR		0x72180
 #define   DVS_ENABLE			REG_BIT(31)
@@ -5707,6 +5716,7 @@
 #define GEN8_DE_MISC_IER _MMIO(0x4446c)
 #define  GEN8_DE_MISC_GSE		(1 << 27)
 #define  GEN8_DE_EDP_PSR		(1 << 19)
+#define  GEN8_DE_MISC_WD0		(1 << 23)
 
 #define GEN8_PCU_ISR _MMIO(0x444e0)
 #define GEN8_PCU_IMR _MMIO(0x444e4)
@@ -8847,6 +8857,133 @@ enum skl_power_gate {
 #define   DSB_ENABLE			(1 << 31)
 #define   DSB_STATUS			(1 << 0)
 
+#define TGL_ROOT_DEVICE_ID		0x9A00
+#define TGL_ROOT_DEVICE_MASK		0xFF00
+#define TGL_ROOT_DEVICE_SKU_MASK	0xF
+#define TGL_ROOT_DEVICE_SKU_ULX		0x2
+#define TGL_ROOT_DEVICE_SKU_ULT		0x4
+
+/* Gen12 WD */
+#define _MMIO_WD(tc, wd0, wd1)		_MMIO_TRANS((tc) - TRANSCODER_WD_0, \
+							wd0, wd1)
+
+#define WD_TRANS_ENABLE			(1 << 31)
+#define WD_TRANS_DISABLE		0
+#define WD_TRANS_ACTIVE			(1 << 30)
+
+/* WD transcoder control */
+#define _WD_TRANS_FUNC_CTL_0		0x6e400
+#define _WD_TRANS_FUNC_CTL_1		0x6ec00
+#define WD_TRANS_FUNC_CTL(tc)		_MMIO_WD(tc,\
+					_WD_TRANS_FUNC_CTL_0,\
+					_WD_TRANS_FUNC_CTL_1)
+
+#define TRANS_WD_FUNC_ENABLE		(1 << 31)
+#define WD_TRIGGERED_CAP_MODE_ENABLE	(1 << 30)
+#define START_TRIGGER_FRAME		(1 << 29)
+#define STOP_TRIGGER_FRAME		(1 << 28)
+#define WD_CTL_POINTER_ETEH		(0 << 18)
+#define WD_CTL_POINTER_ETDH		(1 << 18)
+#define WD_CTL_POINTER_DTDH		(2 << 18)
+#define WD_INPUT_SELECT_MASK		(7 << 12)
+#define WD_INPUT_PIPE_A			(0 << 12)
+#define WD_INPUT_PIPE_B			(5 << 12)
+#define WD_INPUT_PIPE_C			(6 << 12)
+#define WD_INPUT_PIPE_D			(7 << 12)
+
+#define WD_PIX_FMT_MASK			(0x3 << 20)
+#define WD_PIX_FMT_YUYV			(0x1 << 20)
+#define WD_PIX_FMT_XYUV8888		(0x2 << 20)
+#define WD_PIX_FMT_XBGR8888		(0x3 << 20)
+#define WD_PIX_FMT_Y410			(0x4 << 20)
+#define WD_PIX_FMT_YUV422		(0x5 << 20)
+#define WD_PIX_FMT_XBGR2101010		(0x6 << 20)
+#define WD_PIX_FMT_RGB565		(0x7 << 20)
+
+#define WD_FRAME_NUMBER_MASK		15
+
+#define _WD_STRIDE_0			0x6e510
+#define _WD_STRIDE_1			0x6ed10
+#define WD_STRIDE(tc)			_MMIO_WD(tc,\
+					_WD_STRIDE_0,\
+					_WD_STRIDE_1)
+#define WD_STRIDE_SHIFT			6
+#define WD_STRIDE_MASK			(0x3ff << WD_STRIDE_SHIFT)
+
+#define _WD_STREAMCAP_CTL0		0x6e590
+#define _WD_STREAMCAP_CTL1		0x6ed90
+#define WD_STREAMCAP_CTL(tc)		_MMIO_WD(tc,\
+					_WD_STREAMCAP_CTL0,\
+					_WD_STREAMCAP_CTL1)
+
+#define WD_STREAM_CAP_MODE_EN		(1 << 31)
+#define WD_STRAT_MASK			(3 << 24)
+#define WD_SLICING_STRAT_1_1		(0 << 24)
+#define WD_SLICING_STRAT_2_1		(1 << 24)
+#define WD_SLICING_STRAT_4_1		(2 << 24)
+#define WD_SLICING_STRAT_8_1		(3 << 24)
+#define WD_STREAM_OVERRUN_STATUS	1
+
+#define _WD_SURF_0			0x6e514
+#define _WD_SURF_1			0x6ed14
+#define WD_SURF(tc)			_MMIO_WD(tc,\
+					_WD_SURF_0,\
+					_WD_SURF_1)
+
+#define _WD_IMR_0			0x6e560
+#define _WD_IMR_1			0x6ed60
+#define WD_IMR(tc)			_MMIO_WD(tc,\
+					_WD_IMR_0,\
+					_WD_IMR_1)
+#define WD_FRAME_COMPLETE_INT		(1 << 7)
+#define WD_GTT_FAULT_INT		(1 << 6)
+#define WD_VBLANK_INT			(1 << 5)
+#define WD_OVERRUN_INT			(1 << 4)
+#define WD_CAPTURING_INT		(1 << 3)
+#define WD_WRITE_COMPLETE_INT		(1 << 2)
+
+#define _WD_IIR_0			0x6e564
+#define _WD_IIR_1			0x6ed64
+#define WD_IIR(tc)			_MMIO_WD(tc,\
+					_WD_IIR_0,\
+					_WD_IIR_1)
+
+#define _WD_FRAME_STATUS_0		0x6e56b
+#define _WD_FRAME_STATUS_1		0x6ed6b
+#define WD_FRAME_STATUS(tc)		_MMIO_WD(tc,\
+					_WD_FRAME_STATUS_0,\
+					_WD_FRAME_STATUS_1)
+
+#define WD_FRAME_COMPLETE		(1 << 31)
+#define WD_STATE_IDLE			(0 << 24)
+#define WD_STATE_CAPSTART		(1 << 24)
+#define WD_STATE_FRAME_START		(2 << 24)
+#define WD_STATE_CAPACITIVE		(3 << 24)
+#define WD_STATE_TG_DONE		(4 << 24)
+#define WD_STATE_WDX_DONE		(5 << 24)
+#define WD_STATE_QUICK_CAP		(6 << 24)
+
+#define _WD_27_M_0			0x6e524
+#define _WD_27_M_1			0x6ed24
+#define WD_27_M(tc)			_MMIO_WD(tc,\
+					_WD_27_M_0,\
+					_WD_27_M_1)
+
+#define _WD_27_N_0			0x6e528
+
+//Address looks wrong in bspec:
+#define _WD_27_N_1			0x6ec28
+#define WD_27_N(tc)			_MMIO_WD(tc,\
+					_WD_27_N_0,\
+					_WD_27_N_1)
+
+#define _WD_TAIL_CFG_0			0x6e520
+#define _WD_TAIL_CFG_1			0x6ed20
+
+#define WD_TAIL_CFG(tc)			_MMIO_WD(tc,\
+					_WD_TAIL_CFG_0,\
+					_WD_TAIL_CFG_1)
+
 #define CLKREQ_POLICY			_MMIO(0x101038)
 #define  CLKREQ_POLICY_MEM_UP_OVRD	REG_BIT(1)
 
-- 
2.35.1


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

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915 writeback private framework (rev4)
  2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
                   ` (6 preceding siblings ...)
  2022-03-17  8:39 ` [Intel-gfx] [RFC PATCH v2 0/3] " Suraj Kandpal
@ 2022-03-18  4:48 ` Patchwork
  2022-03-18  4:49 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2022-03-18  4:48 UTC (permalink / raw)
  To: Suraj Kandpal; +Cc: intel-gfx

== Series Details ==

Series: i915 writeback private framework (rev4)
URL   : https://patchwork.freedesktop.org/series/101425/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
224406362f12 drm/i915: Creating writeback pipeline to bypass drm_writeback framework
-:52: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#52: 
new file mode 100644

-:86: CHECK:LINE_SPACING: Please don't use multiple blank lines
#86: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:30:
+
+

-:99: CHECK:MACRO_ARG_PRECEDENCE: Macro argument 'x' may be better as '(x)' to avoid precedence issues
#99: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:43:
+#define fence_to_wb_connector(x) container_of(x->lock, \
+					      struct intel_writeback_connector, \
+					      fence_lock)

-:138: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#138: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:82:
+		prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+						"WRITEBACK_FB_ID",

-:157: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#157: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:101:
+		prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+						"WRITEBACK_OUT_FENCE_PTR", 0,

-:172: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#172: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:116:
+int intel_writeback_connector_init(struct drm_device *dev,
+				 struct intel_writeback_connector *wb_connector,

-:195: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#195: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:139:
+	ret = drm_encoder_init(dev, wb_connector->encoder,
+			&intel_writeback_encoder_funcs,

-:203: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#203: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:147:
+	ret = drm_connector_init(dev, connector, con_funcs,
+				DRM_MODE_CONNECTOR_WRITEBACK);

-:208: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#208: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:152:
+	ret = drm_connector_attach_encoder(connector,
+					wb_connector->encoder);

-:218: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#218: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:162:
+	snprintf(wb_connector->timeline_name,
+		sizeof(wb_connector->timeline_name),

-:222: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#222: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:166:
+	drm_object_attach_property(&connector->base,
+				i915->wb_out_fence_ptr_property, 0);

-:225: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#225: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:169:
+	drm_object_attach_property(&connector->base,
+				i915->wb_fb_id_property, 0);

-:228: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#228: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:172:
+	drm_object_attach_property(&connector->base,
+				i915->wb_pixel_formats_property,

-:244: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#244: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:188:
+void intel_writeback_queue_job(struct intel_writeback_connector *wb_connector,
+		struct drm_connector_state *conn_state)

-:260: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#260: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:204:
+int intel_writeback_set_fb(struct drm_connector_state *conn_state,
+			 struct drm_framebuffer *fb)

-:303: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#303: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:247:
+intel_writeback_signal_completion(struct intel_writeback_connector *wb_connector,
+				int status)

-:311: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#311: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:255:
+	job = list_first_entry_or_null(&wb_connector->job_queue,
+					struct intel_writeback_job,

-:348: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#348: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.c:292:
+	dma_fence_init(fence, &intel_writeback_fence_ops,
+		&wb_connector->fence_lock, wb_connector->fence_context,

-:405: CHECK:UNCOMMENTED_DEFINITION: spinlock_t definition without comment
#405: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:47:
+	spinlock_t job_lock;

-:408: CHECK:UNCOMMENTED_DEFINITION: spinlock_t definition without comment
#408: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:50:
+	spinlock_t fence_lock;

-:427: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#427: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:69:
+int intel_writeback_connector_init(struct drm_device *dev,
+			struct intel_writeback_connector *wb_connector,

-:433: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#433: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:75:
+int intel_writeback_set_fb(struct drm_connector_state *conn_state,
+			struct drm_framebuffer *fb);

-:438: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#438: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:80:
+void intel_writeback_queue_job(struct intel_writeback_connector *wb_connector,
+			struct drm_connector_state *conn_state);

-:444: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#444: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:86:
+intel_writeback_signal_completion(struct intel_writeback_connector *wb_connector,
+			int status);

-:454: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#454: FILE: drivers/gpu/drm/i915/display/intel_wb_connector.h:96:
+void intel_wb_connector_attach_encoder(struct intel_wb_connector *connector,
+					struct intel_encoder *encoder);

total: 0 errors, 1 warnings, 24 checks, 432 lines checked
cec4957b100a drm/i915: Define WD trancoder for i915
2589a007a64d drm/i915: Enabling WD Transcoder
-:52: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#52: FILE: drivers/gpu/drm/i915/display/intel_display.c:1551:
+static void intel_queue_writeback_job(struct intel_atomic_state *state,
+		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)

-:69: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#69: FILE: drivers/gpu/drm/i915/display/intel_display.c:1568:
+
+	}

-:83: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#83: FILE: drivers/gpu/drm/i915/display/intel_display.c:1582:
+static void intel_find_writeback_connector(struct intel_atomic_state *state,
+		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)

-:98: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#98: FILE: drivers/gpu/drm/i915/display/intel_display.c:1597:
+
+	}

-:106: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#106: FILE: drivers/gpu/drm/i915/display/intel_display.c:1605:
+		drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]: status: %s\n",
+				connector->base.id, connector->name,

-:115: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#115: FILE: drivers/gpu/drm/i915/display/intel_display.c:1614:
+
+}

-:204: ERROR:COMPLEX_MACRO: Macros with complex values should be enclosed in parentheses
#204: FILE: drivers/gpu/drm/i915/display/intel_display.h:475:
+#define for_each_intel_encoder_with_wd(dev, intel_encoder)	\
+	for_each_intel_encoder(dev, intel_encoder)		\
+		for_each_if(intel_encoder_is_wd(intel_encoder))

-:204: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'intel_encoder' - possible side-effects?
#204: FILE: drivers/gpu/drm/i915/display/intel_display.h:475:
+#define for_each_intel_encoder_with_wd(dev, intel_encoder)	\
+	for_each_intel_encoder(dev, intel_encoder)		\
+		for_each_if(intel_encoder_is_wd(intel_encoder))

-:278: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#278: 
new file mode 100644

-:338: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#338: FILE: drivers/gpu/drm/i915/display/intel_wd.c:56:
+	job = list_first_entry_or_null(&wb_conn->job_queue,
+			struct intel_writeback_job,

-:341: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "!job"
#341: FILE: drivers/gpu/drm/i915/display/intel_wd.c:59:
+	if (job == NULL) {

-:380: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#380: FILE: drivers/gpu/drm/i915/display/intel_wd.c:98:
+		DRM_ERROR("unsupported pixel format %x!\n",
+			pixel_format);

-:400: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#400: FILE: drivers/gpu/drm/i915/display/intel_wd.c:118:
+static u32 intel_wd_get_stride(const struct intel_crtc_state *crtc_state,
+			int format)

-:426: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#426: FILE: drivers/gpu/drm/i915/display/intel_wd.c:144:
+static int intel_wd_pin_fb(struct intel_wd *intel_wd,
+			struct drm_framebuffer *fb)

-:434: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#434: FILE: drivers/gpu/drm/i915/display/intel_wd.c:152:
+	vma = intel_pin_and_fence_fb_obj(fb, false, &view, false,
+			&intel_wd->flags);

-:444: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#444: FILE: drivers/gpu/drm/i915/display/intel_wd.c:162:
+static void intel_configure_slicing_strategy(struct drm_i915_private *i915,
+		struct intel_wd *intel_wd, u32 *tmp)

-:457: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#457: FILE: drivers/gpu/drm/i915/display/intel_wd.c:175:
+	intel_de_write(i915, WD_STREAMCAP_CTL(intel_wd->trans),
+			*tmp);

-:459: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#459: FILE: drivers/gpu/drm/i915/display/intel_wd.c:177:
+
+}

-:463: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#463: FILE: drivers/gpu/drm/i915/display/intel_wd.c:181:
+intel_wd_mode_valid(struct drm_connector *connector,
+		struct drm_display_mode *mode)

-:474: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#474: FILE: drivers/gpu/drm/i915/display/intel_wd.c:192:
+static void intel_wd_get_config(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config)

-:483: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#483: FILE: drivers/gpu/drm/i915/display/intel_wd.c:201:
+		memcpy(pipe_config, intel_crtc->config,
+			sizeof(*pipe_config));

-:488: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#488: FILE: drivers/gpu/drm/i915/display/intel_wd.c:206:
+
+}

-:491: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#491: FILE: drivers/gpu/drm/i915/display/intel_wd.c:209:
+static int intel_wd_compute_config(struct intel_encoder *encoder,
+			struct intel_crtc_state *pipe_config,

-:512: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#512: FILE: drivers/gpu/drm/i915/display/intel_wd.c:230:
+static void intel_wd_get_power_domains(struct intel_encoder *encoder,
+			struct intel_crtc_state *crtc_state)

-:519: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#519: FILE: drivers/gpu/drm/i915/display/intel_wd.c:237:
+	wakeref = intel_display_power_get(i915,
+				encoder->power_domain);

-:526: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#526: FILE: drivers/gpu/drm/i915/display/intel_wd.c:244:
+static bool intel_wd_get_hw_state(struct intel_encoder *encoder,
+		enum pipe *pipe)

-:539: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#539: FILE: drivers/gpu/drm/i915/display/intel_wd.c:257:
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+				encoder->power_domain);

-:541: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#541: FILE: drivers/gpu/drm/i915/display/intel_wd.c:259:
+	drm_dbg_kms(encoder->base.dev, "power enabled : %s\n",
+			!wakeref ? "false":"true");

-:541: CHECK:SPACING: spaces required around that ':' (ctx:VxV)
#541: FILE: drivers/gpu/drm/i915/display/intel_wd.c:259:
+			!wakeref ? "false":"true");
 			                  ^

-:549: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#549: FILE: drivers/gpu/drm/i915/display/intel_wd.c:267:
+	drm_dbg_kms(encoder->base.dev, "trancoder enabled: %s\n",
+			ret ? "true":"false");

-:549: CHECK:SPACING: spaces required around that ':' (ctx:VxV)
#549: FILE: drivers/gpu/drm/i915/display/intel_wd.c:267:
+			ret ? "true":"false");
 			            ^

-:553: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#553: FILE: drivers/gpu/drm/i915/display/intel_wd.c:271:
+		drm_dbg_kms(encoder->base.dev, "pipe selected is %d\n",
+			wd_crtc->pipe);

-:559: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#559: FILE: drivers/gpu/drm/i915/display/intel_wd.c:277:
+static int intel_wd_encoder_atomic_check(struct drm_encoder *encoder,
+				    struct drm_crtc_state *crtc_st,

-:587: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#587: FILE: drivers/gpu/drm/i915/display/intel_wd.c:305:
+		drm_dbg_kms(&i915->drm, "Invalid framebuffer size %ux%u\n",
+				fb->width, fb->height);

-:595: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#595: FILE: drivers/gpu/drm/i915/display/intel_wd.c:313:
+		drm_dbg_kms(&i915->drm, "Unsupported framebuffer format %08x\n",
+				fb->format->format);

-:602: CHECK:LINE_SPACING: Please don't use multiple blank lines
#602: FILE: drivers/gpu/drm/i915/display/intel_wd.c:320:
+
+

-:621: CHECK:OPEN_ENDED_LINE: Lines should not end with a '('
#621: FILE: drivers/gpu/drm/i915/display/intel_wd.c:339:
+static int intel_atomic_set_writeback_fb_for_connector(

-:634: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#634: FILE: drivers/gpu/drm/i915/display/intel_wd.c:352:
+		drm_dbg_atomic(conn->dev,
+			"Set [FB:%d] for connector state %p\n",

-:638: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#638: FILE: drivers/gpu/drm/i915/display/intel_wd.c:356:
+		drm_dbg_atomic(conn->dev,
+			"Set [NOFB] for connector state %p\n",

-:645: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#645: FILE: drivers/gpu/drm/i915/display/intel_wd.c:363:
+static int set_out_fence_for_connector(struct drm_atomic_state *state,
+					struct drm_connector *connector,

-:662: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#662: FILE: drivers/gpu/drm/i915/display/intel_wd.c:380:
+static struct drm_mode_object *__intel_object_find(struct drm_device *dev,
+					       uint32_t id, uint32_t type)

-:662: CHECK:PREFER_KERNEL_TYPES: Prefer kernel type 'u32' over 'uint32_t'
#662: FILE: drivers/gpu/drm/i915/display/intel_wd.c:380:
+					       uint32_t id, uint32_t type)

-:682: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#682: FILE: drivers/gpu/drm/i915/display/intel_wd.c:400:
+static struct drm_framebuffer *intel_wb_framebuffer_lookup(struct drm_device *dev,
+					       uint32_t id)

-:694: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#694: FILE: drivers/gpu/drm/i915/display/intel_wd.c:412:
+static s32 *intel_get_out_fence_for_connector(struct drm_atomic_state *state,
+					       struct drm_connector *connector)

-:706: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#706: FILE: drivers/gpu/drm/i915/display/intel_wd.c:424:
+static int intel_setup_out_fence(struct intel_out_fence_state *fence_state,
+			   struct dma_fence *fence)

-:708: CHECK:BRACES: Blank lines aren't necessary after an open brace '{'
#708: FILE: drivers/gpu/drm/i915/display/intel_wd.c:426:
+{
+

-:724: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#724: FILE: drivers/gpu/drm/i915/display/intel_wd.c:442:
+int intel_wd_prepare_out_fence(struct drm_device *dev,
+				struct drm_atomic_state *state)

-:778: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#778: FILE: drivers/gpu/drm/i915/display/intel_wd.c:496:
+	fd_install(fence_state->fd,
+		fence_state->sync_file->file);

-:780: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#780: FILE: drivers/gpu/drm/i915/display/intel_wd.c:498:
+
+}

-:783: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#783: FILE: drivers/gpu/drm/i915/display/intel_wd.c:501:
+static int intel_set_writeback_property(struct drm_connector *connector,
+	struct drm_connector_state *state, struct drm_property *property,

-:805: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#805: FILE: drivers/gpu/drm/i915/display/intel_wd.c:523:
+		drm_dbg_atomic(connector->dev,
+			"[CONNECTOR:%d:%s] unknown property [PROP:%d:%s]]\n",

-:813: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#813: FILE: drivers/gpu/drm/i915/display/intel_wd.c:531:
+
+}

-:816: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#816: FILE: drivers/gpu/drm/i915/display/intel_wd.c:534:
+static int intel_get_writeback_property(struct drm_connector *connector,
+	const struct drm_connector_state *state, struct drm_property *property,

-:822: CHECK:BRACES: braces {} should be used on all arms of this statement
#822: FILE: drivers/gpu/drm/i915/display/intel_wd.c:540:
+	if (property == i915->wb_fb_id_property)
[...]
+	else if (property == i915->wb_out_fence_ptr_property)
[...]
+	else {
[...]

-:826: CHECK:BRACES: Unbalanced braces around else statement
#826: FILE: drivers/gpu/drm/i915/display/intel_wd.c:544:
+	else {

-:828: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#828: FILE: drivers/gpu/drm/i915/display/intel_wd.c:546:
+		drm_dbg_atomic(&i915->drm,
+				"Unknown property [PROP:%d:%s]\n",

-:853: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#853: FILE: drivers/gpu/drm/i915/display/intel_wd.c:571:
+static bool intel_fastset_dis(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config)

-:913: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#913: FILE: drivers/gpu/drm/i915/display/intel_wd.c:631:
+	err = intel_writeback_connector_init(&i915->drm, wb_conn,
+		&wd_connector_funcs,

-:919: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#919: FILE: drivers/gpu/drm/i915/display/intel_wd.c:637:
+		drm_dbg_kms(&i915->drm,
+		"intel_writeback_connector_init: Failed: %d\n",

-:935: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#935: FILE: drivers/gpu/drm/i915/display/intel_wd.c:653:
+static void intel_wd_writeback_complete(struct intel_wd *intel_wd,
+	struct intel_writeback_job *job, int status)

-:944: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#944: FILE: drivers/gpu/drm/i915/display/intel_wd.c:662:
+static int intel_wd_setup_transcoder(struct intel_wd *intel_wd,
+		struct intel_crtc_state *pipe_config,

-:978: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#978: FILE: drivers/gpu/drm/i915/display/intel_wd.c:696:
+	intel_de_write(dev_priv, WD_SURF(intel_wd->trans),
+			i915_ggtt_offset(intel_wd->vma));

-:983: CHECK:SPACING: spaces preferred around that '|' (ctx:VxV)
#983: FILE: drivers/gpu/drm/i915/display/intel_wd.c:701:
+	tmp = ~(WD_GTT_FAULT_INT|WD_WRITE_COMPLETE_INT|WD_FRAME_COMPLETE_INT|
 	                        ^

-:983: CHECK:SPACING: spaces preferred around that '|' (ctx:VxV)
#983: FILE: drivers/gpu/drm/i915/display/intel_wd.c:701:
+	tmp = ~(WD_GTT_FAULT_INT|WD_WRITE_COMPLETE_INT|WD_FRAME_COMPLETE_INT|
 	                                              ^

-:983: CHECK:SPACING: space preferred before that '|' (ctx:VxE)
#983: FILE: drivers/gpu/drm/i915/display/intel_wd.c:701:
+	tmp = ~(WD_GTT_FAULT_INT|WD_WRITE_COMPLETE_INT|WD_FRAME_COMPLETE_INT|
 	                                                                    ^

-:984: CHECK:SPACING: spaces preferred around that '|' (ctx:VxV)
#984: FILE: drivers/gpu/drm/i915/display/intel_wd.c:702:
+			WD_VBLANK_INT|WD_OVERRUN_INT|WD_CAPTURING_INT);
 			             ^

-:984: CHECK:SPACING: spaces preferred around that '|' (ctx:VxV)
#984: FILE: drivers/gpu/drm/i915/display/intel_wd.c:702:
+			WD_VBLANK_INT|WD_OVERRUN_INT|WD_CAPTURING_INT);
 			                            ^

-:989: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#989: FILE: drivers/gpu/drm/i915/display/intel_wd.c:707:
+		tmp = intel_de_read(dev_priv,
+				WD_STREAMCAP_CTL(intel_wd->trans));

-:1074: CHECK:SPACING: spaces required around that ':' (ctx:VxV)
#1074: FILE: drivers/gpu/drm/i915/display/intel_wd.c:792:
+	drm_dbg_kms(&dev_priv->drm, "Trancoder enabled: %s\n", ret ? "true":"false");
 	                                                                   ^

-:1084: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1084: FILE: drivers/gpu/drm/i915/display/intel_wd.c:802:
+		if (intel_de_wait_for_set(dev_priv, PIPECONF(intel_wd->trans),
+				WD_TRANS_ACTIVE, 10))

-:1102: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1102: FILE: drivers/gpu/drm/i915/display/intel_wd.c:820:
+	drm_dbg_kms(&dev_priv->drm, "WD Trans_Conf value after disable = 0x%08x\n",
+		intel_de_read(dev_priv, PIPECONF(intel_wd->trans)));

-:1108: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1108: FILE: drivers/gpu/drm/i915/display/intel_wd.c:826:
+static int intel_wd_capture(struct intel_wd *intel_wd,
+		struct intel_crtc_state *pipe_config,

-:1126: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1126: FILE: drivers/gpu/drm/i915/display/intel_wd.c:844:
+		drm_dbg_kms(&i915->drm,
+		"wd transcoder setup not completed aborting capture\n");

-:1130: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "!wd_crtc"
#1130: FILE: drivers/gpu/drm/i915/display/intel_wd.c:848:
+	if (wd_crtc == NULL) {

-:1136: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1136: FILE: drivers/gpu/drm/i915/display/intel_wd.c:854:
+	tmp = intel_de_read_fw(i915,
+			WD_TRANS_FUNC_CTL(intel_wd->trans));

-:1141: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1141: FILE: drivers/gpu/drm/i915/display/intel_wd.c:859:
+	intel_de_write_fw(i915,
+			WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);

-:1144: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1144: FILE: drivers/gpu/drm/i915/display/intel_wd.c:862:
+	if (!intel_de_wait_for_set(i915, WD_IIR(intel_wd->trans),
+				WD_FRAME_COMPLETE_INT, 100)){

-:1152: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1152: FILE: drivers/gpu/drm/i915/display/intel_wd.c:870:
+		tmp = intel_de_read(i915,
+				WD_TRANS_FUNC_CTL(intel_wd->trans));

-:1155: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1155: FILE: drivers/gpu/drm/i915/display/intel_wd.c:873:
+		intel_de_write(i915,
+				WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);

-:1161: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "!intel_get_writeback_job_from_queue"
#1161: FILE: drivers/gpu/drm/i915/display/intel_wd.c:879:
+	if (intel_get_writeback_job_from_queue(intel_wd) == NULL)

-:1167: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1167: FILE: drivers/gpu/drm/i915/display/intel_wd.c:885:
+		drm_crtc_send_vblank_event(&wd_crtc->base,
+					wd_crtc->wd.e);

-:1172: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1172: FILE: drivers/gpu/drm/i915/display/intel_wd.c:890:
+		DRM_ERROR("Event NULL! %p, %p\n", &i915->drm,
+			wd_crtc);

-:1176: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#1176: FILE: drivers/gpu/drm/i915/display/intel_wd.c:894:
+
+}

-:1179: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1179: FILE: drivers/gpu/drm/i915/display/intel_wd.c:897:
+void intel_wd_enable_capture(struct intel_encoder *encoder,
+		struct intel_crtc_state *pipe_config,

-:1189: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "!job"
#1189: FILE: drivers/gpu/drm/i915/display/intel_wd.c:907:
+	if (job == NULL) {

-:1191: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1191: FILE: drivers/gpu/drm/i915/display/intel_wd.c:909:
+		drm_dbg_kms(&i915->drm,
+			"job queue is empty not capturing any frame\n");

-:1198: CHECK:BRACES: Blank lines aren't necessary before a close brace '}'
#1198: FILE: drivers/gpu/drm/i915/display/intel_wd.c:916:
+
+}

-:1201: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1201: FILE: drivers/gpu/drm/i915/display/intel_wd.c:919:
+void intel_wd_set_vblank_event(struct intel_crtc *intel_crtc,
+			struct intel_crtc_state *intel_crtc_state)

-:1222: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1222: FILE: drivers/gpu/drm/i915/display/intel_wd.c:940:
+			drm_dbg_kms(&i915->drm, "WD event:%p\n",
+				intel_crtc->wd.e);

-:1250: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1250: FILE: drivers/gpu/drm/i915/display/intel_wd.c:968:
+		drm_dbg_kms(&i915->drm,
+		"wd write complete interrupt encountered\n");

-:1255: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1255: FILE: drivers/gpu/drm/i915/display/intel_wd.c:973:
+		drm_dbg_kms(&i915->drm,
+			"frame complete interrupt for wd transcoder\n");

-:1333: CHECK:AVOID_EXTERNS: extern prototypes should be avoided in .h files
#1333: FILE: drivers/gpu/drm/i915/display/intel_wd.h:67:
+extern struct sync_file *sync_file_create(struct dma_fence *fence);

-:1338: CHECK:LINE_SPACING: Please use a blank line after function/struct/union/enum declarations
#1338: FILE: drivers/gpu/drm/i915/display/intel_wd.h:72:
+}
+void intel_wd_init(struct drm_i915_private *dev_priv, enum transcoder trans);

-:1340: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1340: FILE: drivers/gpu/drm/i915/display/intel_wd.h:74:
+void intel_wd_enable_capture(struct intel_encoder *encoder,
+				struct intel_crtc_state *pipe_config,

-:1344: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1344: FILE: drivers/gpu/drm/i915/display/intel_wd.h:78:
+void intel_wd_set_vblank_event(struct intel_crtc *crtc,
+				struct intel_crtc_state *state);

-:1346: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1346: FILE: drivers/gpu/drm/i915/display/intel_wd.h:80:
+int intel_wd_prepare_out_fence(struct drm_device *dev,
+				struct drm_atomic_state *state);

-:1404: CHECK:SPACING: spaces preferred around that '|' (ctx:VxE)
#1404: FILE: drivers/gpu/drm/i915/i915_pci.c:856:
+		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1)| \
 		                                             ^

-:1439: CHECK:LINE_SPACING: Please don't use multiple blank lines
#1439: FILE: drivers/gpu/drm/i915/i915_reg.h:3804:
+
+

total: 1 errors, 1 warnings, 96 checks, 1501 lines checked



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

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for i915 writeback private framework (rev4)
  2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
                   ` (7 preceding siblings ...)
  2022-03-18  4:48 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915 writeback private framework (rev4) Patchwork
@ 2022-03-18  4:49 ` Patchwork
  2022-03-18  5:20 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
  2022-03-18  8:29 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork
  10 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2022-03-18  4:49 UTC (permalink / raw)
  To: Suraj Kandpal; +Cc: intel-gfx

== Series Details ==

Series: i915 writeback private framework (rev4)
URL   : https://patchwork.freedesktop.org/series/101425/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.



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

* [Intel-gfx] ✓ Fi.CI.BAT: success for i915 writeback private framework (rev4)
  2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
                   ` (8 preceding siblings ...)
  2022-03-18  4:49 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
@ 2022-03-18  5:20 ` Patchwork
  2022-03-18  8:29 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork
  10 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2022-03-18  5:20 UTC (permalink / raw)
  To: Suraj Kandpal; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 5179 bytes --]

== Series Details ==

Series: i915 writeback private framework (rev4)
URL   : https://patchwork.freedesktop.org/series/101425/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11380 -> Patchwork_22604
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/index.html

Participating hosts (45 -> 45)
------------------------------

  Additional (2): bat-adls-5 fi-pnv-d510 
  Missing    (2): fi-bsw-cyan fi-bdw-samus 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_22604:

### IGT changes ###

#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@runner@aborted:
    - {fi-rkl-11600}:     NOTRUN -> [FAIL][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/fi-rkl-11600/igt@runner@aborted.html
    - {bat-adls-5}:       NOTRUN -> [FAIL][2]
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/bat-adls-5/igt@runner@aborted.html
    - {fi-adl-ddr5}:      NOTRUN -> [FAIL][3]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/fi-adl-ddr5/igt@runner@aborted.html

  
Known issues
------------

  Here are the changes found in Patchwork_22604 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@i915_selftest@live@gtt:
    - fi-bdw-5557u:       NOTRUN -> [DMESG-FAIL][4] ([i915#3674])
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/fi-bdw-5557u/igt@i915_selftest@live@gtt.html

  * igt@i915_selftest@live@hangcheck:
    - fi-bdw-5557u:       NOTRUN -> [INCOMPLETE][5] ([i915#3921])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/fi-bdw-5557u/igt@i915_selftest@live@hangcheck.html

  * igt@kms_chamelium@dp-crc-fast:
    - fi-bdw-5557u:       NOTRUN -> [SKIP][6] ([fdo#109271] / [fdo#111827]) +8 similar issues
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/fi-bdw-5557u/igt@kms_chamelium@dp-crc-fast.html

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c:
    - fi-pnv-d510:        NOTRUN -> [SKIP][7] ([fdo#109271] / [i915#5341])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/fi-pnv-d510/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-c.html

  * igt@kms_setmode@basic-clone-single-crtc:
    - fi-bdw-5557u:       NOTRUN -> [SKIP][8] ([fdo#109271]) +14 similar issues
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/fi-bdw-5557u/igt@kms_setmode@basic-clone-single-crtc.html

  * igt@prime_vgem@basic-userptr:
    - fi-pnv-d510:        NOTRUN -> [SKIP][9] ([fdo#109271]) +57 similar issues
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/fi-pnv-d510/igt@prime_vgem@basic-userptr.html

  * igt@runner@aborted:
    - bat-dg1-5:          NOTRUN -> [FAIL][10] ([i915#2426])
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/bat-dg1-5/igt@runner@aborted.html
    - fi-rkl-guc:         NOTRUN -> [FAIL][11] ([i915#2426])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/fi-rkl-guc/igt@runner@aborted.html
    - fi-tgl-1115g4:      NOTRUN -> [FAIL][12] ([i915#5257])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/fi-tgl-1115g4/igt@runner@aborted.html
    - bat-dg1-6:          NOTRUN -> [FAIL][13] ([i915#2426])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/bat-dg1-6/igt@runner@aborted.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#2426]: https://gitlab.freedesktop.org/drm/intel/issues/2426
  [i915#3674]: https://gitlab.freedesktop.org/drm/intel/issues/3674
  [i915#3921]: https://gitlab.freedesktop.org/drm/intel/issues/3921
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4897]: https://gitlab.freedesktop.org/drm/intel/issues/4897
  [i915#5137]: https://gitlab.freedesktop.org/drm/intel/issues/5137
  [i915#5257]: https://gitlab.freedesktop.org/drm/intel/issues/5257
  [i915#5269]: https://gitlab.freedesktop.org/drm/intel/issues/5269
  [i915#5341]: https://gitlab.freedesktop.org/drm/intel/issues/5341


Build changes
-------------

  * Linux: CI_DRM_11380 -> Patchwork_22604

  CI-20190529: 20190529
  CI_DRM_11380: fe83949cd4316608ea785fc376b6ed444224adad @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6385: f3df40281d93d5a63ee98fa30e90852d780673c9 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_22604: 2589a007a64d481383c815a6abdc0eec3b38fcef @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

2589a007a64d drm/i915: Enabling WD Transcoder
cec4957b100a drm/i915: Define WD trancoder for i915
224406362f12 drm/i915: Creating writeback pipeline to bypass drm_writeback framework

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/index.html

[-- Attachment #2: Type: text/html, Size: 6154 bytes --]

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

* [Intel-gfx] ✓ Fi.CI.IGT: success for i915 writeback private framework (rev4)
  2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
                   ` (9 preceding siblings ...)
  2022-03-18  5:20 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
@ 2022-03-18  8:29 ` Patchwork
  10 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2022-03-18  8:29 UTC (permalink / raw)
  To: Suraj Kandpal; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 30263 bytes --]

== Series Details ==

Series: i915 writeback private framework (rev4)
URL   : https://patchwork.freedesktop.org/series/101425/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11380_full -> Patchwork_22604_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Participating hosts (12 -> 12)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_22604_full:

### IGT changes ###

#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@runner@aborted:
    - {shard-rkl}:        ([FAIL][1], [FAIL][2], [FAIL][3], [FAIL][4]) ([i915#3002] / [i915#4312]) -> ([FAIL][5], [FAIL][6], [FAIL][7], [FAIL][8], [FAIL][9], [FAIL][10], [FAIL][11], [FAIL][12], [FAIL][13], [FAIL][14], [FAIL][15], [FAIL][16], [FAIL][17], [FAIL][18], [FAIL][19], [FAIL][20], [FAIL][21], [FAIL][22], [FAIL][23], [FAIL][24], [FAIL][25])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-rkl-2/igt@runner@aborted.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-rkl-1/igt@runner@aborted.html
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-rkl-4/igt@runner@aborted.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-rkl-5/igt@runner@aborted.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-6/igt@runner@aborted.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-6/igt@runner@aborted.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-6/igt@runner@aborted.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-5/igt@runner@aborted.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-5/igt@runner@aborted.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-6/igt@runner@aborted.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-5/igt@runner@aborted.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-5/igt@runner@aborted.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-6/igt@runner@aborted.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-5/igt@runner@aborted.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-5/igt@runner@aborted.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-5/igt@runner@aborted.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-4/igt@runner@aborted.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-1/igt@runner@aborted.html
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-1/igt@runner@aborted.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-2/igt@runner@aborted.html
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-1/igt@runner@aborted.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-1/igt@runner@aborted.html
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-2/igt@runner@aborted.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-2/igt@runner@aborted.html
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-rkl-1/igt@runner@aborted.html

  
Known issues
------------

  Here are the changes found in Patchwork_22604_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_isolation@preservation-s3@rcs0:
    - shard-skl:          NOTRUN -> [INCOMPLETE][26] ([i915#1373] / [i915#4793])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl10/igt@gem_ctx_isolation@preservation-s3@rcs0.html

  * igt@gem_eio@unwedge-stress:
    - shard-iclb:         [PASS][27] -> [TIMEOUT][28] ([i915#2481] / [i915#3070])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-iclb5/igt@gem_eio@unwedge-stress.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb2/igt@gem_eio@unwedge-stress.html

  * igt@gem_exec_fair@basic-none@vcs0:
    - shard-apl:          [PASS][29] -> [FAIL][30] ([i915#2842]) +2 similar issues
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-apl3/igt@gem_exec_fair@basic-none@vcs0.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl2/igt@gem_exec_fair@basic-none@vcs0.html

  * igt@gem_exec_fair@basic-none@vecs0:
    - shard-kbl:          [PASS][31] -> [FAIL][32] ([i915#2842])
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-kbl1/igt@gem_exec_fair@basic-none@vecs0.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-kbl4/igt@gem_exec_fair@basic-none@vecs0.html

  * igt@gem_lmem_swapping@heavy-verify-random:
    - shard-iclb:         NOTRUN -> [SKIP][33] ([i915#4613])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@gem_lmem_swapping@heavy-verify-random.html

  * igt@gem_lmem_swapping@random-engines:
    - shard-skl:          NOTRUN -> [SKIP][34] ([fdo#109271] / [i915#4613]) +1 similar issue
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl1/igt@gem_lmem_swapping@random-engines.html

  * igt@gem_render_copy@x-tiled-to-vebox-yf-tiled:
    - shard-iclb:         NOTRUN -> [SKIP][35] ([i915#768]) +1 similar issue
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb7/igt@gem_render_copy@x-tiled-to-vebox-yf-tiled.html

  * igt@gem_userptr_blits@dmabuf-sync:
    - shard-skl:          NOTRUN -> [SKIP][36] ([fdo#109271] / [i915#3323])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl9/igt@gem_userptr_blits@dmabuf-sync.html

  * igt@i915_pm_dc@dc6-dpms:
    - shard-skl:          NOTRUN -> [FAIL][37] ([i915#454])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl1/igt@i915_pm_dc@dc6-dpms.html

  * igt@i915_pm_rc6_residency@rc6-idle:
    - shard-iclb:         NOTRUN -> [WARN][38] ([i915#1804] / [i915#2684])
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@i915_pm_rc6_residency@rc6-idle.html

  * igt@i915_selftest@live@gt_pm:
    - shard-skl:          NOTRUN -> [DMESG-FAIL][39] ([i915#1886])
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl9/igt@i915_selftest@live@gt_pm.html

  * igt@kms_big_fb@4-tiled-8bpp-rotate-270:
    - shard-iclb:         NOTRUN -> [SKIP][40] ([i915#5286])
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@kms_big_fb@4-tiled-8bpp-rotate-270.html

  * igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-0:
    - shard-skl:          [PASS][41] -> [DMESG-WARN][42] ([i915#1982])
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-skl9/igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-0.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl8/igt@kms_big_fb@linear-max-hw-stride-64bpp-rotate-0.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-async-flip:
    - shard-skl:          NOTRUN -> [FAIL][43] ([i915#3743])
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl1/igt@kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-async-flip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip:
    - shard-apl:          NOTRUN -> [SKIP][44] ([fdo#109271] / [i915#3777])
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl3/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip:
    - shard-skl:          NOTRUN -> [SKIP][45] ([fdo#109271] / [i915#3777]) +2 similar issues
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl6/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip.html

  * igt@kms_ccs@pipe-a-bad-aux-stride-y_tiled_gen12_mc_ccs:
    - shard-skl:          NOTRUN -> [SKIP][46] ([fdo#109271] / [i915#1888] / [i915#3886])
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl6/igt@kms_ccs@pipe-a-bad-aux-stride-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-a-bad-aux-stride-y_tiled_gen12_rc_ccs_cc:
    - shard-apl:          NOTRUN -> [SKIP][47] ([fdo#109271] / [i915#3886])
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl3/igt@kms_ccs@pipe-a-bad-aux-stride-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-a-crc-primary-rotation-180-y_tiled_gen12_mc_ccs:
    - shard-skl:          NOTRUN -> [SKIP][48] ([fdo#109271] / [i915#3886]) +6 similar issues
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl6/igt@kms_ccs@pipe-a-crc-primary-rotation-180-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-b-crc-sprite-planes-basic-y_tiled_gen12_mc_ccs:
    - shard-iclb:         NOTRUN -> [SKIP][49] ([fdo#109278] / [i915#3886]) +1 similar issue
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@kms_ccs@pipe-b-crc-sprite-planes-basic-y_tiled_gen12_mc_ccs.html

  * igt@kms_color@pipe-d-ctm-negative:
    - shard-iclb:         NOTRUN -> [SKIP][50] ([fdo#109278] / [i915#1149])
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@kms_color@pipe-d-ctm-negative.html

  * igt@kms_color_chamelium@pipe-b-ctm-0-75:
    - shard-apl:          NOTRUN -> [SKIP][51] ([fdo#109271] / [fdo#111827]) +1 similar issue
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl3/igt@kms_color_chamelium@pipe-b-ctm-0-75.html

  * igt@kms_color_chamelium@pipe-b-ctm-max:
    - shard-skl:          NOTRUN -> [SKIP][52] ([fdo#109271] / [fdo#111827]) +15 similar issues
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl9/igt@kms_color_chamelium@pipe-b-ctm-max.html

  * igt@kms_color_chamelium@pipe-c-ctm-blue-to-red:
    - shard-iclb:         NOTRUN -> [SKIP][53] ([fdo#109284] / [fdo#111827])
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@kms_color_chamelium@pipe-c-ctm-blue-to-red.html

  * igt@kms_cursor_crc@pipe-a-cursor-512x170-random:
    - shard-iclb:         NOTRUN -> [SKIP][54] ([fdo#109278] / [fdo#109279])
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@kms_cursor_crc@pipe-a-cursor-512x170-random.html

  * igt@kms_cursor_legacy@2x-long-flip-vs-cursor-legacy:
    - shard-glk:          [PASS][55] -> [FAIL][56] ([i915#72])
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-glk6/igt@kms_cursor_legacy@2x-long-flip-vs-cursor-legacy.html
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-glk2/igt@kms_cursor_legacy@2x-long-flip-vs-cursor-legacy.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions:
    - shard-skl:          [PASS][57] -> [FAIL][58] ([i915#2346])
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-skl10/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl3/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html

  * igt@kms_cursor_legacy@pipe-d-single-move:
    - shard-iclb:         NOTRUN -> [SKIP][59] ([fdo#109278]) +11 similar issues
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@kms_cursor_legacy@pipe-d-single-move.html

  * igt@kms_flip@flip-vs-expired-vblank@a-hdmi-a2:
    - shard-glk:          [PASS][60] -> [FAIL][61] ([i915#79])
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-glk4/igt@kms_flip@flip-vs-expired-vblank@a-hdmi-a2.html
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-glk7/igt@kms_flip@flip-vs-expired-vblank@a-hdmi-a2.html

  * igt@kms_flip@flip-vs-suspend-interruptible@a-dp1:
    - shard-apl:          [PASS][62] -> [DMESG-WARN][63] ([i915#180]) +3 similar issues
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-apl6/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl4/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html

  * igt@kms_flip@plain-flip-fb-recreate@b-edp1:
    - shard-skl:          [PASS][64] -> [FAIL][65] ([i915#2122]) +3 similar issues
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-skl10/igt@kms_flip@plain-flip-fb-recreate@b-edp1.html
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl3/igt@kms_flip@plain-flip-fb-recreate@b-edp1.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-upscaling:
    - shard-glk:          [PASS][66] -> [FAIL][67] ([i915#4911])
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-glk4/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-upscaling.html
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-glk8/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytileccs-upscaling.html

  * igt@kms_force_connector_basic@prune-stale-modes:
    - shard-apl:          NOTRUN -> [SKIP][68] ([fdo#109271]) +25 similar issues
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl3/igt@kms_force_connector_basic@prune-stale-modes.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-mmap-wc:
    - shard-iclb:         NOTRUN -> [SKIP][69] ([fdo#109280]) +6 similar issues
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@kms_frontbuffer_tracking@psr-2p-primscrn-pri-shrfb-draw-mmap-wc.html

  * igt@kms_hdr@bpc-switch@bpc-switch-edp-1-pipe-a:
    - shard-skl:          NOTRUN -> [FAIL][70] ([i915#1188])
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl1/igt@kms_hdr@bpc-switch@bpc-switch-edp-1-pipe-a.html

  * igt@kms_pipe_crc_basic@read-crc-pipe-d-frame-sequence:
    - shard-apl:          NOTRUN -> [SKIP][71] ([fdo#109271] / [i915#533]) +1 similar issue
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl3/igt@kms_pipe_crc_basic@read-crc-pipe-d-frame-sequence.html

  * igt@kms_plane_alpha_blend@pipe-a-alpha-7efc:
    - shard-skl:          NOTRUN -> [FAIL][72] ([fdo#108145] / [i915#265]) +4 similar issues
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl10/igt@kms_plane_alpha_blend@pipe-a-alpha-7efc.html

  * igt@kms_plane_alpha_blend@pipe-a-alpha-transparent-fb:
    - shard-skl:          NOTRUN -> [FAIL][73] ([i915#265]) +1 similar issue
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl1/igt@kms_plane_alpha_blend@pipe-a-alpha-transparent-fb.html

  * igt@kms_plane_alpha_blend@pipe-b-coverage-7efc:
    - shard-skl:          [PASS][74] -> [FAIL][75] ([fdo#108145] / [i915#265])
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-skl7/igt@kms_plane_alpha_blend@pipe-b-coverage-7efc.html
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl7/igt@kms_plane_alpha_blend@pipe-b-coverage-7efc.html

  * igt@kms_plane_lowres@pipe-a-tiling-x:
    - shard-iclb:         NOTRUN -> [SKIP][76] ([i915#3536]) +1 similar issue
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@kms_plane_lowres@pipe-a-tiling-x.html

  * igt@kms_plane_scaling@planes-downscale-factor-0-25@pipe-b-edp-1-planes-downscale:
    - shard-iclb:         NOTRUN -> [SKIP][77] ([i915#5235]) +2 similar issues
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@kms_plane_scaling@planes-downscale-factor-0-25@pipe-b-edp-1-planes-downscale.html

  * igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-25@pipe-a-edp-1-planes-upscale-downscale:
    - shard-skl:          NOTRUN -> [SKIP][78] ([fdo#109271]) +200 similar issues
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl1/igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-25@pipe-a-edp-1-planes-upscale-downscale.html

  * igt@kms_psr2_sf@cursor-plane-update-sf:
    - shard-skl:          NOTRUN -> [SKIP][79] ([fdo#109271] / [i915#658]) +2 similar issues
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl8/igt@kms_psr2_sf@cursor-plane-update-sf.html

  * igt@kms_psr2_sf@overlay-plane-update-sf-dmg-area:
    - shard-apl:          NOTRUN -> [SKIP][80] ([fdo#109271] / [i915#658])
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl3/igt@kms_psr2_sf@overlay-plane-update-sf-dmg-area.html

  * igt@kms_psr2_sf@plane-move-sf-dmg-area:
    - shard-iclb:         NOTRUN -> [SKIP][81] ([fdo#111068] / [i915#658])
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@kms_psr2_sf@plane-move-sf-dmg-area.html

  * igt@kms_psr@psr2_sprite_plane_move:
    - shard-iclb:         [PASS][82] -> [SKIP][83] ([fdo#109441]) +1 similar issue
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-iclb2/igt@kms_psr@psr2_sprite_plane_move.html
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb7/igt@kms_psr@psr2_sprite_plane_move.html

  * igt@kms_writeback@writeback-check-output:
    - shard-skl:          NOTRUN -> [SKIP][84] ([fdo#109271] / [i915#2437])
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl1/igt@kms_writeback@writeback-check-output.html

  * igt@kms_writeback@writeback-pixel-formats:
    - shard-iclb:         NOTRUN -> [SKIP][85] ([i915#2437])
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@kms_writeback@writeback-pixel-formats.html

  * igt@prime_nv_pcopy@test3_2:
    - shard-iclb:         NOTRUN -> [SKIP][86] ([fdo#109291])
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@prime_nv_pcopy@test3_2.html

  * igt@syncobj_timeline@transfer-timeline-point:
    - shard-skl:          NOTRUN -> [DMESG-FAIL][87] ([i915#5098])
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl9/igt@syncobj_timeline@transfer-timeline-point.html

  * igt@sysfs_clients@fair-7:
    - shard-iclb:         NOTRUN -> [SKIP][88] ([i915#2994])
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb3/igt@sysfs_clients@fair-7.html

  * igt@sysfs_clients@split-50:
    - shard-skl:          NOTRUN -> [SKIP][89] ([fdo#109271] / [i915#2994]) +1 similar issue
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl1/igt@sysfs_clients@split-50.html

  
#### Possible fixes ####

  * igt@gem_exec_fair@basic-none@vcs0:
    - shard-kbl:          [FAIL][90] ([i915#2842]) -> [PASS][91] +2 similar issues
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-kbl1/igt@gem_exec_fair@basic-none@vcs0.html
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-kbl4/igt@gem_exec_fair@basic-none@vcs0.html

  * igt@gem_exec_fair@basic-throttle@rcs0:
    - shard-iclb:         [FAIL][92] ([i915#2849]) -> [PASS][93]
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-iclb7/igt@gem_exec_fair@basic-throttle@rcs0.html
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb5/igt@gem_exec_fair@basic-throttle@rcs0.html

  * igt@gem_workarounds@suspend-resume:
    - shard-apl:          [DMESG-WARN][94] ([i915#180]) -> [PASS][95] +2 similar issues
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-apl3/igt@gem_workarounds@suspend-resume.html
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl3/igt@gem_workarounds@suspend-resume.html

  * igt@kms_draw_crc@draw-method-xrgb2101010-pwrite-untiled:
    - shard-snb:          [SKIP][96] ([fdo#109271]) -> [PASS][97]
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-snb4/igt@kms_draw_crc@draw-method-xrgb2101010-pwrite-untiled.html
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-snb5/igt@kms_draw_crc@draw-method-xrgb2101010-pwrite-untiled.html

  * igt@kms_flip@flip-vs-expired-vblank@c-hdmi-a1:
    - shard-glk:          [FAIL][98] ([i915#79]) -> [PASS][99]
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-glk4/igt@kms_flip@flip-vs-expired-vblank@c-hdmi-a1.html
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-glk7/igt@kms_flip@flip-vs-expired-vblank@c-hdmi-a1.html

  * igt@kms_flip@flip-vs-suspend@c-edp1:
    - shard-skl:          [INCOMPLETE][100] ([i915#4839]) -> [PASS][101]
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-skl9/igt@kms_flip@flip-vs-suspend@c-edp1.html
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl6/igt@kms_flip@flip-vs-suspend@c-edp1.html

  * igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5@pipe-c-edp-1-planes-upscale-downscale:
    - shard-iclb:         [SKIP][102] ([i915#5235]) -> [PASS][103] +2 similar issues
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-iclb2/igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5@pipe-c-edp-1-planes-upscale-downscale.html
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb1/igt@kms_plane_scaling@planes-upscale-factor-0-25-downscale-factor-0-5@pipe-c-edp-1-planes-upscale-downscale.html

  * igt@kms_psr@psr2_cursor_plane_onoff:
    - shard-iclb:         [SKIP][104] ([fdo#109441]) -> [PASS][105] +1 similar issue
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-iclb5/igt@kms_psr@psr2_cursor_plane_onoff.html
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb2/igt@kms_psr@psr2_cursor_plane_onoff.html

  * igt@kms_sequence@queue-busy:
    - shard-skl:          [FAIL][106] ([i915#2995]) -> [PASS][107]
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-skl6/igt@kms_sequence@queue-busy.html
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl4/igt@kms_sequence@queue-busy.html

  
#### Warnings ####

  * igt@gem_exec_balancer@parallel-contexts:
    - shard-iclb:         [SKIP][108] ([i915#4525]) -> [DMESG-WARN][109] ([i915#5076])
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-iclb5/igt@gem_exec_balancer@parallel-contexts.html
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb2/igt@gem_exec_balancer@parallel-contexts.html

  * igt@gem_exec_balancer@parallel-out-fence:
    - shard-iclb:         [DMESG-WARN][110] ([i915#5076]) -> [SKIP][111] ([i915#4525]) +1 similar issue
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-iclb2/igt@gem_exec_balancer@parallel-out-fence.html
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb7/igt@gem_exec_balancer@parallel-out-fence.html

  * igt@kms_chamelium@vga-hpd-enable-disable-mode:
    - shard-skl:          [SKIP][112] ([fdo#109271] / [fdo#111827]) -> [SKIP][113] ([fdo#109271] / [fdo#111827] / [i915#1888])
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-skl6/igt@kms_chamelium@vga-hpd-enable-disable-mode.html
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-skl2/igt@kms_chamelium@vga-hpd-enable-disable-mode.html

  * igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area:
    - shard-iclb:         [SKIP][114] ([i915#2920]) -> [SKIP][115] ([fdo#111068] / [i915#658])
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-iclb2/igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area.html
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-iclb7/igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area.html

  * igt@runner@aborted:
    - shard-apl:          ([FAIL][116], [FAIL][117], [FAIL][118], [FAIL][119], [FAIL][120], [FAIL][121], [FAIL][122]) ([fdo#109271] / [i915#180] / [i915#3002] / [i915#4312] / [i915#5257]) -> ([FAIL][123], [FAIL][124], [FAIL][125], [FAIL][126], [FAIL][127], [FAIL][128], [FAIL][129], [FAIL][130]) ([i915#180] / [i915#3002] / [i915#4312] / [i915#5257])
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-apl7/igt@runner@aborted.html
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-apl2/igt@runner@aborted.html
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-apl3/igt@runner@aborted.html
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-apl3/igt@runner@aborted.html
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-apl4/igt@runner@aborted.html
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-apl1/igt@runner@aborted.html
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-apl6/igt@runner@aborted.html
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl3/igt@runner@aborted.html
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl3/igt@runner@aborted.html
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl1/igt@runner@aborted.html
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl1/igt@runner@aborted.html
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl7/igt@runner@aborted.html
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl4/igt@runner@aborted.html
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl6/igt@runner@aborted.html
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-apl2/igt@runner@aborted.html
    - shard-tglb:         ([FAIL][131], [FAIL][132], [FAIL][133], [FAIL][134], [FAIL][135], [FAIL][136], [FAIL][137], [FAIL][138], [FAIL][139]) ([i915#3002] / [i915#4312] / [i915#5257]) -> ([FAIL][140], [FAIL][141], [FAIL][142], [FAIL][143], [FAIL][144], [FAIL][145], [FAIL][146], [FAIL][147], [FAIL][148], [FAIL][149], [FAIL][150], [FAIL][151], [FAIL][152], [FAIL][153], [FAIL][154], [FAIL][155], [FAIL][156], [FAIL][157], [FAIL][158], [FAIL][159], [FAIL][160], [FAIL][161], [FAIL][162], [FAIL][163], [FAIL][164]) ([i915#5257])
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-tglb2/igt@runner@aborted.html
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-tglb3/igt@runner@aborted.html
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-tglb6/igt@runner@aborted.html
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-tglb3/igt@runner@aborted.html
   [135]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-tglb5/igt@runner@aborted.html
   [136]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-tglb5/igt@runner@aborted.html
   [137]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-tglb2/igt@runner@aborted.html
   [138]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-tglb7/igt@runner@aborted.html
   [139]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11380/shard-tglb8/igt@runner@aborted.html
   [140]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb6/igt@runner@aborted.html
   [141]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb5/igt@runner@aborted.html
   [142]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb7/igt@runner@aborted.html
   [143]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb6/igt@runner@aborted.html
   [144]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb7/igt@runner@aborted.html
   [145]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb8/igt@runner@aborted.html
   [146]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb8/igt@runner@aborted.html
   [147]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb5/igt@runner@aborted.html
   [148]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb8/igt@runner@aborted.html
   [149]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb8/igt@runner@aborted.html
   [150]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb6/igt@runner@aborted.html
   [151]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb7/igt@runner@aborted.html
   [152]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb5/igt@runner@aborted.html
   [153]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb3/igt@runner@aborted.html
   [154]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb7/igt@runner@aborted.html
   [155]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb5/igt@runner@aborted.html
   [156]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb6/igt@runner@aborted.html
   [157]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb2/igt@runner@aborted.html
   [158]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb2/igt@runner@aborted.html
   [159]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb3/igt@runner@aborted.html
   [160]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb2/igt@runner@aborted.html
   [161]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb2/igt@runner@aborted.html
   [162]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb1/igt@runner@aborted.html
   [163]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb2/igt@runner@aborted.html
   [164]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/shard-tglb1/igt@runner@aborted.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109279]: https://

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22604/index.html

[-- Attachment #2: Type: text/html, Size: 34480 bytes --]

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

* Re: [Intel-gfx] [RFC PATCH v2 3/3] drm/i915: Enabling WD Transcoder
  2022-03-18  4:21   ` [Intel-gfx] [RFC PATCH v2 " Suraj Kandpal
@ 2022-03-25  5:35     ` Kandpal, Suraj
  0 siblings, 0 replies; 24+ messages in thread
From: Kandpal, Suraj @ 2022-03-25  5:35 UTC (permalink / raw)
  To: intel-gfx; +Cc: Nikula, Jani

Hi All,
Gentle Reminder

Regards,
Suraj Kandpal
>  drivers/gpu/drm/i915/Makefile                 |   1 +
>  drivers/gpu/drm/i915/display/intel_acpi.c     |   1 +
>  drivers/gpu/drm/i915/display/intel_display.c  |  89 +-
>  drivers/gpu/drm/i915/display/intel_display.h  |   9 +
>  .../drm/i915/display/intel_display_types.h    |  13 +
>  drivers/gpu/drm/i915/display/intel_dpll.c     |   3 +
>  drivers/gpu/drm/i915/display/intel_opregion.c |   3 +
>  drivers/gpu/drm/i915/display/intel_wd.c       | 978 ++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_wd.h       |  82 ++
>  drivers/gpu/drm/i915/i915_drv.h               |   2 +
>  drivers/gpu/drm/i915/i915_irq.c               |   8 +-
>  drivers/gpu/drm/i915/i915_pci.c               |   7 +-
>  drivers/gpu/drm/i915/i915_reg.h               | 137 +++
>  13 files changed, 1330 insertions(+), 3 deletions(-)  create mode 100644
> drivers/gpu/drm/i915/display/intel_wd.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_wd.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 087bd9d1b397..5ee32513a945 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -287,6 +287,7 @@ i915-y += \
>  	display/intel_vdsc.o \
>  	display/intel_vrr.o \
>  	display/intel_wb_connector.o\
> +	display/intel_wd.o\
>  	display/vlv_dsi.o \
>  	display/vlv_dsi_pll.o
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c
> b/drivers/gpu/drm/i915/display/intel_acpi.c
> index e78430001f07..ae08db164f73 100644
> --- a/drivers/gpu/drm/i915/display/intel_acpi.c
> +++ b/drivers/gpu/drm/i915/display/intel_acpi.c
> @@ -247,6 +247,7 @@ static u32 acpi_display_type(struct intel_connector
> *connector)
>  	case DRM_MODE_CONNECTOR_LVDS:
>  	case DRM_MODE_CONNECTOR_eDP:
>  	case DRM_MODE_CONNECTOR_DSI:
> +	case DRM_MODE_CONNECTOR_WRITEBACK:
>  		display_type = ACPI_DISPLAY_TYPE_INTERNAL_DIGITAL;
>  		break;
>  	case DRM_MODE_CONNECTOR_Unknown:
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> b/drivers/gpu/drm/i915/display/intel_display.c
> index eb49973621f0..6dedc7921f54 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -111,6 +111,7 @@
>  #include "intel_sprite.h"
>  #include "intel_tc.h"
>  #include "intel_vga.h"
> +#include "intel_wd.h"
>  #include "i9xx_plane.h"
>  #include "skl_scaler.h"
>  #include "skl_universal_plane.h"
> @@ -1544,6 +1545,72 @@ static void
> intel_encoders_update_complete(struct intel_atomic_state *state)
>  	}
>  }
> 
> +static void intel_queue_writeback_job(struct intel_atomic_state *state,
> +		struct intel_crtc *intel_crtc, struct intel_crtc_state
> *crtc_state) {
> +	struct drm_connector_state *new_conn_state;
> +	struct drm_connector *connector;
> +	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
> +	struct intel_wd *intel_wd;
> +	struct intel_connector *intel_connector;
> +	struct intel_digital_connector_state *intel_conn_state;
> +	struct intel_encoder *encoder;
> +	int i;
> +
> +	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
> +		intel_wd = enc_to_intel_wd(encoder);
> +
> +		if (intel_wd->wd_crtc != intel_crtc)
> +			return;
> +
> +	}
> +
> +	for_each_new_connector_in_state(&state->base, connector,
> new_conn_state,
> +					i) {
> +		intel_conn_state =
> to_intel_digital_connector_state(new_conn_state);
> +		if (!intel_conn_state->job)
> +			continue;
> +		intel_connector = to_intel_connector(connector);
> +		intel_writeback_queue_job(&intel_connector->wb_conn,
> new_conn_state);
> +		drm_dbg_kms(&i915->drm, "queueing writeback job\n");
> +	}
> +}
> +
> +static void intel_find_writeback_connector(struct intel_atomic_state
> *state,
> +		struct intel_crtc *intel_crtc, struct intel_crtc_state
> *crtc_state) {
> +	struct drm_connector_state *new_conn_state;
> +	struct drm_connector *connector;
> +	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
> +	struct intel_wd *intel_wd;
> +	struct intel_encoder *encoder;
> +	int i;
> +
> +	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
> +		intel_wd = enc_to_intel_wd(encoder);
> +
> +		if (intel_wd->wd_crtc != intel_crtc)
> +			return;
> +
> +	}
> +
> +	for_each_new_connector_in_state(&state->base, connector,
> new_conn_state,
> +					i) {
> +		struct intel_connector *intel_connector;
> +
> +		intel_connector = to_intel_connector(connector);
> +		drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]: status:
> %s\n",
> +				connector->base.id, connector->name,
> +
> 	drm_get_connector_status_name(connector->status));
> +		encoder =
> intel_connector_primary_encoder(intel_connector);
> +		if (encoder->type == INTEL_OUTPUT_WD) {
> +			drm_dbg_kms(&i915->drm, "encoder
> intel_output_wd found\n");
> +			intel_wd_enable_capture(encoder, crtc_state,
> new_conn_state);
> +		}
> +	}
> +
> +}
> +
>  static void intel_encoders_pre_pll_enable(struct intel_atomic_state *state,
>  					  struct intel_crtc *crtc)
>  {
> @@ -1944,7 +2011,8 @@ static void hsw_crtc_enable(struct
> intel_atomic_state *state,
>  		bdw_set_pipemisc(new_crtc_state);
> 
>  	if (!intel_crtc_is_bigjoiner_slave(new_crtc_state) &&
> -	    !transcoder_is_dsi(cpu_transcoder))
> +	    !transcoder_is_dsi(cpu_transcoder) &&
> +	    !transcoder_is_wd(cpu_transcoder))
>  		hsw_configure_cpu_transcoder(new_crtc_state);
> 
>  	crtc->active = true;
> @@ -2632,6 +2700,9 @@ static void intel_connector_verify_state(struct
> intel_crtc_state *crtc_state,
>  	if (connector->get_hw_state(connector)) {
>  		struct intel_encoder *encoder =
> intel_attached_encoder(connector);
> 
> +		if (conn_state->connector->connector_type ==
> DRM_MODE_CONNECTOR_WRITEBACK)
> +			return;
> +
>  		I915_STATE_WARN(!crtc_state,
>  			 "connector enabled without attached crtc\n");
> 
> @@ -5233,6 +5304,7 @@ static const char * const output_type_str[] = {
>  	OUTPUT_TYPE(DSI),
>  	OUTPUT_TYPE(DDI),
>  	OUTPUT_TYPE(DP_MST),
> +	OUTPUT_TYPE(WD),
>  };
> 
>  #undef OUTPUT_TYPE
> @@ -8577,6 +8649,12 @@ static void intel_atomic_commit_tail(struct
> intel_atomic_state *state)
>  		}
>  	}
> 
> +	if (DISPLAY_VER(dev_priv) >= 12) {
> +		for_each_new_intel_crtc_in_state(state, crtc,
> new_crtc_state, i) {
> +			intel_wd_set_vblank_event(crtc, new_crtc_state);
> +		}
> +	}
> +
>  	intel_encoders_update_prepare(state);
> 
>  	intel_dbuf_pre_plane_update(state);
> @@ -8662,6 +8740,14 @@ static void intel_atomic_commit_tail(struct
> intel_atomic_state *state)
> 
>  	intel_sagv_post_plane_update(state);
> 
> +	if (DISPLAY_VER(dev_priv) >= 12) {
> +		intel_wd_prepare_out_fence(dev, &state->base);
> +		for_each_new_intel_crtc_in_state(state, crtc,
> new_crtc_state, i) {
> +			intel_queue_writeback_job(state, crtc,
> new_crtc_state);
> +			intel_find_writeback_connector(state, crtc,
> new_crtc_state);
> +		}
> +	}
> +
>  	drm_atomic_helper_commit_hw_done(&state->base);
> 
>  	if (state->modeset) {
> @@ -8966,6 +9052,7 @@ static void intel_setup_outputs(struct
> drm_i915_private *dev_priv)
>  		intel_ddi_init(dev_priv, PORT_TC1);
>  		intel_ddi_init(dev_priv, PORT_TC2);
>  	} else if (DISPLAY_VER(dev_priv) >= 12) {
> +		intel_wd_init(dev_priv, TRANSCODER_WD_0);
>  		intel_ddi_init(dev_priv, PORT_A);
>  		intel_ddi_init(dev_priv, PORT_B);
>  		intel_ddi_init(dev_priv, PORT_TC1);
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h
> b/drivers/gpu/drm/i915/display/intel_display.h
> index 8c93a5de8e07..27237d36a888 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -156,6 +156,11 @@ static inline bool transcoder_is_dsi(enum transcoder
> transcoder)
>  	return transcoder == TRANSCODER_DSI_A || transcoder ==
> TRANSCODER_DSI_C;  }
> 
> +static inline bool transcoder_is_wd(enum transcoder transcoder) {
> +	return transcoder == TRANSCODER_WD_0 || transcoder ==
> TRANSCODER_WD_1;
> +}
> +
>  /*
>   * Global legacy plane identifier. Valid only for primary/sprite
>   * planes on pre-g4x, and only for primary planes on g4x-bdw.
> @@ -467,6 +472,10 @@ enum hpd_pin {
>  	for_each_intel_encoder((dev), (intel_encoder)) \
>  		for_each_if(intel_encoder_can_psr(intel_encoder))
> 
> +#define for_each_intel_encoder_with_wd(dev, intel_encoder)	\
> +	for_each_intel_encoder(dev, intel_encoder)		\
> +		for_each_if(intel_encoder_is_wd(intel_encoder))
> +
>  #define for_each_intel_connector_iter(intel_connector, iter) \
>  	while ((intel_connector =
> to_intel_connector(drm_connector_list_iter_next(iter))))
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index dcb4ad43cf88..8522c348a73d 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1293,6 +1293,11 @@ struct intel_crtc {
>  	bool cpu_fifo_underrun_disabled;
>  	bool pch_fifo_underrun_disabled;
> 
> +	struct {
> +		struct drm_pending_vblank_event *e;
> +		atomic_t work_busy;
> +		wait_queue_head_t wd_wait;
> +	} wd;
>  	/* per-pipe watermark state */
>  	struct {
>  		/* watermarks currently being used  */ @@ -1420,6 +1425,7
> @@ struct cxsr_latency {  #define to_intel_crtc(x) container_of(x, struct
> intel_crtc, base)  #define to_intel_crtc_state(x) container_of(x, struct
> intel_crtc_state, uapi)  #define to_intel_connector(x) container_of(x, struct
> intel_connector, base)
> +#define to_intel_wb_connector(x) container_of(x, struct
> +intel_wb_connector, base)
>  #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
> #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer,
> base)  #define to_intel_plane(x) container_of(x, struct intel_plane, base)
> @@ -1851,6 +1857,13 @@ static inline bool intel_encoder_is_dp(struct
> intel_encoder *encoder)
>  	}
>  }
> 
> +static inline bool intel_encoder_is_wd(struct intel_encoder *encoder) {
> +	if (encoder->type == INTEL_OUTPUT_WD)
> +		return true;
> +	return false;
> +}
> +
>  static inline struct intel_lspcon *
>  enc_to_intel_lspcon(struct intel_encoder *encoder)  { diff --git
> a/drivers/gpu/drm/i915/display/intel_dpll.c
> b/drivers/gpu/drm/i915/display/intel_dpll.c
> index 95b9d327ed4d..dfea17f5f99d 100644
> --- a/drivers/gpu/drm/i915/display/intel_dpll.c
> +++ b/drivers/gpu/drm/i915/display/intel_dpll.c
> @@ -939,6 +939,9 @@ static int hsw_crtc_compute_clock(struct
> intel_crtc_state *crtc_state)
>  	if (IS_DG2(dev_priv))
>  		return intel_mpllb_calc_state(crtc_state, encoder);
> 
> +	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_WD))
> +		return 0;
> +
>  	if (DISPLAY_VER(dev_priv) < 11 &&
>  	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
>  		return 0;
> diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c
> b/drivers/gpu/drm/i915/display/intel_opregion.c
> index f31e8c3f8ce0..b7a0ac9bad05 100644
> --- a/drivers/gpu/drm/i915/display/intel_opregion.c
> +++ b/drivers/gpu/drm/i915/display/intel_opregion.c
> @@ -370,6 +370,9 @@ int intel_opregion_notify_encoder(struct
> intel_encoder *intel_encoder,
>  	if (ret)
>  		return ret;
> 
> +	if (intel_encoder->type == INTEL_OUTPUT_WD)
> +		return 0;
> +
>  	if (intel_encoder->type == INTEL_OUTPUT_DSI)
>  		port = 0;
>  	else
> diff --git a/drivers/gpu/drm/i915/display/intel_wd.c
> b/drivers/gpu/drm/i915/display/intel_wd.c
> new file mode 100644
> index 000000000000..a6c9350c3986
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_wd.c
> @@ -0,0 +1,978 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright © 2021 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a
> + * copy of this software and associated documentation files (the
> +"Software"),
> + * to deal in the Software without restriction, including without
> +limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> +sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom
> +the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> +next
> + * paragraph) shall be included in all copies or substantial portions
> +of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO
> EVENT
> +SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> DAMAGES OR
> +OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> +ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> OTHER
> +DEALINGS
> + * IN THE SOFTWARE.
> + *
> + * Authors:
> + *	Suraj Kandpal <suraj.kandpal@intel.com>
> + *	Arun Murthy <arun.r.murthy@intel.com>
> + *
> + */
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_fourcc.h>
> +
> +#include "intel_atomic.h"
> +#include "intel_connector.h"
> +#include "intel_wd.h"
> +#include "intel_fb_pin.h"
> +#include "intel_de.h"
> +#include "intel_wb_connector.h"
> +
> +enum {
> +	WD_CAPTURE_4_PIX,
> +	WD_CAPTURE_2_PIX,
> +} wd_capture_format;
> +
> +static struct intel_writeback_job
> +*intel_get_writeback_job_from_queue(struct intel_wd *intel_wd) {
> +	struct intel_writeback_job *job;
> +	struct drm_i915_private *i915 = to_i915(intel_wd->base.base.dev);
> +	struct intel_writeback_connector *wb_conn =
> +		&intel_wd->attached_connector->wb_conn;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&wb_conn->job_lock, flags);
> +	job = list_first_entry_or_null(&wb_conn->job_queue,
> +			struct intel_writeback_job,
> +			list_entry);
> +	spin_unlock_irqrestore(&wb_conn->job_lock, flags);
> +	if (job == NULL) {
> +		drm_dbg_kms(&i915->drm, "job queue is empty\n");
> +		return NULL;
> +	}
> +
> +	return job;
> +}
> +
> +/*Check with Spec*/
> +static const u32 wb_fmts[] = {
> +		DRM_FORMAT_YUV444,
> +		DRM_FORMAT_XYUV8888,
> +		DRM_FORMAT_XBGR8888,
> +		DRM_FORMAT_XRGB8888,
> +		DRM_FORMAT_Y410,
> +		DRM_FORMAT_YUV422,
> +		DRM_FORMAT_XBGR2101010,
> +		DRM_FORMAT_RGB565,
> +
> +};
> +
> +static int intel_wd_get_format(int pixel_format) {
> +	int wd_format = -EINVAL;
> +
> +	switch (pixel_format) {
> +	case DRM_FORMAT_XBGR8888:
> +	case DRM_FORMAT_XRGB8888:
> +	case DRM_FORMAT_XBGR2101010:
> +	case DRM_FORMAT_XYUV8888:
> +	case DRM_FORMAT_YUV444:
> +		wd_format = WD_CAPTURE_4_PIX;
> +		break;
> +	case DRM_FORMAT_YUV422:
> +	case DRM_FORMAT_RGB565:
> +		wd_format = WD_CAPTURE_2_PIX;
> +		break;
> +	default:
> +		DRM_ERROR("unsupported pixel format %x!\n",
> +			pixel_format);
> +	}
> +
> +	return wd_format;
> +}
> +
> +static int intel_wd_verify_pix_format(int format) {
> +	const struct drm_format_info *info = drm_format_info(format);
> +	int pix_format = info->format;
> +	int i = 0;
> +
> +	for (i = 0; i < ARRAY_SIZE(wb_fmts); i++)
> +		if (pix_format == wb_fmts[i])
> +			return 0;
> +
> +	return 1;
> +}
> +
> +static u32 intel_wd_get_stride(const struct intel_crtc_state *crtc_state,
> +			int format)
> +{
> +	const struct drm_format_info *info = drm_format_info(format);
> +	int wd_format;
> +	int hactive, pixel_size;
> +
> +	wd_format = intel_wd_get_format(info->format);
> +
> +	switch (wd_format) {
> +	case WD_CAPTURE_4_PIX:
> +		pixel_size = 4;
> +		break;
> +	case WD_CAPTURE_2_PIX:
> +		pixel_size = 2;
> +		break;
> +	default:
> +		pixel_size = 1;
> +		break;
> +	}
> +
> +	hactive = crtc_state->hw.adjusted_mode.crtc_hdisplay;
> +
> +	return DIV_ROUND_UP(hactive * pixel_size, 64); }
> +
> +static int intel_wd_pin_fb(struct intel_wd *intel_wd,
> +			struct drm_framebuffer *fb)
> +{
> +	const struct i915_ggtt_view view = {
> +		.type = I915_GGTT_VIEW_NORMAL,
> +		};
> +	struct i915_vma *vma;
> +
> +	vma = intel_pin_and_fence_fb_obj(fb, false, &view, false,
> +			&intel_wd->flags);
> +
> +	if (IS_ERR(vma))
> +		return PTR_ERR(vma);
> +
> +	intel_wd->vma = vma;
> +	return 0;
> +}
> +
> +static void intel_configure_slicing_strategy(struct drm_i915_private *i915,
> +		struct intel_wd *intel_wd, u32 *tmp)
> +{
> +	*tmp &= ~WD_STRAT_MASK;
> +	if (intel_wd->slicing_strategy == 1)
> +		*tmp |= WD_SLICING_STRAT_1_1;
> +	else if (intel_wd->slicing_strategy == 2)
> +		*tmp |= WD_SLICING_STRAT_2_1;
> +	else if (intel_wd->slicing_strategy == 3)
> +		*tmp |= WD_SLICING_STRAT_4_1;
> +	else if (intel_wd->slicing_strategy == 4)
> +		*tmp |= WD_SLICING_STRAT_8_1;
> +
> +	intel_de_write(i915, WD_STREAMCAP_CTL(intel_wd->trans),
> +			*tmp);
> +
> +}
> +
> +static enum drm_mode_status
> +intel_wd_mode_valid(struct drm_connector *connector,
> +		struct drm_display_mode *mode)
> +{
> +	return MODE_OK;
> +}
> +
> +static int intel_wd_get_modes(struct drm_connector *connector) {
> +	return 0;
> +}
> +
> +static void intel_wd_get_config(struct intel_encoder *encoder,
> +		struct intel_crtc_state *pipe_config) {
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +	struct intel_crtc *intel_crtc =
> +		to_intel_crtc(pipe_config->uapi.crtc);
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +	if (intel_crtc) {
> +		memcpy(pipe_config, intel_crtc->config,
> +			sizeof(*pipe_config));
> +		pipe_config->output_types |= BIT(INTEL_OUTPUT_WD);
> +		drm_dbg_kms(&i915->drm, "crtc found\n");
> +	}
> +
> +}
> +
> +static int intel_wd_compute_config(struct intel_encoder *encoder,
> +			struct intel_crtc_state *pipe_config,
> +			struct drm_connector_state *conn_state) {
> +	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +	struct intel_digital_connector_state *intel_conn_state =
> +		to_intel_digital_connector_state(conn_state);
> +	struct intel_writeback_job *job;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +	job = intel_get_writeback_job_from_queue(intel_wd);
> +	if (job || intel_conn_state->job) {
> +		intel_wd->wd_crtc = to_intel_crtc(pipe_config->uapi.crtc);
> +		return 0;
> +	}
> +	drm_dbg_kms(&i915->drm, "No writebackjob in queue\n");
> +
> +	return 0;
> +}
> +
> +static void intel_wd_get_power_domains(struct intel_encoder *encoder,
> +			struct intel_crtc_state *crtc_state) {
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
> +	intel_wakeref_t wakeref;
> +
> +	wakeref = intel_display_power_get(i915,
> +				encoder->power_domain);
> +
> +	intel_wd->io_wakeref[0] = wakeref;
> +	drm_dbg_kms(&i915->drm, "\n");
> +}
> +
> +static bool intel_wd_get_hw_state(struct intel_encoder *encoder,
> +		enum pipe *pipe)
> +{
> +	bool ret = false;
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
> +	struct intel_crtc *wd_crtc = intel_wd->wd_crtc;
> +	intel_wakeref_t wakeref;
> +	u32 tmp;
> +
> +	if (wd_crtc)
> +		return false;
> +
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +				encoder->power_domain);
> +	drm_dbg_kms(encoder->base.dev, "power enabled : %s\n",
> +			!wakeref ? "false":"true");
> +
> +	if (!wakeref)
> +		return false;
> +
> +	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
> +	ret = tmp & WD_TRANS_ACTIVE;
> +	drm_dbg_kms(encoder->base.dev, "trancoder enabled: %s\n",
> +			ret ? "true":"false");
> +	if (ret) {
> +		*pipe = wd_crtc->pipe;
> +		drm_dbg_kms(encoder->base.dev, "pipe selected is %d\n",
> +			wd_crtc->pipe);
> +	}
> +	return true;
> +}
> +
> +static int intel_wd_encoder_atomic_check(struct drm_encoder *encoder,
> +				    struct drm_crtc_state *crtc_st,
> +				    struct drm_connector_state *conn_st) {
> +	/* Check for the format and buffers and property validity */
> +	struct drm_framebuffer *fb;
> +	struct intel_digital_connector_state *intel_conn_state =
> +		to_intel_digital_connector_state(conn_st);
> +	struct intel_writeback_job *job = intel_conn_state->job;
> +	struct drm_i915_private *i915 = to_i915(encoder->dev);
> +	const struct drm_display_mode *mode = &crtc_st->mode;
> +	int ret;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +
> +	if (!job) {
> +		drm_dbg_kms(&i915->drm, "No writeback job created
> returning\n");
> +		return -EINVAL;
> +	}
> +
> +	fb = job->fb;
> +
> +	if (!fb) {
> +		drm_dbg_kms(&i915->drm, "Invalid framebuffer\n");
> +		return -EINVAL;
> +	}
> +
> +	if (fb->width != mode->hdisplay || fb->height != mode->vdisplay) {
> +		drm_dbg_kms(&i915->drm, "Invalid framebuffer size
> %ux%u\n",
> +				fb->width, fb->height);
> +		return -EINVAL;
> +	}
> +
> +	ret = intel_wd_verify_pix_format(fb->format->format);
> +
> +	if (ret) {
> +		drm_dbg_kms(&i915->drm, "Unsupported framebuffer
> format %08x\n",
> +				fb->format->format);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +
> +static const struct drm_encoder_helper_funcs wd_encoder_helper_funcs
> = {
> +	.atomic_check = intel_wd_encoder_atomic_check, };
> +
> +static void intel_wd_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_dbg_kms(connector->dev, "\n");
> +	drm_connector_cleanup(connector);
> +	kfree(connector);
> +}
> +
> +static enum drm_connector_status
> +intel_wb_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	drm_dbg_kms(connector->dev, "Writeback connector
> connected\n");
> +	return connector_status_connected;
> +}
> +
> +static int intel_atomic_set_writeback_fb_for_connector(
> +		struct drm_connector_state *conn_state,
> +		struct drm_framebuffer *fb)
> +{
> +	int ret;
> +	struct drm_connector *conn = conn_state->connector;
> +
> +	ret = intel_writeback_set_fb(conn_state, fb);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (fb)
> +		drm_dbg_atomic(conn->dev,
> +			"Set [FB:%d] for connector state %p\n",
> +			fb->base.id, conn_state);
> +	else
> +		drm_dbg_atomic(conn->dev,
> +			"Set [NOFB] for connector state %p\n",
> +			conn_state);
> +
> +	return 0;
> +}
> +
> +static int set_out_fence_for_connector(struct drm_atomic_state *state,
> +					struct drm_connector *connector,
> +					s32 __user *fence_ptr)
> +{
> +	unsigned int index = drm_connector_index(connector);
> +
> +	if (!fence_ptr)
> +		return 0;
> +
> +	if (put_user(-1, fence_ptr))
> +		return -EFAULT;
> +
> +	state->connectors[index].out_fence_ptr = fence_ptr;
> +
> +	return 0;
> +}
> +
> +static struct drm_mode_object *__intel_object_find(struct drm_device
> *dev,
> +					       uint32_t id, uint32_t type) {
> +	struct drm_mode_object *obj = NULL;
> +
> +	mutex_lock(&dev->mode_config.idr_mutex);
> +	obj = idr_find(&dev->mode_config.object_idr, id);
> +	if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
> +		obj = NULL;
> +	if (obj && obj->id != id)
> +		obj = NULL;
> +	if (obj && obj->free_cb) {
> +		if (!kref_get_unless_zero(&obj->refcount))
> +			obj = NULL;
> +	}
> +	mutex_unlock(&dev->mode_config.idr_mutex);
> +
> +	return obj;
> +}
> +
> +static struct drm_framebuffer *intel_wb_framebuffer_lookup(struct
> drm_device *dev,
> +					       uint32_t id)
> +{
> +	struct drm_mode_object *obj;
> +	struct drm_framebuffer *fb = NULL;
> +
> +	obj = __intel_object_find(dev, id, DRM_MODE_OBJECT_FB);
> +	if (obj)
> +		fb = obj_to_fb(obj);
> +	return fb;
> +}
> +
> +static s32 *intel_get_out_fence_for_connector(struct drm_atomic_state
> *state,
> +					       struct drm_connector
> *connector) {
> +	unsigned int index = drm_connector_index(connector);
> +	s32 __user *fence_ptr;
> +
> +	fence_ptr = state->connectors[index].out_fence_ptr;
> +	state->connectors[index].out_fence_ptr = NULL;
> +
> +	return fence_ptr;
> +}
> +
> +static int intel_setup_out_fence(struct intel_out_fence_state
> *fence_state,
> +			   struct dma_fence *fence)
> +{
> +
> +	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
> +	if (fence_state->fd < 0)
> +		return fence_state->fd;
> +
> +	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
> +		return -EFAULT;
> +
> +	fence_state->sync_file = sync_file_create(fence);
> +	if (!fence_state->sync_file)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
> +int intel_wd_prepare_out_fence(struct drm_device *dev,
> +				struct drm_atomic_state *state)
> +{
> +	struct drm_connector *conn;
> +	struct drm_connector_state *conn_state;
> +	int i, ret;
> +
> +	drm_dbg_kms(dev, "\n");
> +
> +	for_each_new_connector_in_state(state, conn, conn_state, i) {
> +		struct intel_writeback_connector *wb_conn;
> +		struct intel_connector *intel_conn =
> +			to_intel_connector(conn);
> +		struct dma_fence *fence;
> +		struct intel_wd *intel_wd;
> +		struct intel_digital_connector_state *intel_conn_state =
> +			to_intel_digital_connector_state(conn_state);
> +		s32 __user *fence_ptr;
> +
> +		if (conn->connector_type !=
> DRM_MODE_CONNECTOR_WRITEBACK)
> +			continue;
> +
> +		if (!intel_conn_state->job)
> +			continue;
> +
> +		intel_wd = enc_to_intel_wd(intel_conn->encoder);
> +		fence_ptr = intel_get_out_fence_for_connector(state,
> conn);
> +		if (!fence_ptr)
> +			continue;
> +
> +		intel_wd->fence_state->out_fence_ptr = fence_ptr;
> +
> +		wb_conn = &intel_conn->wb_conn;
> +		fence = intel_writeback_get_out_fence(wb_conn);
> +		if (!fence)
> +			return -ENOMEM;
> +
> +		ret = intel_setup_out_fence(intel_wd->fence_state, fence);
> +		if (ret) {
> +			dma_fence_put(fence);
> +			return ret;
> +		}
> +
> +		intel_conn_state->job->out_fence = fence;
> +	}
> +
> +	return 0;
> +}
> +
> +void intel_wd_complete_signaling(struct intel_wd *intel_wd) {
> +	struct intel_out_fence_state *fence_state;
> +
> +	fence_state = intel_wd->fence_state;
> +	fd_install(fence_state->fd,
> +		fence_state->sync_file->file);
> +
> +}
> +
> +static int intel_set_writeback_property(struct drm_connector *connector,
> +	struct drm_connector_state *state, struct drm_property *property,
> +	uint64_t val)
> +{
> +	struct drm_device *dev = connector->dev;
> +	struct drm_i915_private *i915 = to_i915(dev);
> +
> +	if (property == i915->wb_fb_id_property) {
> +		struct drm_framebuffer *fb;
> +		int ret;
> +
> +		fb = intel_wb_framebuffer_lookup(dev, val);
> +		ret = intel_atomic_set_writeback_fb_for_connector(state,
> fb);
> +		if (fb)
> +			drm_framebuffer_put(fb);
> +		return ret;
> +	} else if (property == i915->wb_out_fence_ptr_property) {
> +		s32 __user *fence_ptr = u64_to_user_ptr(val);
> +
> +		return set_out_fence_for_connector(state->state,
> connector,
> +						fence_ptr);
> +	} else {
> +		drm_dbg_atomic(connector->dev,
> +			"[CONNECTOR:%d:%s] unknown property
> [PROP:%d:%s]]\n",
> +			connector->base.id, connector->name,
> +			property->base.id, property->name);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +
> +}
> +
> +static int intel_get_writeback_property(struct drm_connector *connector,
> +	const struct drm_connector_state *state, struct drm_property
> *property,
> +	uint64_t *val)
> +{
> +	struct drm_device *dev = connector->dev;
> +	struct drm_i915_private *i915 = to_i915(dev);
> +
> +	if (property == i915->wb_fb_id_property)
> +		*val = 0;
> +	else if (property == i915->wb_out_fence_ptr_property)
> +		*val = 0;
> +	else {
> +		drm_dbg_atomic(&i915->drm,
> +				"Unknown property [PROP:%d:%s]\n",
> +				property->base.id, property->name);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct drm_connector_funcs wd_connector_funcs = {
> +	.detect = intel_wb_connector_detect,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.destroy = intel_wd_connector_destroy,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.atomic_destroy_state =
> drm_atomic_helper_connector_destroy_state,
> +	.atomic_set_property = intel_set_writeback_property,
> +	.atomic_get_property = intel_get_writeback_property,
> +	.atomic_duplicate_state = intel_digital_connector_duplicate_state,
> +};
> +
> +static const struct drm_connector_helper_funcs
> wd_connector_helper_funcs = {
> +	.get_modes = intel_wd_get_modes,
> +	.mode_valid = intel_wd_mode_valid,
> +};
> +
> +static bool intel_fastset_dis(struct intel_encoder *encoder,
> +		struct intel_crtc_state *pipe_config) {
> +	pipe_config->uapi.mode_changed = true;
> +	drm_dbg_kms(encoder->base.dev, "\n");
> +	return false;
> +}
> +
> +void intel_wd_init(struct drm_i915_private *i915, enum transcoder
> +trans) {
> +	struct intel_wd *intel_wd;
> +	struct intel_encoder *encoder;
> +	struct intel_out_fence_state *fence_state;
> +	struct intel_connector *intel_connector;
> +	struct intel_writeback_connector *wb_conn;
> +	int n_formats = ARRAY_SIZE(wb_fmts);
> +	int err;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +	intel_wd = kzalloc(sizeof(*intel_wd), GFP_KERNEL);
> +	if (!intel_wd)
> +		return;
> +
> +	intel_connector = intel_connector_alloc();
> +	if (!intel_connector) {
> +		kfree(intel_wd);
> +		return;
> +	}
> +
> +	fence_state = kzalloc(sizeof(*fence_state), GFP_KERNEL);
> +	if (!intel_wd) {
> +		kfree(intel_wd);
> +		kfree(intel_connector);
> +		return;
> +	}
> +
> +	wb_conn = &intel_connector->wb_conn;
> +	wb_conn->base = &intel_connector->base;
> +	wb_conn->encoder = &intel_wd->base.base;
> +
> +	encoder = &intel_wd->base;
> +	intel_wd->attached_connector = intel_connector;
> +	intel_wd->fence_state = fence_state;
> +	intel_wd->trans = trans;
> +	intel_wd->triggered_cap_mode = 1;
> +	intel_wd->frame_num = 1;
> +	intel_wd->slicing_strategy = 1;
> +	encoder->get_config = intel_wd_get_config;
> +	encoder->compute_config = intel_wd_compute_config;
> +	encoder->get_hw_state = intel_wd_get_hw_state;
> +	encoder->type = INTEL_OUTPUT_WD;
> +	encoder->cloneable = 0;
> +	encoder->pipe_mask = ~0;
> +	encoder->power_domain = POWER_DOMAIN_TRANSCODER_B;
> +	encoder->get_power_domains = intel_wd_get_power_domains;
> +	encoder->initial_fastset_check = intel_fastset_dis;
> +	intel_connector->get_hw_state =
> +		intel_connector_get_hw_state;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +	err = intel_writeback_connector_init(&i915->drm, wb_conn,
> +		&wd_connector_funcs,
> +		&wd_encoder_helper_funcs,
> +		wb_fmts, n_formats);
> +
> +	if (err != 0) {
> +		drm_dbg_kms(&i915->drm,
> +		"intel_writeback_connector_init: Failed: %d\n",
> +			err);
> +		goto cleanup;
> +	}
> +
> +	drm_connector_helper_add(wb_conn->base,
> &wd_connector_helper_funcs);
> +	intel_connector_attach_encoder(intel_connector, encoder);
> +	wb_conn->base->status = connector_status_connected;
> +	return;
> +
> +cleanup:
> +	kfree(intel_wd);
> +	intel_connector_free(intel_connector);
> +}
> +
> +static void intel_wd_writeback_complete(struct intel_wd *intel_wd,
> +	struct intel_writeback_job *job, int status) {
> +	struct intel_writeback_connector *wb_conn =
> +		&intel_wd->attached_connector->wb_conn;
> +	intel_writeback_signal_completion(wb_conn, status);
> +	intel_wd_complete_signaling(intel_wd);
> +}
> +
> +static int intel_wd_setup_transcoder(struct intel_wd *intel_wd,
> +		struct intel_crtc_state *pipe_config,
> +		struct intel_writeback_job *job)
> +{
> +	struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
> +	enum pipe pipe = intel_crtc->pipe;
> +	struct drm_framebuffer *fb;
> +	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
> +	struct drm_gem_object *wd_fb_obj;
> +	int ret;
> +	u32 stride, tmp;
> +	u16 hactive, vactive;
> +
> +	fb = job->fb;
> +	wd_fb_obj = fb->obj[0];
> +	if (!wd_fb_obj) {
> +		drm_dbg_kms(&dev_priv->drm, "No framebuffer gem
> object created\n");
> +		return -1;
> +	}
> +	ret = intel_wd_pin_fb(intel_wd, fb);
> +	drm_WARN_ON(&dev_priv->drm, ret != 0);
> +
> +	/*Write stride and surface registers in that particular order*/
> +	stride = intel_wd_get_stride(pipe_config, fb->format->format);
> +
> +	tmp = intel_de_read(dev_priv, WD_STRIDE(intel_wd->trans));
> +	tmp &= ~WD_STRIDE_MASK;
> +	tmp |= (stride << WD_STRIDE_SHIFT);
> +
> +	intel_de_write(dev_priv, WD_STRIDE(intel_wd->trans), tmp);
> +
> +	tmp = intel_de_read(dev_priv, WD_SURF(intel_wd->trans));
> +	drm_dbg_kms(&dev_priv->drm, "%d is the surface address\n",
> tmp);
> +
> +	intel_de_write(dev_priv, WD_SURF(intel_wd->trans),
> +			i915_ggtt_offset(intel_wd->vma));
> +
> +	tmp = intel_de_read_fw(dev_priv, WD_IIR(intel_wd->trans));
> +	intel_de_write_fw(dev_priv, WD_IIR(intel_wd->trans), tmp);
> +
> +	tmp =
> ~(WD_GTT_FAULT_INT|WD_WRITE_COMPLETE_INT|WD_FRAME_COMPLET
> E_INT|
> +
> 	WD_VBLANK_INT|WD_OVERRUN_INT|WD_CAPTURING_INT);
> +	intel_de_write_fw(dev_priv, WD_IMR(intel_wd->trans), tmp);
> +
> +	if (intel_wd->stream_cap) {
> +		tmp = intel_de_read(dev_priv,
> +				WD_STREAMCAP_CTL(intel_wd->trans));
> +		tmp |= WD_STREAM_CAP_MODE_EN;
> +		intel_configure_slicing_strategy(dev_priv, intel_wd, &tmp);
> +	}
> +
> +	hactive = pipe_config->uapi.mode.hdisplay;
> +	vactive = pipe_config->uapi.mode.vdisplay;
> +
> +	drm_dbg_kms(&dev_priv->drm, "hactive : %d, vactive: %d\n",
> hactive,
> +vactive);
> +
> +	tmp = intel_de_read(dev_priv, HTOTAL(intel_wd->trans));
> +	drm_dbg_kms(&dev_priv->drm, "hactive_reg : %d\n", tmp);
> +	tmp = intel_de_read(dev_priv, VTOTAL(intel_wd->trans));
> +	drm_dbg_kms(&dev_priv->drm, "vactive_reg : %d\n", tmp);
> +	/* minimum hactive as per bspec: 64 pixels*/
> +	if (hactive < 64)
> +		drm_err(&dev_priv->drm, "hactive is less then 64 pixels\n");
> +
> +	intel_de_write(dev_priv, HTOTAL(intel_wd->trans), hactive - 1);
> +	intel_de_write(dev_priv, VTOTAL(intel_wd->trans), vactive - 1);
> +
> +	tmp = intel_de_read(dev_priv, WD_TRANS_FUNC_CTL(intel_wd-
> >trans));
> +	/* select pixel format */
> +	tmp &= ~WD_PIX_FMT_MASK;
> +
> +	switch (fb->format->format) {
> +	default:
> +	fallthrough;
> +	case DRM_FORMAT_YUYV:
> +		tmp |= WD_PIX_FMT_YUYV;
> +		break;
> +	case DRM_FORMAT_XYUV8888:
> +		tmp |= WD_PIX_FMT_XYUV8888;
> +		break;
> +	case DRM_FORMAT_XBGR8888:
> +		tmp |= WD_PIX_FMT_XBGR8888;
> +		break;
> +	case DRM_FORMAT_Y410:
> +		tmp |= WD_PIX_FMT_Y410;
> +		break;
> +	case DRM_FORMAT_YUV422:
> +		tmp |= WD_PIX_FMT_YUV422;
> +		break;
> +	case DRM_FORMAT_XBGR2101010:
> +		tmp |= WD_PIX_FMT_XBGR2101010;
> +		break;
> +	case DRM_FORMAT_RGB565:
> +		tmp |= WD_PIX_FMT_RGB565;
> +		break;
> +	}
> +
> +	if (intel_wd->triggered_cap_mode)
> +		tmp |= WD_TRIGGERED_CAP_MODE_ENABLE;
> +
> +	if (intel_wd->stream_cap)
> +		tmp |= WD_CTL_POINTER_DTDH;
> +
> +	/*select input pipe*/
> +	tmp &= ~WD_INPUT_SELECT_MASK;
> +	drm_dbg_kms(&dev_priv->drm, "Selected pipe is %d\n", pipe);
> +	switch (pipe) {
> +	default:
> +		fallthrough;
> +	case PIPE_A:
> +		tmp |= WD_INPUT_PIPE_A;
> +		break;
> +	case PIPE_B:
> +		tmp |= WD_INPUT_PIPE_B;
> +		break;
> +	case PIPE_C:
> +		tmp |= WD_INPUT_PIPE_C;
> +		break;
> +	case PIPE_D:
> +		tmp |= WD_INPUT_PIPE_D;
> +		break;
> +	}
> +
> +	/* enable DDI buffer */
> +	if (!(tmp & TRANS_WD_FUNC_ENABLE))
> +		tmp |= TRANS_WD_FUNC_ENABLE;
> +
> +	intel_de_write(dev_priv, WD_TRANS_FUNC_CTL(intel_wd->trans),
> tmp);
> +
> +	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
> +	ret = tmp & WD_TRANS_ACTIVE;
> +	drm_dbg_kms(&dev_priv->drm, "Trancoder enabled: %s\n", ret ?
> +"true":"false");
> +
> +	if (!ret) {
> +		/*enable the transcoder	*/
> +		tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
> +		tmp |= WD_TRANS_ENABLE;
> +		intel_de_write(dev_priv, PIPECONF(intel_wd->trans), tmp);
> +
> +		/* wait for transcoder to be enabled */
> +		if (intel_de_wait_for_set(dev_priv, PIPECONF(intel_wd-
> >trans),
> +				WD_TRANS_ACTIVE, 10))
> +			drm_err(&dev_priv->drm, "WD transcoder not
> enabled\n");
> +	}
> +
> +	return 0;
> +}
> +
> +static void intel_wd_disable_capture(struct intel_wd *intel_wd) {
> +	struct drm_i915_private *dev_priv = to_i915(intel_wd-
> >base.base.dev);
> +	u32 tmp;
> +
> +	intel_de_write_fw(dev_priv, WD_IMR(intel_wd->trans), 0xFF);
> +	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
> +	tmp &= WD_TRANS_DISABLE;
> +	intel_de_write(dev_priv, PIPECONF(intel_wd->trans), tmp);
> +
> +	drm_dbg_kms(&dev_priv->drm, "WD Trans_Conf value after disable
> = 0x%08x\n",
> +		intel_de_read(dev_priv, PIPECONF(intel_wd->trans)));
> +	tmp = intel_de_read(dev_priv, WD_TRANS_FUNC_CTL(intel_wd-
> >trans));
> +	tmp |= ~TRANS_WD_FUNC_ENABLE;
> +}
> +
> +static int intel_wd_capture(struct intel_wd *intel_wd,
> +		struct intel_crtc_state *pipe_config,
> +		struct intel_writeback_job *job)
> +{
> +	u32 tmp;
> +	struct drm_i915_private *i915 = to_i915(intel_wd->base.base.dev);
> +	int ret = 0, status = 0;
> +	struct intel_crtc *wd_crtc = intel_wd->wd_crtc;
> +	unsigned long flags;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +
> +	if (!job->out_fence)
> +		drm_dbg_kms(&i915->drm, "Not able to get out_fence for
> job\n");
> +
> +	ret = intel_wd_setup_transcoder(intel_wd, pipe_config, job);
> +
> +	if (ret < 0) {
> +		drm_dbg_kms(&i915->drm,
> +		"wd transcoder setup not completed aborting capture\n");
> +		return -1;
> +	}
> +
> +	if (wd_crtc == NULL) {
> +		DRM_ERROR("CRTC not attached\n");
> +		return -1;
> +	}
> +
> +	tmp = intel_de_read_fw(i915,
> +			WD_TRANS_FUNC_CTL(intel_wd->trans));
> +	tmp |= START_TRIGGER_FRAME;
> +	tmp &= ~WD_FRAME_NUMBER_MASK;
> +	tmp |= intel_wd->frame_num;
> +	intel_de_write_fw(i915,
> +			WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);
> +
> +	if (!intel_de_wait_for_set(i915, WD_IIR(intel_wd->trans),
> +				WD_FRAME_COMPLETE_INT, 100)){
> +		drm_dbg_kms(&i915->drm, "frame captured\n");
> +		tmp = intel_de_read(i915, WD_IIR(intel_wd->trans));
> +		drm_dbg_kms(&i915->drm, "iir value : %d\n", tmp);
> +		status = 0;
> +	} else {
> +		drm_dbg_kms(&i915->drm, "frame not captured triggering
> stop frame\n");
> +		tmp = intel_de_read(i915,
> +				WD_TRANS_FUNC_CTL(intel_wd->trans));
> +		tmp |= STOP_TRIGGER_FRAME;
> +		intel_de_write(i915,
> +				WD_TRANS_FUNC_CTL(intel_wd->trans),
> tmp);
> +		status = -1;
> +	}
> +
> +	intel_de_write(i915, WD_IIR(intel_wd->trans), tmp);
> +	intel_wd_writeback_complete(intel_wd, job, status);
> +	if (intel_get_writeback_job_from_queue(intel_wd) == NULL)
> +		intel_wd_disable_capture(intel_wd);
> +	if (wd_crtc->wd.e) {
> +		spin_lock_irqsave(&i915->drm.event_lock, flags);
> +		drm_dbg_kms(&i915->drm, "send %p\n", wd_crtc->wd.e);
> +		drm_crtc_send_vblank_event(&wd_crtc->base,
> +					wd_crtc->wd.e);
> +		spin_unlock_irqrestore(&i915->drm.event_lock, flags);
> +		wd_crtc->wd.e = NULL;
> +	} else {
> +		DRM_ERROR("Event NULL! %p, %p\n", &i915->drm,
> +			wd_crtc);
> +	}
> +	return 0;
> +
> +}
> +
> +void intel_wd_enable_capture(struct intel_encoder *encoder,
> +		struct intel_crtc_state *pipe_config,
> +		struct drm_connector_state *conn_state) {
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
> +	struct intel_writeback_job *job;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +
> +	job = intel_get_writeback_job_from_queue(intel_wd);
> +	if (job == NULL) {
> +		drm_dbg_kms(&i915->drm,
> +			"job queue is empty not capturing any frame\n");
> +		return;
> +	}
> +
> +	intel_wd_capture(intel_wd, pipe_config, job);
> +	intel_wd->frame_num += 1;
> +
> +}
> +
> +void intel_wd_set_vblank_event(struct intel_crtc *intel_crtc,
> +			struct intel_crtc_state *intel_crtc_state) {
> +	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
> +	struct drm_crtc_state *state = &intel_crtc_state->uapi;
> +	struct intel_encoder *encoder;
> +	struct intel_wd *intel_wd;
> +
> +	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
> +		intel_wd = enc_to_intel_wd(encoder);
> +
> +		if (!intel_wd->wd_crtc) {
> +			drm_dbg_kms(&i915->drm, "wd crtc not found\n");
> +			return;
> +		}
> +	}
> +
> +	if (intel_crtc == intel_wd->wd_crtc) {
> +		intel_crtc->wd.e = state->event;
> +		state->event = NULL;
> +		if (intel_crtc->wd.e)
> +			drm_dbg_kms(&i915->drm, "WD event:%p\n",
> +				intel_crtc->wd.e);
> +		else
> +			drm_dbg_kms(&i915->drm, "WD no event\n");
> +	}
> +}
> +
> +void intel_wd_handle_isr(struct drm_i915_private *i915) {
> +	u32 iir_value = 0;
> +	struct intel_encoder *encoder;
> +	struct intel_wd *intel_wd;
> +
> +	iir_value = intel_de_read(i915, WD_IIR(TRANSCODER_WD_0));
> +	drm_dbg_kms(&i915->drm, "\n");
> +
> +	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
> +		intel_wd = enc_to_intel_wd(encoder);
> +
> +		if (!intel_wd->wd_crtc) {
> +			DRM_ERROR("NO CRTC attached with WD\n");
> +			goto clear_iir;
> +		}
> +	}
> +
> +	if (iir_value & WD_VBLANK_INT)
> +		drm_dbg_kms(&i915->drm, "vblank interrupt for wd
> transcoder\n");
> +	if (iir_value & WD_WRITE_COMPLETE_INT)
> +		drm_dbg_kms(&i915->drm,
> +		"wd write complete interrupt encountered\n");
> +	else
> +		DRM_INFO("iir: %x\n", iir_value);
> +	if (iir_value & WD_FRAME_COMPLETE_INT) {
> +		drm_dbg_kms(&i915->drm,
> +			"frame complete interrupt for wd transcoder\n");
> +		return;
> +	}
> +clear_iir:
> +	intel_de_write(i915, WD_IIR(TRANSCODER_WD_0), iir_value); }
> diff --git a/drivers/gpu/drm/i915/display/intel_wd.h
> b/drivers/gpu/drm/i915/display/intel_wd.h
> new file mode 100644
> index 000000000000..2309afa23bb8
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_wd.h
> @@ -0,0 +1,82 @@
> +/* SPDX-License-Identifier: GPL-2.0
> + * Copyright © 2021 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a
> + * copy of this software and associated documentation files (the
> +"Software"),
> + * to deal in the Software without restriction, including without
> +limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> +sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom
> +the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> +next
> + * paragraph) shall be included in all copies or substantial portions
> +of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO
> EVENT
> +SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> DAMAGES OR
> +OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> +ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Author :
> + *	Suraj Kandpal<suraj.kandpal@intel.com>
> + *	Arun Murthy<arun.r.murthy@intel.com>
> + */
> +
> +#ifndef _INTEL_WD_H
> +#define _INTEL_WD_H
> +
> +#include <drm/drm_crtc.h>
> +#include <linux/sync_file.h>
> +
> +#include "intel_display_types.h"
> +
> +#define I915_MAX_WD_TANSCODERS 2
> +
> +struct intel_out_fence_state {
> +	s32 __user *out_fence_ptr;
> +	struct sync_file *sync_file;
> +	int fd;
> +};
> +
> +struct intel_wd {
> +	struct intel_encoder base;
> +	struct intel_crtc *wd_crtc;
> +	struct intel_out_fence_state *fence_state;
> +	intel_wakeref_t io_wakeref[I915_MAX_WD_TANSCODERS];
> +	struct intel_connector *attached_connector;
> +	enum transcoder trans;
> +	struct i915_vma *vma;
> +	unsigned long flags;
> +	struct intel_writeback_job *job;
> +	int triggered_cap_mode;
> +	int frame_num;
> +	bool stream_cap;
> +	bool start_capture;
> +	int slicing_strategy;
> +};
> +
> +struct intel_wd_clk_vals {
> +	u32 cdclk;
> +	u16 link_m;
> +	u16 link_n;
> +};
> +
> +extern struct sync_file *sync_file_create(struct dma_fence *fence);
> +static inline struct intel_wd *enc_to_intel_wd(struct intel_encoder
> +*encoder) {
> +	return container_of(&encoder->base, struct intel_wd, base.base); }
> +void intel_wd_init(struct drm_i915_private *dev_priv, enum transcoder
> +trans); void intel_wd_enable_capture(struct intel_encoder *encoder,
> +				struct intel_crtc_state *pipe_config,
> +				struct drm_connector_state *conn_state);
> void
> +intel_wd_handle_isr(struct drm_i915_private *dev_priv); void
> +intel_wd_set_vblank_event(struct intel_crtc *crtc,
> +				struct intel_crtc_state *state);
> +int intel_wd_prepare_out_fence(struct drm_device *dev,
> +				struct drm_atomic_state *state);
> +void intel_wd_complete_signaling(struct intel_wd *intel_wd);
> +#endif/* _INTEL_WD_H */
> diff --git a/drivers/gpu/drm/i915/i915_drv.h
> b/drivers/gpu/drm/i915/i915_drv.h index 9a86ee88089e..b7e92a18125c
> 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -38,6 +38,8 @@
>  #include <linux/pm_qos.h>
> 
>  #include <drm/drm_connector.h>
> +#include <drm/drm_writeback.h>
> +#include <drm/i915_mei_hdcp_interface.h>
>  #include <drm/ttm/ttm_device.h>
> 
>  #include "display/intel_bios.h"
> diff --git a/drivers/gpu/drm/i915/i915_irq.c
> b/drivers/gpu/drm/i915/i915_irq.c index 73cebc6aa650..95a6a8f7a911 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -42,6 +42,7 @@
>  #include "display/intel_hotplug.h"
>  #include "display/intel_lpe_audio.h"
>  #include "display/intel_psr.h"
> +#include "display/intel_wd.h"
> 
>  #include "gt/intel_breadcrumbs.h"
>  #include "gt/intel_gt.h"
> @@ -2342,6 +2343,11 @@ gen8_de_misc_irq_handler(struct
> drm_i915_private *dev_priv, u32 iir)
>  		found = true;
>  	}
> 
> +	if (iir & GEN8_DE_MISC_WD0) {
> +		intel_wd_handle_isr(dev_priv);
> +		found = true;
> +	}
> +
>  	if (iir & GEN8_DE_EDP_PSR) {
>  		struct intel_encoder *encoder;
>  		u32 psr_iir;
> @@ -3767,7 +3773,7 @@ static void gen8_de_irq_postinstall(struct
> drm_i915_private *dev_priv)
>  	u32 de_pipe_enables;
>  	u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
>  	u32 de_port_enables;
> -	u32 de_misc_masked = GEN8_DE_EDP_PSR;
> +	u32 de_misc_masked = GEN8_DE_EDP_PSR | GEN8_DE_MISC_WD0;
>  	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
>  		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
>  	enum pipe pipe;
> diff --git a/drivers/gpu/drm/i915/i915_pci.c
> b/drivers/gpu/drm/i915/i915_pci.c index 67b89769f577..a524e0f030b6
> 100644
> --- a/drivers/gpu/drm/i915/i915_pci.c
> +++ b/drivers/gpu/drm/i915/i915_pci.c
> @@ -853,7 +853,8 @@ static const struct intel_device_info jsl_info = {
>  	.display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) |
> BIT(PIPE_D), \
>  	.display.cpu_transcoder_mask = BIT(TRANSCODER_A) |
> BIT(TRANSCODER_B) | \
>  		BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | \
> -		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \
> +		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1)| \
> +		BIT(TRANSCODER_WD_0), \
>  	.pipe_offsets = { \
>  		[TRANSCODER_A] = PIPE_A_OFFSET, \
>  		[TRANSCODER_B] = PIPE_B_OFFSET, \
> @@ -861,6 +862,8 @@ static const struct intel_device_info jsl_info = {
>  		[TRANSCODER_D] = PIPE_D_OFFSET, \
>  		[TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \
>  		[TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \
> +		[TRANSCODER_WD_0] = PIPE_WD0_OFFSET, \
> +		[TRANSCODER_WD_1] = PIPE_WD1_OFFSET, \
>  	}, \
>  	.trans_offsets = { \
>  		[TRANSCODER_A] = TRANSCODER_A_OFFSET, \ @@ -869,6
> +872,8 @@ static const struct intel_device_info jsl_info = {
>  		[TRANSCODER_D] = TRANSCODER_D_OFFSET, \
>  		[TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \
>  		[TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
> +		[TRANSCODER_WD_0] = TRANSCODER_WD0_OFFSET, \
> +		[TRANSCODER_WD_1] = TRANSCODER_WD1_OFFSET, \
>  	}, \
>  	TGL_CURSOR_OFFSETS, \
>  	.has_global_mocs = 1, \
> diff --git a/drivers/gpu/drm/i915/i915_reg.h
> b/drivers/gpu/drm/i915/i915_reg.h index 6396afd77209..abc41e7de0b5
> 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3797,6 +3797,11 @@
>  #define PIPE_DSI0_OFFSET	0x7b000
>  #define PIPE_DSI1_OFFSET	0x7b800
> 
> +/* WD 0 and 1 */
> +#define PIPE_WD0_OFFSET		0x7e000
> +#define PIPE_WD1_OFFSET		0x7d000
> +
> +
>  #define PIPECONF(pipe)		_MMIO_PIPE2(pipe, _PIPEACONF)
>  #define PIPEDSL(pipe)		_MMIO_PIPE2(pipe, _PIPEADSL)
>  #define PIPEFRAME(pipe)		_MMIO_PIPE2(pipe,
> _PIPEAFRAMEHIGH)
> @@ -4461,6 +4466,10 @@
>  #define _PIPEDSI0CONF		0x7b008
>  #define _PIPEDSI1CONF		0x7b808
> 
> +/* WD 0 and 1 */
> +#define _PIPEWD0CONF		0x7e008
> +#define _PIPEWD1CONF		0x7d008
> +
>  /* Sprite A control */
>  #define _DVSACNTR		0x72180
>  #define   DVS_ENABLE			REG_BIT(31)
> @@ -5707,6 +5716,7 @@
>  #define GEN8_DE_MISC_IER _MMIO(0x4446c)
>  #define  GEN8_DE_MISC_GSE		(1 << 27)
>  #define  GEN8_DE_EDP_PSR		(1 << 19)
> +#define  GEN8_DE_MISC_WD0		(1 << 23)
> 
>  #define GEN8_PCU_ISR _MMIO(0x444e0)
>  #define GEN8_PCU_IMR _MMIO(0x444e4)
> @@ -8847,6 +8857,133 @@ enum skl_power_gate {
>  #define   DSB_ENABLE			(1 << 31)
>  #define   DSB_STATUS			(1 << 0)
> 
> +#define TGL_ROOT_DEVICE_ID		0x9A00
> +#define TGL_ROOT_DEVICE_MASK		0xFF00
> +#define TGL_ROOT_DEVICE_SKU_MASK	0xF
> +#define TGL_ROOT_DEVICE_SKU_ULX		0x2
> +#define TGL_ROOT_DEVICE_SKU_ULT		0x4
> +
> +/* Gen12 WD */
> +#define _MMIO_WD(tc, wd0, wd1)		_MMIO_TRANS((tc) -
> TRANSCODER_WD_0, \
> +							wd0, wd1)
> +
> +#define WD_TRANS_ENABLE			(1 << 31)
> +#define WD_TRANS_DISABLE		0
> +#define WD_TRANS_ACTIVE			(1 << 30)
> +
> +/* WD transcoder control */
> +#define _WD_TRANS_FUNC_CTL_0		0x6e400
> +#define _WD_TRANS_FUNC_CTL_1		0x6ec00
> +#define WD_TRANS_FUNC_CTL(tc)		_MMIO_WD(tc,\
> +					_WD_TRANS_FUNC_CTL_0,\
> +					_WD_TRANS_FUNC_CTL_1)
> +
> +#define TRANS_WD_FUNC_ENABLE		(1 << 31)
> +#define WD_TRIGGERED_CAP_MODE_ENABLE	(1 << 30)
> +#define START_TRIGGER_FRAME		(1 << 29)
> +#define STOP_TRIGGER_FRAME		(1 << 28)
> +#define WD_CTL_POINTER_ETEH		(0 << 18)
> +#define WD_CTL_POINTER_ETDH		(1 << 18)
> +#define WD_CTL_POINTER_DTDH		(2 << 18)
> +#define WD_INPUT_SELECT_MASK		(7 << 12)
> +#define WD_INPUT_PIPE_A			(0 << 12)
> +#define WD_INPUT_PIPE_B			(5 << 12)
> +#define WD_INPUT_PIPE_C			(6 << 12)
> +#define WD_INPUT_PIPE_D			(7 << 12)
> +
> +#define WD_PIX_FMT_MASK			(0x3 << 20)
> +#define WD_PIX_FMT_YUYV			(0x1 << 20)
> +#define WD_PIX_FMT_XYUV8888		(0x2 << 20)
> +#define WD_PIX_FMT_XBGR8888		(0x3 << 20)
> +#define WD_PIX_FMT_Y410			(0x4 << 20)
> +#define WD_PIX_FMT_YUV422		(0x5 << 20)
> +#define WD_PIX_FMT_XBGR2101010		(0x6 << 20)
> +#define WD_PIX_FMT_RGB565		(0x7 << 20)
> +
> +#define WD_FRAME_NUMBER_MASK		15
> +
> +#define _WD_STRIDE_0			0x6e510
> +#define _WD_STRIDE_1			0x6ed10
> +#define WD_STRIDE(tc)			_MMIO_WD(tc,\
> +					_WD_STRIDE_0,\
> +					_WD_STRIDE_1)
> +#define WD_STRIDE_SHIFT			6
> +#define WD_STRIDE_MASK			(0x3ff << WD_STRIDE_SHIFT)
> +
> +#define _WD_STREAMCAP_CTL0		0x6e590
> +#define _WD_STREAMCAP_CTL1		0x6ed90
> +#define WD_STREAMCAP_CTL(tc)		_MMIO_WD(tc,\
> +					_WD_STREAMCAP_CTL0,\
> +					_WD_STREAMCAP_CTL1)
> +
> +#define WD_STREAM_CAP_MODE_EN		(1 << 31)
> +#define WD_STRAT_MASK			(3 << 24)
> +#define WD_SLICING_STRAT_1_1		(0 << 24)
> +#define WD_SLICING_STRAT_2_1		(1 << 24)
> +#define WD_SLICING_STRAT_4_1		(2 << 24)
> +#define WD_SLICING_STRAT_8_1		(3 << 24)
> +#define WD_STREAM_OVERRUN_STATUS	1
> +
> +#define _WD_SURF_0			0x6e514
> +#define _WD_SURF_1			0x6ed14
> +#define WD_SURF(tc)			_MMIO_WD(tc,\
> +					_WD_SURF_0,\
> +					_WD_SURF_1)
> +
> +#define _WD_IMR_0			0x6e560
> +#define _WD_IMR_1			0x6ed60
> +#define WD_IMR(tc)			_MMIO_WD(tc,\
> +					_WD_IMR_0,\
> +					_WD_IMR_1)
> +#define WD_FRAME_COMPLETE_INT		(1 << 7)
> +#define WD_GTT_FAULT_INT		(1 << 6)
> +#define WD_VBLANK_INT			(1 << 5)
> +#define WD_OVERRUN_INT			(1 << 4)
> +#define WD_CAPTURING_INT		(1 << 3)
> +#define WD_WRITE_COMPLETE_INT		(1 << 2)
> +
> +#define _WD_IIR_0			0x6e564
> +#define _WD_IIR_1			0x6ed64
> +#define WD_IIR(tc)			_MMIO_WD(tc,\
> +					_WD_IIR_0,\
> +					_WD_IIR_1)
> +
> +#define _WD_FRAME_STATUS_0		0x6e56b
> +#define _WD_FRAME_STATUS_1		0x6ed6b
> +#define WD_FRAME_STATUS(tc)		_MMIO_WD(tc,\
> +					_WD_FRAME_STATUS_0,\
> +					_WD_FRAME_STATUS_1)
> +
> +#define WD_FRAME_COMPLETE		(1 << 31)
> +#define WD_STATE_IDLE			(0 << 24)
> +#define WD_STATE_CAPSTART		(1 << 24)
> +#define WD_STATE_FRAME_START		(2 << 24)
> +#define WD_STATE_CAPACITIVE		(3 << 24)
> +#define WD_STATE_TG_DONE		(4 << 24)
> +#define WD_STATE_WDX_DONE		(5 << 24)
> +#define WD_STATE_QUICK_CAP		(6 << 24)
> +
> +#define _WD_27_M_0			0x6e524
> +#define _WD_27_M_1			0x6ed24
> +#define WD_27_M(tc)			_MMIO_WD(tc,\
> +					_WD_27_M_0,\
> +					_WD_27_M_1)
> +
> +#define _WD_27_N_0			0x6e528
> +
> +//Address looks wrong in bspec:
> +#define _WD_27_N_1			0x6ec28
> +#define WD_27_N(tc)			_MMIO_WD(tc,\
> +					_WD_27_N_0,\
> +					_WD_27_N_1)
> +
> +#define _WD_TAIL_CFG_0			0x6e520
> +#define _WD_TAIL_CFG_1			0x6ed20
> +
> +#define WD_TAIL_CFG(tc)			_MMIO_WD(tc,\
> +					_WD_TAIL_CFG_0,\
> +					_WD_TAIL_CFG_1)
> +
>  #define CLKREQ_POLICY			_MMIO(0x101038)
>  #define  CLKREQ_POLICY_MEM_UP_OVRD	REG_BIT(1)
> 
> --
> 2.35.1


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

* Re: [Intel-gfx] [RFC PATCH v2 0/3] i915 writeback private framework
  2022-03-17  8:39 ` [Intel-gfx] [RFC PATCH v2 0/3] " Suraj Kandpal
                     ` (2 preceding siblings ...)
  2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 3/3] drm/i915: Enabling WD Transcoder Suraj Kandpal
@ 2022-04-06  4:56   ` Kandpal, Suraj
  3 siblings, 0 replies; 24+ messages in thread
From: Kandpal, Suraj @ 2022-04-06  4:56 UTC (permalink / raw)
  To: intel-gfx; +Cc: Nikula, Jani

Hi All,
Gentle Reminder.
++Uma

Regards
Suraj Kandapal

> A patch series was floated in the drm mailing list which aimed to change the
> drm_connector and drm_encoder fields to pointer in the
> drm_connector_writeback structure, this received a huge pushback from the
> community but since i915 expects each connector present in the drm_device
> list to be a intel_connector but drm_writeback framework forces us to use a
> drm_connector which is not embedded in intel_connector the current
> drm_writeback framework becomes very unfeasible to us as it would mean a
> lot of checks at a lot of places to take into account the above issue. One of
> the solutions is to make our own writeback pipeline bypassing one provided
> by drm which is what these patches do.
> 
> -----
> Version 2:
> adding fixes to avoid regression in previous gen and some basic checkpatch
> changes.
> 
> Suraj Kandpal (3):
>   drm/i915: Creating writeback pipeline to bypass drm_writeback
>     framework
>   drm/i915: Define WD trancoder for i915
>   drm/i915: Enabling WD Transcoder
> 
>  drivers/gpu/drm/i915/Makefile                 |   2 +
>  drivers/gpu/drm/i915/display/intel_acpi.c     |   1 +
>  drivers/gpu/drm/i915/display/intel_display.c  |  89 +-
> drivers/gpu/drm/i915/display/intel_display.h  |  15 +
>  .../drm/i915/display/intel_display_types.h    |  18 +
>  drivers/gpu/drm/i915/display/intel_dpll.c     |   3 +
>  drivers/gpu/drm/i915/display/intel_opregion.c |   3 +
>  .../gpu/drm/i915/display/intel_wb_connector.c | 296 ++++++
> .../gpu/drm/i915/display/intel_wb_connector.h |  99 ++
>  drivers/gpu/drm/i915/display/intel_wd.c       | 978 ++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_wd.h       |  82 ++
>  drivers/gpu/drm/i915/i915_drv.h               |   5 +
>  drivers/gpu/drm/i915/i915_irq.c               |   8 +-
>  drivers/gpu/drm/i915/i915_pci.c               |   7 +-
>  drivers/gpu/drm/i915/i915_reg.h               | 139 +++
>  15 files changed, 1742 insertions(+), 3 deletions(-)  create mode 100644
> drivers/gpu/drm/i915/display/intel_wb_connector.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.h
>  create mode 100644 drivers/gpu/drm/i915/display/intel_wd.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_wd.h
> 
> --
> 2.35.1


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

* Re: [Intel-gfx] [RFC PATCH v2 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework
  2022-03-18  4:18   ` [Intel-gfx] [RFC PATCH v2 " Suraj Kandpal
@ 2022-04-06  4:58     ` Kandpal, Suraj
  0 siblings, 0 replies; 24+ messages in thread
From: Kandpal, Suraj @ 2022-04-06  4:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Nikula, Jani

++Uma

Regards,
Suraj Kandpal

> Changes to create a i915 private pipeline to enable the WD transcoder
> without relying on the current drm_writeback framework.
> 
> Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile                 |   1 +
>  .../drm/i915/display/intel_display_types.h    |   4 +
>  .../gpu/drm/i915/display/intel_wb_connector.c | 296 ++++++++++++++++++
> .../gpu/drm/i915/display/intel_wb_connector.h |  99 ++++++
>  drivers/gpu/drm/i915/i915_drv.h               |   3 +
>  5 files changed, 403 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_wb_connector.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 1a771ee5b1d0..087bd9d1b397 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -286,6 +286,7 @@ i915-y += \
>  	display/intel_tv.o \
>  	display/intel_vdsc.o \
>  	display/intel_vrr.o \
> +	display/intel_wb_connector.o\
>  	display/vlv_dsi.o \
>  	display/vlv_dsi_pll.o
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index d84e82f3eab9..7a96ecba73c0 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -52,6 +52,7 @@
>  #include "intel_display_power.h"
>  #include "intel_dpll_mgr.h"
>  #include "intel_pm_types.h"
> +#include "intel_wb_connector.h"
> 
>  struct drm_printer;
>  struct __intel_global_objs_state;
> @@ -537,11 +538,14 @@ struct intel_connector {
>  	struct work_struct modeset_retry_work;
> 
>  	struct intel_hdcp hdcp;
> +
> +	struct intel_writeback_connector wb_conn;
>  };
> 
>  struct intel_digital_connector_state {
>  	struct drm_connector_state base;
> 
> +	struct intel_writeback_job *job;
>  	enum hdmi_force_audio force_audio;
>  	int broadcast_rgb;
>  };
> diff --git a/drivers/gpu/drm/i915/display/intel_wb_connector.c
> b/drivers/gpu/drm/i915/display/intel_wb_connector.c
> new file mode 100644
> index 000000000000..65f4abef53d0
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_wb_connector.c
> @@ -0,0 +1,296 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright © 2022 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a
> + * copy of this software and associated documentation files (the
> +"Software"),
> + * to deal in the Software without restriction, including without
> +limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> +sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom
> +the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> +next
> + * paragraph) shall be included in all copies or substantial portions
> +of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO
> EVENT
> +SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> DAMAGES OR
> +OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> +ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> OTHER
> +DEALINGS
> + * IN THE SOFTWARE.
> + *
> + * Authors:
> + *	Suraj Kandpal <suraj.kandpal@intel.com>
> + *	Arun Murthy <arun.r.murthy@intel.com>
> + *
> + */
> +
> +
> +#include <linux/dma-fence.h>
> +
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_device.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +#include <drm/drm_property.h>
> +
> +#include "i915_drv.h"
> +#include "intel_wb_connector.h"
> +#include "intel_display_types.h"
> +
> +#define fence_to_wb_connector(x) container_of(x->lock, \
> +					      struct intel_writeback_connector,
> \
> +					      fence_lock)
> +
> +static const char *intel_writeback_fence_get_driver_name(struct
> +dma_fence *fence) {
> +	struct intel_writeback_connector *wb_connector =
> +		fence_to_wb_connector(fence);
> +
> +	return wb_connector->base->dev->driver->name;
> +}
> +
> +static const char *
> +intel_writeback_fence_get_timeline_name(struct dma_fence *fence) {
> +	struct intel_writeback_connector *wb_connector =
> +		fence_to_wb_connector(fence);
> +
> +	return wb_connector->timeline_name;
> +}
> +
> +static bool intel_writeback_fence_enable_signaling(struct dma_fence
> +*fence) {
> +	return true;
> +}
> +
> +static const struct dma_fence_ops intel_writeback_fence_ops = {
> +	.get_driver_name = intel_writeback_fence_get_driver_name,
> +	.get_timeline_name = intel_writeback_fence_get_timeline_name,
> +	.enable_signaling = intel_writeback_fence_enable_signaling,
> +};
> +
> +static int intel_create_writeback_properties(struct drm_device *dev) {
> +	struct drm_property *prop;
> +	struct drm_i915_private *i915 = to_i915(dev);
> +
> +	if (!i915->wb_fb_id_property) {
> +		prop = drm_property_create_object(dev,
> DRM_MODE_PROP_ATOMIC,
> +						"WRITEBACK_FB_ID",
> +						DRM_MODE_OBJECT_FB);
> +		if (!prop)
> +			return -ENOMEM;
> +		i915->wb_fb_id_property = prop;
> +	}
> +
> +	if (!i915->wb_pixel_formats_property) {
> +		prop = drm_property_create(dev, DRM_MODE_PROP_BLOB
> |
> +					DRM_MODE_PROP_ATOMIC |
> +					DRM_MODE_PROP_IMMUTABLE,
> +					"WRITEBACK_PIXEL_FORMATS", 0);
> +		if (!prop)
> +			return -ENOMEM;
> +		i915->wb_pixel_formats_property = prop;
> +	}
> +
> +	if (!i915->wb_out_fence_ptr_property) {
> +		prop = drm_property_create_range(dev,
> DRM_MODE_PROP_ATOMIC,
> +
> 	"WRITEBACK_OUT_FENCE_PTR", 0,
> +						U64_MAX);
> +		if (!prop)
> +			return -ENOMEM;
> +		i915->wb_out_fence_ptr_property = prop;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct drm_encoder_funcs intel_writeback_encoder_funcs = {
> +	.destroy = drm_encoder_cleanup,
> +};
> +
> +int intel_writeback_connector_init(struct drm_device *dev,
> +				 struct intel_writeback_connector
> *wb_connector,
> +				 const struct drm_connector_funcs
> *con_funcs,
> +				 const struct drm_encoder_helper_funcs
> *enc_helper_funcs,
> +				 const u32 *formats, int n_formats) {
> +	struct drm_property_blob *blob;
> +	struct drm_i915_private *i915 = to_i915(dev);
> +	struct drm_connector *connector = wb_connector->base;
> +	int ret;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +	ret = intel_create_writeback_properties(dev);
> +
> +	if (ret != 0)
> +		return ret;
> +
> +	blob = drm_property_create_blob(dev, n_formats *
> sizeof(*formats),
> +					formats);
> +	if (IS_ERR(blob))
> +		return PTR_ERR(blob);
> +
> +	drm_encoder_helper_add(wb_connector->encoder,
> enc_helper_funcs);
> +	ret = drm_encoder_init(dev, wb_connector->encoder,
> +			&intel_writeback_encoder_funcs,
> +			DRM_MODE_ENCODER_VIRTUAL, NULL);
> +	if (ret)
> +		goto fail;
> +
> +	connector->interlace_allowed = 0;
> +
> +	ret = drm_connector_init(dev, connector, con_funcs,
> +				DRM_MODE_CONNECTOR_WRITEBACK);
> +	if (ret)
> +		goto connector_fail;
> +
> +	ret = drm_connector_attach_encoder(connector,
> +					wb_connector->encoder);
> +	if (ret)
> +		goto attach_fail;
> +
> +	INIT_LIST_HEAD(&wb_connector->job_queue);
> +	spin_lock_init(&wb_connector->job_lock);
> +
> +	wb_connector->fence_context = dma_fence_context_alloc(1);
> +	spin_lock_init(&wb_connector->fence_lock);
> +	snprintf(wb_connector->timeline_name,
> +		sizeof(wb_connector->timeline_name),
> +		"CONNECTOR:%d-%s", connector->base.id, connector-
> >name);
> +
> +	drm_object_attach_property(&connector->base,
> +				i915->wb_out_fence_ptr_property, 0);
> +
> +	drm_object_attach_property(&connector->base,
> +				i915->wb_fb_id_property, 0);
> +
> +	drm_object_attach_property(&connector->base,
> +				i915->wb_pixel_formats_property,
> +				blob->base.id);
> +	wb_connector->pixel_formats_blob_ptr = blob;
> +
> +	return 0;
> +
> +attach_fail:
> +	drm_connector_cleanup(connector);
> +connector_fail:
> +	drm_encoder_cleanup(wb_connector->encoder);
> +fail:
> +	drm_property_blob_put(blob);
> +	return ret;
> +}
> +
> +void intel_writeback_queue_job(struct intel_writeback_connector
> *wb_connector,
> +		struct drm_connector_state *conn_state) {
> +	struct intel_writeback_job *wb_job;
> +	struct intel_digital_connector_state *intel_conn_state =
> +		to_intel_digital_connector_state(conn_state);
> +	unsigned long flags;
> +
> +	wb_job = intel_conn_state->job;
> +	intel_conn_state->job = NULL;
> +
> +	spin_lock_irqsave(&wb_connector->job_lock, flags);
> +	list_add_tail(&wb_job->list_entry, &wb_connector->job_queue);
> +	spin_unlock_irqrestore(&wb_connector->job_lock, flags); }
> +
> +int intel_writeback_set_fb(struct drm_connector_state *conn_state,
> +			 struct drm_framebuffer *fb)
> +{
> +	struct intel_connector *intel_connector =
> to_intel_connector(conn_state->connector);
> +	struct intel_writeback_connector *wb_connector = &intel_connector-
> >wb_conn;
> +	struct intel_digital_connector_state *intel_conn_state =
> +		to_intel_digital_connector_state(conn_state);
> +	WARN_ON(conn_state->connector->connector_type !=
> +DRM_MODE_CONNECTOR_WRITEBACK);
> +
> +	if (!intel_conn_state->job) {
> +		intel_conn_state->job =
> +			kzalloc(sizeof(*intel_conn_state->job), GFP_KERNEL);
> +		if (!intel_conn_state->job)
> +			return -ENOMEM;
> +
> +		intel_conn_state->job->connector = wb_connector;
> +	}
> +
> +	drm_framebuffer_assign(&intel_conn_state->job->fb, fb);
> +	return 0;
> +}
> +
> +void intel_writeback_cleanup_job(struct intel_writeback_job *job) {
> +	if (job->fb)
> +		drm_framebuffer_put(job->fb);
> +
> +	if (job->out_fence)
> +		dma_fence_put(job->out_fence);
> +
> +	kfree(job);
> +}
> +
> +static void cleanup_work(struct work_struct *work) {
> +	struct intel_writeback_job *job = container_of(work,
> +						struct intel_writeback_job,
> +						cleanup_work);
> +
> +	intel_writeback_cleanup_job(job);
> +}
> +
> +void
> +intel_writeback_signal_completion(struct intel_writeback_connector
> *wb_connector,
> +				int status)
> +{
> +	unsigned long flags;
> +	struct intel_writeback_job *job;
> +	struct dma_fence *out_fence;
> +
> +	spin_lock_irqsave(&wb_connector->job_lock, flags);
> +	job = list_first_entry_or_null(&wb_connector->job_queue,
> +					struct intel_writeback_job,
> +					list_entry);
> +	if (job)
> +		list_del(&job->list_entry);
> +
> +	spin_unlock_irqrestore(&wb_connector->job_lock, flags);
> +
> +	if (WARN_ON(!job))
> +		return;
> +
> +	out_fence = job->out_fence;
> +	if (out_fence) {
> +		if (status)
> +			dma_fence_set_error(out_fence, status);
> +		dma_fence_signal(out_fence);
> +		dma_fence_put(out_fence);
> +		job->out_fence = NULL;
> +	}
> +
> +	INIT_WORK(&job->cleanup_work, cleanup_work);
> +	queue_work(system_long_wq, &job->cleanup_work); }
> +
> +struct dma_fence *
> +intel_writeback_get_out_fence(struct intel_writeback_connector
> +*wb_connector) {
> +	struct dma_fence *fence;
> +
> +	if (WARN_ON(wb_connector->base->connector_type !=
> +		DRM_MODE_CONNECTOR_WRITEBACK))
> +		return NULL;
> +
> +	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
> +	if (!fence)
> +		return NULL;
> +
> +	dma_fence_init(fence, &intel_writeback_fence_ops,
> +		&wb_connector->fence_lock, wb_connector->fence_context,
> +		++wb_connector->fence_seqno);
> +
> +	return fence;
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_wb_connector.h
> b/drivers/gpu/drm/i915/display/intel_wb_connector.h
> new file mode 100644
> index 000000000000..71142457b7c1
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_wb_connector.h
> @@ -0,0 +1,99 @@
> +/* SPDX-License-Identifier: GPL-2.0
> + * Copyright © 2022 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a
> + * copy of this software and associated documentation files (the
> +"Software"),
> + * to deal in the Software without restriction, including without
> +limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> +sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom
> +the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> +next
> + * paragraph) shall be included in all copies or substantial portions
> +of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO
> EVENT
> +SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> DAMAGES OR
> +OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> +ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> OTHER
> +DEALINGS
> + * IN THE SOFTWARE.
> + *
> + * Authors:
> + *	Suraj Kandpal <suraj.kandpal@intel.com>
> + *	Arun Murthy <arun.r.murthy@intel.com>
> + *
> + */
> +
> +#ifndef __INTEL_WB_CONNECTOR_H__
> +#define __INTEL_WB_CONNECTOR_H__
> +
> +#include <drm/drm_connector.h>
> +#include <drm/drm_encoder.h>
> +#include <linux/workqueue.h>
> +#include "intel_display.h"
> +
> +/**
> + * struct intel_writeback_connector - Intel writeback connector
> + * to get a idea of each individual variable please look at
> + * documentation in drm_writeback.h we emulate the same structure
> + * ditto for intel_writeback_job structure.
> + */
> +struct intel_writeback_connector {
> +	struct drm_connector *base;
> +	struct drm_encoder *encoder;
> +	struct drm_property_blob *pixel_formats_blob_ptr;
> +	spinlock_t job_lock;
> +	struct list_head job_queue;
> +	unsigned int fence_context;
> +	spinlock_t fence_lock;
> +	unsigned long fence_seqno;
> +	char timeline_name[32];
> +};
> +
> +/**
> + * struct intel_writeback_job - DRM writeback job  */ struct
> +intel_writeback_job {
> +	struct intel_writeback_connector *connector;
> +	bool *prepared;
> +	struct work_struct cleanup_work;
> +	struct list_head list_entry;
> +	struct drm_framebuffer *fb;
> +	struct dma_fence *out_fence;
> +	void *priv;
> +};
> +
> +int intel_writeback_connector_init(struct drm_device *dev,
> +			struct intel_writeback_connector *wb_connector,
> +			const struct drm_connector_funcs *con_funcs,
> +			const struct drm_encoder_helper_funcs
> *enc_helper_funcs,
> +			const u32 *formats, int n_formats);
> +
> +int intel_writeback_set_fb(struct drm_connector_state *conn_state,
> +			struct drm_framebuffer *fb);
> +
> +int intel_writeback_prepare_job(struct intel_writeback_job *job);
> +
> +void intel_writeback_queue_job(struct intel_writeback_connector
> *wb_connector,
> +			struct drm_connector_state *conn_state);
> +
> +void intel_writeback_cleanup_job(struct intel_writeback_job *job);
> +
> +void
> +intel_writeback_signal_completion(struct intel_writeback_connector
> *wb_connector,
> +			int status);
> +
> +struct dma_fence *
> +intel_writeback_get_out_fence(struct intel_writeback_connector
> +*wb_connector); struct intel_wb_connector
> +*intel_wb_connector_alloc(void); void intel_wb_connector_free(struct
> +intel_wb_connector *connector); void intel_wb_connector_destroy(struct
> +drm_connector *connector); bool intel_wb_connector_get_hw_state(struct
> +intel_wb_connector *connector); enum pipe
> +intel_wb_connector_get_pipe(struct intel_wb_connector *connector); void
> intel_wb_connector_attach_encoder(struct intel_wb_connector *connector,
> +					struct intel_encoder *encoder);
> +
> +#endif /* __INTEL_WB_CONNECTOR_H__ */
> +
> diff --git a/drivers/gpu/drm/i915/i915_drv.h
> b/drivers/gpu/drm/i915/i915_drv.h index 26df561a4e94..9a86ee88089e
> 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -678,6 +678,9 @@ struct drm_i915_private {
> 
>  	struct drm_property *broadcast_rgb_property;
>  	struct drm_property *force_audio_property;
> +	struct drm_property *wb_fb_id_property;
> +	struct drm_property *wb_out_fence_ptr_property;
> +	struct drm_property *wb_pixel_formats_property;
> 
>  	u32 fdi_rx_config;
> 
> --
> 2.35.1


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

* Re: [Intel-gfx] [RFC PATCH v2 3/3] drm/i915: Enabling WD Transcoder
  2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 3/3] drm/i915: Enabling WD Transcoder Suraj Kandpal
@ 2022-04-06  4:58     ` Kandpal, Suraj
  0 siblings, 0 replies; 24+ messages in thread
From: Kandpal, Suraj @ 2022-04-06  4:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Nikula, Jani

Hi All,
++Uma

Regards,
Suraj Kandpal
> Adding support for writeback transcoder to start capturing frames using
> interrupt mechanism
> 
> Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile                 |   1 +
>  drivers/gpu/drm/i915/display/intel_acpi.c     |   1 +
>  drivers/gpu/drm/i915/display/intel_display.c  |  89 +-
>  drivers/gpu/drm/i915/display/intel_display.h  |   9 +
>  .../drm/i915/display/intel_display_types.h    |  13 +
>  drivers/gpu/drm/i915/display/intel_dpll.c     |   3 +
>  drivers/gpu/drm/i915/display/intel_opregion.c |   3 +
>  drivers/gpu/drm/i915/display/intel_wd.c       | 978 ++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_wd.h       |  82 ++
>  drivers/gpu/drm/i915/i915_drv.h               |   2 +
>  drivers/gpu/drm/i915/i915_irq.c               |   8 +-
>  drivers/gpu/drm/i915/i915_pci.c               |   7 +-
>  drivers/gpu/drm/i915/i915_reg.h               | 137 +++
>  13 files changed, 1330 insertions(+), 3 deletions(-)  create mode 100644
> drivers/gpu/drm/i915/display/intel_wd.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_wd.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 087bd9d1b397..5ee32513a945 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -287,6 +287,7 @@ i915-y += \
>  	display/intel_vdsc.o \
>  	display/intel_vrr.o \
>  	display/intel_wb_connector.o\
> +	display/intel_wd.o\
>  	display/vlv_dsi.o \
>  	display/vlv_dsi_pll.o
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c
> b/drivers/gpu/drm/i915/display/intel_acpi.c
> index e78430001f07..ae08db164f73 100644
> --- a/drivers/gpu/drm/i915/display/intel_acpi.c
> +++ b/drivers/gpu/drm/i915/display/intel_acpi.c
> @@ -247,6 +247,7 @@ static u32 acpi_display_type(struct intel_connector
> *connector)
>  	case DRM_MODE_CONNECTOR_LVDS:
>  	case DRM_MODE_CONNECTOR_eDP:
>  	case DRM_MODE_CONNECTOR_DSI:
> +	case DRM_MODE_CONNECTOR_WRITEBACK:
>  		display_type = ACPI_DISPLAY_TYPE_INTERNAL_DIGITAL;
>  		break;
>  	case DRM_MODE_CONNECTOR_Unknown:
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> b/drivers/gpu/drm/i915/display/intel_display.c
> index eb49973621f0..6dedc7921f54 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -111,6 +111,7 @@
>  #include "intel_sprite.h"
>  #include "intel_tc.h"
>  #include "intel_vga.h"
> +#include "intel_wd.h"
>  #include "i9xx_plane.h"
>  #include "skl_scaler.h"
>  #include "skl_universal_plane.h"
> @@ -1544,6 +1545,72 @@ static void
> intel_encoders_update_complete(struct intel_atomic_state *state)
>  	}
>  }
> 
> +static void intel_queue_writeback_job(struct intel_atomic_state *state,
> +		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)
> {
> +	struct drm_connector_state *new_conn_state;
> +	struct drm_connector *connector;
> +	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
> +	struct intel_wd *intel_wd;
> +	struct intel_connector *intel_connector;
> +	struct intel_digital_connector_state *intel_conn_state;
> +	struct intel_encoder *encoder;
> +	int i;
> +
> +	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
> +		intel_wd = enc_to_intel_wd(encoder);
> +
> +		if (intel_wd->wd_crtc != intel_crtc)
> +			return;
> +
> +	}
> +
> +	for_each_new_connector_in_state(&state->base, connector,
> new_conn_state,
> +					i) {
> +		intel_conn_state =
> to_intel_digital_connector_state(new_conn_state);
> +		if (!intel_conn_state->job)
> +			continue;
> +		intel_connector = to_intel_connector(connector);
> +		intel_writeback_queue_job(&intel_connector->wb_conn,
> new_conn_state);
> +		drm_dbg_kms(&i915->drm, "queueing writeback job\n");
> +	}
> +}
> +
> +static void intel_find_writeback_connector(struct intel_atomic_state *state,
> +		struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state)
> {
> +	struct drm_connector_state *new_conn_state;
> +	struct drm_connector *connector;
> +	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
> +	struct intel_wd *intel_wd;
> +	struct intel_encoder *encoder;
> +	int i;
> +
> +	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
> +		intel_wd = enc_to_intel_wd(encoder);
> +
> +		if (intel_wd->wd_crtc != intel_crtc)
> +			return;
> +
> +	}
> +
> +	for_each_new_connector_in_state(&state->base, connector,
> new_conn_state,
> +					i) {
> +		struct intel_connector *intel_connector;
> +
> +		intel_connector = to_intel_connector(connector);
> +		drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]: status:
> %s\n",
> +				connector->base.id, connector->name,
> +				drm_get_connector_status_name(connector-
> >status));
> +		encoder =
> intel_connector_primary_encoder(intel_connector);
> +		if (encoder->type == INTEL_OUTPUT_WD) {
> +			drm_dbg_kms(&i915->drm, "encoder
> intel_output_wd found\n");
> +			intel_wd_enable_capture(encoder, crtc_state,
> new_conn_state);
> +		}
> +	}
> +
> +}
> +
>  static void intel_encoders_pre_pll_enable(struct intel_atomic_state *state,
>  					  struct intel_crtc *crtc)
>  {
> @@ -1944,7 +2011,8 @@ static void hsw_crtc_enable(struct
> intel_atomic_state *state,
>  		bdw_set_pipemisc(new_crtc_state);
> 
>  	if (!intel_crtc_is_bigjoiner_slave(new_crtc_state) &&
> -	    !transcoder_is_dsi(cpu_transcoder))
> +	    !transcoder_is_dsi(cpu_transcoder) &&
> +	    !transcoder_is_wd(cpu_transcoder))
>  		hsw_configure_cpu_transcoder(new_crtc_state);
> 
>  	crtc->active = true;
> @@ -2632,6 +2700,9 @@ static void intel_connector_verify_state(struct
> intel_crtc_state *crtc_state,
>  	if (connector->get_hw_state(connector)) {
>  		struct intel_encoder *encoder =
> intel_attached_encoder(connector);
> 
> +		if (conn_state->connector->connector_type ==
> DRM_MODE_CONNECTOR_WRITEBACK)
> +			return;
> +
>  		I915_STATE_WARN(!crtc_state,
>  			 "connector enabled without attached crtc\n");
> 
> @@ -5233,6 +5304,7 @@ static const char * const output_type_str[] = {
>  	OUTPUT_TYPE(DSI),
>  	OUTPUT_TYPE(DDI),
>  	OUTPUT_TYPE(DP_MST),
> +	OUTPUT_TYPE(WD),
>  };
> 
>  #undef OUTPUT_TYPE
> @@ -8577,6 +8649,12 @@ static void intel_atomic_commit_tail(struct
> intel_atomic_state *state)
>  		}
>  	}
> 
> +	if (DISPLAY_VER(dev_priv) >= 12) {
> +		for_each_new_intel_crtc_in_state(state, crtc,
> new_crtc_state, i) {
> +			intel_wd_set_vblank_event(crtc, new_crtc_state);
> +		}
> +	}
> +
>  	intel_encoders_update_prepare(state);
> 
>  	intel_dbuf_pre_plane_update(state);
> @@ -8662,6 +8740,14 @@ static void intel_atomic_commit_tail(struct
> intel_atomic_state *state)
> 
>  	intel_sagv_post_plane_update(state);
> 
> +	if (DISPLAY_VER(dev_priv) >= 12) {
> +		intel_wd_prepare_out_fence(dev, &state->base);
> +		for_each_new_intel_crtc_in_state(state, crtc,
> new_crtc_state, i) {
> +			intel_queue_writeback_job(state, crtc,
> new_crtc_state);
> +			intel_find_writeback_connector(state, crtc,
> new_crtc_state);
> +		}
> +	}
> +
>  	drm_atomic_helper_commit_hw_done(&state->base);
> 
>  	if (state->modeset) {
> @@ -8966,6 +9052,7 @@ static void intel_setup_outputs(struct
> drm_i915_private *dev_priv)
>  		intel_ddi_init(dev_priv, PORT_TC1);
>  		intel_ddi_init(dev_priv, PORT_TC2);
>  	} else if (DISPLAY_VER(dev_priv) >= 12) {
> +		intel_wd_init(dev_priv, TRANSCODER_WD_0);
>  		intel_ddi_init(dev_priv, PORT_A);
>  		intel_ddi_init(dev_priv, PORT_B);
>  		intel_ddi_init(dev_priv, PORT_TC1);
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h
> b/drivers/gpu/drm/i915/display/intel_display.h
> index 8c93a5de8e07..27237d36a888 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -156,6 +156,11 @@ static inline bool transcoder_is_dsi(enum
> transcoder transcoder)
>  	return transcoder == TRANSCODER_DSI_A || transcoder ==
> TRANSCODER_DSI_C;  }
> 
> +static inline bool transcoder_is_wd(enum transcoder transcoder) {
> +	return transcoder == TRANSCODER_WD_0 || transcoder ==
> TRANSCODER_WD_1;
> +}
> +
>  /*
>   * Global legacy plane identifier. Valid only for primary/sprite
>   * planes on pre-g4x, and only for primary planes on g4x-bdw.
> @@ -467,6 +472,10 @@ enum hpd_pin {
>  	for_each_intel_encoder((dev), (intel_encoder)) \
>  		for_each_if(intel_encoder_can_psr(intel_encoder))
> 
> +#define for_each_intel_encoder_with_wd(dev, intel_encoder)	\
> +	for_each_intel_encoder(dev, intel_encoder)		\
> +		for_each_if(intel_encoder_is_wd(intel_encoder))
> +
>  #define for_each_intel_connector_iter(intel_connector, iter) \
>  	while ((intel_connector =
> to_intel_connector(drm_connector_list_iter_next(iter))))
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index dcb4ad43cf88..8522c348a73d 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1293,6 +1293,11 @@ struct intel_crtc {
>  	bool cpu_fifo_underrun_disabled;
>  	bool pch_fifo_underrun_disabled;
> 
> +	struct {
> +		struct drm_pending_vblank_event *e;
> +		atomic_t work_busy;
> +		wait_queue_head_t wd_wait;
> +	} wd;
>  	/* per-pipe watermark state */
>  	struct {
>  		/* watermarks currently being used  */ @@ -1420,6 +1425,7
> @@ struct cxsr_latency {  #define to_intel_crtc(x) container_of(x, struct
> intel_crtc, base)  #define to_intel_crtc_state(x) container_of(x, struct
> intel_crtc_state, uapi)  #define to_intel_connector(x) container_of(x, struct
> intel_connector, base)
> +#define to_intel_wb_connector(x) container_of(x, struct
> +intel_wb_connector, base)
>  #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
> #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer,
> base)  #define to_intel_plane(x) container_of(x, struct intel_plane, base) @@
> -1851,6 +1857,13 @@ static inline bool intel_encoder_is_dp(struct
> intel_encoder *encoder)
>  	}
>  }
> 
> +static inline bool intel_encoder_is_wd(struct intel_encoder *encoder) {
> +	if (encoder->type == INTEL_OUTPUT_WD)
> +		return true;
> +	return false;
> +}
> +
>  static inline struct intel_lspcon *
>  enc_to_intel_lspcon(struct intel_encoder *encoder)  { diff --git
> a/drivers/gpu/drm/i915/display/intel_dpll.c
> b/drivers/gpu/drm/i915/display/intel_dpll.c
> index 95b9d327ed4d..dfea17f5f99d 100644
> --- a/drivers/gpu/drm/i915/display/intel_dpll.c
> +++ b/drivers/gpu/drm/i915/display/intel_dpll.c
> @@ -939,6 +939,9 @@ static int hsw_crtc_compute_clock(struct
> intel_crtc_state *crtc_state)
>  	if (IS_DG2(dev_priv))
>  		return intel_mpllb_calc_state(crtc_state, encoder);
> 
> +	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_WD))
> +		return 0;
> +
>  	if (DISPLAY_VER(dev_priv) < 11 &&
>  	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
>  		return 0;
> diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c
> b/drivers/gpu/drm/i915/display/intel_opregion.c
> index f31e8c3f8ce0..b7a0ac9bad05 100644
> --- a/drivers/gpu/drm/i915/display/intel_opregion.c
> +++ b/drivers/gpu/drm/i915/display/intel_opregion.c
> @@ -370,6 +370,9 @@ int intel_opregion_notify_encoder(struct
> intel_encoder *intel_encoder,
>  	if (ret)
>  		return ret;
> 
> +	if (intel_encoder->type == INTEL_OUTPUT_WD)
> +		return 0;
> +
>  	if (intel_encoder->type == INTEL_OUTPUT_DSI)
>  		port = 0;
>  	else
> diff --git a/drivers/gpu/drm/i915/display/intel_wd.c
> b/drivers/gpu/drm/i915/display/intel_wd.c
> new file mode 100644
> index 000000000000..a6c9350c3986
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_wd.c
> @@ -0,0 +1,978 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright © 2021 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a
> + * copy of this software and associated documentation files (the
> +"Software"),
> + * to deal in the Software without restriction, including without
> +limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> +sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom
> +the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> +next
> + * paragraph) shall be included in all copies or substantial portions
> +of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO
> EVENT
> +SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> DAMAGES OR
> +OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> +ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> OTHER
> +DEALINGS
> + * IN THE SOFTWARE.
> + *
> + * Authors:
> + *	Suraj Kandpal <suraj.kandpal@intel.com>
> + *	Arun Murthy <arun.r.murthy@intel.com>
> + *
> + */
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_fourcc.h>
> +
> +#include "intel_atomic.h"
> +#include "intel_connector.h"
> +#include "intel_wd.h"
> +#include "intel_fb_pin.h"
> +#include "intel_de.h"
> +#include "intel_wb_connector.h"
> +
> +enum {
> +	WD_CAPTURE_4_PIX,
> +	WD_CAPTURE_2_PIX,
> +} wd_capture_format;
> +
> +static struct intel_writeback_job
> +*intel_get_writeback_job_from_queue(struct intel_wd *intel_wd) {
> +	struct intel_writeback_job *job;
> +	struct drm_i915_private *i915 = to_i915(intel_wd->base.base.dev);
> +	struct intel_writeback_connector *wb_conn =
> +		&intel_wd->attached_connector->wb_conn;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&wb_conn->job_lock, flags);
> +	job = list_first_entry_or_null(&wb_conn->job_queue,
> +			struct intel_writeback_job,
> +			list_entry);
> +	spin_unlock_irqrestore(&wb_conn->job_lock, flags);
> +	if (job == NULL) {
> +		drm_dbg_kms(&i915->drm, "job queue is empty\n");
> +		return NULL;
> +	}
> +
> +	return job;
> +}
> +
> +/*Check with Spec*/
> +static const u32 wb_fmts[] = {
> +		DRM_FORMAT_YUV444,
> +		DRM_FORMAT_XYUV8888,
> +		DRM_FORMAT_XBGR8888,
> +		DRM_FORMAT_XRGB8888,
> +		DRM_FORMAT_Y410,
> +		DRM_FORMAT_YUV422,
> +		DRM_FORMAT_XBGR2101010,
> +		DRM_FORMAT_RGB565,
> +
> +};
> +
> +static int intel_wd_get_format(int pixel_format) {
> +	int wd_format = -EINVAL;
> +
> +	switch (pixel_format) {
> +	case DRM_FORMAT_XBGR8888:
> +	case DRM_FORMAT_XRGB8888:
> +	case DRM_FORMAT_XBGR2101010:
> +	case DRM_FORMAT_XYUV8888:
> +	case DRM_FORMAT_YUV444:
> +		wd_format = WD_CAPTURE_4_PIX;
> +		break;
> +	case DRM_FORMAT_YUV422:
> +	case DRM_FORMAT_RGB565:
> +		wd_format = WD_CAPTURE_2_PIX;
> +		break;
> +	default:
> +		DRM_ERROR("unsupported pixel format %x!\n",
> +			pixel_format);
> +	}
> +
> +	return wd_format;
> +}
> +
> +static int intel_wd_verify_pix_format(int format) {
> +	const struct drm_format_info *info = drm_format_info(format);
> +	int pix_format = info->format;
> +	int i = 0;
> +
> +	for (i = 0; i < ARRAY_SIZE(wb_fmts); i++)
> +		if (pix_format == wb_fmts[i])
> +			return 0;
> +
> +	return 1;
> +}
> +
> +static u32 intel_wd_get_stride(const struct intel_crtc_state *crtc_state,
> +			int format)
> +{
> +	const struct drm_format_info *info = drm_format_info(format);
> +	int wd_format;
> +	int hactive, pixel_size;
> +
> +	wd_format = intel_wd_get_format(info->format);
> +
> +	switch (wd_format) {
> +	case WD_CAPTURE_4_PIX:
> +		pixel_size = 4;
> +		break;
> +	case WD_CAPTURE_2_PIX:
> +		pixel_size = 2;
> +		break;
> +	default:
> +		pixel_size = 1;
> +		break;
> +	}
> +
> +	hactive = crtc_state->hw.adjusted_mode.crtc_hdisplay;
> +
> +	return DIV_ROUND_UP(hactive * pixel_size, 64); }
> +
> +static int intel_wd_pin_fb(struct intel_wd *intel_wd,
> +			struct drm_framebuffer *fb)
> +{
> +	const struct i915_ggtt_view view = {
> +		.type = I915_GGTT_VIEW_NORMAL,
> +		};
> +	struct i915_vma *vma;
> +
> +	vma = intel_pin_and_fence_fb_obj(fb, false, &view, false,
> +			&intel_wd->flags);
> +
> +	if (IS_ERR(vma))
> +		return PTR_ERR(vma);
> +
> +	intel_wd->vma = vma;
> +	return 0;
> +}
> +
> +static void intel_configure_slicing_strategy(struct drm_i915_private *i915,
> +		struct intel_wd *intel_wd, u32 *tmp)
> +{
> +	*tmp &= ~WD_STRAT_MASK;
> +	if (intel_wd->slicing_strategy == 1)
> +		*tmp |= WD_SLICING_STRAT_1_1;
> +	else if (intel_wd->slicing_strategy == 2)
> +		*tmp |= WD_SLICING_STRAT_2_1;
> +	else if (intel_wd->slicing_strategy == 3)
> +		*tmp |= WD_SLICING_STRAT_4_1;
> +	else if (intel_wd->slicing_strategy == 4)
> +		*tmp |= WD_SLICING_STRAT_8_1;
> +
> +	intel_de_write(i915, WD_STREAMCAP_CTL(intel_wd->trans),
> +			*tmp);
> +
> +}
> +
> +static enum drm_mode_status
> +intel_wd_mode_valid(struct drm_connector *connector,
> +		struct drm_display_mode *mode)
> +{
> +	return MODE_OK;
> +}
> +
> +static int intel_wd_get_modes(struct drm_connector *connector) {
> +	return 0;
> +}
> +
> +static void intel_wd_get_config(struct intel_encoder *encoder,
> +		struct intel_crtc_state *pipe_config) {
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +	struct intel_crtc *intel_crtc =
> +		to_intel_crtc(pipe_config->uapi.crtc);
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +	if (intel_crtc) {
> +		memcpy(pipe_config, intel_crtc->config,
> +			sizeof(*pipe_config));
> +		pipe_config->output_types |= BIT(INTEL_OUTPUT_WD);
> +		drm_dbg_kms(&i915->drm, "crtc found\n");
> +	}
> +
> +}
> +
> +static int intel_wd_compute_config(struct intel_encoder *encoder,
> +			struct intel_crtc_state *pipe_config,
> +			struct drm_connector_state *conn_state) {
> +	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +	struct intel_digital_connector_state *intel_conn_state =
> +		to_intel_digital_connector_state(conn_state);
> +	struct intel_writeback_job *job;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +	job = intel_get_writeback_job_from_queue(intel_wd);
> +	if (job || intel_conn_state->job) {
> +		intel_wd->wd_crtc = to_intel_crtc(pipe_config->uapi.crtc);
> +		return 0;
> +	}
> +	drm_dbg_kms(&i915->drm, "No writebackjob in queue\n");
> +
> +	return 0;
> +}
> +
> +static void intel_wd_get_power_domains(struct intel_encoder *encoder,
> +			struct intel_crtc_state *crtc_state) {
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
> +	intel_wakeref_t wakeref;
> +
> +	wakeref = intel_display_power_get(i915,
> +				encoder->power_domain);
> +
> +	intel_wd->io_wakeref[0] = wakeref;
> +	drm_dbg_kms(&i915->drm, "\n");
> +}
> +
> +static bool intel_wd_get_hw_state(struct intel_encoder *encoder,
> +		enum pipe *pipe)
> +{
> +	bool ret = false;
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
> +	struct intel_crtc *wd_crtc = intel_wd->wd_crtc;
> +	intel_wakeref_t wakeref;
> +	u32 tmp;
> +
> +	if (wd_crtc)
> +		return false;
> +
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +				encoder->power_domain);
> +	drm_dbg_kms(encoder->base.dev, "power enabled : %s\n",
> +			!wakeref ? "false":"true");
> +
> +	if (!wakeref)
> +		return false;
> +
> +	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
> +	ret = tmp & WD_TRANS_ACTIVE;
> +	drm_dbg_kms(encoder->base.dev, "trancoder enabled: %s\n",
> +			ret ? "true":"false");
> +	if (ret) {
> +		*pipe = wd_crtc->pipe;
> +		drm_dbg_kms(encoder->base.dev, "pipe selected is %d\n",
> +			wd_crtc->pipe);
> +	}
> +	return true;
> +}
> +
> +static int intel_wd_encoder_atomic_check(struct drm_encoder *encoder,
> +				    struct drm_crtc_state *crtc_st,
> +				    struct drm_connector_state *conn_st) {
> +	/* Check for the format and buffers and property validity */
> +	struct drm_framebuffer *fb;
> +	struct intel_digital_connector_state *intel_conn_state =
> +		to_intel_digital_connector_state(conn_st);
> +	struct intel_writeback_job *job = intel_conn_state->job;
> +	struct drm_i915_private *i915 = to_i915(encoder->dev);
> +	const struct drm_display_mode *mode = &crtc_st->mode;
> +	int ret;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +
> +	if (!job) {
> +		drm_dbg_kms(&i915->drm, "No writeback job created
> returning\n");
> +		return -EINVAL;
> +	}
> +
> +	fb = job->fb;
> +
> +	if (!fb) {
> +		drm_dbg_kms(&i915->drm, "Invalid framebuffer\n");
> +		return -EINVAL;
> +	}
> +
> +	if (fb->width != mode->hdisplay || fb->height != mode->vdisplay) {
> +		drm_dbg_kms(&i915->drm, "Invalid framebuffer size
> %ux%u\n",
> +				fb->width, fb->height);
> +		return -EINVAL;
> +	}
> +
> +	ret = intel_wd_verify_pix_format(fb->format->format);
> +
> +	if (ret) {
> +		drm_dbg_kms(&i915->drm, "Unsupported framebuffer
> format %08x\n",
> +				fb->format->format);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +
> +static const struct drm_encoder_helper_funcs wd_encoder_helper_funcs =
> {
> +	.atomic_check = intel_wd_encoder_atomic_check, };
> +
> +static void intel_wd_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_dbg_kms(connector->dev, "\n");
> +	drm_connector_cleanup(connector);
> +	kfree(connector);
> +}
> +
> +static enum drm_connector_status
> +intel_wb_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	drm_dbg_kms(connector->dev, "Writeback connector
> connected\n");
> +	return connector_status_connected;
> +}
> +
> +static int intel_atomic_set_writeback_fb_for_connector(
> +		struct drm_connector_state *conn_state,
> +		struct drm_framebuffer *fb)
> +{
> +	int ret;
> +	struct drm_connector *conn = conn_state->connector;
> +
> +	ret = intel_writeback_set_fb(conn_state, fb);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (fb)
> +		drm_dbg_atomic(conn->dev,
> +			"Set [FB:%d] for connector state %p\n",
> +			fb->base.id, conn_state);
> +	else
> +		drm_dbg_atomic(conn->dev,
> +			"Set [NOFB] for connector state %p\n",
> +			conn_state);
> +
> +	return 0;
> +}
> +
> +static int set_out_fence_for_connector(struct drm_atomic_state *state,
> +					struct drm_connector *connector,
> +					s32 __user *fence_ptr)
> +{
> +	unsigned int index = drm_connector_index(connector);
> +
> +	if (!fence_ptr)
> +		return 0;
> +
> +	if (put_user(-1, fence_ptr))
> +		return -EFAULT;
> +
> +	state->connectors[index].out_fence_ptr = fence_ptr;
> +
> +	return 0;
> +}
> +
> +static struct drm_mode_object *__intel_object_find(struct drm_device
> *dev,
> +					       uint32_t id, uint32_t type) {
> +	struct drm_mode_object *obj = NULL;
> +
> +	mutex_lock(&dev->mode_config.idr_mutex);
> +	obj = idr_find(&dev->mode_config.object_idr, id);
> +	if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
> +		obj = NULL;
> +	if (obj && obj->id != id)
> +		obj = NULL;
> +	if (obj && obj->free_cb) {
> +		if (!kref_get_unless_zero(&obj->refcount))
> +			obj = NULL;
> +	}
> +	mutex_unlock(&dev->mode_config.idr_mutex);
> +
> +	return obj;
> +}
> +
> +static struct drm_framebuffer *intel_wb_framebuffer_lookup(struct
> drm_device *dev,
> +					       uint32_t id)
> +{
> +	struct drm_mode_object *obj;
> +	struct drm_framebuffer *fb = NULL;
> +
> +	obj = __intel_object_find(dev, id, DRM_MODE_OBJECT_FB);
> +	if (obj)
> +		fb = obj_to_fb(obj);
> +	return fb;
> +}
> +
> +static s32 *intel_get_out_fence_for_connector(struct drm_atomic_state
> *state,
> +					       struct drm_connector
> *connector) {
> +	unsigned int index = drm_connector_index(connector);
> +	s32 __user *fence_ptr;
> +
> +	fence_ptr = state->connectors[index].out_fence_ptr;
> +	state->connectors[index].out_fence_ptr = NULL;
> +
> +	return fence_ptr;
> +}
> +
> +static int intel_setup_out_fence(struct intel_out_fence_state *fence_state,
> +			   struct dma_fence *fence)
> +{
> +
> +	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
> +	if (fence_state->fd < 0)
> +		return fence_state->fd;
> +
> +	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
> +		return -EFAULT;
> +
> +	fence_state->sync_file = sync_file_create(fence);
> +	if (!fence_state->sync_file)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
> +int intel_wd_prepare_out_fence(struct drm_device *dev,
> +				struct drm_atomic_state *state)
> +{
> +	struct drm_connector *conn;
> +	struct drm_connector_state *conn_state;
> +	int i, ret;
> +
> +	drm_dbg_kms(dev, "\n");
> +
> +	for_each_new_connector_in_state(state, conn, conn_state, i) {
> +		struct intel_writeback_connector *wb_conn;
> +		struct intel_connector *intel_conn =
> +			to_intel_connector(conn);
> +		struct dma_fence *fence;
> +		struct intel_wd *intel_wd;
> +		struct intel_digital_connector_state *intel_conn_state =
> +			to_intel_digital_connector_state(conn_state);
> +		s32 __user *fence_ptr;
> +
> +		if (conn->connector_type !=
> DRM_MODE_CONNECTOR_WRITEBACK)
> +			continue;
> +
> +		if (!intel_conn_state->job)
> +			continue;
> +
> +		intel_wd = enc_to_intel_wd(intel_conn->encoder);
> +		fence_ptr = intel_get_out_fence_for_connector(state, conn);
> +		if (!fence_ptr)
> +			continue;
> +
> +		intel_wd->fence_state->out_fence_ptr = fence_ptr;
> +
> +		wb_conn = &intel_conn->wb_conn;
> +		fence = intel_writeback_get_out_fence(wb_conn);
> +		if (!fence)
> +			return -ENOMEM;
> +
> +		ret = intel_setup_out_fence(intel_wd->fence_state, fence);
> +		if (ret) {
> +			dma_fence_put(fence);
> +			return ret;
> +		}
> +
> +		intel_conn_state->job->out_fence = fence;
> +	}
> +
> +	return 0;
> +}
> +
> +void intel_wd_complete_signaling(struct intel_wd *intel_wd) {
> +	struct intel_out_fence_state *fence_state;
> +
> +	fence_state = intel_wd->fence_state;
> +	fd_install(fence_state->fd,
> +		fence_state->sync_file->file);
> +
> +}
> +
> +static int intel_set_writeback_property(struct drm_connector *connector,
> +	struct drm_connector_state *state, struct drm_property *property,
> +	uint64_t val)
> +{
> +	struct drm_device *dev = connector->dev;
> +	struct drm_i915_private *i915 = to_i915(dev);
> +
> +	if (property == i915->wb_fb_id_property) {
> +		struct drm_framebuffer *fb;
> +		int ret;
> +
> +		fb = intel_wb_framebuffer_lookup(dev, val);
> +		ret = intel_atomic_set_writeback_fb_for_connector(state,
> fb);
> +		if (fb)
> +			drm_framebuffer_put(fb);
> +		return ret;
> +	} else if (property == i915->wb_out_fence_ptr_property) {
> +		s32 __user *fence_ptr = u64_to_user_ptr(val);
> +
> +		return set_out_fence_for_connector(state->state, connector,
> +						fence_ptr);
> +	} else {
> +		drm_dbg_atomic(connector->dev,
> +			"[CONNECTOR:%d:%s] unknown property
> [PROP:%d:%s]]\n",
> +			connector->base.id, connector->name,
> +			property->base.id, property->name);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +
> +}
> +
> +static int intel_get_writeback_property(struct drm_connector *connector,
> +	const struct drm_connector_state *state, struct drm_property
> *property,
> +	uint64_t *val)
> +{
> +	struct drm_device *dev = connector->dev;
> +	struct drm_i915_private *i915 = to_i915(dev);
> +
> +	if (property == i915->wb_fb_id_property)
> +		*val = 0;
> +	else if (property == i915->wb_out_fence_ptr_property)
> +		*val = 0;
> +	else {
> +		drm_dbg_atomic(&i915->drm,
> +				"Unknown property [PROP:%d:%s]\n",
> +				property->base.id, property->name);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct drm_connector_funcs wd_connector_funcs = {
> +	.detect = intel_wb_connector_detect,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.destroy = intel_wd_connector_destroy,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.atomic_destroy_state =
> drm_atomic_helper_connector_destroy_state,
> +	.atomic_set_property = intel_set_writeback_property,
> +	.atomic_get_property = intel_get_writeback_property,
> +	.atomic_duplicate_state = intel_digital_connector_duplicate_state,
> +};
> +
> +static const struct drm_connector_helper_funcs
> wd_connector_helper_funcs = {
> +	.get_modes = intel_wd_get_modes,
> +	.mode_valid = intel_wd_mode_valid,
> +};
> +
> +static bool intel_fastset_dis(struct intel_encoder *encoder,
> +		struct intel_crtc_state *pipe_config) {
> +	pipe_config->uapi.mode_changed = true;
> +	drm_dbg_kms(encoder->base.dev, "\n");
> +	return false;
> +}
> +
> +void intel_wd_init(struct drm_i915_private *i915, enum transcoder
> +trans) {
> +	struct intel_wd *intel_wd;
> +	struct intel_encoder *encoder;
> +	struct intel_out_fence_state *fence_state;
> +	struct intel_connector *intel_connector;
> +	struct intel_writeback_connector *wb_conn;
> +	int n_formats = ARRAY_SIZE(wb_fmts);
> +	int err;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +	intel_wd = kzalloc(sizeof(*intel_wd), GFP_KERNEL);
> +	if (!intel_wd)
> +		return;
> +
> +	intel_connector = intel_connector_alloc();
> +	if (!intel_connector) {
> +		kfree(intel_wd);
> +		return;
> +	}
> +
> +	fence_state = kzalloc(sizeof(*fence_state), GFP_KERNEL);
> +	if (!intel_wd) {
> +		kfree(intel_wd);
> +		kfree(intel_connector);
> +		return;
> +	}
> +
> +	wb_conn = &intel_connector->wb_conn;
> +	wb_conn->base = &intel_connector->base;
> +	wb_conn->encoder = &intel_wd->base.base;
> +
> +	encoder = &intel_wd->base;
> +	intel_wd->attached_connector = intel_connector;
> +	intel_wd->fence_state = fence_state;
> +	intel_wd->trans = trans;
> +	intel_wd->triggered_cap_mode = 1;
> +	intel_wd->frame_num = 1;
> +	intel_wd->slicing_strategy = 1;
> +	encoder->get_config = intel_wd_get_config;
> +	encoder->compute_config = intel_wd_compute_config;
> +	encoder->get_hw_state = intel_wd_get_hw_state;
> +	encoder->type = INTEL_OUTPUT_WD;
> +	encoder->cloneable = 0;
> +	encoder->pipe_mask = ~0;
> +	encoder->power_domain = POWER_DOMAIN_TRANSCODER_B;
> +	encoder->get_power_domains = intel_wd_get_power_domains;
> +	encoder->initial_fastset_check = intel_fastset_dis;
> +	intel_connector->get_hw_state =
> +		intel_connector_get_hw_state;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +	err = intel_writeback_connector_init(&i915->drm, wb_conn,
> +		&wd_connector_funcs,
> +		&wd_encoder_helper_funcs,
> +		wb_fmts, n_formats);
> +
> +	if (err != 0) {
> +		drm_dbg_kms(&i915->drm,
> +		"intel_writeback_connector_init: Failed: %d\n",
> +			err);
> +		goto cleanup;
> +	}
> +
> +	drm_connector_helper_add(wb_conn->base,
> &wd_connector_helper_funcs);
> +	intel_connector_attach_encoder(intel_connector, encoder);
> +	wb_conn->base->status = connector_status_connected;
> +	return;
> +
> +cleanup:
> +	kfree(intel_wd);
> +	intel_connector_free(intel_connector);
> +}
> +
> +static void intel_wd_writeback_complete(struct intel_wd *intel_wd,
> +	struct intel_writeback_job *job, int status) {
> +	struct intel_writeback_connector *wb_conn =
> +		&intel_wd->attached_connector->wb_conn;
> +	intel_writeback_signal_completion(wb_conn, status);
> +	intel_wd_complete_signaling(intel_wd);
> +}
> +
> +static int intel_wd_setup_transcoder(struct intel_wd *intel_wd,
> +		struct intel_crtc_state *pipe_config,
> +		struct intel_writeback_job *job)
> +{
> +	struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
> +	enum pipe pipe = intel_crtc->pipe;
> +	struct drm_framebuffer *fb;
> +	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
> +	struct drm_gem_object *wd_fb_obj;
> +	int ret;
> +	u32 stride, tmp;
> +	u16 hactive, vactive;
> +
> +	fb = job->fb;
> +	wd_fb_obj = fb->obj[0];
> +	if (!wd_fb_obj) {
> +		drm_dbg_kms(&dev_priv->drm, "No framebuffer gem object
> created\n");
> +		return -1;
> +	}
> +	ret = intel_wd_pin_fb(intel_wd, fb);
> +	drm_WARN_ON(&dev_priv->drm, ret != 0);
> +
> +	/*Write stride and surface registers in that particular order*/
> +	stride = intel_wd_get_stride(pipe_config, fb->format->format);
> +
> +	tmp = intel_de_read(dev_priv, WD_STRIDE(intel_wd->trans));
> +	tmp &= ~WD_STRIDE_MASK;
> +	tmp |= (stride << WD_STRIDE_SHIFT);
> +
> +	intel_de_write(dev_priv, WD_STRIDE(intel_wd->trans), tmp);
> +
> +	tmp = intel_de_read(dev_priv, WD_SURF(intel_wd->trans));
> +	drm_dbg_kms(&dev_priv->drm, "%d is the surface address\n", tmp);
> +
> +	intel_de_write(dev_priv, WD_SURF(intel_wd->trans),
> +			i915_ggtt_offset(intel_wd->vma));
> +
> +	tmp = intel_de_read_fw(dev_priv, WD_IIR(intel_wd->trans));
> +	intel_de_write_fw(dev_priv, WD_IIR(intel_wd->trans), tmp);
> +
> +	tmp =
> ~(WD_GTT_FAULT_INT|WD_WRITE_COMPLETE_INT|WD_FRAME_COMPLET
> E_INT|
> +
> 	WD_VBLANK_INT|WD_OVERRUN_INT|WD_CAPTURING_INT);
> +	intel_de_write_fw(dev_priv, WD_IMR(intel_wd->trans), tmp);
> +
> +	if (intel_wd->stream_cap) {
> +		tmp = intel_de_read(dev_priv,
> +				WD_STREAMCAP_CTL(intel_wd->trans));
> +		tmp |= WD_STREAM_CAP_MODE_EN;
> +		intel_configure_slicing_strategy(dev_priv, intel_wd, &tmp);
> +	}
> +
> +	hactive = pipe_config->uapi.mode.hdisplay;
> +	vactive = pipe_config->uapi.mode.vdisplay;
> +
> +	drm_dbg_kms(&dev_priv->drm, "hactive : %d, vactive: %d\n",
> hactive,
> +vactive);
> +
> +	tmp = intel_de_read(dev_priv, HTOTAL(intel_wd->trans));
> +	drm_dbg_kms(&dev_priv->drm, "hactive_reg : %d\n", tmp);
> +	tmp = intel_de_read(dev_priv, VTOTAL(intel_wd->trans));
> +	drm_dbg_kms(&dev_priv->drm, "vactive_reg : %d\n", tmp);
> +	/* minimum hactive as per bspec: 64 pixels*/
> +	if (hactive < 64)
> +		drm_err(&dev_priv->drm, "hactive is less then 64 pixels\n");
> +
> +	intel_de_write(dev_priv, HTOTAL(intel_wd->trans), hactive - 1);
> +	intel_de_write(dev_priv, VTOTAL(intel_wd->trans), vactive - 1);
> +
> +	tmp = intel_de_read(dev_priv, WD_TRANS_FUNC_CTL(intel_wd-
> >trans));
> +	/* select pixel format */
> +	tmp &= ~WD_PIX_FMT_MASK;
> +
> +	switch (fb->format->format) {
> +	default:
> +	fallthrough;
> +	case DRM_FORMAT_YUYV:
> +		tmp |= WD_PIX_FMT_YUYV;
> +		break;
> +	case DRM_FORMAT_XYUV8888:
> +		tmp |= WD_PIX_FMT_XYUV8888;
> +		break;
> +	case DRM_FORMAT_XBGR8888:
> +		tmp |= WD_PIX_FMT_XBGR8888;
> +		break;
> +	case DRM_FORMAT_Y410:
> +		tmp |= WD_PIX_FMT_Y410;
> +		break;
> +	case DRM_FORMAT_YUV422:
> +		tmp |= WD_PIX_FMT_YUV422;
> +		break;
> +	case DRM_FORMAT_XBGR2101010:
> +		tmp |= WD_PIX_FMT_XBGR2101010;
> +		break;
> +	case DRM_FORMAT_RGB565:
> +		tmp |= WD_PIX_FMT_RGB565;
> +		break;
> +	}
> +
> +	if (intel_wd->triggered_cap_mode)
> +		tmp |= WD_TRIGGERED_CAP_MODE_ENABLE;
> +
> +	if (intel_wd->stream_cap)
> +		tmp |= WD_CTL_POINTER_DTDH;
> +
> +	/*select input pipe*/
> +	tmp &= ~WD_INPUT_SELECT_MASK;
> +	drm_dbg_kms(&dev_priv->drm, "Selected pipe is %d\n", pipe);
> +	switch (pipe) {
> +	default:
> +		fallthrough;
> +	case PIPE_A:
> +		tmp |= WD_INPUT_PIPE_A;
> +		break;
> +	case PIPE_B:
> +		tmp |= WD_INPUT_PIPE_B;
> +		break;
> +	case PIPE_C:
> +		tmp |= WD_INPUT_PIPE_C;
> +		break;
> +	case PIPE_D:
> +		tmp |= WD_INPUT_PIPE_D;
> +		break;
> +	}
> +
> +	/* enable DDI buffer */
> +	if (!(tmp & TRANS_WD_FUNC_ENABLE))
> +		tmp |= TRANS_WD_FUNC_ENABLE;
> +
> +	intel_de_write(dev_priv, WD_TRANS_FUNC_CTL(intel_wd->trans),
> tmp);
> +
> +	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
> +	ret = tmp & WD_TRANS_ACTIVE;
> +	drm_dbg_kms(&dev_priv->drm, "Trancoder enabled: %s\n", ret ?
> +"true":"false");
> +
> +	if (!ret) {
> +		/*enable the transcoder	*/
> +		tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
> +		tmp |= WD_TRANS_ENABLE;
> +		intel_de_write(dev_priv, PIPECONF(intel_wd->trans), tmp);
> +
> +		/* wait for transcoder to be enabled */
> +		if (intel_de_wait_for_set(dev_priv, PIPECONF(intel_wd-
> >trans),
> +				WD_TRANS_ACTIVE, 10))
> +			drm_err(&dev_priv->drm, "WD transcoder not
> enabled\n");
> +	}
> +
> +	return 0;
> +}
> +
> +static void intel_wd_disable_capture(struct intel_wd *intel_wd) {
> +	struct drm_i915_private *dev_priv = to_i915(intel_wd-
> >base.base.dev);
> +	u32 tmp;
> +
> +	intel_de_write_fw(dev_priv, WD_IMR(intel_wd->trans), 0xFF);
> +	tmp = intel_de_read(dev_priv, PIPECONF(intel_wd->trans));
> +	tmp &= WD_TRANS_DISABLE;
> +	intel_de_write(dev_priv, PIPECONF(intel_wd->trans), tmp);
> +
> +	drm_dbg_kms(&dev_priv->drm, "WD Trans_Conf value after disable
> = 0x%08x\n",
> +		intel_de_read(dev_priv, PIPECONF(intel_wd->trans)));
> +	tmp = intel_de_read(dev_priv, WD_TRANS_FUNC_CTL(intel_wd-
> >trans));
> +	tmp |= ~TRANS_WD_FUNC_ENABLE;
> +}
> +
> +static int intel_wd_capture(struct intel_wd *intel_wd,
> +		struct intel_crtc_state *pipe_config,
> +		struct intel_writeback_job *job)
> +{
> +	u32 tmp;
> +	struct drm_i915_private *i915 = to_i915(intel_wd->base.base.dev);
> +	int ret = 0, status = 0;
> +	struct intel_crtc *wd_crtc = intel_wd->wd_crtc;
> +	unsigned long flags;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +
> +	if (!job->out_fence)
> +		drm_dbg_kms(&i915->drm, "Not able to get out_fence for
> job\n");
> +
> +	ret = intel_wd_setup_transcoder(intel_wd, pipe_config, job);
> +
> +	if (ret < 0) {
> +		drm_dbg_kms(&i915->drm,
> +		"wd transcoder setup not completed aborting capture\n");
> +		return -1;
> +	}
> +
> +	if (wd_crtc == NULL) {
> +		DRM_ERROR("CRTC not attached\n");
> +		return -1;
> +	}
> +
> +	tmp = intel_de_read_fw(i915,
> +			WD_TRANS_FUNC_CTL(intel_wd->trans));
> +	tmp |= START_TRIGGER_FRAME;
> +	tmp &= ~WD_FRAME_NUMBER_MASK;
> +	tmp |= intel_wd->frame_num;
> +	intel_de_write_fw(i915,
> +			WD_TRANS_FUNC_CTL(intel_wd->trans), tmp);
> +
> +	if (!intel_de_wait_for_set(i915, WD_IIR(intel_wd->trans),
> +				WD_FRAME_COMPLETE_INT, 100)){
> +		drm_dbg_kms(&i915->drm, "frame captured\n");
> +		tmp = intel_de_read(i915, WD_IIR(intel_wd->trans));
> +		drm_dbg_kms(&i915->drm, "iir value : %d\n", tmp);
> +		status = 0;
> +	} else {
> +		drm_dbg_kms(&i915->drm, "frame not captured triggering
> stop frame\n");
> +		tmp = intel_de_read(i915,
> +				WD_TRANS_FUNC_CTL(intel_wd->trans));
> +		tmp |= STOP_TRIGGER_FRAME;
> +		intel_de_write(i915,
> +				WD_TRANS_FUNC_CTL(intel_wd->trans),
> tmp);
> +		status = -1;
> +	}
> +
> +	intel_de_write(i915, WD_IIR(intel_wd->trans), tmp);
> +	intel_wd_writeback_complete(intel_wd, job, status);
> +	if (intel_get_writeback_job_from_queue(intel_wd) == NULL)
> +		intel_wd_disable_capture(intel_wd);
> +	if (wd_crtc->wd.e) {
> +		spin_lock_irqsave(&i915->drm.event_lock, flags);
> +		drm_dbg_kms(&i915->drm, "send %p\n", wd_crtc->wd.e);
> +		drm_crtc_send_vblank_event(&wd_crtc->base,
> +					wd_crtc->wd.e);
> +		spin_unlock_irqrestore(&i915->drm.event_lock, flags);
> +		wd_crtc->wd.e = NULL;
> +	} else {
> +		DRM_ERROR("Event NULL! %p, %p\n", &i915->drm,
> +			wd_crtc);
> +	}
> +	return 0;
> +
> +}
> +
> +void intel_wd_enable_capture(struct intel_encoder *encoder,
> +		struct intel_crtc_state *pipe_config,
> +		struct drm_connector_state *conn_state) {
> +	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +	struct intel_wd *intel_wd = enc_to_intel_wd(encoder);
> +	struct intel_writeback_job *job;
> +
> +	drm_dbg_kms(&i915->drm, "\n");
> +
> +	job = intel_get_writeback_job_from_queue(intel_wd);
> +	if (job == NULL) {
> +		drm_dbg_kms(&i915->drm,
> +			"job queue is empty not capturing any frame\n");
> +		return;
> +	}
> +
> +	intel_wd_capture(intel_wd, pipe_config, job);
> +	intel_wd->frame_num += 1;
> +
> +}
> +
> +void intel_wd_set_vblank_event(struct intel_crtc *intel_crtc,
> +			struct intel_crtc_state *intel_crtc_state) {
> +	struct drm_i915_private *i915 = to_i915(intel_crtc->base.dev);
> +	struct drm_crtc_state *state = &intel_crtc_state->uapi;
> +	struct intel_encoder *encoder;
> +	struct intel_wd *intel_wd;
> +
> +	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
> +		intel_wd = enc_to_intel_wd(encoder);
> +
> +		if (!intel_wd->wd_crtc) {
> +			drm_dbg_kms(&i915->drm, "wd crtc not found\n");
> +			return;
> +		}
> +	}
> +
> +	if (intel_crtc == intel_wd->wd_crtc) {
> +		intel_crtc->wd.e = state->event;
> +		state->event = NULL;
> +		if (intel_crtc->wd.e)
> +			drm_dbg_kms(&i915->drm, "WD event:%p\n",
> +				intel_crtc->wd.e);
> +		else
> +			drm_dbg_kms(&i915->drm, "WD no event\n");
> +	}
> +}
> +
> +void intel_wd_handle_isr(struct drm_i915_private *i915) {
> +	u32 iir_value = 0;
> +	struct intel_encoder *encoder;
> +	struct intel_wd *intel_wd;
> +
> +	iir_value = intel_de_read(i915, WD_IIR(TRANSCODER_WD_0));
> +	drm_dbg_kms(&i915->drm, "\n");
> +
> +	for_each_intel_encoder_with_wd(&i915->drm, encoder) {
> +		intel_wd = enc_to_intel_wd(encoder);
> +
> +		if (!intel_wd->wd_crtc) {
> +			DRM_ERROR("NO CRTC attached with WD\n");
> +			goto clear_iir;
> +		}
> +	}
> +
> +	if (iir_value & WD_VBLANK_INT)
> +		drm_dbg_kms(&i915->drm, "vblank interrupt for wd
> transcoder\n");
> +	if (iir_value & WD_WRITE_COMPLETE_INT)
> +		drm_dbg_kms(&i915->drm,
> +		"wd write complete interrupt encountered\n");
> +	else
> +		DRM_INFO("iir: %x\n", iir_value);
> +	if (iir_value & WD_FRAME_COMPLETE_INT) {
> +		drm_dbg_kms(&i915->drm,
> +			"frame complete interrupt for wd transcoder\n");
> +		return;
> +	}
> +clear_iir:
> +	intel_de_write(i915, WD_IIR(TRANSCODER_WD_0), iir_value); }
> diff --git a/drivers/gpu/drm/i915/display/intel_wd.h
> b/drivers/gpu/drm/i915/display/intel_wd.h
> new file mode 100644
> index 000000000000..2309afa23bb8
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_wd.h
> @@ -0,0 +1,82 @@
> +/* SPDX-License-Identifier: GPL-2.0
> + * Copyright © 2021 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a
> + * copy of this software and associated documentation files (the
> +"Software"),
> + * to deal in the Software without restriction, including without
> +limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> +sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom
> +the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> +next
> + * paragraph) shall be included in all copies or substantial portions
> +of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO
> EVENT
> +SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> DAMAGES OR
> +OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> +ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Author :
> + *	Suraj Kandpal<suraj.kandpal@intel.com>
> + *	Arun Murthy<arun.r.murthy@intel.com>
> + */
> +
> +#ifndef _INTEL_WD_H
> +#define _INTEL_WD_H
> +
> +#include <drm/drm_crtc.h>
> +#include <linux/sync_file.h>
> +
> +#include "intel_display_types.h"
> +
> +#define I915_MAX_WD_TANSCODERS 2
> +
> +struct intel_out_fence_state {
> +	s32 __user *out_fence_ptr;
> +	struct sync_file *sync_file;
> +	int fd;
> +};
> +
> +struct intel_wd {
> +	struct intel_encoder base;
> +	struct intel_crtc *wd_crtc;
> +	struct intel_out_fence_state *fence_state;
> +	intel_wakeref_t io_wakeref[I915_MAX_WD_TANSCODERS];
> +	struct intel_connector *attached_connector;
> +	enum transcoder trans;
> +	struct i915_vma *vma;
> +	unsigned long flags;
> +	struct intel_writeback_job *job;
> +	int triggered_cap_mode;
> +	int frame_num;
> +	bool stream_cap;
> +	bool start_capture;
> +	int slicing_strategy;
> +};
> +
> +struct intel_wd_clk_vals {
> +	u32 cdclk;
> +	u16 link_m;
> +	u16 link_n;
> +};
> +
> +extern struct sync_file *sync_file_create(struct dma_fence *fence);
> +static inline struct intel_wd *enc_to_intel_wd(struct intel_encoder
> +*encoder) {
> +	return container_of(&encoder->base, struct intel_wd, base.base); }
> +void intel_wd_init(struct drm_i915_private *dev_priv, enum transcoder
> +trans); void intel_wd_enable_capture(struct intel_encoder *encoder,
> +				struct intel_crtc_state *pipe_config,
> +				struct drm_connector_state *conn_state);
> void
> +intel_wd_handle_isr(struct drm_i915_private *dev_priv); void
> +intel_wd_set_vblank_event(struct intel_crtc *crtc,
> +				struct intel_crtc_state *state);
> +int intel_wd_prepare_out_fence(struct drm_device *dev,
> +				struct drm_atomic_state *state);
> +void intel_wd_complete_signaling(struct intel_wd *intel_wd);
> +#endif/* _INTEL_WD_H */
> diff --git a/drivers/gpu/drm/i915/i915_drv.h
> b/drivers/gpu/drm/i915/i915_drv.h index 9a86ee88089e..b7e92a18125c
> 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -38,6 +38,8 @@
>  #include <linux/pm_qos.h>
> 
>  #include <drm/drm_connector.h>
> +#include <drm/drm_writeback.h>
> +#include <drm/i915_mei_hdcp_interface.h>
>  #include <drm/ttm/ttm_device.h>
> 
>  #include "display/intel_bios.h"
> diff --git a/drivers/gpu/drm/i915/i915_irq.c
> b/drivers/gpu/drm/i915/i915_irq.c index 73cebc6aa650..95a6a8f7a911
> 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -42,6 +42,7 @@
>  #include "display/intel_hotplug.h"
>  #include "display/intel_lpe_audio.h"
>  #include "display/intel_psr.h"
> +#include "display/intel_wd.h"
> 
>  #include "gt/intel_breadcrumbs.h"
>  #include "gt/intel_gt.h"
> @@ -2342,6 +2343,11 @@ gen8_de_misc_irq_handler(struct
> drm_i915_private *dev_priv, u32 iir)
>  		found = true;
>  	}
> 
> +	if (iir & GEN8_DE_MISC_WD0) {
> +		intel_wd_handle_isr(dev_priv);
> +		found = true;
> +	}
> +
>  	if (iir & GEN8_DE_EDP_PSR) {
>  		struct intel_encoder *encoder;
>  		u32 psr_iir;
> @@ -3767,7 +3773,7 @@ static void gen8_de_irq_postinstall(struct
> drm_i915_private *dev_priv)
>  	u32 de_pipe_enables;
>  	u32 de_port_masked = gen8_de_port_aux_mask(dev_priv);
>  	u32 de_port_enables;
> -	u32 de_misc_masked = GEN8_DE_EDP_PSR;
> +	u32 de_misc_masked = GEN8_DE_EDP_PSR | GEN8_DE_MISC_WD0;
>  	u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
>  		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
>  	enum pipe pipe;
> diff --git a/drivers/gpu/drm/i915/i915_pci.c
> b/drivers/gpu/drm/i915/i915_pci.c index 67b89769f577..a524e0f030b6
> 100644
> --- a/drivers/gpu/drm/i915/i915_pci.c
> +++ b/drivers/gpu/drm/i915/i915_pci.c
> @@ -853,7 +853,8 @@ static const struct intel_device_info jsl_info = {
>  	.display.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) |
> BIT(PIPE_D), \
>  	.display.cpu_transcoder_mask = BIT(TRANSCODER_A) |
> BIT(TRANSCODER_B) | \
>  		BIT(TRANSCODER_C) | BIT(TRANSCODER_D) | \
> -		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1), \
> +		BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1)| \
> +		BIT(TRANSCODER_WD_0), \
>  	.pipe_offsets = { \
>  		[TRANSCODER_A] = PIPE_A_OFFSET, \
>  		[TRANSCODER_B] = PIPE_B_OFFSET, \
> @@ -861,6 +862,8 @@ static const struct intel_device_info jsl_info = {
>  		[TRANSCODER_D] = PIPE_D_OFFSET, \
>  		[TRANSCODER_DSI_0] = PIPE_DSI0_OFFSET, \
>  		[TRANSCODER_DSI_1] = PIPE_DSI1_OFFSET, \
> +		[TRANSCODER_WD_0] = PIPE_WD0_OFFSET, \
> +		[TRANSCODER_WD_1] = PIPE_WD1_OFFSET, \
>  	}, \
>  	.trans_offsets = { \
>  		[TRANSCODER_A] = TRANSCODER_A_OFFSET, \ @@ -869,6
> +872,8 @@ static const struct intel_device_info jsl_info = {
>  		[TRANSCODER_D] = TRANSCODER_D_OFFSET, \
>  		[TRANSCODER_DSI_0] = TRANSCODER_DSI0_OFFSET, \
>  		[TRANSCODER_DSI_1] = TRANSCODER_DSI1_OFFSET, \
> +		[TRANSCODER_WD_0] = TRANSCODER_WD0_OFFSET, \
> +		[TRANSCODER_WD_1] = TRANSCODER_WD1_OFFSET, \
>  	}, \
>  	TGL_CURSOR_OFFSETS, \
>  	.has_global_mocs = 1, \
> diff --git a/drivers/gpu/drm/i915/i915_reg.h
> b/drivers/gpu/drm/i915/i915_reg.h index 6396afd77209..abc41e7de0b5
> 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3797,6 +3797,11 @@
>  #define PIPE_DSI0_OFFSET	0x7b000
>  #define PIPE_DSI1_OFFSET	0x7b800
> 
> +/* WD 0 and 1 */
> +#define PIPE_WD0_OFFSET		0x7e000
> +#define PIPE_WD1_OFFSET		0x7d000
> +
> +
>  #define PIPECONF(pipe)		_MMIO_PIPE2(pipe, _PIPEACONF)
>  #define PIPEDSL(pipe)		_MMIO_PIPE2(pipe, _PIPEADSL)
>  #define PIPEFRAME(pipe)		_MMIO_PIPE2(pipe,
> _PIPEAFRAMEHIGH)
> @@ -4461,6 +4466,10 @@
>  #define _PIPEDSI0CONF		0x7b008
>  #define _PIPEDSI1CONF		0x7b808
> 
> +/* WD 0 and 1 */
> +#define _PIPEWD0CONF		0x7e008
> +#define _PIPEWD1CONF		0x7d008
> +
>  /* Sprite A control */
>  #define _DVSACNTR		0x72180
>  #define   DVS_ENABLE			REG_BIT(31)
> @@ -5707,6 +5716,7 @@
>  #define GEN8_DE_MISC_IER _MMIO(0x4446c)
>  #define  GEN8_DE_MISC_GSE		(1 << 27)
>  #define  GEN8_DE_EDP_PSR		(1 << 19)
> +#define  GEN8_DE_MISC_WD0		(1 << 23)
> 
>  #define GEN8_PCU_ISR _MMIO(0x444e0)
>  #define GEN8_PCU_IMR _MMIO(0x444e4)
> @@ -8847,6 +8857,133 @@ enum skl_power_gate {
>  #define   DSB_ENABLE			(1 << 31)
>  #define   DSB_STATUS			(1 << 0)
> 
> +#define TGL_ROOT_DEVICE_ID		0x9A00
> +#define TGL_ROOT_DEVICE_MASK		0xFF00
> +#define TGL_ROOT_DEVICE_SKU_MASK	0xF
> +#define TGL_ROOT_DEVICE_SKU_ULX		0x2
> +#define TGL_ROOT_DEVICE_SKU_ULT		0x4
> +
> +/* Gen12 WD */
> +#define _MMIO_WD(tc, wd0, wd1)		_MMIO_TRANS((tc) -
> TRANSCODER_WD_0, \
> +							wd0, wd1)
> +
> +#define WD_TRANS_ENABLE			(1 << 31)
> +#define WD_TRANS_DISABLE		0
> +#define WD_TRANS_ACTIVE			(1 << 30)
> +
> +/* WD transcoder control */
> +#define _WD_TRANS_FUNC_CTL_0		0x6e400
> +#define _WD_TRANS_FUNC_CTL_1		0x6ec00
> +#define WD_TRANS_FUNC_CTL(tc)		_MMIO_WD(tc,\
> +					_WD_TRANS_FUNC_CTL_0,\
> +					_WD_TRANS_FUNC_CTL_1)
> +
> +#define TRANS_WD_FUNC_ENABLE		(1 << 31)
> +#define WD_TRIGGERED_CAP_MODE_ENABLE	(1 << 30)
> +#define START_TRIGGER_FRAME		(1 << 29)
> +#define STOP_TRIGGER_FRAME		(1 << 28)
> +#define WD_CTL_POINTER_ETEH		(0 << 18)
> +#define WD_CTL_POINTER_ETDH		(1 << 18)
> +#define WD_CTL_POINTER_DTDH		(2 << 18)
> +#define WD_INPUT_SELECT_MASK		(7 << 12)
> +#define WD_INPUT_PIPE_A			(0 << 12)
> +#define WD_INPUT_PIPE_B			(5 << 12)
> +#define WD_INPUT_PIPE_C			(6 << 12)
> +#define WD_INPUT_PIPE_D			(7 << 12)
> +
> +#define WD_PIX_FMT_MASK			(0x3 << 20)
> +#define WD_PIX_FMT_YUYV			(0x1 << 20)
> +#define WD_PIX_FMT_XYUV8888		(0x2 << 20)
> +#define WD_PIX_FMT_XBGR8888		(0x3 << 20)
> +#define WD_PIX_FMT_Y410			(0x4 << 20)
> +#define WD_PIX_FMT_YUV422		(0x5 << 20)
> +#define WD_PIX_FMT_XBGR2101010		(0x6 << 20)
> +#define WD_PIX_FMT_RGB565		(0x7 << 20)
> +
> +#define WD_FRAME_NUMBER_MASK		15
> +
> +#define _WD_STRIDE_0			0x6e510
> +#define _WD_STRIDE_1			0x6ed10
> +#define WD_STRIDE(tc)			_MMIO_WD(tc,\
> +					_WD_STRIDE_0,\
> +					_WD_STRIDE_1)
> +#define WD_STRIDE_SHIFT			6
> +#define WD_STRIDE_MASK			(0x3ff << WD_STRIDE_SHIFT)
> +
> +#define _WD_STREAMCAP_CTL0		0x6e590
> +#define _WD_STREAMCAP_CTL1		0x6ed90
> +#define WD_STREAMCAP_CTL(tc)		_MMIO_WD(tc,\
> +					_WD_STREAMCAP_CTL0,\
> +					_WD_STREAMCAP_CTL1)
> +
> +#define WD_STREAM_CAP_MODE_EN		(1 << 31)
> +#define WD_STRAT_MASK			(3 << 24)
> +#define WD_SLICING_STRAT_1_1		(0 << 24)
> +#define WD_SLICING_STRAT_2_1		(1 << 24)
> +#define WD_SLICING_STRAT_4_1		(2 << 24)
> +#define WD_SLICING_STRAT_8_1		(3 << 24)
> +#define WD_STREAM_OVERRUN_STATUS	1
> +
> +#define _WD_SURF_0			0x6e514
> +#define _WD_SURF_1			0x6ed14
> +#define WD_SURF(tc)			_MMIO_WD(tc,\
> +					_WD_SURF_0,\
> +					_WD_SURF_1)
> +
> +#define _WD_IMR_0			0x6e560
> +#define _WD_IMR_1			0x6ed60
> +#define WD_IMR(tc)			_MMIO_WD(tc,\
> +					_WD_IMR_0,\
> +					_WD_IMR_1)
> +#define WD_FRAME_COMPLETE_INT		(1 << 7)
> +#define WD_GTT_FAULT_INT		(1 << 6)
> +#define WD_VBLANK_INT			(1 << 5)
> +#define WD_OVERRUN_INT			(1 << 4)
> +#define WD_CAPTURING_INT		(1 << 3)
> +#define WD_WRITE_COMPLETE_INT		(1 << 2)
> +
> +#define _WD_IIR_0			0x6e564
> +#define _WD_IIR_1			0x6ed64
> +#define WD_IIR(tc)			_MMIO_WD(tc,\
> +					_WD_IIR_0,\
> +					_WD_IIR_1)
> +
> +#define _WD_FRAME_STATUS_0		0x6e56b
> +#define _WD_FRAME_STATUS_1		0x6ed6b
> +#define WD_FRAME_STATUS(tc)		_MMIO_WD(tc,\
> +					_WD_FRAME_STATUS_0,\
> +					_WD_FRAME_STATUS_1)
> +
> +#define WD_FRAME_COMPLETE		(1 << 31)
> +#define WD_STATE_IDLE			(0 << 24)
> +#define WD_STATE_CAPSTART		(1 << 24)
> +#define WD_STATE_FRAME_START		(2 << 24)
> +#define WD_STATE_CAPACITIVE		(3 << 24)
> +#define WD_STATE_TG_DONE		(4 << 24)
> +#define WD_STATE_WDX_DONE		(5 << 24)
> +#define WD_STATE_QUICK_CAP		(6 << 24)
> +
> +#define _WD_27_M_0			0x6e524
> +#define _WD_27_M_1			0x6ed24
> +#define WD_27_M(tc)			_MMIO_WD(tc,\
> +					_WD_27_M_0,\
> +					_WD_27_M_1)
> +
> +#define _WD_27_N_0			0x6e528
> +
> +//Address looks wrong in bspec:
> +#define _WD_27_N_1			0x6ec28
> +#define WD_27_N(tc)			_MMIO_WD(tc,\
> +					_WD_27_N_0,\
> +					_WD_27_N_1)
> +
> +#define _WD_TAIL_CFG_0			0x6e520
> +#define _WD_TAIL_CFG_1			0x6ed20
> +
> +#define WD_TAIL_CFG(tc)			_MMIO_WD(tc,\
> +					_WD_TAIL_CFG_0,\
> +					_WD_TAIL_CFG_1)
> +
>  #define CLKREQ_POLICY			_MMIO(0x101038)
>  #define  CLKREQ_POLICY_MEM_UP_OVRD	REG_BIT(1)
> 
> --
> 2.35.1


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

* Re: [Intel-gfx] [RFC PATCH v2 2/3] drm/i915: Define WD trancoder for i915
  2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 2/3] drm/i915: Define WD trancoder for i915 Suraj Kandpal
@ 2022-04-06  5:00     ` Kandpal, Suraj
  0 siblings, 0 replies; 24+ messages in thread
From: Kandpal, Suraj @ 2022-04-06  5:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Nikula, Jani

Hi All,
++Uma

Regards,
Suraj Kandpal

> -----Original Message-----
> From: Kandpal, Suraj <suraj.kandpal@intel.com>
> Sent: Thursday, March 17, 2022 2:09 PM
> To: intel-gfx@lists.freedesktop.org
> Cc: Nikula, Jani <jani.nikula@intel.com>; ville.syrjala@linux.intel.com;
> Murthy, Arun R <arun.r.murthy@intel.com>; Kandpal, Suraj
> <suraj.kandpal@intel.com>
> Subject: [RFC PATCH v2 2/3] drm/i915: Define WD trancoder for i915
> 
> Adding WD Types, WD transcoder to enum list and WD Transcoder offsets
> 
> Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.h       | 6 ++++++
>  drivers/gpu/drm/i915/display/intel_display_types.h | 1 +
>  drivers/gpu/drm/i915/i915_reg.h                    | 2 ++
>  3 files changed, 9 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h
> b/drivers/gpu/drm/i915/display/intel_display.h
> index 8513703086b7..8c93a5de8e07 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -119,6 +119,8 @@ enum transcoder {
>  	TRANSCODER_DSI_1,
>  	TRANSCODER_DSI_A = TRANSCODER_DSI_0,	/* legacy DSI */
>  	TRANSCODER_DSI_C = TRANSCODER_DSI_1,	/* legacy DSI */
> +	TRANSCODER_WD_0,
> +	TRANSCODER_WD_1,
> 
>  	I915_MAX_TRANSCODERS
>  };
> @@ -140,6 +142,10 @@ static inline const char *transcoder_name(enum
> transcoder transcoder)
>  		return "DSI A";
>  	case TRANSCODER_DSI_C:
>  		return "DSI C";
> +	case TRANSCODER_WD_0:
> +		return "WD 0";
> +	case TRANSCODER_WD_1:
> +		return "WD 1";
>  	default:
>  		return "<invalid>";
>  	}
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 7a96ecba73c0..dcb4ad43cf88 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -79,6 +79,7 @@ enum intel_output_type {
>  	INTEL_OUTPUT_DSI = 9,
>  	INTEL_OUTPUT_DDI = 10,
>  	INTEL_OUTPUT_DP_MST = 11,
> +	INTEL_OUTPUT_WD = 12,
>  };
> 
>  enum hdmi_force_audio {
> diff --git a/drivers/gpu/drm/i915/i915_reg.h
> b/drivers/gpu/drm/i915/i915_reg.h index ddbc7a685a50..6396afd77209
> 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -2023,6 +2023,8 @@
>  #define TRANSCODER_EDP_OFFSET 0x6f000
>  #define TRANSCODER_DSI0_OFFSET	0x6b000
>  #define TRANSCODER_DSI1_OFFSET	0x6b800
> +#define TRANSCODER_WD0_OFFSET	0x6e000
> +#define TRANSCODER_WD1_OFFSET	0x6e800
> 
>  #define HTOTAL(trans)		_MMIO_TRANS2(trans, _HTOTAL_A)
>  #define HBLANK(trans)		_MMIO_TRANS2(trans, _HBLANK_A)
> --
> 2.35.1


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

end of thread, other threads:[~2022-04-06  5:00 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-16  9:37 [Intel-gfx] [RFC PATCH 0/3] i915 writeback private framework Suraj Kandpal
2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework Suraj Kandpal
2022-03-16 14:25   ` kernel test robot
2022-03-18  4:18   ` [Intel-gfx] [RFC PATCH v2 " Suraj Kandpal
2022-04-06  4:58     ` Kandpal, Suraj
2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 2/3] drm/i915: Define WD trancoder for i915 Suraj Kandpal
2022-03-18  4:20   ` [Intel-gfx] [RFC PATCH v2 " Suraj Kandpal
2022-03-16  9:37 ` [Intel-gfx] [RFC PATCH 3/3] drm/i915: Enabling WD Transcoder Suraj Kandpal
2022-03-18  4:21   ` [Intel-gfx] [RFC PATCH v2 " Suraj Kandpal
2022-03-25  5:35     ` Kandpal, Suraj
2022-03-16  9:51 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915 writeback private framework Patchwork
2022-03-16  9:52 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2022-03-16 10:07 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
2022-03-17  8:39 ` [Intel-gfx] [RFC PATCH v2 0/3] " Suraj Kandpal
2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 1/3] drm/i915: Creating writeback pipeline to bypass drm_writeback framework Suraj Kandpal
2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 2/3] drm/i915: Define WD trancoder for i915 Suraj Kandpal
2022-04-06  5:00     ` Kandpal, Suraj
2022-03-17  8:39   ` [Intel-gfx] [RFC PATCH v2 3/3] drm/i915: Enabling WD Transcoder Suraj Kandpal
2022-04-06  4:58     ` Kandpal, Suraj
2022-04-06  4:56   ` [Intel-gfx] [RFC PATCH v2 0/3] i915 writeback private framework Kandpal, Suraj
2022-03-18  4:48 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for i915 writeback private framework (rev4) Patchwork
2022-03-18  4:49 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2022-03-18  5:20 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2022-03-18  8:29 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork

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.