All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] drm/amdgpu: modernize virtual display feature
@ 2021-07-21 17:07 ` Ryan Taylor
  0 siblings, 0 replies; 24+ messages in thread
From: Ryan Taylor @ 2021-07-21 17:07 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: melissa.srw, daniel.vetter, rodrigo.siqueira, Ryan Taylor

The amdgpu vkms interface provides a virtual KMS interface for several use
cases: devices without display hardware, platforms where the actual display
hardware is not useful (e.g., servers), SR-IOV virtual functions, device
emulation/simulation, and device bring up prior to display hardware being
usable. We previously emulated a legacy KMS interface, but there was a desire
to move to the atomic KMS interface. The vkms driver did everything we
needed, but we wanted KMS support natively in the driver without buffer
sharing and the ability to support an instance of VKMS per device. We first
looked at splitting vkms into a stub driver and a helper module that other
drivers could use to implement a virtual display, but this strategy ended up
being messy due to driver specific callbacks needed for buffer management.
Ultimately, it proved easier to import the vkms code as it mostly used core
drm helpers anyway.

Ryan Taylor (3):
  drm/amdgpu: create amdgpu_vkms (v2)
  drm/amdgpu: cleanup dce_virtual
  drm/amdgpu: replace dce_virtual with amdgpu_vkms (v3)

 drivers/gpu/drm/amd/amdgpu/Makefile      |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 639 +++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |  26 +
 drivers/gpu/drm/amd/amdgpu/cik.c         |  10 +-
 drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 780 -----------------------
 drivers/gpu/drm/amd/amdgpu/dce_virtual.h |  30 -
 drivers/gpu/drm/amd/amdgpu/nv.c          |  20 +-
 drivers/gpu/drm/amd/amdgpu/si.c          |   8 +-
 drivers/gpu/drm/amd/amdgpu/soc15.c       |  10 +-
 drivers/gpu/drm/amd/amdgpu/vi.c          |  14 +-
 13 files changed, 700 insertions(+), 844 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
 delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.c
 delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.h


base-commit: cfd09f1e35231aa7f69845b6195e7d935e81421d
-- 
2.32.0


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

* [PATCH 0/3] drm/amdgpu: modernize virtual display feature
@ 2021-07-21 17:07 ` Ryan Taylor
  0 siblings, 0 replies; 24+ messages in thread
From: Ryan Taylor @ 2021-07-21 17:07 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: melissa.srw, daniel.vetter, rodrigo.siqueira, Ryan Taylor

The amdgpu vkms interface provides a virtual KMS interface for several use
cases: devices without display hardware, platforms where the actual display
hardware is not useful (e.g., servers), SR-IOV virtual functions, device
emulation/simulation, and device bring up prior to display hardware being
usable. We previously emulated a legacy KMS interface, but there was a desire
to move to the atomic KMS interface. The vkms driver did everything we
needed, but we wanted KMS support natively in the driver without buffer
sharing and the ability to support an instance of VKMS per device. We first
looked at splitting vkms into a stub driver and a helper module that other
drivers could use to implement a virtual display, but this strategy ended up
being messy due to driver specific callbacks needed for buffer management.
Ultimately, it proved easier to import the vkms code as it mostly used core
drm helpers anyway.

Ryan Taylor (3):
  drm/amdgpu: create amdgpu_vkms (v2)
  drm/amdgpu: cleanup dce_virtual
  drm/amdgpu: replace dce_virtual with amdgpu_vkms (v3)

 drivers/gpu/drm/amd/amdgpu/Makefile      |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 639 +++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |  26 +
 drivers/gpu/drm/amd/amdgpu/cik.c         |  10 +-
 drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 780 -----------------------
 drivers/gpu/drm/amd/amdgpu/dce_virtual.h |  30 -
 drivers/gpu/drm/amd/amdgpu/nv.c          |  20 +-
 drivers/gpu/drm/amd/amdgpu/si.c          |   8 +-
 drivers/gpu/drm/amd/amdgpu/soc15.c       |  10 +-
 drivers/gpu/drm/amd/amdgpu/vi.c          |  14 +-
 13 files changed, 700 insertions(+), 844 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
 delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.c
 delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.h


base-commit: cfd09f1e35231aa7f69845b6195e7d935e81421d
-- 
2.32.0

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
  2021-07-21 17:07 ` Ryan Taylor
@ 2021-07-21 17:07   ` Ryan Taylor
  -1 siblings, 0 replies; 24+ messages in thread
From: Ryan Taylor @ 2021-07-21 17:07 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: melissa.srw, daniel.vetter, rodrigo.siqueira, Ryan Taylor,
	kernel test robot

Modify the VKMS driver into an api that dce_virtual can use to create
virtual displays that obey drm's atomic modesetting api.

v2: Made local functions static.

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411 +++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |  29 ++
 drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
 7 files changed, 458 insertions(+), 11 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h

diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index f089794bbdd5..30cbcd5ce1cc 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -120,6 +120,7 @@ amdgpu-y += \
 amdgpu-y += \
 	dce_v10_0.o \
 	dce_v11_0.o \
+	amdgpu_vkms.o \
 	dce_virtual.o
 
 # add GFX block
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 54cf647bd018..d0a2f2ed433d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -919,6 +919,7 @@ struct amdgpu_device {
 
 	/* display */
 	bool				enable_virtual_display;
+	struct amdgpu_vkms_output       *amdgpu_vkms_output;
 	struct amdgpu_mode_info		mode_info;
 	/* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
 	struct work_struct		hotplug_work;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index d0c935cf4f0f..1b016e5bc75f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
 	int ret, retry = 0;
 	bool supports_atomic = false;
 
-	if (!amdgpu_virtual_display &&
+	if (amdgpu_virtual_display ||
 	    amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
 		supports_atomic = true;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 09b048647523..5a143ca02cf9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
 	}
 
 	/* disable all the possible outputs/crtcs before entering KMS mode */
-	if (!amdgpu_device_has_dc_support(adev))
+	if (!amdgpu_device_has_dc_support(adev) && !amdgpu_virtual_display)
 		drm_helper_disable_unused_functions(adev_to_drm(adev));
 
 	drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
new file mode 100644
index 000000000000..d5c1f1c58f5f
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -0,0 +1,411 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_vblank.h>
+
+#include "amdgpu.h"
+#include "amdgpu_vkms.h"
+#include "amdgpu_display.h"
+
+/**
+ * DOC: amdgpu_vkms
+ *
+ * The amdgpu vkms interface provides a virtual KMS interface for several use
+ * cases: devices without display hardware, platforms where the actual display
+ * hardware is not useful (e.g., servers), SR-IOV virtual functions, device
+ * emulation/simulation, and device bring up prior to display hardware being
+ * usable. We previously emulated a legacy KMS interface, but there was a desire
+ * to move to the atomic KMS interface. The vkms driver did everything we
+ * needed, but we wanted KMS support natively in the driver without buffer
+ * sharing and the ability to support an instance of VKMS per device. We first
+ * looked at splitting vkms into a stub driver and a helper module that other
+ * drivers could use to implement a virtual display, but this strategy ended up
+ * being messy due to driver specific callbacks needed for buffer management.
+ * Ultimately, it proved easier to import the vkms code as it mostly used core
+ * drm helpers anyway.
+ */
+
+static const u32 amdgpu_vkms_formats[] = {
+	DRM_FORMAT_XRGB8888,
+};
+
+static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
+{
+	struct amdgpu_vkms_output *output = container_of(timer,
+							 struct amdgpu_vkms_output,
+							 vblank_hrtimer);
+	struct drm_crtc *crtc = &output->crtc;
+	u64 ret_overrun;
+	bool ret;
+
+	ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
+					  output->period_ns);
+	WARN_ON(ret_overrun != 1);
+
+	ret = drm_crtc_handle_vblank(crtc);
+	if (!ret)
+		DRM_ERROR("amdgpu_vkms failure on handling vblank");
+
+	return HRTIMER_RESTART;
+}
+
+static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	unsigned int pipe = drm_crtc_index(crtc);
+	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
+
+	drm_calc_timestamping_constants(crtc, &crtc->mode);
+
+	hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
+	out->period_ns = ktime_set(0, vblank->framedur_ns);
+	hrtimer_start(&out->vblank_hrtimer, out->period_ns, HRTIMER_MODE_REL);
+
+	return 0;
+}
+
+static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc)
+{
+	struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
+
+	hrtimer_cancel(&out->vblank_hrtimer);
+}
+
+static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
+					     int *max_error,
+					     ktime_t *vblank_time,
+					     bool in_vblank_irq)
+{
+	struct drm_device *dev = crtc->dev;
+	unsigned int pipe = crtc->index;
+	struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
+	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+
+	if (!READ_ONCE(vblank->enabled)) {
+		*vblank_time = ktime_get();
+		return true;
+	}
+
+	*vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
+
+	if (WARN_ON(*vblank_time == vblank->time))
+		return true;
+
+	/*
+	 * To prevent races we roll the hrtimer forward before we do any
+	 * interrupt processing - this is how real hw works (the interrupt is
+	 * only generated after all the vblank registers are updated) and what
+	 * the vblank core expects. Therefore we need to always correct the
+	 * timestampe by one frame.
+	 */
+	*vblank_time -= output->period_ns;
+
+	return true;
+}
+
+static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
+	.set_config             = drm_atomic_helper_set_config,
+	.destroy                = drm_crtc_cleanup,
+	.page_flip              = drm_atomic_helper_page_flip,
+	.reset                  = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
+	.enable_vblank		= amdgpu_vkms_enable_vblank,
+	.disable_vblank		= amdgpu_vkms_disable_vblank,
+	.get_vblank_timestamp	= amdgpu_vkms_get_vblank_timestamp,
+};
+
+static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
+					   struct drm_atomic_state *state)
+{
+	drm_crtc_vblank_on(crtc);
+}
+
+static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
+					    struct drm_atomic_state *state)
+{
+	drm_crtc_vblank_off(crtc);
+}
+
+static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
+					  struct drm_atomic_state *state)
+{
+	if (crtc->state->event) {
+		spin_lock(&crtc->dev->event_lock);
+
+		if (drm_crtc_vblank_get(crtc) != 0)
+			drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		else
+			drm_crtc_arm_vblank_event(crtc, crtc->state->event);
+
+		spin_unlock(&crtc->dev->event_lock);
+
+		crtc->state->event = NULL;
+	}
+}
+
+static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
+	.atomic_flush	= amdgpu_vkms_crtc_atomic_flush,
+	.atomic_enable	= amdgpu_vkms_crtc_atomic_enable,
+	.atomic_disable	= amdgpu_vkms_crtc_atomic_disable,
+};
+
+static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
+			  struct drm_plane *primary, struct drm_plane *cursor)
+{
+	int ret;
+
+	ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
+					&amdgpu_vkms_crtc_funcs, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to init CRTC\n");
+		return ret;
+	}
+
+	drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
+
+	return ret;
+}
+
+static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
+{
+	int count;
+
+	count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
+	drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
+
+	return count;
+}
+
+static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
+	.get_modes    = amdgpu_vkms_conn_get_modes,
+};
+
+static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= drm_plane_cleanup,
+	.reset			= drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+};
+
+static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
+					    struct drm_plane_state *old_state)
+{
+	return;
+}
+
+static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
+					  struct drm_plane_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	bool can_position = false;
+	int ret;
+
+	if (!state->fb || WARN_ON(!state->crtc))
+		return 0;
+
+	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	ret = drm_atomic_helper_check_plane_state(state, crtc_state,
+						  DRM_PLANE_HELPER_NO_SCALING,
+						  DRM_PLANE_HELPER_NO_SCALING,
+						  can_position, true);
+	if (ret != 0)
+		return ret;
+
+	/* for now primary plane must be visible and full screen */
+	if (!state->visible && !can_position)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
+				  struct drm_plane_state *new_state)
+{
+	struct amdgpu_framebuffer *afb;
+	struct drm_gem_object *obj;
+	struct amdgpu_device *adev;
+	struct amdgpu_bo *rbo;
+	struct list_head list;
+	struct ttm_validate_buffer tv;
+	struct ww_acquire_ctx ticket;
+	uint32_t domain;
+	int r;
+
+	if (!new_state->fb) {
+		DRM_DEBUG_KMS("No FB bound\n");
+		return 0;
+	}
+	afb = to_amdgpu_framebuffer(new_state->fb);
+	obj = new_state->fb->obj[0];
+	rbo = gem_to_amdgpu_bo(obj);
+	adev = amdgpu_ttm_adev(rbo->tbo.bdev);
+	INIT_LIST_HEAD(&list);
+
+	tv.bo = &rbo->tbo;
+	tv.num_shared = 1;
+	list_add(&tv.head, &list);
+
+	r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
+	if (r) {
+		dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
+		return r;
+	}
+
+	if (plane->type != DRM_PLANE_TYPE_CURSOR)
+		domain = amdgpu_display_supported_domains(adev, rbo->flags);
+	else
+		domain = AMDGPU_GEM_DOMAIN_VRAM;
+
+	r = amdgpu_bo_pin(rbo, domain);
+	if (unlikely(r != 0)) {
+		if (r != -ERESTARTSYS)
+			DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
+		ttm_eu_backoff_reservation(&ticket, &list);
+		return r;
+	}
+
+	r = amdgpu_ttm_alloc_gart(&rbo->tbo);
+	if (unlikely(r != 0)) {
+		amdgpu_bo_unpin(rbo);
+		ttm_eu_backoff_reservation(&ticket, &list);
+		DRM_ERROR("%p bind failed\n", rbo);
+		return r;
+	}
+
+	ttm_eu_backoff_reservation(&ticket, &list);
+
+	afb->address = amdgpu_bo_gpu_offset(rbo);
+
+	amdgpu_bo_ref(rbo);
+
+	return 0;
+}
+
+static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
+				   struct drm_plane_state *old_state)
+{
+	struct amdgpu_bo *rbo;
+	int r;
+
+	if (!old_state->fb)
+		return;
+
+	rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
+	r = amdgpu_bo_reserve(rbo, false);
+	if (unlikely(r)) {
+		DRM_ERROR("failed to reserve rbo before unpin\n");
+		return;
+	}
+
+	amdgpu_bo_unpin(rbo);
+	amdgpu_bo_unreserve(rbo);
+	amdgpu_bo_unref(&rbo);
+}
+
+static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
+	.atomic_update		= amdgpu_vkms_plane_atomic_update,
+	.atomic_check		= amdgpu_vkms_plane_atomic_check,
+	.prepare_fb		= amdgpu_vkms_prepare_fb,
+	.cleanup_fb		= amdgpu_vkms_cleanup_fb,
+};
+
+static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
+						enum drm_plane_type type,
+						int index)
+{
+	struct drm_plane *plane;
+	int ret;
+
+	plane = kzalloc(sizeof(*plane), GFP_KERNEL);
+	if (!plane)
+		return ERR_PTR(-ENOMEM);
+
+	ret = drm_universal_plane_init(dev, plane, 1 << index,
+				       &amdgpu_vkms_plane_funcs,
+				       amdgpu_vkms_formats,
+				       ARRAY_SIZE(amdgpu_vkms_formats),
+				       NULL, type, NULL);
+	if (ret) {
+		kfree(plane);
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(plane, &amdgpu_vkms_primary_helper_funcs);
+
+	return plane;
+}
+
+int amdgpu_vkms_output_init(struct drm_device *dev,
+			    struct amdgpu_vkms_output *output, int index)
+{
+	struct drm_connector *connector = &output->connector;
+	struct drm_encoder *encoder = &output->encoder;
+	struct drm_crtc *crtc = &output->crtc;
+	struct drm_plane *primary, *cursor = NULL;
+	int ret;
+
+	primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
+	if (IS_ERR(primary))
+		return PTR_ERR(primary);
+
+	ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
+	if (ret)
+		goto err_crtc;
+
+	ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
+				 DRM_MODE_CONNECTOR_VIRTUAL);
+	if (ret) {
+		DRM_ERROR("Failed to init connector\n");
+		goto err_connector;
+	}
+
+	drm_connector_helper_add(connector, &amdgpu_vkms_conn_helper_funcs);
+
+	ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
+	if (ret) {
+		DRM_ERROR("Failed to init encoder\n");
+		goto err_encoder;
+	}
+	encoder->possible_crtcs = 1 << index;
+
+	ret = drm_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		DRM_ERROR("Failed to attach connector to encoder\n");
+		goto err_attach;
+	}
+
+	drm_mode_config_reset(dev);
+
+	return 0;
+
+err_attach:
+	drm_encoder_cleanup(encoder);
+
+err_encoder:
+	drm_connector_cleanup(connector);
+
+err_connector:
+	drm_crtc_cleanup(crtc);
+
+err_crtc:
+	drm_plane_cleanup(primary);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
new file mode 100644
index 000000000000..5dab51fbecf3
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _AMDGPU_VKMS_H_
+#define _AMDGPU_VKMS_H_
+
+#define XRES_DEF  1024
+#define YRES_DEF   764
+
+#define XRES_MAX  16384
+#define YRES_MAX  16384
+
+#define drm_crtc_to_amdgpu_vkms_output(target) \
+	container_of(target, struct amdgpu_vkms_output, crtc)
+
+extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
+
+struct amdgpu_vkms_output {
+	struct drm_crtc crtc;
+	struct drm_encoder encoder;
+	struct drm_connector connector;
+	struct hrtimer vblank_hrtimer;
+	ktime_t period_ns;
+	struct drm_pending_vblank_event *event;
+};
+
+int amdgpu_vkms_output_init(struct drm_device *dev,
+			    struct amdgpu_vkms_output *output, int index);
+
+#endif /* _AMDGPU_VKMS_H_ */
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
index 7e0d8c092c7e..642c77533157 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
@@ -22,6 +22,7 @@
  */
 
 #include <drm/drm_vblank.h>
+#include <drm/drm_atomic_helper.h>
 
 #include "amdgpu.h"
 #include "amdgpu_pm.h"
@@ -40,6 +41,7 @@
 #include "dce_virtual.h"
 #include "ivsrcid/ivsrcid_vislands30.h"
 #include "amdgpu_display.h"
+#include "amdgpu_vkms.h"
 
 #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
 
@@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
 	.force = dce_virtual_force,
 };
 
+const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
+	.fb_create = amdgpu_display_user_framebuffer_create,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
 static int dce_virtual_sw_init(void *handle)
 {
 	int r, i;
@@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
 
 	adev_to_drm(adev)->max_vblank_count = 0;
 
-	adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
+	adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
 
-	adev_to_drm(adev)->mode_config.max_width = 16384;
-	adev_to_drm(adev)->mode_config.max_height = 16384;
+	adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
+	adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
 
 	adev_to_drm(adev)->mode_config.preferred_depth = 24;
 	adev_to_drm(adev)->mode_config.prefer_shadow = 1;
@@ -399,15 +407,11 @@ static int dce_virtual_sw_init(void *handle)
 	if (r)
 		return r;
 
-	adev_to_drm(adev)->mode_config.max_width = 16384;
-	adev_to_drm(adev)->mode_config.max_height = 16384;
+	adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
 
 	/* allocate crtcs, encoders, connectors */
 	for (i = 0; i < adev->mode_info.num_crtc; i++) {
-		r = dce_virtual_crtc_init(adev, i);
-		if (r)
-			return r;
-		r = dce_virtual_connector_encoder_init(adev, i);
+		r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
 		if (r)
 			return r;
 	}
@@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
 			hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
 
 	kfree(adev->mode_info.bios_hardcoded_edid);
+	kfree(adev->amdgpu_vkms_output);
 
 	drm_kms_helper_poll_fini(adev_to_drm(adev));
 
-- 
2.32.0


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

* [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
@ 2021-07-21 17:07   ` Ryan Taylor
  0 siblings, 0 replies; 24+ messages in thread
From: Ryan Taylor @ 2021-07-21 17:07 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: melissa.srw, daniel.vetter, rodrigo.siqueira, Ryan Taylor,
	kernel test robot

Modify the VKMS driver into an api that dce_virtual can use to create
virtual displays that obey drm's atomic modesetting api.

v2: Made local functions static.

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411 +++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |  29 ++
 drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
 7 files changed, 458 insertions(+), 11 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h

diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index f089794bbdd5..30cbcd5ce1cc 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -120,6 +120,7 @@ amdgpu-y += \
 amdgpu-y += \
 	dce_v10_0.o \
 	dce_v11_0.o \
+	amdgpu_vkms.o \
 	dce_virtual.o
 
 # add GFX block
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 54cf647bd018..d0a2f2ed433d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -919,6 +919,7 @@ struct amdgpu_device {
 
 	/* display */
 	bool				enable_virtual_display;
+	struct amdgpu_vkms_output       *amdgpu_vkms_output;
 	struct amdgpu_mode_info		mode_info;
 	/* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
 	struct work_struct		hotplug_work;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index d0c935cf4f0f..1b016e5bc75f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
 	int ret, retry = 0;
 	bool supports_atomic = false;
 
-	if (!amdgpu_virtual_display &&
+	if (amdgpu_virtual_display ||
 	    amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
 		supports_atomic = true;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 09b048647523..5a143ca02cf9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
 	}
 
 	/* disable all the possible outputs/crtcs before entering KMS mode */
-	if (!amdgpu_device_has_dc_support(adev))
+	if (!amdgpu_device_has_dc_support(adev) && !amdgpu_virtual_display)
 		drm_helper_disable_unused_functions(adev_to_drm(adev));
 
 	drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
new file mode 100644
index 000000000000..d5c1f1c58f5f
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -0,0 +1,411 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_vblank.h>
+
+#include "amdgpu.h"
+#include "amdgpu_vkms.h"
+#include "amdgpu_display.h"
+
+/**
+ * DOC: amdgpu_vkms
+ *
+ * The amdgpu vkms interface provides a virtual KMS interface for several use
+ * cases: devices without display hardware, platforms where the actual display
+ * hardware is not useful (e.g., servers), SR-IOV virtual functions, device
+ * emulation/simulation, and device bring up prior to display hardware being
+ * usable. We previously emulated a legacy KMS interface, but there was a desire
+ * to move to the atomic KMS interface. The vkms driver did everything we
+ * needed, but we wanted KMS support natively in the driver without buffer
+ * sharing and the ability to support an instance of VKMS per device. We first
+ * looked at splitting vkms into a stub driver and a helper module that other
+ * drivers could use to implement a virtual display, but this strategy ended up
+ * being messy due to driver specific callbacks needed for buffer management.
+ * Ultimately, it proved easier to import the vkms code as it mostly used core
+ * drm helpers anyway.
+ */
+
+static const u32 amdgpu_vkms_formats[] = {
+	DRM_FORMAT_XRGB8888,
+};
+
+static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
+{
+	struct amdgpu_vkms_output *output = container_of(timer,
+							 struct amdgpu_vkms_output,
+							 vblank_hrtimer);
+	struct drm_crtc *crtc = &output->crtc;
+	u64 ret_overrun;
+	bool ret;
+
+	ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
+					  output->period_ns);
+	WARN_ON(ret_overrun != 1);
+
+	ret = drm_crtc_handle_vblank(crtc);
+	if (!ret)
+		DRM_ERROR("amdgpu_vkms failure on handling vblank");
+
+	return HRTIMER_RESTART;
+}
+
+static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	unsigned int pipe = drm_crtc_index(crtc);
+	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
+
+	drm_calc_timestamping_constants(crtc, &crtc->mode);
+
+	hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
+	out->period_ns = ktime_set(0, vblank->framedur_ns);
+	hrtimer_start(&out->vblank_hrtimer, out->period_ns, HRTIMER_MODE_REL);
+
+	return 0;
+}
+
+static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc)
+{
+	struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
+
+	hrtimer_cancel(&out->vblank_hrtimer);
+}
+
+static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
+					     int *max_error,
+					     ktime_t *vblank_time,
+					     bool in_vblank_irq)
+{
+	struct drm_device *dev = crtc->dev;
+	unsigned int pipe = crtc->index;
+	struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
+	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+
+	if (!READ_ONCE(vblank->enabled)) {
+		*vblank_time = ktime_get();
+		return true;
+	}
+
+	*vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
+
+	if (WARN_ON(*vblank_time == vblank->time))
+		return true;
+
+	/*
+	 * To prevent races we roll the hrtimer forward before we do any
+	 * interrupt processing - this is how real hw works (the interrupt is
+	 * only generated after all the vblank registers are updated) and what
+	 * the vblank core expects. Therefore we need to always correct the
+	 * timestampe by one frame.
+	 */
+	*vblank_time -= output->period_ns;
+
+	return true;
+}
+
+static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
+	.set_config             = drm_atomic_helper_set_config,
+	.destroy                = drm_crtc_cleanup,
+	.page_flip              = drm_atomic_helper_page_flip,
+	.reset                  = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
+	.enable_vblank		= amdgpu_vkms_enable_vblank,
+	.disable_vblank		= amdgpu_vkms_disable_vblank,
+	.get_vblank_timestamp	= amdgpu_vkms_get_vblank_timestamp,
+};
+
+static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
+					   struct drm_atomic_state *state)
+{
+	drm_crtc_vblank_on(crtc);
+}
+
+static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
+					    struct drm_atomic_state *state)
+{
+	drm_crtc_vblank_off(crtc);
+}
+
+static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
+					  struct drm_atomic_state *state)
+{
+	if (crtc->state->event) {
+		spin_lock(&crtc->dev->event_lock);
+
+		if (drm_crtc_vblank_get(crtc) != 0)
+			drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		else
+			drm_crtc_arm_vblank_event(crtc, crtc->state->event);
+
+		spin_unlock(&crtc->dev->event_lock);
+
+		crtc->state->event = NULL;
+	}
+}
+
+static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
+	.atomic_flush	= amdgpu_vkms_crtc_atomic_flush,
+	.atomic_enable	= amdgpu_vkms_crtc_atomic_enable,
+	.atomic_disable	= amdgpu_vkms_crtc_atomic_disable,
+};
+
+static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
+			  struct drm_plane *primary, struct drm_plane *cursor)
+{
+	int ret;
+
+	ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
+					&amdgpu_vkms_crtc_funcs, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to init CRTC\n");
+		return ret;
+	}
+
+	drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
+
+	return ret;
+}
+
+static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
+{
+	int count;
+
+	count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
+	drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
+
+	return count;
+}
+
+static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
+	.get_modes    = amdgpu_vkms_conn_get_modes,
+};
+
+static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= drm_plane_cleanup,
+	.reset			= drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+};
+
+static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
+					    struct drm_plane_state *old_state)
+{
+	return;
+}
+
+static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
+					  struct drm_plane_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	bool can_position = false;
+	int ret;
+
+	if (!state->fb || WARN_ON(!state->crtc))
+		return 0;
+
+	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	ret = drm_atomic_helper_check_plane_state(state, crtc_state,
+						  DRM_PLANE_HELPER_NO_SCALING,
+						  DRM_PLANE_HELPER_NO_SCALING,
+						  can_position, true);
+	if (ret != 0)
+		return ret;
+
+	/* for now primary plane must be visible and full screen */
+	if (!state->visible && !can_position)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
+				  struct drm_plane_state *new_state)
+{
+	struct amdgpu_framebuffer *afb;
+	struct drm_gem_object *obj;
+	struct amdgpu_device *adev;
+	struct amdgpu_bo *rbo;
+	struct list_head list;
+	struct ttm_validate_buffer tv;
+	struct ww_acquire_ctx ticket;
+	uint32_t domain;
+	int r;
+
+	if (!new_state->fb) {
+		DRM_DEBUG_KMS("No FB bound\n");
+		return 0;
+	}
+	afb = to_amdgpu_framebuffer(new_state->fb);
+	obj = new_state->fb->obj[0];
+	rbo = gem_to_amdgpu_bo(obj);
+	adev = amdgpu_ttm_adev(rbo->tbo.bdev);
+	INIT_LIST_HEAD(&list);
+
+	tv.bo = &rbo->tbo;
+	tv.num_shared = 1;
+	list_add(&tv.head, &list);
+
+	r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
+	if (r) {
+		dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
+		return r;
+	}
+
+	if (plane->type != DRM_PLANE_TYPE_CURSOR)
+		domain = amdgpu_display_supported_domains(adev, rbo->flags);
+	else
+		domain = AMDGPU_GEM_DOMAIN_VRAM;
+
+	r = amdgpu_bo_pin(rbo, domain);
+	if (unlikely(r != 0)) {
+		if (r != -ERESTARTSYS)
+			DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
+		ttm_eu_backoff_reservation(&ticket, &list);
+		return r;
+	}
+
+	r = amdgpu_ttm_alloc_gart(&rbo->tbo);
+	if (unlikely(r != 0)) {
+		amdgpu_bo_unpin(rbo);
+		ttm_eu_backoff_reservation(&ticket, &list);
+		DRM_ERROR("%p bind failed\n", rbo);
+		return r;
+	}
+
+	ttm_eu_backoff_reservation(&ticket, &list);
+
+	afb->address = amdgpu_bo_gpu_offset(rbo);
+
+	amdgpu_bo_ref(rbo);
+
+	return 0;
+}
+
+static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
+				   struct drm_plane_state *old_state)
+{
+	struct amdgpu_bo *rbo;
+	int r;
+
+	if (!old_state->fb)
+		return;
+
+	rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
+	r = amdgpu_bo_reserve(rbo, false);
+	if (unlikely(r)) {
+		DRM_ERROR("failed to reserve rbo before unpin\n");
+		return;
+	}
+
+	amdgpu_bo_unpin(rbo);
+	amdgpu_bo_unreserve(rbo);
+	amdgpu_bo_unref(&rbo);
+}
+
+static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
+	.atomic_update		= amdgpu_vkms_plane_atomic_update,
+	.atomic_check		= amdgpu_vkms_plane_atomic_check,
+	.prepare_fb		= amdgpu_vkms_prepare_fb,
+	.cleanup_fb		= amdgpu_vkms_cleanup_fb,
+};
+
+static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
+						enum drm_plane_type type,
+						int index)
+{
+	struct drm_plane *plane;
+	int ret;
+
+	plane = kzalloc(sizeof(*plane), GFP_KERNEL);
+	if (!plane)
+		return ERR_PTR(-ENOMEM);
+
+	ret = drm_universal_plane_init(dev, plane, 1 << index,
+				       &amdgpu_vkms_plane_funcs,
+				       amdgpu_vkms_formats,
+				       ARRAY_SIZE(amdgpu_vkms_formats),
+				       NULL, type, NULL);
+	if (ret) {
+		kfree(plane);
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(plane, &amdgpu_vkms_primary_helper_funcs);
+
+	return plane;
+}
+
+int amdgpu_vkms_output_init(struct drm_device *dev,
+			    struct amdgpu_vkms_output *output, int index)
+{
+	struct drm_connector *connector = &output->connector;
+	struct drm_encoder *encoder = &output->encoder;
+	struct drm_crtc *crtc = &output->crtc;
+	struct drm_plane *primary, *cursor = NULL;
+	int ret;
+
+	primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
+	if (IS_ERR(primary))
+		return PTR_ERR(primary);
+
+	ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
+	if (ret)
+		goto err_crtc;
+
+	ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
+				 DRM_MODE_CONNECTOR_VIRTUAL);
+	if (ret) {
+		DRM_ERROR("Failed to init connector\n");
+		goto err_connector;
+	}
+
+	drm_connector_helper_add(connector, &amdgpu_vkms_conn_helper_funcs);
+
+	ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
+	if (ret) {
+		DRM_ERROR("Failed to init encoder\n");
+		goto err_encoder;
+	}
+	encoder->possible_crtcs = 1 << index;
+
+	ret = drm_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		DRM_ERROR("Failed to attach connector to encoder\n");
+		goto err_attach;
+	}
+
+	drm_mode_config_reset(dev);
+
+	return 0;
+
+err_attach:
+	drm_encoder_cleanup(encoder);
+
+err_encoder:
+	drm_connector_cleanup(connector);
+
+err_connector:
+	drm_crtc_cleanup(crtc);
+
+err_crtc:
+	drm_plane_cleanup(primary);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
new file mode 100644
index 000000000000..5dab51fbecf3
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _AMDGPU_VKMS_H_
+#define _AMDGPU_VKMS_H_
+
+#define XRES_DEF  1024
+#define YRES_DEF   764
+
+#define XRES_MAX  16384
+#define YRES_MAX  16384
+
+#define drm_crtc_to_amdgpu_vkms_output(target) \
+	container_of(target, struct amdgpu_vkms_output, crtc)
+
+extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
+
+struct amdgpu_vkms_output {
+	struct drm_crtc crtc;
+	struct drm_encoder encoder;
+	struct drm_connector connector;
+	struct hrtimer vblank_hrtimer;
+	ktime_t period_ns;
+	struct drm_pending_vblank_event *event;
+};
+
+int amdgpu_vkms_output_init(struct drm_device *dev,
+			    struct amdgpu_vkms_output *output, int index);
+
+#endif /* _AMDGPU_VKMS_H_ */
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
index 7e0d8c092c7e..642c77533157 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
@@ -22,6 +22,7 @@
  */
 
 #include <drm/drm_vblank.h>
+#include <drm/drm_atomic_helper.h>
 
 #include "amdgpu.h"
 #include "amdgpu_pm.h"
@@ -40,6 +41,7 @@
 #include "dce_virtual.h"
 #include "ivsrcid/ivsrcid_vislands30.h"
 #include "amdgpu_display.h"
+#include "amdgpu_vkms.h"
 
 #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
 
@@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
 	.force = dce_virtual_force,
 };
 
+const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
+	.fb_create = amdgpu_display_user_framebuffer_create,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
 static int dce_virtual_sw_init(void *handle)
 {
 	int r, i;
@@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
 
 	adev_to_drm(adev)->max_vblank_count = 0;
 
-	adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
+	adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
 
-	adev_to_drm(adev)->mode_config.max_width = 16384;
-	adev_to_drm(adev)->mode_config.max_height = 16384;
+	adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
+	adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
 
 	adev_to_drm(adev)->mode_config.preferred_depth = 24;
 	adev_to_drm(adev)->mode_config.prefer_shadow = 1;
@@ -399,15 +407,11 @@ static int dce_virtual_sw_init(void *handle)
 	if (r)
 		return r;
 
-	adev_to_drm(adev)->mode_config.max_width = 16384;
-	adev_to_drm(adev)->mode_config.max_height = 16384;
+	adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
 
 	/* allocate crtcs, encoders, connectors */
 	for (i = 0; i < adev->mode_info.num_crtc; i++) {
-		r = dce_virtual_crtc_init(adev, i);
-		if (r)
-			return r;
-		r = dce_virtual_connector_encoder_init(adev, i);
+		r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
 		if (r)
 			return r;
 	}
@@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
 			hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
 
 	kfree(adev->mode_info.bios_hardcoded_edid);
+	kfree(adev->amdgpu_vkms_output);
 
 	drm_kms_helper_poll_fini(adev_to_drm(adev));
 
-- 
2.32.0

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* [PATCH 2/3] drm/amdgpu: cleanup dce_virtual
  2021-07-21 17:07 ` Ryan Taylor
@ 2021-07-21 17:07   ` Ryan Taylor
  -1 siblings, 0 replies; 24+ messages in thread
From: Ryan Taylor @ 2021-07-21 17:07 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: melissa.srw, daniel.vetter, rodrigo.siqueira, Ryan Taylor

Remove obsolete functions and variables from dce_virtual.

Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 568 +----------------------
 1 file changed, 3 insertions(+), 565 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
index 642c77533157..18369b47eac7 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
@@ -21,15 +21,9 @@
  *
  */
 
-#include <drm/drm_vblank.h>
 #include <drm/drm_atomic_helper.h>
 
 #include "amdgpu.h"
-#include "amdgpu_pm.h"
-#include "amdgpu_i2c.h"
-#include "atom.h"
-#include "amdgpu_pll.h"
-#include "amdgpu_connectors.h"
 #ifdef CONFIG_DRM_AMDGPU_SI
 #include "dce_v6_0.h"
 #endif
@@ -43,339 +37,6 @@
 #include "amdgpu_display.h"
 #include "amdgpu_vkms.h"
 
-#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
-
-
-static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
-static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
-static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
-					      int index);
-static int dce_virtual_pageflip(struct amdgpu_device *adev,
-				unsigned crtc_id);
-static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer);
-static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
-							int crtc,
-							enum amdgpu_interrupt_state state);
-
-static u32 dce_virtual_vblank_get_counter(struct amdgpu_device *adev, int crtc)
-{
-	return 0;
-}
-
-static void dce_virtual_page_flip(struct amdgpu_device *adev,
-			      int crtc_id, u64 crtc_base, bool async)
-{
-	return;
-}
-
-static int dce_virtual_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
-					u32 *vbl, u32 *position)
-{
-	*vbl = 0;
-	*position = 0;
-
-	return -EINVAL;
-}
-
-static bool dce_virtual_hpd_sense(struct amdgpu_device *adev,
-			       enum amdgpu_hpd_id hpd)
-{
-	return true;
-}
-
-static void dce_virtual_hpd_set_polarity(struct amdgpu_device *adev,
-				      enum amdgpu_hpd_id hpd)
-{
-	return;
-}
-
-static u32 dce_virtual_hpd_get_gpio_reg(struct amdgpu_device *adev)
-{
-	return 0;
-}
-
-/**
- * dce_virtual_bandwidth_update - program display watermarks
- *
- * @adev: amdgpu_device pointer
- *
- * Calculate and program the display watermarks and line
- * buffer allocation (CIK).
- */
-static void dce_virtual_bandwidth_update(struct amdgpu_device *adev)
-{
-	return;
-}
-
-static int dce_virtual_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
-				      u16 *green, u16 *blue, uint32_t size,
-				      struct drm_modeset_acquire_ctx *ctx)
-{
-	return 0;
-}
-
-static void dce_virtual_crtc_destroy(struct drm_crtc *crtc)
-{
-	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-
-	drm_crtc_cleanup(crtc);
-	kfree(amdgpu_crtc);
-}
-
-static const struct drm_crtc_funcs dce_virtual_crtc_funcs = {
-	.cursor_set2 = NULL,
-	.cursor_move = NULL,
-	.gamma_set = dce_virtual_crtc_gamma_set,
-	.set_config = amdgpu_display_crtc_set_config,
-	.destroy = dce_virtual_crtc_destroy,
-	.page_flip_target = amdgpu_display_crtc_page_flip_target,
-	.get_vblank_counter = amdgpu_get_vblank_counter_kms,
-	.enable_vblank = amdgpu_enable_vblank_kms,
-	.disable_vblank = amdgpu_disable_vblank_kms,
-	.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
-};
-
-static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-	struct drm_device *dev = crtc->dev;
-	struct amdgpu_device *adev = drm_to_adev(dev);
-	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-	unsigned type;
-
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		amdgpu_crtc->enabled = true;
-		/* Make sure VBLANK interrupts are still enabled */
-		type = amdgpu_display_crtc_idx_to_irq_type(adev,
-						amdgpu_crtc->crtc_id);
-		amdgpu_irq_update(adev, &adev->crtc_irq, type);
-		drm_crtc_vblank_on(crtc);
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-	case DRM_MODE_DPMS_OFF:
-		drm_crtc_vblank_off(crtc);
-		amdgpu_crtc->enabled = false;
-		break;
-	}
-}
-
-
-static void dce_virtual_crtc_prepare(struct drm_crtc *crtc)
-{
-	dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void dce_virtual_crtc_commit(struct drm_crtc *crtc)
-{
-	dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-static void dce_virtual_crtc_disable(struct drm_crtc *crtc)
-{
-	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-	struct drm_device *dev = crtc->dev;
-
-	if (dev->num_crtcs)
-		drm_crtc_vblank_off(crtc);
-
-	amdgpu_crtc->enabled = false;
-	amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
-	amdgpu_crtc->encoder = NULL;
-	amdgpu_crtc->connector = NULL;
-}
-
-static int dce_virtual_crtc_mode_set(struct drm_crtc *crtc,
-				  struct drm_display_mode *mode,
-				  struct drm_display_mode *adjusted_mode,
-				  int x, int y, struct drm_framebuffer *old_fb)
-{
-	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-
-	/* update the hw version fpr dpm */
-	amdgpu_crtc->hw_mode = *adjusted_mode;
-
-	return 0;
-}
-
-static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc,
-				     const struct drm_display_mode *mode,
-				     struct drm_display_mode *adjusted_mode)
-{
-	return true;
-}
-
-
-static int dce_virtual_crtc_set_base(struct drm_crtc *crtc, int x, int y,
-				  struct drm_framebuffer *old_fb)
-{
-	return 0;
-}
-
-static int dce_virtual_crtc_set_base_atomic(struct drm_crtc *crtc,
-					 struct drm_framebuffer *fb,
-					 int x, int y, enum mode_set_atomic state)
-{
-	return 0;
-}
-
-static const struct drm_crtc_helper_funcs dce_virtual_crtc_helper_funcs = {
-	.dpms = dce_virtual_crtc_dpms,
-	.mode_fixup = dce_virtual_crtc_mode_fixup,
-	.mode_set = dce_virtual_crtc_mode_set,
-	.mode_set_base = dce_virtual_crtc_set_base,
-	.mode_set_base_atomic = dce_virtual_crtc_set_base_atomic,
-	.prepare = dce_virtual_crtc_prepare,
-	.commit = dce_virtual_crtc_commit,
-	.disable = dce_virtual_crtc_disable,
-	.get_scanout_position = amdgpu_crtc_get_scanout_position,
-};
-
-static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index)
-{
-	struct amdgpu_crtc *amdgpu_crtc;
-
-	amdgpu_crtc = kzalloc(sizeof(struct amdgpu_crtc) +
-			      (AMDGPUFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
-	if (amdgpu_crtc == NULL)
-		return -ENOMEM;
-
-	drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_virtual_crtc_funcs);
-
-	drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256);
-	amdgpu_crtc->crtc_id = index;
-	adev->mode_info.crtcs[index] = amdgpu_crtc;
-
-	amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
-	amdgpu_crtc->encoder = NULL;
-	amdgpu_crtc->connector = NULL;
-	amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
-	drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs);
-
-	hrtimer_init(&amdgpu_crtc->vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-	hrtimer_set_expires(&amdgpu_crtc->vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD);
-	amdgpu_crtc->vblank_timer.function = dce_virtual_vblank_timer_handle;
-	hrtimer_start(&amdgpu_crtc->vblank_timer,
-		      DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL);
-	return 0;
-}
-
-static int dce_virtual_early_init(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dce_virtual_set_display_funcs(adev);
-	dce_virtual_set_irq_funcs(adev);
-
-	adev->mode_info.num_hpd = 1;
-	adev->mode_info.num_dig = 1;
-	return 0;
-}
-
-static struct drm_encoder *
-dce_virtual_encoder(struct drm_connector *connector)
-{
-	struct drm_encoder *encoder;
-
-	drm_connector_for_each_possible_encoder(connector, encoder) {
-		if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
-			return encoder;
-	}
-
-	/* pick the first one */
-	drm_connector_for_each_possible_encoder(connector, encoder)
-		return encoder;
-
-	return NULL;
-}
-
-static int dce_virtual_get_modes(struct drm_connector *connector)
-{
-	struct drm_device *dev = connector->dev;
-	struct drm_display_mode *mode = NULL;
-	unsigned i;
-	static const struct mode_size {
-		int w;
-		int h;
-	} common_modes[] = {
-		{ 640,  480},
-		{ 720,  480},
-		{ 800,  600},
-		{ 848,  480},
-		{1024,  768},
-		{1152,  768},
-		{1280,  720},
-		{1280,  800},
-		{1280,  854},
-		{1280,  960},
-		{1280, 1024},
-		{1440,  900},
-		{1400, 1050},
-		{1680, 1050},
-		{1600, 1200},
-		{1920, 1080},
-		{1920, 1200},
-		{2560, 1440},
-		{4096, 3112},
-		{3656, 2664},
-		{3840, 2160},
-		{4096, 2160},
-	};
-
-	for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
-		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
-		drm_mode_probed_add(connector, mode);
-	}
-
-	return 0;
-}
-
-static enum drm_mode_status dce_virtual_mode_valid(struct drm_connector *connector,
-				  struct drm_display_mode *mode)
-{
-	return MODE_OK;
-}
-
-static int
-dce_virtual_dpms(struct drm_connector *connector, int mode)
-{
-	return 0;
-}
-
-static int
-dce_virtual_set_property(struct drm_connector *connector,
-			 struct drm_property *property,
-			 uint64_t val)
-{
-	return 0;
-}
-
-static void dce_virtual_destroy(struct drm_connector *connector)
-{
-	drm_connector_unregister(connector);
-	drm_connector_cleanup(connector);
-	kfree(connector);
-}
-
-static void dce_virtual_force(struct drm_connector *connector)
-{
-	return;
-}
-
-static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = {
-	.get_modes = dce_virtual_get_modes,
-	.mode_valid = dce_virtual_mode_valid,
-	.best_encoder = dce_virtual_encoder,
-};
-
-static const struct drm_connector_funcs dce_virtual_connector_funcs = {
-	.dpms = dce_virtual_dpms,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.set_property = dce_virtual_set_property,
-	.destroy = dce_virtual_destroy,
-	.force = dce_virtual_force,
-};
-
 const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
 	.fb_create = amdgpu_display_user_framebuffer_create,
 	.atomic_check = drm_atomic_helper_check,
@@ -387,10 +48,6 @@ static int dce_virtual_sw_init(void *handle)
 	int r, i;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER, &adev->crtc_irq);
-	if (r)
-		return r;
-
 	adev_to_drm(adev)->max_vblank_count = 0;
 
 	adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
@@ -436,9 +93,6 @@ static int dce_virtual_sw_fini(void *handle)
 
 	drm_kms_helper_poll_fini(adev_to_drm(adev));
 
-	drm_mode_config_cleanup(adev_to_drm(adev));
-	/* clear crtcs pointer to avoid dce irq finish routine access freed data */
-	memset(adev->mode_info.crtcs, 0, sizeof(adev->mode_info.crtcs[0]) * AMDGPU_MAX_CRTCS);
 	adev->mode_info.mode_config_initialized = false;
 	return 0;
 }
@@ -498,7 +152,7 @@ static int dce_virtual_suspend(void *handle)
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	int r;
 
-	r = amdgpu_display_suspend_helper(adev);
+	r = drm_mode_config_helper_suspend(adev_to_drm(adev));
 	if (r)
 		return r;
 	return dce_virtual_hw_fini(handle);
@@ -512,7 +166,7 @@ static int dce_virtual_resume(void *handle)
 	r = dce_virtual_hw_init(handle);
 	if (r)
 		return r;
-	return amdgpu_display_resume_helper(adev);
+	return drm_mode_config_helper_resume(adev_to_drm(adev));
 }
 
 static bool dce_virtual_is_idle(void *handle)
@@ -544,7 +198,7 @@ static int dce_virtual_set_powergating_state(void *handle,
 
 static const struct amd_ip_funcs dce_virtual_ip_funcs = {
 	.name = "dce_virtual",
-	.early_init = dce_virtual_early_init,
+	.early_init = NULL,
 	.late_init = NULL,
 	.sw_init = dce_virtual_sw_init,
 	.sw_fini = dce_virtual_sw_fini,
@@ -559,222 +213,6 @@ static const struct amd_ip_funcs dce_virtual_ip_funcs = {
 	.set_powergating_state = dce_virtual_set_powergating_state,
 };
 
-/* these are handled by the primary encoders */
-static void dce_virtual_encoder_prepare(struct drm_encoder *encoder)
-{
-	return;
-}
-
-static void dce_virtual_encoder_commit(struct drm_encoder *encoder)
-{
-	return;
-}
-
-static void
-dce_virtual_encoder_mode_set(struct drm_encoder *encoder,
-			     struct drm_display_mode *mode,
-			     struct drm_display_mode *adjusted_mode)
-{
-	return;
-}
-
-static void dce_virtual_encoder_disable(struct drm_encoder *encoder)
-{
-	return;
-}
-
-static void
-dce_virtual_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-	return;
-}
-
-static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder,
-				    const struct drm_display_mode *mode,
-				    struct drm_display_mode *adjusted_mode)
-{
-	return true;
-}
-
-static const struct drm_encoder_helper_funcs dce_virtual_encoder_helper_funcs = {
-	.dpms = dce_virtual_encoder_dpms,
-	.mode_fixup = dce_virtual_encoder_mode_fixup,
-	.prepare = dce_virtual_encoder_prepare,
-	.mode_set = dce_virtual_encoder_mode_set,
-	.commit = dce_virtual_encoder_commit,
-	.disable = dce_virtual_encoder_disable,
-};
-
-static void dce_virtual_encoder_destroy(struct drm_encoder *encoder)
-{
-	drm_encoder_cleanup(encoder);
-	kfree(encoder);
-}
-
-static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
-	.destroy = dce_virtual_encoder_destroy,
-};
-
-static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
-					      int index)
-{
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
-
-	/* add a new encoder */
-	encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL);
-	if (!encoder)
-		return -ENOMEM;
-	encoder->possible_crtcs = 1 << index;
-	drm_encoder_init(adev_to_drm(adev), encoder, &dce_virtual_encoder_funcs,
-			 DRM_MODE_ENCODER_VIRTUAL, NULL);
-	drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
-
-	connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
-	if (!connector) {
-		kfree(encoder);
-		return -ENOMEM;
-	}
-
-	/* add a new connector */
-	drm_connector_init(adev_to_drm(adev), connector, &dce_virtual_connector_funcs,
-			   DRM_MODE_CONNECTOR_VIRTUAL);
-	drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs);
-	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
-	connector->interlace_allowed = false;
-	connector->doublescan_allowed = false;
-
-	/* link them */
-	drm_connector_attach_encoder(connector, encoder);
-
-	return 0;
-}
-
-static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
-	.bandwidth_update = &dce_virtual_bandwidth_update,
-	.vblank_get_counter = &dce_virtual_vblank_get_counter,
-	.backlight_set_level = NULL,
-	.backlight_get_level = NULL,
-	.hpd_sense = &dce_virtual_hpd_sense,
-	.hpd_set_polarity = &dce_virtual_hpd_set_polarity,
-	.hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg,
-	.page_flip = &dce_virtual_page_flip,
-	.page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos,
-	.add_encoder = NULL,
-	.add_connector = NULL,
-};
-
-static void dce_virtual_set_display_funcs(struct amdgpu_device *adev)
-{
-	adev->mode_info.funcs = &dce_virtual_display_funcs;
-}
-
-static int dce_virtual_pageflip(struct amdgpu_device *adev,
-				unsigned crtc_id)
-{
-	unsigned long flags;
-	struct amdgpu_crtc *amdgpu_crtc;
-	struct amdgpu_flip_work *works;
-
-	amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
-
-	if (crtc_id >= adev->mode_info.num_crtc) {
-		DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
-		return -EINVAL;
-	}
-
-	/* IRQ could occur when in initial stage */
-	if (amdgpu_crtc == NULL)
-		return 0;
-
-	spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
-	works = amdgpu_crtc->pflip_works;
-	if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
-		DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != "
-			"AMDGPU_FLIP_SUBMITTED(%d)\n",
-			amdgpu_crtc->pflip_status,
-			AMDGPU_FLIP_SUBMITTED);
-		spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
-		return 0;
-	}
-
-	/* page flip completed. clean up */
-	amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
-	amdgpu_crtc->pflip_works = NULL;
-
-	/* wakeup usersapce */
-	if (works->event)
-		drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event);
-
-	spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
-
-	drm_crtc_vblank_put(&amdgpu_crtc->base);
-	amdgpu_bo_unref(&works->old_abo);
-	kfree(works->shared);
-	kfree(works);
-
-	return 0;
-}
-
-static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
-{
-	struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer,
-						       struct amdgpu_crtc, vblank_timer);
-	struct drm_device *ddev = amdgpu_crtc->base.dev;
-	struct amdgpu_device *adev = drm_to_adev(ddev);
-	struct amdgpu_irq_src *source = adev->irq.client[AMDGPU_IRQ_CLIENTID_LEGACY].sources
-		[VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER];
-	int irq_type = amdgpu_display_crtc_idx_to_irq_type(adev,
-						amdgpu_crtc->crtc_id);
-
-	if (amdgpu_irq_enabled(adev, source, irq_type)) {
-		drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
-		dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
-	}
-	hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD,
-		      HRTIMER_MODE_REL);
-
-	return HRTIMER_NORESTART;
-}
-
-static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
-							int crtc,
-							enum amdgpu_interrupt_state state)
-{
-	if (crtc >= adev->mode_info.num_crtc || !adev->mode_info.crtcs[crtc]) {
-		DRM_DEBUG("invalid crtc %d\n", crtc);
-		return;
-	}
-
-	adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
-	DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
-}
-
-
-static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
-					  struct amdgpu_irq_src *source,
-					  unsigned type,
-					  enum amdgpu_interrupt_state state)
-{
-	if (type > AMDGPU_CRTC_IRQ_VBLANK6)
-		return -EINVAL;
-
-	dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state);
-
-	return 0;
-}
-
-static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = {
-	.set = dce_virtual_set_crtc_irq_state,
-	.process = NULL,
-};
-
-static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev)
-{
-	adev->crtc_irq.num_types = adev->mode_info.num_crtc;
-	adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs;
-}
-
 const struct amdgpu_ip_block_version dce_virtual_ip_block =
 {
 	.type = AMD_IP_BLOCK_TYPE_DCE,
-- 
2.32.0


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

* [PATCH 2/3] drm/amdgpu: cleanup dce_virtual
@ 2021-07-21 17:07   ` Ryan Taylor
  0 siblings, 0 replies; 24+ messages in thread
From: Ryan Taylor @ 2021-07-21 17:07 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: melissa.srw, daniel.vetter, rodrigo.siqueira, Ryan Taylor

Remove obsolete functions and variables from dce_virtual.

Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 568 +----------------------
 1 file changed, 3 insertions(+), 565 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
index 642c77533157..18369b47eac7 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
@@ -21,15 +21,9 @@
  *
  */
 
-#include <drm/drm_vblank.h>
 #include <drm/drm_atomic_helper.h>
 
 #include "amdgpu.h"
-#include "amdgpu_pm.h"
-#include "amdgpu_i2c.h"
-#include "atom.h"
-#include "amdgpu_pll.h"
-#include "amdgpu_connectors.h"
 #ifdef CONFIG_DRM_AMDGPU_SI
 #include "dce_v6_0.h"
 #endif
@@ -43,339 +37,6 @@
 #include "amdgpu_display.h"
 #include "amdgpu_vkms.h"
 
-#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
-
-
-static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
-static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
-static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
-					      int index);
-static int dce_virtual_pageflip(struct amdgpu_device *adev,
-				unsigned crtc_id);
-static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer);
-static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
-							int crtc,
-							enum amdgpu_interrupt_state state);
-
-static u32 dce_virtual_vblank_get_counter(struct amdgpu_device *adev, int crtc)
-{
-	return 0;
-}
-
-static void dce_virtual_page_flip(struct amdgpu_device *adev,
-			      int crtc_id, u64 crtc_base, bool async)
-{
-	return;
-}
-
-static int dce_virtual_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
-					u32 *vbl, u32 *position)
-{
-	*vbl = 0;
-	*position = 0;
-
-	return -EINVAL;
-}
-
-static bool dce_virtual_hpd_sense(struct amdgpu_device *adev,
-			       enum amdgpu_hpd_id hpd)
-{
-	return true;
-}
-
-static void dce_virtual_hpd_set_polarity(struct amdgpu_device *adev,
-				      enum amdgpu_hpd_id hpd)
-{
-	return;
-}
-
-static u32 dce_virtual_hpd_get_gpio_reg(struct amdgpu_device *adev)
-{
-	return 0;
-}
-
-/**
- * dce_virtual_bandwidth_update - program display watermarks
- *
- * @adev: amdgpu_device pointer
- *
- * Calculate and program the display watermarks and line
- * buffer allocation (CIK).
- */
-static void dce_virtual_bandwidth_update(struct amdgpu_device *adev)
-{
-	return;
-}
-
-static int dce_virtual_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
-				      u16 *green, u16 *blue, uint32_t size,
-				      struct drm_modeset_acquire_ctx *ctx)
-{
-	return 0;
-}
-
-static void dce_virtual_crtc_destroy(struct drm_crtc *crtc)
-{
-	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-
-	drm_crtc_cleanup(crtc);
-	kfree(amdgpu_crtc);
-}
-
-static const struct drm_crtc_funcs dce_virtual_crtc_funcs = {
-	.cursor_set2 = NULL,
-	.cursor_move = NULL,
-	.gamma_set = dce_virtual_crtc_gamma_set,
-	.set_config = amdgpu_display_crtc_set_config,
-	.destroy = dce_virtual_crtc_destroy,
-	.page_flip_target = amdgpu_display_crtc_page_flip_target,
-	.get_vblank_counter = amdgpu_get_vblank_counter_kms,
-	.enable_vblank = amdgpu_enable_vblank_kms,
-	.disable_vblank = amdgpu_disable_vblank_kms,
-	.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
-};
-
-static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-	struct drm_device *dev = crtc->dev;
-	struct amdgpu_device *adev = drm_to_adev(dev);
-	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-	unsigned type;
-
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		amdgpu_crtc->enabled = true;
-		/* Make sure VBLANK interrupts are still enabled */
-		type = amdgpu_display_crtc_idx_to_irq_type(adev,
-						amdgpu_crtc->crtc_id);
-		amdgpu_irq_update(adev, &adev->crtc_irq, type);
-		drm_crtc_vblank_on(crtc);
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-	case DRM_MODE_DPMS_OFF:
-		drm_crtc_vblank_off(crtc);
-		amdgpu_crtc->enabled = false;
-		break;
-	}
-}
-
-
-static void dce_virtual_crtc_prepare(struct drm_crtc *crtc)
-{
-	dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void dce_virtual_crtc_commit(struct drm_crtc *crtc)
-{
-	dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-static void dce_virtual_crtc_disable(struct drm_crtc *crtc)
-{
-	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-	struct drm_device *dev = crtc->dev;
-
-	if (dev->num_crtcs)
-		drm_crtc_vblank_off(crtc);
-
-	amdgpu_crtc->enabled = false;
-	amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
-	amdgpu_crtc->encoder = NULL;
-	amdgpu_crtc->connector = NULL;
-}
-
-static int dce_virtual_crtc_mode_set(struct drm_crtc *crtc,
-				  struct drm_display_mode *mode,
-				  struct drm_display_mode *adjusted_mode,
-				  int x, int y, struct drm_framebuffer *old_fb)
-{
-	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-
-	/* update the hw version fpr dpm */
-	amdgpu_crtc->hw_mode = *adjusted_mode;
-
-	return 0;
-}
-
-static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc,
-				     const struct drm_display_mode *mode,
-				     struct drm_display_mode *adjusted_mode)
-{
-	return true;
-}
-
-
-static int dce_virtual_crtc_set_base(struct drm_crtc *crtc, int x, int y,
-				  struct drm_framebuffer *old_fb)
-{
-	return 0;
-}
-
-static int dce_virtual_crtc_set_base_atomic(struct drm_crtc *crtc,
-					 struct drm_framebuffer *fb,
-					 int x, int y, enum mode_set_atomic state)
-{
-	return 0;
-}
-
-static const struct drm_crtc_helper_funcs dce_virtual_crtc_helper_funcs = {
-	.dpms = dce_virtual_crtc_dpms,
-	.mode_fixup = dce_virtual_crtc_mode_fixup,
-	.mode_set = dce_virtual_crtc_mode_set,
-	.mode_set_base = dce_virtual_crtc_set_base,
-	.mode_set_base_atomic = dce_virtual_crtc_set_base_atomic,
-	.prepare = dce_virtual_crtc_prepare,
-	.commit = dce_virtual_crtc_commit,
-	.disable = dce_virtual_crtc_disable,
-	.get_scanout_position = amdgpu_crtc_get_scanout_position,
-};
-
-static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index)
-{
-	struct amdgpu_crtc *amdgpu_crtc;
-
-	amdgpu_crtc = kzalloc(sizeof(struct amdgpu_crtc) +
-			      (AMDGPUFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
-	if (amdgpu_crtc == NULL)
-		return -ENOMEM;
-
-	drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_virtual_crtc_funcs);
-
-	drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256);
-	amdgpu_crtc->crtc_id = index;
-	adev->mode_info.crtcs[index] = amdgpu_crtc;
-
-	amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
-	amdgpu_crtc->encoder = NULL;
-	amdgpu_crtc->connector = NULL;
-	amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
-	drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs);
-
-	hrtimer_init(&amdgpu_crtc->vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-	hrtimer_set_expires(&amdgpu_crtc->vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD);
-	amdgpu_crtc->vblank_timer.function = dce_virtual_vblank_timer_handle;
-	hrtimer_start(&amdgpu_crtc->vblank_timer,
-		      DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL);
-	return 0;
-}
-
-static int dce_virtual_early_init(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dce_virtual_set_display_funcs(adev);
-	dce_virtual_set_irq_funcs(adev);
-
-	adev->mode_info.num_hpd = 1;
-	adev->mode_info.num_dig = 1;
-	return 0;
-}
-
-static struct drm_encoder *
-dce_virtual_encoder(struct drm_connector *connector)
-{
-	struct drm_encoder *encoder;
-
-	drm_connector_for_each_possible_encoder(connector, encoder) {
-		if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
-			return encoder;
-	}
-
-	/* pick the first one */
-	drm_connector_for_each_possible_encoder(connector, encoder)
-		return encoder;
-
-	return NULL;
-}
-
-static int dce_virtual_get_modes(struct drm_connector *connector)
-{
-	struct drm_device *dev = connector->dev;
-	struct drm_display_mode *mode = NULL;
-	unsigned i;
-	static const struct mode_size {
-		int w;
-		int h;
-	} common_modes[] = {
-		{ 640,  480},
-		{ 720,  480},
-		{ 800,  600},
-		{ 848,  480},
-		{1024,  768},
-		{1152,  768},
-		{1280,  720},
-		{1280,  800},
-		{1280,  854},
-		{1280,  960},
-		{1280, 1024},
-		{1440,  900},
-		{1400, 1050},
-		{1680, 1050},
-		{1600, 1200},
-		{1920, 1080},
-		{1920, 1200},
-		{2560, 1440},
-		{4096, 3112},
-		{3656, 2664},
-		{3840, 2160},
-		{4096, 2160},
-	};
-
-	for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
-		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
-		drm_mode_probed_add(connector, mode);
-	}
-
-	return 0;
-}
-
-static enum drm_mode_status dce_virtual_mode_valid(struct drm_connector *connector,
-				  struct drm_display_mode *mode)
-{
-	return MODE_OK;
-}
-
-static int
-dce_virtual_dpms(struct drm_connector *connector, int mode)
-{
-	return 0;
-}
-
-static int
-dce_virtual_set_property(struct drm_connector *connector,
-			 struct drm_property *property,
-			 uint64_t val)
-{
-	return 0;
-}
-
-static void dce_virtual_destroy(struct drm_connector *connector)
-{
-	drm_connector_unregister(connector);
-	drm_connector_cleanup(connector);
-	kfree(connector);
-}
-
-static void dce_virtual_force(struct drm_connector *connector)
-{
-	return;
-}
-
-static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = {
-	.get_modes = dce_virtual_get_modes,
-	.mode_valid = dce_virtual_mode_valid,
-	.best_encoder = dce_virtual_encoder,
-};
-
-static const struct drm_connector_funcs dce_virtual_connector_funcs = {
-	.dpms = dce_virtual_dpms,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.set_property = dce_virtual_set_property,
-	.destroy = dce_virtual_destroy,
-	.force = dce_virtual_force,
-};
-
 const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
 	.fb_create = amdgpu_display_user_framebuffer_create,
 	.atomic_check = drm_atomic_helper_check,
@@ -387,10 +48,6 @@ static int dce_virtual_sw_init(void *handle)
 	int r, i;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER, &adev->crtc_irq);
-	if (r)
-		return r;
-
 	adev_to_drm(adev)->max_vblank_count = 0;
 
 	adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
@@ -436,9 +93,6 @@ static int dce_virtual_sw_fini(void *handle)
 
 	drm_kms_helper_poll_fini(adev_to_drm(adev));
 
-	drm_mode_config_cleanup(adev_to_drm(adev));
-	/* clear crtcs pointer to avoid dce irq finish routine access freed data */
-	memset(adev->mode_info.crtcs, 0, sizeof(adev->mode_info.crtcs[0]) * AMDGPU_MAX_CRTCS);
 	adev->mode_info.mode_config_initialized = false;
 	return 0;
 }
@@ -498,7 +152,7 @@ static int dce_virtual_suspend(void *handle)
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	int r;
 
-	r = amdgpu_display_suspend_helper(adev);
+	r = drm_mode_config_helper_suspend(adev_to_drm(adev));
 	if (r)
 		return r;
 	return dce_virtual_hw_fini(handle);
@@ -512,7 +166,7 @@ static int dce_virtual_resume(void *handle)
 	r = dce_virtual_hw_init(handle);
 	if (r)
 		return r;
-	return amdgpu_display_resume_helper(adev);
+	return drm_mode_config_helper_resume(adev_to_drm(adev));
 }
 
 static bool dce_virtual_is_idle(void *handle)
@@ -544,7 +198,7 @@ static int dce_virtual_set_powergating_state(void *handle,
 
 static const struct amd_ip_funcs dce_virtual_ip_funcs = {
 	.name = "dce_virtual",
-	.early_init = dce_virtual_early_init,
+	.early_init = NULL,
 	.late_init = NULL,
 	.sw_init = dce_virtual_sw_init,
 	.sw_fini = dce_virtual_sw_fini,
@@ -559,222 +213,6 @@ static const struct amd_ip_funcs dce_virtual_ip_funcs = {
 	.set_powergating_state = dce_virtual_set_powergating_state,
 };
 
-/* these are handled by the primary encoders */
-static void dce_virtual_encoder_prepare(struct drm_encoder *encoder)
-{
-	return;
-}
-
-static void dce_virtual_encoder_commit(struct drm_encoder *encoder)
-{
-	return;
-}
-
-static void
-dce_virtual_encoder_mode_set(struct drm_encoder *encoder,
-			     struct drm_display_mode *mode,
-			     struct drm_display_mode *adjusted_mode)
-{
-	return;
-}
-
-static void dce_virtual_encoder_disable(struct drm_encoder *encoder)
-{
-	return;
-}
-
-static void
-dce_virtual_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-	return;
-}
-
-static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder,
-				    const struct drm_display_mode *mode,
-				    struct drm_display_mode *adjusted_mode)
-{
-	return true;
-}
-
-static const struct drm_encoder_helper_funcs dce_virtual_encoder_helper_funcs = {
-	.dpms = dce_virtual_encoder_dpms,
-	.mode_fixup = dce_virtual_encoder_mode_fixup,
-	.prepare = dce_virtual_encoder_prepare,
-	.mode_set = dce_virtual_encoder_mode_set,
-	.commit = dce_virtual_encoder_commit,
-	.disable = dce_virtual_encoder_disable,
-};
-
-static void dce_virtual_encoder_destroy(struct drm_encoder *encoder)
-{
-	drm_encoder_cleanup(encoder);
-	kfree(encoder);
-}
-
-static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
-	.destroy = dce_virtual_encoder_destroy,
-};
-
-static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
-					      int index)
-{
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
-
-	/* add a new encoder */
-	encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL);
-	if (!encoder)
-		return -ENOMEM;
-	encoder->possible_crtcs = 1 << index;
-	drm_encoder_init(adev_to_drm(adev), encoder, &dce_virtual_encoder_funcs,
-			 DRM_MODE_ENCODER_VIRTUAL, NULL);
-	drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
-
-	connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
-	if (!connector) {
-		kfree(encoder);
-		return -ENOMEM;
-	}
-
-	/* add a new connector */
-	drm_connector_init(adev_to_drm(adev), connector, &dce_virtual_connector_funcs,
-			   DRM_MODE_CONNECTOR_VIRTUAL);
-	drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs);
-	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
-	connector->interlace_allowed = false;
-	connector->doublescan_allowed = false;
-
-	/* link them */
-	drm_connector_attach_encoder(connector, encoder);
-
-	return 0;
-}
-
-static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
-	.bandwidth_update = &dce_virtual_bandwidth_update,
-	.vblank_get_counter = &dce_virtual_vblank_get_counter,
-	.backlight_set_level = NULL,
-	.backlight_get_level = NULL,
-	.hpd_sense = &dce_virtual_hpd_sense,
-	.hpd_set_polarity = &dce_virtual_hpd_set_polarity,
-	.hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg,
-	.page_flip = &dce_virtual_page_flip,
-	.page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos,
-	.add_encoder = NULL,
-	.add_connector = NULL,
-};
-
-static void dce_virtual_set_display_funcs(struct amdgpu_device *adev)
-{
-	adev->mode_info.funcs = &dce_virtual_display_funcs;
-}
-
-static int dce_virtual_pageflip(struct amdgpu_device *adev,
-				unsigned crtc_id)
-{
-	unsigned long flags;
-	struct amdgpu_crtc *amdgpu_crtc;
-	struct amdgpu_flip_work *works;
-
-	amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
-
-	if (crtc_id >= adev->mode_info.num_crtc) {
-		DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
-		return -EINVAL;
-	}
-
-	/* IRQ could occur when in initial stage */
-	if (amdgpu_crtc == NULL)
-		return 0;
-
-	spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
-	works = amdgpu_crtc->pflip_works;
-	if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
-		DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != "
-			"AMDGPU_FLIP_SUBMITTED(%d)\n",
-			amdgpu_crtc->pflip_status,
-			AMDGPU_FLIP_SUBMITTED);
-		spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
-		return 0;
-	}
-
-	/* page flip completed. clean up */
-	amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
-	amdgpu_crtc->pflip_works = NULL;
-
-	/* wakeup usersapce */
-	if (works->event)
-		drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event);
-
-	spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
-
-	drm_crtc_vblank_put(&amdgpu_crtc->base);
-	amdgpu_bo_unref(&works->old_abo);
-	kfree(works->shared);
-	kfree(works);
-
-	return 0;
-}
-
-static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
-{
-	struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer,
-						       struct amdgpu_crtc, vblank_timer);
-	struct drm_device *ddev = amdgpu_crtc->base.dev;
-	struct amdgpu_device *adev = drm_to_adev(ddev);
-	struct amdgpu_irq_src *source = adev->irq.client[AMDGPU_IRQ_CLIENTID_LEGACY].sources
-		[VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER];
-	int irq_type = amdgpu_display_crtc_idx_to_irq_type(adev,
-						amdgpu_crtc->crtc_id);
-
-	if (amdgpu_irq_enabled(adev, source, irq_type)) {
-		drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
-		dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
-	}
-	hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD,
-		      HRTIMER_MODE_REL);
-
-	return HRTIMER_NORESTART;
-}
-
-static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
-							int crtc,
-							enum amdgpu_interrupt_state state)
-{
-	if (crtc >= adev->mode_info.num_crtc || !adev->mode_info.crtcs[crtc]) {
-		DRM_DEBUG("invalid crtc %d\n", crtc);
-		return;
-	}
-
-	adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
-	DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
-}
-
-
-static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
-					  struct amdgpu_irq_src *source,
-					  unsigned type,
-					  enum amdgpu_interrupt_state state)
-{
-	if (type > AMDGPU_CRTC_IRQ_VBLANK6)
-		return -EINVAL;
-
-	dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state);
-
-	return 0;
-}
-
-static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = {
-	.set = dce_virtual_set_crtc_irq_state,
-	.process = NULL,
-};
-
-static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev)
-{
-	adev->crtc_irq.num_types = adev->mode_info.num_crtc;
-	adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs;
-}
-
 const struct amdgpu_ip_block_version dce_virtual_ip_block =
 {
 	.type = AMD_IP_BLOCK_TYPE_DCE,
-- 
2.32.0

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* [PATCH 3/3] drm/amdgpu: replace dce_virtual with amdgpu_vkms (v3)
  2021-07-21 17:07 ` Ryan Taylor
@ 2021-07-21 17:07   ` Ryan Taylor
  -1 siblings, 0 replies; 24+ messages in thread
From: Ryan Taylor @ 2021-07-21 17:07 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: kernel test robot, daniel.vetter, rodrigo.siqueira, Ryan Taylor,
	melissa.srw, Alex Deucher

Move dce_virtual into amdgpu_vkms and update all references to
dce_virtual with amdgpu_vkms.

v2: Removed more references to dce_virtual.

v3: Restored display modes from previous implementation.

Reported-by: kernel test robot <lkp@intel.com>
Suggested-by: Alex Deucher <Alexander.Deucher@amd.com>
Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/Makefile      |   3 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 234 ++++++++++++++++++++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |   5 +-
 drivers/gpu/drm/amd/amdgpu/cik.c         |  10 +-
 drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 223 ---------------------
 drivers/gpu/drm/amd/amdgpu/dce_virtual.h |  30 ---
 drivers/gpu/drm/amd/amdgpu/nv.c          |  20 +-
 drivers/gpu/drm/amd/amdgpu/si.c          |   8 +-
 drivers/gpu/drm/amd/amdgpu/soc15.c       |  10 +-
 drivers/gpu/drm/amd/amdgpu/vi.c          |  14 +-
 10 files changed, 264 insertions(+), 293 deletions(-)
 delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.c
 delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.h

diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 30cbcd5ce1cc..0d814c957461 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -120,8 +120,7 @@ amdgpu-y += \
 amdgpu-y += \
 	dce_v10_0.o \
 	dce_v11_0.o \
-	amdgpu_vkms.o \
-	dce_virtual.o
+	amdgpu_vkms.o
 
 # add GFX block
 amdgpu-y += \
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
index d5c1f1c58f5f..538d41e6666a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -5,6 +5,15 @@
 #include <drm/drm_vblank.h>
 
 #include "amdgpu.h"
+#ifdef CONFIG_DRM_AMDGPU_SI
+#include "dce_v6_0.h"
+#endif
+#ifdef CONFIG_DRM_AMDGPU_CIK
+#include "dce_v8_0.h"
+#endif
+#include "dce_v10_0.h"
+#include "dce_v11_0.h"
+#include "ivsrcid/ivsrcid_vislands30.h"
 #include "amdgpu_vkms.h"
 #include "amdgpu_display.h"
 
@@ -180,12 +189,45 @@ static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
 
 static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
 {
-	int count;
+	struct drm_device *dev = connector->dev;
+	struct drm_display_mode *mode = NULL;
+	unsigned i;
+	static const struct mode_size {
+		int w;
+		int h;
+	} common_modes[] = {
+		{ 640,  480},
+		{ 720,  480},
+		{ 800,  600},
+		{ 848,  480},
+		{1024,  768},
+		{1152,  768},
+		{1280,  720},
+		{1280,  800},
+		{1280,  854},
+		{1280,  960},
+		{1280, 1024},
+		{1440,  900},
+		{1400, 1050},
+		{1680, 1050},
+		{1600, 1200},
+		{1920, 1080},
+		{1920, 1200},
+		{2560, 1440},
+		{4096, 3112},
+		{3656, 2664},
+		{3840, 2160},
+		{4096, 2160},
+	};
+
+	for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
+		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
+		drm_mode_probed_add(connector, mode);
+	}
 
-	count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
 	drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
 
-	return count;
+	return ARRAY_SIZE(common_modes);
 }
 
 static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
@@ -409,3 +451,189 @@ int amdgpu_vkms_output_init(struct drm_device *dev,
 
 	return ret;
 }
+
+const struct drm_mode_config_funcs amdgpu_vkms_mode_funcs = {
+	.fb_create = amdgpu_display_user_framebuffer_create,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+static int amdgpu_vkms_sw_init(void *handle)
+{
+	int r, i;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	adev_to_drm(adev)->max_vblank_count = 0;
+
+	adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs;
+
+	adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
+	adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
+
+	adev_to_drm(adev)->mode_config.preferred_depth = 24;
+	adev_to_drm(adev)->mode_config.prefer_shadow = 1;
+
+	adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
+
+	r = amdgpu_display_modeset_create_props(adev);
+	if (r)
+		return r;
+
+	adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
+
+	/* allocate crtcs, encoders, connectors */
+	for (i = 0; i < adev->mode_info.num_crtc; i++) {
+		r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
+		if (r)
+			return r;
+	}
+
+	drm_kms_helper_poll_init(adev_to_drm(adev));
+
+	adev->mode_info.mode_config_initialized = true;
+	return 0;
+}
+
+static int amdgpu_vkms_sw_fini(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int i = 0;
+
+	for (i = 0; i < adev->mode_info.num_crtc; i++)
+		if (adev->mode_info.crtcs[i])
+			hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
+
+	kfree(adev->mode_info.bios_hardcoded_edid);
+	kfree(adev->amdgpu_vkms_output);
+
+	drm_kms_helper_poll_fini(adev_to_drm(adev));
+
+	adev->mode_info.mode_config_initialized = false;
+	return 0;
+}
+
+static int amdgpu_vkms_hw_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	switch (adev->asic_type) {
+#ifdef CONFIG_DRM_AMDGPU_SI
+	case CHIP_TAHITI:
+	case CHIP_PITCAIRN:
+	case CHIP_VERDE:
+	case CHIP_OLAND:
+		dce_v6_0_disable_dce(adev);
+		break;
+#endif
+#ifdef CONFIG_DRM_AMDGPU_CIK
+	case CHIP_BONAIRE:
+	case CHIP_HAWAII:
+	case CHIP_KAVERI:
+	case CHIP_KABINI:
+	case CHIP_MULLINS:
+		dce_v8_0_disable_dce(adev);
+		break;
+#endif
+	case CHIP_FIJI:
+	case CHIP_TONGA:
+		dce_v10_0_disable_dce(adev);
+		break;
+	case CHIP_CARRIZO:
+	case CHIP_STONEY:
+	case CHIP_POLARIS10:
+	case CHIP_POLARIS11:
+	case CHIP_VEGAM:
+		dce_v11_0_disable_dce(adev);
+		break;
+	case CHIP_TOPAZ:
+#ifdef CONFIG_DRM_AMDGPU_SI
+	case CHIP_HAINAN:
+#endif
+		/* no DCE */
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int amdgpu_vkms_hw_fini(void *handle)
+{
+	return 0;
+}
+
+static int amdgpu_vkms_suspend(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int r;
+
+	r = drm_mode_config_helper_suspend(adev_to_drm(adev));
+	if (r)
+		return r;
+	return amdgpu_vkms_hw_fini(handle);
+}
+
+static int amdgpu_vkms_resume(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int r;
+
+	r = amdgpu_vkms_hw_init(handle);
+	if (r)
+		return r;
+	return drm_mode_config_helper_resume(adev_to_drm(adev));
+}
+
+static bool amdgpu_vkms_is_idle(void *handle)
+{
+	return true;
+}
+
+static int amdgpu_vkms_wait_for_idle(void *handle)
+{
+	return 0;
+}
+
+static int amdgpu_vkms_soft_reset(void *handle)
+{
+	return 0;
+}
+
+static int amdgpu_vkms_set_clockgating_state(void *handle,
+					  enum amd_clockgating_state state)
+{
+	return 0;
+}
+
+static int amdgpu_vkms_set_powergating_state(void *handle,
+					  enum amd_powergating_state state)
+{
+	return 0;
+}
+
+static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = {
+	.name = "amdgpu_vkms",
+	.early_init = NULL,
+	.late_init = NULL,
+	.sw_init = amdgpu_vkms_sw_init,
+	.sw_fini = amdgpu_vkms_sw_fini,
+	.hw_init = amdgpu_vkms_hw_init,
+	.hw_fini = amdgpu_vkms_hw_fini,
+	.suspend = amdgpu_vkms_suspend,
+	.resume = amdgpu_vkms_resume,
+	.is_idle = amdgpu_vkms_is_idle,
+	.wait_for_idle = amdgpu_vkms_wait_for_idle,
+	.soft_reset = amdgpu_vkms_soft_reset,
+	.set_clockgating_state = amdgpu_vkms_set_clockgating_state,
+	.set_powergating_state = amdgpu_vkms_set_powergating_state,
+};
+
+const struct amdgpu_ip_block_version amdgpu_vkms_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 1,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &amdgpu_vkms_ip_funcs,
+};
+
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
index 5dab51fbecf3..97f1b79c0724 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
@@ -4,7 +4,7 @@
 #define _AMDGPU_VKMS_H_
 
 #define XRES_DEF  1024
-#define YRES_DEF   764
+#define YRES_DEF   768
 
 #define XRES_MAX  16384
 #define YRES_MAX  16384
@@ -23,7 +23,4 @@ struct amdgpu_vkms_output {
 	struct drm_pending_vblank_event *event;
 };
 
-int amdgpu_vkms_output_init(struct drm_device *dev,
-			    struct amdgpu_vkms_output *output, int index);
-
 #endif /* _AMDGPU_VKMS_H_ */
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index c0fcc41ee574..54f28c075f21 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -70,7 +70,7 @@
 
 #include "amdgpu_dm.h"
 #include "amdgpu_amdkfd.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
 
 static const struct amdgpu_video_codec_info cik_video_codecs_encode_array[] =
 {
@@ -2259,7 +2259,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2277,7 +2277,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2295,7 +2295,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
 		amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2315,7 +2315,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
 		amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
deleted file mode 100644
index 18369b47eac7..000000000000
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright 2014 Advanced Micro Devices, Inc.
- *
- * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
- *
- */
-
-#include <drm/drm_atomic_helper.h>
-
-#include "amdgpu.h"
-#ifdef CONFIG_DRM_AMDGPU_SI
-#include "dce_v6_0.h"
-#endif
-#ifdef CONFIG_DRM_AMDGPU_CIK
-#include "dce_v8_0.h"
-#endif
-#include "dce_v10_0.h"
-#include "dce_v11_0.h"
-#include "dce_virtual.h"
-#include "ivsrcid/ivsrcid_vislands30.h"
-#include "amdgpu_display.h"
-#include "amdgpu_vkms.h"
-
-const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
-	.fb_create = amdgpu_display_user_framebuffer_create,
-	.atomic_check = drm_atomic_helper_check,
-	.atomic_commit = drm_atomic_helper_commit,
-};
-
-static int dce_virtual_sw_init(void *handle)
-{
-	int r, i;
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	adev_to_drm(adev)->max_vblank_count = 0;
-
-	adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
-
-	adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
-	adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
-
-	adev_to_drm(adev)->mode_config.preferred_depth = 24;
-	adev_to_drm(adev)->mode_config.prefer_shadow = 1;
-
-	adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
-
-	r = amdgpu_display_modeset_create_props(adev);
-	if (r)
-		return r;
-
-	adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
-
-	/* allocate crtcs, encoders, connectors */
-	for (i = 0; i < adev->mode_info.num_crtc; i++) {
-		r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
-		if (r)
-			return r;
-	}
-
-	drm_kms_helper_poll_init(adev_to_drm(adev));
-
-	adev->mode_info.mode_config_initialized = true;
-	return 0;
-}
-
-static int dce_virtual_sw_fini(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	int i = 0;
-
-	for (i = 0; i < adev->mode_info.num_crtc; i++)
-		if (adev->mode_info.crtcs[i])
-			hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
-
-	kfree(adev->mode_info.bios_hardcoded_edid);
-	kfree(adev->amdgpu_vkms_output);
-
-	drm_kms_helper_poll_fini(adev_to_drm(adev));
-
-	adev->mode_info.mode_config_initialized = false;
-	return 0;
-}
-
-static int dce_virtual_hw_init(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	switch (adev->asic_type) {
-#ifdef CONFIG_DRM_AMDGPU_SI
-	case CHIP_TAHITI:
-	case CHIP_PITCAIRN:
-	case CHIP_VERDE:
-	case CHIP_OLAND:
-		dce_v6_0_disable_dce(adev);
-		break;
-#endif
-#ifdef CONFIG_DRM_AMDGPU_CIK
-	case CHIP_BONAIRE:
-	case CHIP_HAWAII:
-	case CHIP_KAVERI:
-	case CHIP_KABINI:
-	case CHIP_MULLINS:
-		dce_v8_0_disable_dce(adev);
-		break;
-#endif
-	case CHIP_FIJI:
-	case CHIP_TONGA:
-		dce_v10_0_disable_dce(adev);
-		break;
-	case CHIP_CARRIZO:
-	case CHIP_STONEY:
-	case CHIP_POLARIS10:
-	case CHIP_POLARIS11:
-	case CHIP_VEGAM:
-		dce_v11_0_disable_dce(adev);
-		break;
-	case CHIP_TOPAZ:
-#ifdef CONFIG_DRM_AMDGPU_SI
-	case CHIP_HAINAN:
-#endif
-		/* no DCE */
-		break;
-	default:
-		break;
-	}
-	return 0;
-}
-
-static int dce_virtual_hw_fini(void *handle)
-{
-	return 0;
-}
-
-static int dce_virtual_suspend(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	int r;
-
-	r = drm_mode_config_helper_suspend(adev_to_drm(adev));
-	if (r)
-		return r;
-	return dce_virtual_hw_fini(handle);
-}
-
-static int dce_virtual_resume(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	int r;
-
-	r = dce_virtual_hw_init(handle);
-	if (r)
-		return r;
-	return drm_mode_config_helper_resume(adev_to_drm(adev));
-}
-
-static bool dce_virtual_is_idle(void *handle)
-{
-	return true;
-}
-
-static int dce_virtual_wait_for_idle(void *handle)
-{
-	return 0;
-}
-
-static int dce_virtual_soft_reset(void *handle)
-{
-	return 0;
-}
-
-static int dce_virtual_set_clockgating_state(void *handle,
-					  enum amd_clockgating_state state)
-{
-	return 0;
-}
-
-static int dce_virtual_set_powergating_state(void *handle,
-					  enum amd_powergating_state state)
-{
-	return 0;
-}
-
-static const struct amd_ip_funcs dce_virtual_ip_funcs = {
-	.name = "dce_virtual",
-	.early_init = NULL,
-	.late_init = NULL,
-	.sw_init = dce_virtual_sw_init,
-	.sw_fini = dce_virtual_sw_fini,
-	.hw_init = dce_virtual_hw_init,
-	.hw_fini = dce_virtual_hw_fini,
-	.suspend = dce_virtual_suspend,
-	.resume = dce_virtual_resume,
-	.is_idle = dce_virtual_is_idle,
-	.wait_for_idle = dce_virtual_wait_for_idle,
-	.soft_reset = dce_virtual_soft_reset,
-	.set_clockgating_state = dce_virtual_set_clockgating_state,
-	.set_powergating_state = dce_virtual_set_powergating_state,
-};
-
-const struct amdgpu_ip_block_version dce_virtual_ip_block =
-{
-	.type = AMD_IP_BLOCK_TYPE_DCE,
-	.major = 1,
-	.minor = 0,
-	.rev = 0,
-	.funcs = &dce_virtual_ip_funcs,
-};
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
deleted file mode 100644
index ed422012c8c6..000000000000
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2014 Advanced Micro Devices, Inc.
- *
- * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
- *
- */
-
-#ifndef __DCE_VIRTUAL_H__
-#define __DCE_VIRTUAL_H__
-
-extern const struct amdgpu_ip_block_version dce_virtual_ip_block;
-
-#endif
-
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
index 436fb13e32f0..696ecc1ccb28 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/nv.c
@@ -58,7 +58,7 @@
 #include "jpeg_v2_0.h"
 #include "vcn_v3_0.h"
 #include "jpeg_v3_0.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
 #include "mes_v10_1.h"
 #include "mxgpu_nv.h"
 #include "smuio_v11_0.h"
@@ -721,7 +721,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		    !amdgpu_sriov_vf(adev))
 			amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -749,7 +749,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
 			amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -779,7 +779,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		    is_support_sw_smu(adev))
 			amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -802,7 +802,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		    is_support_sw_smu(adev))
 			amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -823,7 +823,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 			amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -843,7 +843,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		    is_support_sw_smu(adev))
 			amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
                 else if (amdgpu_device_has_dc_support(adev))
                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -865,7 +865,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -883,11 +883,11 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 			amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 		amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index 7cbc2bb03bc6..e6d2f74a7976 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -44,7 +44,7 @@
 #include "dce_v6_0.h"
 #include "si.h"
 #include "uvd_v3_1.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
 #include "gca/gfx_6_0_d.h"
 #include "oss/oss_1_0_d.h"
 #include "oss/oss_1_0_sh_mask.h"
@@ -2759,7 +2759,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
 		amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2777,7 +2777,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
 		amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2795,7 +2795,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
 		amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 		break;
 	default:
 		BUG();
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index a5e085e570f7..f7b56a746c15 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -74,7 +74,7 @@
 #include "smuio_v9_0.h"
 #include "smuio_v11_0.h"
 #include "smuio_v13_0.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
 #include "mxgpu_ai.h"
 #include "amdgpu_ras.h"
 #include "amdgpu_xgmi.h"
@@ -843,7 +843,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
 			amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		}
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -863,7 +863,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -885,7 +885,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
 		}
 
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 		amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
@@ -909,7 +909,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
                 else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 3d21c0799037..fe9a7cc8d9eb 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -77,7 +77,7 @@
 #if defined(CONFIG_DRM_AMD_ACP)
 #include "amdgpu_acp.h"
 #endif
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
 #include "mxgpu_vi.h"
 #include "amdgpu_dm.h"
 
@@ -2102,7 +2102,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 		break;
 	case CHIP_FIJI:
 		amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
@@ -2112,7 +2112,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2132,7 +2132,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2155,7 +2155,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2173,7 +2173,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2194,7 +2194,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
-- 
2.32.0


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

* [PATCH 3/3] drm/amdgpu: replace dce_virtual with amdgpu_vkms (v3)
@ 2021-07-21 17:07   ` Ryan Taylor
  0 siblings, 0 replies; 24+ messages in thread
From: Ryan Taylor @ 2021-07-21 17:07 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: kernel test robot, daniel.vetter, rodrigo.siqueira, Ryan Taylor,
	melissa.srw, Alex Deucher

Move dce_virtual into amdgpu_vkms and update all references to
dce_virtual with amdgpu_vkms.

v2: Removed more references to dce_virtual.

v3: Restored display modes from previous implementation.

Reported-by: kernel test robot <lkp@intel.com>
Suggested-by: Alex Deucher <Alexander.Deucher@amd.com>
Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/Makefile      |   3 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 234 ++++++++++++++++++++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |   5 +-
 drivers/gpu/drm/amd/amdgpu/cik.c         |  10 +-
 drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 223 ---------------------
 drivers/gpu/drm/amd/amdgpu/dce_virtual.h |  30 ---
 drivers/gpu/drm/amd/amdgpu/nv.c          |  20 +-
 drivers/gpu/drm/amd/amdgpu/si.c          |   8 +-
 drivers/gpu/drm/amd/amdgpu/soc15.c       |  10 +-
 drivers/gpu/drm/amd/amdgpu/vi.c          |  14 +-
 10 files changed, 264 insertions(+), 293 deletions(-)
 delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.c
 delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.h

diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 30cbcd5ce1cc..0d814c957461 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -120,8 +120,7 @@ amdgpu-y += \
 amdgpu-y += \
 	dce_v10_0.o \
 	dce_v11_0.o \
-	amdgpu_vkms.o \
-	dce_virtual.o
+	amdgpu_vkms.o
 
 # add GFX block
 amdgpu-y += \
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
index d5c1f1c58f5f..538d41e6666a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -5,6 +5,15 @@
 #include <drm/drm_vblank.h>
 
 #include "amdgpu.h"
+#ifdef CONFIG_DRM_AMDGPU_SI
+#include "dce_v6_0.h"
+#endif
+#ifdef CONFIG_DRM_AMDGPU_CIK
+#include "dce_v8_0.h"
+#endif
+#include "dce_v10_0.h"
+#include "dce_v11_0.h"
+#include "ivsrcid/ivsrcid_vislands30.h"
 #include "amdgpu_vkms.h"
 #include "amdgpu_display.h"
 
@@ -180,12 +189,45 @@ static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
 
 static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
 {
-	int count;
+	struct drm_device *dev = connector->dev;
+	struct drm_display_mode *mode = NULL;
+	unsigned i;
+	static const struct mode_size {
+		int w;
+		int h;
+	} common_modes[] = {
+		{ 640,  480},
+		{ 720,  480},
+		{ 800,  600},
+		{ 848,  480},
+		{1024,  768},
+		{1152,  768},
+		{1280,  720},
+		{1280,  800},
+		{1280,  854},
+		{1280,  960},
+		{1280, 1024},
+		{1440,  900},
+		{1400, 1050},
+		{1680, 1050},
+		{1600, 1200},
+		{1920, 1080},
+		{1920, 1200},
+		{2560, 1440},
+		{4096, 3112},
+		{3656, 2664},
+		{3840, 2160},
+		{4096, 2160},
+	};
+
+	for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
+		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
+		drm_mode_probed_add(connector, mode);
+	}
 
-	count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
 	drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
 
-	return count;
+	return ARRAY_SIZE(common_modes);
 }
 
 static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
@@ -409,3 +451,189 @@ int amdgpu_vkms_output_init(struct drm_device *dev,
 
 	return ret;
 }
+
+const struct drm_mode_config_funcs amdgpu_vkms_mode_funcs = {
+	.fb_create = amdgpu_display_user_framebuffer_create,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+static int amdgpu_vkms_sw_init(void *handle)
+{
+	int r, i;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	adev_to_drm(adev)->max_vblank_count = 0;
+
+	adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs;
+
+	adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
+	adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
+
+	adev_to_drm(adev)->mode_config.preferred_depth = 24;
+	adev_to_drm(adev)->mode_config.prefer_shadow = 1;
+
+	adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
+
+	r = amdgpu_display_modeset_create_props(adev);
+	if (r)
+		return r;
+
+	adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
+
+	/* allocate crtcs, encoders, connectors */
+	for (i = 0; i < adev->mode_info.num_crtc; i++) {
+		r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
+		if (r)
+			return r;
+	}
+
+	drm_kms_helper_poll_init(adev_to_drm(adev));
+
+	adev->mode_info.mode_config_initialized = true;
+	return 0;
+}
+
+static int amdgpu_vkms_sw_fini(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int i = 0;
+
+	for (i = 0; i < adev->mode_info.num_crtc; i++)
+		if (adev->mode_info.crtcs[i])
+			hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
+
+	kfree(adev->mode_info.bios_hardcoded_edid);
+	kfree(adev->amdgpu_vkms_output);
+
+	drm_kms_helper_poll_fini(adev_to_drm(adev));
+
+	adev->mode_info.mode_config_initialized = false;
+	return 0;
+}
+
+static int amdgpu_vkms_hw_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	switch (adev->asic_type) {
+#ifdef CONFIG_DRM_AMDGPU_SI
+	case CHIP_TAHITI:
+	case CHIP_PITCAIRN:
+	case CHIP_VERDE:
+	case CHIP_OLAND:
+		dce_v6_0_disable_dce(adev);
+		break;
+#endif
+#ifdef CONFIG_DRM_AMDGPU_CIK
+	case CHIP_BONAIRE:
+	case CHIP_HAWAII:
+	case CHIP_KAVERI:
+	case CHIP_KABINI:
+	case CHIP_MULLINS:
+		dce_v8_0_disable_dce(adev);
+		break;
+#endif
+	case CHIP_FIJI:
+	case CHIP_TONGA:
+		dce_v10_0_disable_dce(adev);
+		break;
+	case CHIP_CARRIZO:
+	case CHIP_STONEY:
+	case CHIP_POLARIS10:
+	case CHIP_POLARIS11:
+	case CHIP_VEGAM:
+		dce_v11_0_disable_dce(adev);
+		break;
+	case CHIP_TOPAZ:
+#ifdef CONFIG_DRM_AMDGPU_SI
+	case CHIP_HAINAN:
+#endif
+		/* no DCE */
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int amdgpu_vkms_hw_fini(void *handle)
+{
+	return 0;
+}
+
+static int amdgpu_vkms_suspend(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int r;
+
+	r = drm_mode_config_helper_suspend(adev_to_drm(adev));
+	if (r)
+		return r;
+	return amdgpu_vkms_hw_fini(handle);
+}
+
+static int amdgpu_vkms_resume(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int r;
+
+	r = amdgpu_vkms_hw_init(handle);
+	if (r)
+		return r;
+	return drm_mode_config_helper_resume(adev_to_drm(adev));
+}
+
+static bool amdgpu_vkms_is_idle(void *handle)
+{
+	return true;
+}
+
+static int amdgpu_vkms_wait_for_idle(void *handle)
+{
+	return 0;
+}
+
+static int amdgpu_vkms_soft_reset(void *handle)
+{
+	return 0;
+}
+
+static int amdgpu_vkms_set_clockgating_state(void *handle,
+					  enum amd_clockgating_state state)
+{
+	return 0;
+}
+
+static int amdgpu_vkms_set_powergating_state(void *handle,
+					  enum amd_powergating_state state)
+{
+	return 0;
+}
+
+static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = {
+	.name = "amdgpu_vkms",
+	.early_init = NULL,
+	.late_init = NULL,
+	.sw_init = amdgpu_vkms_sw_init,
+	.sw_fini = amdgpu_vkms_sw_fini,
+	.hw_init = amdgpu_vkms_hw_init,
+	.hw_fini = amdgpu_vkms_hw_fini,
+	.suspend = amdgpu_vkms_suspend,
+	.resume = amdgpu_vkms_resume,
+	.is_idle = amdgpu_vkms_is_idle,
+	.wait_for_idle = amdgpu_vkms_wait_for_idle,
+	.soft_reset = amdgpu_vkms_soft_reset,
+	.set_clockgating_state = amdgpu_vkms_set_clockgating_state,
+	.set_powergating_state = amdgpu_vkms_set_powergating_state,
+};
+
+const struct amdgpu_ip_block_version amdgpu_vkms_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 1,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &amdgpu_vkms_ip_funcs,
+};
+
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
index 5dab51fbecf3..97f1b79c0724 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
@@ -4,7 +4,7 @@
 #define _AMDGPU_VKMS_H_
 
 #define XRES_DEF  1024
-#define YRES_DEF   764
+#define YRES_DEF   768
 
 #define XRES_MAX  16384
 #define YRES_MAX  16384
@@ -23,7 +23,4 @@ struct amdgpu_vkms_output {
 	struct drm_pending_vblank_event *event;
 };
 
-int amdgpu_vkms_output_init(struct drm_device *dev,
-			    struct amdgpu_vkms_output *output, int index);
-
 #endif /* _AMDGPU_VKMS_H_ */
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index c0fcc41ee574..54f28c075f21 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -70,7 +70,7 @@
 
 #include "amdgpu_dm.h"
 #include "amdgpu_amdkfd.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
 
 static const struct amdgpu_video_codec_info cik_video_codecs_encode_array[] =
 {
@@ -2259,7 +2259,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2277,7 +2277,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2295,7 +2295,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
 		amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2315,7 +2315,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
 		amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
deleted file mode 100644
index 18369b47eac7..000000000000
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright 2014 Advanced Micro Devices, Inc.
- *
- * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
- *
- */
-
-#include <drm/drm_atomic_helper.h>
-
-#include "amdgpu.h"
-#ifdef CONFIG_DRM_AMDGPU_SI
-#include "dce_v6_0.h"
-#endif
-#ifdef CONFIG_DRM_AMDGPU_CIK
-#include "dce_v8_0.h"
-#endif
-#include "dce_v10_0.h"
-#include "dce_v11_0.h"
-#include "dce_virtual.h"
-#include "ivsrcid/ivsrcid_vislands30.h"
-#include "amdgpu_display.h"
-#include "amdgpu_vkms.h"
-
-const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
-	.fb_create = amdgpu_display_user_framebuffer_create,
-	.atomic_check = drm_atomic_helper_check,
-	.atomic_commit = drm_atomic_helper_commit,
-};
-
-static int dce_virtual_sw_init(void *handle)
-{
-	int r, i;
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	adev_to_drm(adev)->max_vblank_count = 0;
-
-	adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
-
-	adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
-	adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
-
-	adev_to_drm(adev)->mode_config.preferred_depth = 24;
-	adev_to_drm(adev)->mode_config.prefer_shadow = 1;
-
-	adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
-
-	r = amdgpu_display_modeset_create_props(adev);
-	if (r)
-		return r;
-
-	adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
-
-	/* allocate crtcs, encoders, connectors */
-	for (i = 0; i < adev->mode_info.num_crtc; i++) {
-		r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
-		if (r)
-			return r;
-	}
-
-	drm_kms_helper_poll_init(adev_to_drm(adev));
-
-	adev->mode_info.mode_config_initialized = true;
-	return 0;
-}
-
-static int dce_virtual_sw_fini(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	int i = 0;
-
-	for (i = 0; i < adev->mode_info.num_crtc; i++)
-		if (adev->mode_info.crtcs[i])
-			hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
-
-	kfree(adev->mode_info.bios_hardcoded_edid);
-	kfree(adev->amdgpu_vkms_output);
-
-	drm_kms_helper_poll_fini(adev_to_drm(adev));
-
-	adev->mode_info.mode_config_initialized = false;
-	return 0;
-}
-
-static int dce_virtual_hw_init(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	switch (adev->asic_type) {
-#ifdef CONFIG_DRM_AMDGPU_SI
-	case CHIP_TAHITI:
-	case CHIP_PITCAIRN:
-	case CHIP_VERDE:
-	case CHIP_OLAND:
-		dce_v6_0_disable_dce(adev);
-		break;
-#endif
-#ifdef CONFIG_DRM_AMDGPU_CIK
-	case CHIP_BONAIRE:
-	case CHIP_HAWAII:
-	case CHIP_KAVERI:
-	case CHIP_KABINI:
-	case CHIP_MULLINS:
-		dce_v8_0_disable_dce(adev);
-		break;
-#endif
-	case CHIP_FIJI:
-	case CHIP_TONGA:
-		dce_v10_0_disable_dce(adev);
-		break;
-	case CHIP_CARRIZO:
-	case CHIP_STONEY:
-	case CHIP_POLARIS10:
-	case CHIP_POLARIS11:
-	case CHIP_VEGAM:
-		dce_v11_0_disable_dce(adev);
-		break;
-	case CHIP_TOPAZ:
-#ifdef CONFIG_DRM_AMDGPU_SI
-	case CHIP_HAINAN:
-#endif
-		/* no DCE */
-		break;
-	default:
-		break;
-	}
-	return 0;
-}
-
-static int dce_virtual_hw_fini(void *handle)
-{
-	return 0;
-}
-
-static int dce_virtual_suspend(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	int r;
-
-	r = drm_mode_config_helper_suspend(adev_to_drm(adev));
-	if (r)
-		return r;
-	return dce_virtual_hw_fini(handle);
-}
-
-static int dce_virtual_resume(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	int r;
-
-	r = dce_virtual_hw_init(handle);
-	if (r)
-		return r;
-	return drm_mode_config_helper_resume(adev_to_drm(adev));
-}
-
-static bool dce_virtual_is_idle(void *handle)
-{
-	return true;
-}
-
-static int dce_virtual_wait_for_idle(void *handle)
-{
-	return 0;
-}
-
-static int dce_virtual_soft_reset(void *handle)
-{
-	return 0;
-}
-
-static int dce_virtual_set_clockgating_state(void *handle,
-					  enum amd_clockgating_state state)
-{
-	return 0;
-}
-
-static int dce_virtual_set_powergating_state(void *handle,
-					  enum amd_powergating_state state)
-{
-	return 0;
-}
-
-static const struct amd_ip_funcs dce_virtual_ip_funcs = {
-	.name = "dce_virtual",
-	.early_init = NULL,
-	.late_init = NULL,
-	.sw_init = dce_virtual_sw_init,
-	.sw_fini = dce_virtual_sw_fini,
-	.hw_init = dce_virtual_hw_init,
-	.hw_fini = dce_virtual_hw_fini,
-	.suspend = dce_virtual_suspend,
-	.resume = dce_virtual_resume,
-	.is_idle = dce_virtual_is_idle,
-	.wait_for_idle = dce_virtual_wait_for_idle,
-	.soft_reset = dce_virtual_soft_reset,
-	.set_clockgating_state = dce_virtual_set_clockgating_state,
-	.set_powergating_state = dce_virtual_set_powergating_state,
-};
-
-const struct amdgpu_ip_block_version dce_virtual_ip_block =
-{
-	.type = AMD_IP_BLOCK_TYPE_DCE,
-	.major = 1,
-	.minor = 0,
-	.rev = 0,
-	.funcs = &dce_virtual_ip_funcs,
-};
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
deleted file mode 100644
index ed422012c8c6..000000000000
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2014 Advanced Micro Devices, Inc.
- *
- * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
- *
- */
-
-#ifndef __DCE_VIRTUAL_H__
-#define __DCE_VIRTUAL_H__
-
-extern const struct amdgpu_ip_block_version dce_virtual_ip_block;
-
-#endif
-
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
index 436fb13e32f0..696ecc1ccb28 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/nv.c
@@ -58,7 +58,7 @@
 #include "jpeg_v2_0.h"
 #include "vcn_v3_0.h"
 #include "jpeg_v3_0.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
 #include "mes_v10_1.h"
 #include "mxgpu_nv.h"
 #include "smuio_v11_0.h"
@@ -721,7 +721,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		    !amdgpu_sriov_vf(adev))
 			amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -749,7 +749,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
 			amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -779,7 +779,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		    is_support_sw_smu(adev))
 			amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -802,7 +802,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		    is_support_sw_smu(adev))
 			amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -823,7 +823,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 			amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -843,7 +843,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		    is_support_sw_smu(adev))
 			amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
                 else if (amdgpu_device_has_dc_support(adev))
                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -865,7 +865,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -883,11 +883,11 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
 			amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 		amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index 7cbc2bb03bc6..e6d2f74a7976 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -44,7 +44,7 @@
 #include "dce_v6_0.h"
 #include "si.h"
 #include "uvd_v3_1.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
 #include "gca/gfx_6_0_d.h"
 #include "oss/oss_1_0_d.h"
 #include "oss/oss_1_0_sh_mask.h"
@@ -2759,7 +2759,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
 		amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2777,7 +2777,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
 		amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2795,7 +2795,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
 		amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 		break;
 	default:
 		BUG();
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index a5e085e570f7..f7b56a746c15 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -74,7 +74,7 @@
 #include "smuio_v9_0.h"
 #include "smuio_v11_0.h"
 #include "smuio_v13_0.h"
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
 #include "mxgpu_ai.h"
 #include "amdgpu_ras.h"
 #include "amdgpu_xgmi.h"
@@ -843,7 +843,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
 			amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		}
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -863,7 +863,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -885,7 +885,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
 		}
 
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 		amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
@@ -909,7 +909,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
                 else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 3d21c0799037..fe9a7cc8d9eb 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -77,7 +77,7 @@
 #if defined(CONFIG_DRM_AMD_ACP)
 #include "amdgpu_acp.h"
 #endif
-#include "dce_virtual.h"
+#include "amdgpu_vkms.h"
 #include "mxgpu_vi.h"
 #include "amdgpu_dm.h"
 
@@ -2102,7 +2102,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 		break;
 	case CHIP_FIJI:
 		amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
@@ -2112,7 +2112,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2132,7 +2132,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2155,7 +2155,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2173,7 +2173,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
@@ -2194,7 +2194,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
 		amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
 		if (adev->enable_virtual_display)
-			amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+			amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
 #if defined(CONFIG_DRM_AMD_DC)
 		else if (amdgpu_device_has_dc_support(adev))
 			amdgpu_device_ip_block_add(adev, &dm_ip_block);
-- 
2.32.0

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
  2021-07-21 17:07   ` Ryan Taylor
@ 2021-07-23 14:31     ` Alex Deucher
  -1 siblings, 0 replies; 24+ messages in thread
From: Alex Deucher @ 2021-07-23 14:31 UTC (permalink / raw)
  To: Ryan Taylor
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo,
	amd-gfx list, Melissa Wen, Maling list - DRI developers

On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
>
> Modify the VKMS driver into an api that dce_virtual can use to create
> virtual displays that obey drm's atomic modesetting api.
>
> v2: Made local functions static.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411 +++++++++++++++++++++++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |  29 ++
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
>  7 files changed, 458 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
>  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
> index f089794bbdd5..30cbcd5ce1cc 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -120,6 +120,7 @@ amdgpu-y += \
>  amdgpu-y += \
>         dce_v10_0.o \
>         dce_v11_0.o \
> +       amdgpu_vkms.o \
>         dce_virtual.o
>
>  # add GFX block
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 54cf647bd018..d0a2f2ed433d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -919,6 +919,7 @@ struct amdgpu_device {
>
>         /* display */
>         bool                            enable_virtual_display;
> +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
>         struct amdgpu_mode_info         mode_info;
>         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
>         struct work_struct              hotplug_work;
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index d0c935cf4f0f..1b016e5bc75f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
>         int ret, retry = 0;
>         bool supports_atomic = false;
>
> -       if (!amdgpu_virtual_display &&
> +       if (amdgpu_virtual_display ||
>             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
>                 supports_atomic = true;
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> index 09b048647523..5a143ca02cf9 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
>         }
>
>         /* disable all the possible outputs/crtcs before entering KMS mode */
> -       if (!amdgpu_device_has_dc_support(adev))
> +       if (!amdgpu_device_has_dc_support(adev) && !amdgpu_virtual_display)
>                 drm_helper_disable_unused_functions(adev_to_drm(adev));
>
>         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> new file mode 100644
> index 000000000000..d5c1f1c58f5f
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> @@ -0,0 +1,411 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_simple_kms_helper.h>
> +#include <drm/drm_vblank.h>
> +
> +#include "amdgpu.h"
> +#include "amdgpu_vkms.h"
> +#include "amdgpu_display.h"
> +
> +/**
> + * DOC: amdgpu_vkms
> + *
> + * The amdgpu vkms interface provides a virtual KMS interface for several use
> + * cases: devices without display hardware, platforms where the actual display
> + * hardware is not useful (e.g., servers), SR-IOV virtual functions, device
> + * emulation/simulation, and device bring up prior to display hardware being
> + * usable. We previously emulated a legacy KMS interface, but there was a desire
> + * to move to the atomic KMS interface. The vkms driver did everything we
> + * needed, but we wanted KMS support natively in the driver without buffer
> + * sharing and the ability to support an instance of VKMS per device. We first
> + * looked at splitting vkms into a stub driver and a helper module that other
> + * drivers could use to implement a virtual display, but this strategy ended up
> + * being messy due to driver specific callbacks needed for buffer management.
> + * Ultimately, it proved easier to import the vkms code as it mostly used core
> + * drm helpers anyway.
> + */
> +
> +static const u32 amdgpu_vkms_formats[] = {
> +       DRM_FORMAT_XRGB8888,
> +};
> +
> +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
> +{
> +       struct amdgpu_vkms_output *output = container_of(timer,
> +                                                        struct amdgpu_vkms_output,
> +                                                        vblank_hrtimer);
> +       struct drm_crtc *crtc = &output->crtc;
> +       u64 ret_overrun;
> +       bool ret;
> +
> +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> +                                         output->period_ns);
> +       WARN_ON(ret_overrun != 1);
> +
> +       ret = drm_crtc_handle_vblank(crtc);
> +       if (!ret)
> +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> +
> +       return HRTIMER_RESTART;
> +}
> +
> +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       unsigned int pipe = drm_crtc_index(crtc);
> +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +       struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
> +
> +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> +
> +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> +       hrtimer_start(&out->vblank_hrtimer, out->period_ns, HRTIMER_MODE_REL);
> +
> +       return 0;
> +}
> +
> +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc)
> +{
> +       struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
> +
> +       hrtimer_cancel(&out->vblank_hrtimer);
> +}
> +
> +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> +                                            int *max_error,
> +                                            ktime_t *vblank_time,
> +                                            bool in_vblank_irq)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       unsigned int pipe = crtc->index;
> +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +
> +       if (!READ_ONCE(vblank->enabled)) {
> +               *vblank_time = ktime_get();
> +               return true;
> +       }
> +
> +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> +
> +       if (WARN_ON(*vblank_time == vblank->time))
> +               return true;
> +
> +       /*
> +        * To prevent races we roll the hrtimer forward before we do any
> +        * interrupt processing - this is how real hw works (the interrupt is
> +        * only generated after all the vblank registers are updated) and what
> +        * the vblank core expects. Therefore we need to always correct the
> +        * timestampe by one frame.
> +        */
> +       *vblank_time -= output->period_ns;
> +
> +       return true;
> +}
> +
> +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> +       .set_config             = drm_atomic_helper_set_config,
> +       .destroy                = drm_crtc_cleanup,
> +       .page_flip              = drm_atomic_helper_page_flip,
> +       .reset                  = drm_atomic_helper_crtc_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> +};
> +
> +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> +                                          struct drm_atomic_state *state)
> +{
> +       drm_crtc_vblank_on(crtc);
> +}
> +
> +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> +                                           struct drm_atomic_state *state)
> +{
> +       drm_crtc_vblank_off(crtc);
> +}
> +
> +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> +                                         struct drm_atomic_state *state)
> +{
> +       if (crtc->state->event) {
> +               spin_lock(&crtc->dev->event_lock);
> +
> +               if (drm_crtc_vblank_get(crtc) != 0)
> +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> +               else
> +                       drm_crtc_arm_vblank_event(crtc, crtc->state->event);
> +
> +               spin_unlock(&crtc->dev->event_lock);
> +
> +               crtc->state->event = NULL;
> +       }
> +}
> +
> +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable,
> +};
> +
> +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> +                         struct drm_plane *primary, struct drm_plane *cursor)
> +{
> +       int ret;
> +
> +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> +                                       &amdgpu_vkms_crtc_funcs, NULL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init CRTC\n");
> +               return ret;
> +       }
> +
> +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> +
> +       return ret;
> +}
> +
> +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> +       .fill_modes = drm_helper_probe_single_connector_modes,
> +       .destroy = drm_connector_cleanup,
> +       .reset = drm_atomic_helper_connector_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
> +{
> +       int count;
> +
> +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> +
> +       return count;
> +}
> +
> +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> +       .get_modes    = amdgpu_vkms_conn_get_modes,
> +};
> +
> +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> +       .update_plane           = drm_atomic_helper_update_plane,
> +       .disable_plane          = drm_atomic_helper_disable_plane,
> +       .destroy                = drm_plane_cleanup,
> +       .reset                  = drm_atomic_helper_plane_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> +};
> +
> +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> +                                           struct drm_plane_state *old_state)
> +{
> +       return;
> +}
> +
> +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> +                                         struct drm_plane_state *state)
> +{
> +       struct drm_crtc_state *crtc_state;
> +       bool can_position = false;
> +       int ret;
> +
> +       if (!state->fb || WARN_ON(!state->crtc))
> +               return 0;
> +
> +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> +       if (IS_ERR(crtc_state))
> +               return PTR_ERR(crtc_state);
> +
> +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> +                                                 DRM_PLANE_HELPER_NO_SCALING,
> +                                                 DRM_PLANE_HELPER_NO_SCALING,
> +                                                 can_position, true);
> +       if (ret != 0)
> +               return ret;
> +
> +       /* for now primary plane must be visible and full screen */
> +       if (!state->visible && !can_position)
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> +                                 struct drm_plane_state *new_state)
> +{
> +       struct amdgpu_framebuffer *afb;
> +       struct drm_gem_object *obj;
> +       struct amdgpu_device *adev;
> +       struct amdgpu_bo *rbo;
> +       struct list_head list;
> +       struct ttm_validate_buffer tv;
> +       struct ww_acquire_ctx ticket;
> +       uint32_t domain;
> +       int r;
> +
> +       if (!new_state->fb) {
> +               DRM_DEBUG_KMS("No FB bound\n");
> +               return 0;
> +       }
> +       afb = to_amdgpu_framebuffer(new_state->fb);
> +       obj = new_state->fb->obj[0];
> +       rbo = gem_to_amdgpu_bo(obj);
> +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> +       INIT_LIST_HEAD(&list);
> +
> +       tv.bo = &rbo->tbo;
> +       tv.num_shared = 1;
> +       list_add(&tv.head, &list);
> +
> +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> +       if (r) {
> +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> +               return r;
> +       }
> +
> +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> +       else
> +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> +
> +       r = amdgpu_bo_pin(rbo, domain);
> +       if (unlikely(r != 0)) {
> +               if (r != -ERESTARTSYS)
> +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> +               ttm_eu_backoff_reservation(&ticket, &list);
> +               return r;
> +       }
> +
> +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> +       if (unlikely(r != 0)) {
> +               amdgpu_bo_unpin(rbo);
> +               ttm_eu_backoff_reservation(&ticket, &list);
> +               DRM_ERROR("%p bind failed\n", rbo);
> +               return r;
> +       }
> +
> +       ttm_eu_backoff_reservation(&ticket, &list);
> +
> +       afb->address = amdgpu_bo_gpu_offset(rbo);
> +
> +       amdgpu_bo_ref(rbo);
> +
> +       return 0;
> +}
> +
> +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> +                                  struct drm_plane_state *old_state)
> +{
> +       struct amdgpu_bo *rbo;
> +       int r;
> +
> +       if (!old_state->fb)
> +               return;
> +
> +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> +       r = amdgpu_bo_reserve(rbo, false);
> +       if (unlikely(r)) {
> +               DRM_ERROR("failed to reserve rbo before unpin\n");
> +               return;
> +       }
> +
> +       amdgpu_bo_unpin(rbo);
> +       amdgpu_bo_unreserve(rbo);
> +       amdgpu_bo_unref(&rbo);
> +}
> +
> +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> +};
> +
> +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> +                                               enum drm_plane_type type,
> +                                               int index)
> +{
> +       struct drm_plane *plane;
> +       int ret;
> +
> +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> +       if (!plane)
> +               return ERR_PTR(-ENOMEM);
> +
> +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> +                                      &amdgpu_vkms_plane_funcs,
> +                                      amdgpu_vkms_formats,
> +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> +                                      NULL, type, NULL);
> +       if (ret) {
> +               kfree(plane);
> +               return ERR_PTR(ret);
> +       }
> +
> +       drm_plane_helper_add(plane, &amdgpu_vkms_primary_helper_funcs);
> +
> +       return plane;
> +}
> +
> +int amdgpu_vkms_output_init(struct drm_device *dev,
> +                           struct amdgpu_vkms_output *output, int index)
> +{
> +       struct drm_connector *connector = &output->connector;
> +       struct drm_encoder *encoder = &output->encoder;
> +       struct drm_crtc *crtc = &output->crtc;
> +       struct drm_plane *primary, *cursor = NULL;
> +       int ret;
> +
> +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> +       if (IS_ERR(primary))
> +               return PTR_ERR(primary);
> +
> +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> +       if (ret)
> +               goto err_crtc;
> +
> +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> +                                DRM_MODE_CONNECTOR_VIRTUAL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init connector\n");
> +               goto err_connector;
> +       }
> +
> +       drm_connector_helper_add(connector, &amdgpu_vkms_conn_helper_funcs);
> +
> +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init encoder\n");
> +               goto err_encoder;
> +       }
> +       encoder->possible_crtcs = 1 << index;
> +
> +       ret = drm_connector_attach_encoder(connector, encoder);
> +       if (ret) {
> +               DRM_ERROR("Failed to attach connector to encoder\n");
> +               goto err_attach;
> +       }
> +
> +       drm_mode_config_reset(dev);
> +
> +       return 0;
> +
> +err_attach:
> +       drm_encoder_cleanup(encoder);
> +
> +err_encoder:
> +       drm_connector_cleanup(connector);
> +
> +err_connector:
> +       drm_crtc_cleanup(crtc);
> +
> +err_crtc:
> +       drm_plane_cleanup(primary);
> +
> +       return ret;
> +}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> new file mode 100644
> index 000000000000..5dab51fbecf3
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +
> +#ifndef _AMDGPU_VKMS_H_
> +#define _AMDGPU_VKMS_H_
> +
> +#define XRES_DEF  1024
> +#define YRES_DEF   764

Squash in the 768 fix here.

> +
> +#define XRES_MAX  16384
> +#define YRES_MAX  16384
> +
> +#define drm_crtc_to_amdgpu_vkms_output(target) \
> +       container_of(target, struct amdgpu_vkms_output, crtc)
> +
> +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> +
> +struct amdgpu_vkms_output {
> +       struct drm_crtc crtc;
> +       struct drm_encoder encoder;
> +       struct drm_connector connector;
> +       struct hrtimer vblank_hrtimer;
> +       ktime_t period_ns;
> +       struct drm_pending_vblank_event *event;
> +};
> +
> +int amdgpu_vkms_output_init(struct drm_device *dev,
> +                           struct amdgpu_vkms_output *output, int index);
> +
> +#endif /* _AMDGPU_VKMS_H_ */
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> index 7e0d8c092c7e..642c77533157 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> @@ -22,6 +22,7 @@
>   */
>
>  #include <drm/drm_vblank.h>
> +#include <drm/drm_atomic_helper.h>
>
>  #include "amdgpu.h"
>  #include "amdgpu_pm.h"
> @@ -40,6 +41,7 @@
>  #include "dce_virtual.h"
>  #include "ivsrcid/ivsrcid_vislands30.h"
>  #include "amdgpu_display.h"
> +#include "amdgpu_vkms.h"
>
>  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
>
> @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
>         .force = dce_virtual_force,
>  };
>
> +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> +       .fb_create = amdgpu_display_user_framebuffer_create,
> +       .atomic_check = drm_atomic_helper_check,
> +       .atomic_commit = drm_atomic_helper_commit,
> +};
> +
>  static int dce_virtual_sw_init(void *handle)
>  {
>         int r, i;
> @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
>
>         adev_to_drm(adev)->max_vblank_count = 0;
>
> -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> +       adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
>
> -       adev_to_drm(adev)->mode_config.max_width = 16384;
> -       adev_to_drm(adev)->mode_config.max_height = 16384;
> +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
>
>         adev_to_drm(adev)->mode_config.preferred_depth = 24;
>         adev_to_drm(adev)->mode_config.prefer_shadow = 1;
> @@ -399,15 +407,11 @@ static int dce_virtual_sw_init(void *handle)
>         if (r)
>                 return r;
>
> -       adev_to_drm(adev)->mode_config.max_width = 16384;
> -       adev_to_drm(adev)->mode_config.max_height = 16384;
> +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);

You can use kcalloc here.

>
>         /* allocate crtcs, encoders, connectors */
>         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> -               r = dce_virtual_crtc_init(adev, i);
> -               if (r)
> -                       return r;
> -               r = dce_virtual_connector_encoder_init(adev, i);
> +               r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
>                 if (r)
>                         return r;
>         }
> @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
>                         hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
>
>         kfree(adev->mode_info.bios_hardcoded_edid);
> +       kfree(adev->amdgpu_vkms_output);
>
>         drm_kms_helper_poll_fini(adev_to_drm(adev));
>
> --
> 2.32.0
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
@ 2021-07-23 14:31     ` Alex Deucher
  0 siblings, 0 replies; 24+ messages in thread
From: Alex Deucher @ 2021-07-23 14:31 UTC (permalink / raw)
  To: Ryan Taylor
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo,
	amd-gfx list, Melissa Wen, Maling list - DRI developers

On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
>
> Modify the VKMS driver into an api that dce_virtual can use to create
> virtual displays that obey drm's atomic modesetting api.
>
> v2: Made local functions static.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411 +++++++++++++++++++++++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |  29 ++
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
>  7 files changed, 458 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
>  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
> index f089794bbdd5..30cbcd5ce1cc 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -120,6 +120,7 @@ amdgpu-y += \
>  amdgpu-y += \
>         dce_v10_0.o \
>         dce_v11_0.o \
> +       amdgpu_vkms.o \
>         dce_virtual.o
>
>  # add GFX block
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 54cf647bd018..d0a2f2ed433d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -919,6 +919,7 @@ struct amdgpu_device {
>
>         /* display */
>         bool                            enable_virtual_display;
> +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
>         struct amdgpu_mode_info         mode_info;
>         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
>         struct work_struct              hotplug_work;
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index d0c935cf4f0f..1b016e5bc75f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
>         int ret, retry = 0;
>         bool supports_atomic = false;
>
> -       if (!amdgpu_virtual_display &&
> +       if (amdgpu_virtual_display ||
>             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
>                 supports_atomic = true;
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> index 09b048647523..5a143ca02cf9 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
>         }
>
>         /* disable all the possible outputs/crtcs before entering KMS mode */
> -       if (!amdgpu_device_has_dc_support(adev))
> +       if (!amdgpu_device_has_dc_support(adev) && !amdgpu_virtual_display)
>                 drm_helper_disable_unused_functions(adev_to_drm(adev));
>
>         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> new file mode 100644
> index 000000000000..d5c1f1c58f5f
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> @@ -0,0 +1,411 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_simple_kms_helper.h>
> +#include <drm/drm_vblank.h>
> +
> +#include "amdgpu.h"
> +#include "amdgpu_vkms.h"
> +#include "amdgpu_display.h"
> +
> +/**
> + * DOC: amdgpu_vkms
> + *
> + * The amdgpu vkms interface provides a virtual KMS interface for several use
> + * cases: devices without display hardware, platforms where the actual display
> + * hardware is not useful (e.g., servers), SR-IOV virtual functions, device
> + * emulation/simulation, and device bring up prior to display hardware being
> + * usable. We previously emulated a legacy KMS interface, but there was a desire
> + * to move to the atomic KMS interface. The vkms driver did everything we
> + * needed, but we wanted KMS support natively in the driver without buffer
> + * sharing and the ability to support an instance of VKMS per device. We first
> + * looked at splitting vkms into a stub driver and a helper module that other
> + * drivers could use to implement a virtual display, but this strategy ended up
> + * being messy due to driver specific callbacks needed for buffer management.
> + * Ultimately, it proved easier to import the vkms code as it mostly used core
> + * drm helpers anyway.
> + */
> +
> +static const u32 amdgpu_vkms_formats[] = {
> +       DRM_FORMAT_XRGB8888,
> +};
> +
> +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
> +{
> +       struct amdgpu_vkms_output *output = container_of(timer,
> +                                                        struct amdgpu_vkms_output,
> +                                                        vblank_hrtimer);
> +       struct drm_crtc *crtc = &output->crtc;
> +       u64 ret_overrun;
> +       bool ret;
> +
> +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> +                                         output->period_ns);
> +       WARN_ON(ret_overrun != 1);
> +
> +       ret = drm_crtc_handle_vblank(crtc);
> +       if (!ret)
> +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> +
> +       return HRTIMER_RESTART;
> +}
> +
> +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       unsigned int pipe = drm_crtc_index(crtc);
> +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +       struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
> +
> +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> +
> +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> +       hrtimer_start(&out->vblank_hrtimer, out->period_ns, HRTIMER_MODE_REL);
> +
> +       return 0;
> +}
> +
> +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc)
> +{
> +       struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
> +
> +       hrtimer_cancel(&out->vblank_hrtimer);
> +}
> +
> +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> +                                            int *max_error,
> +                                            ktime_t *vblank_time,
> +                                            bool in_vblank_irq)
> +{
> +       struct drm_device *dev = crtc->dev;
> +       unsigned int pipe = crtc->index;
> +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +
> +       if (!READ_ONCE(vblank->enabled)) {
> +               *vblank_time = ktime_get();
> +               return true;
> +       }
> +
> +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> +
> +       if (WARN_ON(*vblank_time == vblank->time))
> +               return true;
> +
> +       /*
> +        * To prevent races we roll the hrtimer forward before we do any
> +        * interrupt processing - this is how real hw works (the interrupt is
> +        * only generated after all the vblank registers are updated) and what
> +        * the vblank core expects. Therefore we need to always correct the
> +        * timestampe by one frame.
> +        */
> +       *vblank_time -= output->period_ns;
> +
> +       return true;
> +}
> +
> +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> +       .set_config             = drm_atomic_helper_set_config,
> +       .destroy                = drm_crtc_cleanup,
> +       .page_flip              = drm_atomic_helper_page_flip,
> +       .reset                  = drm_atomic_helper_crtc_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> +};
> +
> +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> +                                          struct drm_atomic_state *state)
> +{
> +       drm_crtc_vblank_on(crtc);
> +}
> +
> +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> +                                           struct drm_atomic_state *state)
> +{
> +       drm_crtc_vblank_off(crtc);
> +}
> +
> +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> +                                         struct drm_atomic_state *state)
> +{
> +       if (crtc->state->event) {
> +               spin_lock(&crtc->dev->event_lock);
> +
> +               if (drm_crtc_vblank_get(crtc) != 0)
> +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> +               else
> +                       drm_crtc_arm_vblank_event(crtc, crtc->state->event);
> +
> +               spin_unlock(&crtc->dev->event_lock);
> +
> +               crtc->state->event = NULL;
> +       }
> +}
> +
> +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable,
> +};
> +
> +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> +                         struct drm_plane *primary, struct drm_plane *cursor)
> +{
> +       int ret;
> +
> +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> +                                       &amdgpu_vkms_crtc_funcs, NULL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init CRTC\n");
> +               return ret;
> +       }
> +
> +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> +
> +       return ret;
> +}
> +
> +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> +       .fill_modes = drm_helper_probe_single_connector_modes,
> +       .destroy = drm_connector_cleanup,
> +       .reset = drm_atomic_helper_connector_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
> +{
> +       int count;
> +
> +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> +
> +       return count;
> +}
> +
> +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> +       .get_modes    = amdgpu_vkms_conn_get_modes,
> +};
> +
> +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> +       .update_plane           = drm_atomic_helper_update_plane,
> +       .disable_plane          = drm_atomic_helper_disable_plane,
> +       .destroy                = drm_plane_cleanup,
> +       .reset                  = drm_atomic_helper_plane_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> +};
> +
> +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> +                                           struct drm_plane_state *old_state)
> +{
> +       return;
> +}
> +
> +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> +                                         struct drm_plane_state *state)
> +{
> +       struct drm_crtc_state *crtc_state;
> +       bool can_position = false;
> +       int ret;
> +
> +       if (!state->fb || WARN_ON(!state->crtc))
> +               return 0;
> +
> +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> +       if (IS_ERR(crtc_state))
> +               return PTR_ERR(crtc_state);
> +
> +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> +                                                 DRM_PLANE_HELPER_NO_SCALING,
> +                                                 DRM_PLANE_HELPER_NO_SCALING,
> +                                                 can_position, true);
> +       if (ret != 0)
> +               return ret;
> +
> +       /* for now primary plane must be visible and full screen */
> +       if (!state->visible && !can_position)
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> +                                 struct drm_plane_state *new_state)
> +{
> +       struct amdgpu_framebuffer *afb;
> +       struct drm_gem_object *obj;
> +       struct amdgpu_device *adev;
> +       struct amdgpu_bo *rbo;
> +       struct list_head list;
> +       struct ttm_validate_buffer tv;
> +       struct ww_acquire_ctx ticket;
> +       uint32_t domain;
> +       int r;
> +
> +       if (!new_state->fb) {
> +               DRM_DEBUG_KMS("No FB bound\n");
> +               return 0;
> +       }
> +       afb = to_amdgpu_framebuffer(new_state->fb);
> +       obj = new_state->fb->obj[0];
> +       rbo = gem_to_amdgpu_bo(obj);
> +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> +       INIT_LIST_HEAD(&list);
> +
> +       tv.bo = &rbo->tbo;
> +       tv.num_shared = 1;
> +       list_add(&tv.head, &list);
> +
> +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> +       if (r) {
> +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> +               return r;
> +       }
> +
> +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> +       else
> +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> +
> +       r = amdgpu_bo_pin(rbo, domain);
> +       if (unlikely(r != 0)) {
> +               if (r != -ERESTARTSYS)
> +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> +               ttm_eu_backoff_reservation(&ticket, &list);
> +               return r;
> +       }
> +
> +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> +       if (unlikely(r != 0)) {
> +               amdgpu_bo_unpin(rbo);
> +               ttm_eu_backoff_reservation(&ticket, &list);
> +               DRM_ERROR("%p bind failed\n", rbo);
> +               return r;
> +       }
> +
> +       ttm_eu_backoff_reservation(&ticket, &list);
> +
> +       afb->address = amdgpu_bo_gpu_offset(rbo);
> +
> +       amdgpu_bo_ref(rbo);
> +
> +       return 0;
> +}
> +
> +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> +                                  struct drm_plane_state *old_state)
> +{
> +       struct amdgpu_bo *rbo;
> +       int r;
> +
> +       if (!old_state->fb)
> +               return;
> +
> +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> +       r = amdgpu_bo_reserve(rbo, false);
> +       if (unlikely(r)) {
> +               DRM_ERROR("failed to reserve rbo before unpin\n");
> +               return;
> +       }
> +
> +       amdgpu_bo_unpin(rbo);
> +       amdgpu_bo_unreserve(rbo);
> +       amdgpu_bo_unref(&rbo);
> +}
> +
> +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> +};
> +
> +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> +                                               enum drm_plane_type type,
> +                                               int index)
> +{
> +       struct drm_plane *plane;
> +       int ret;
> +
> +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> +       if (!plane)
> +               return ERR_PTR(-ENOMEM);
> +
> +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> +                                      &amdgpu_vkms_plane_funcs,
> +                                      amdgpu_vkms_formats,
> +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> +                                      NULL, type, NULL);
> +       if (ret) {
> +               kfree(plane);
> +               return ERR_PTR(ret);
> +       }
> +
> +       drm_plane_helper_add(plane, &amdgpu_vkms_primary_helper_funcs);
> +
> +       return plane;
> +}
> +
> +int amdgpu_vkms_output_init(struct drm_device *dev,
> +                           struct amdgpu_vkms_output *output, int index)
> +{
> +       struct drm_connector *connector = &output->connector;
> +       struct drm_encoder *encoder = &output->encoder;
> +       struct drm_crtc *crtc = &output->crtc;
> +       struct drm_plane *primary, *cursor = NULL;
> +       int ret;
> +
> +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> +       if (IS_ERR(primary))
> +               return PTR_ERR(primary);
> +
> +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> +       if (ret)
> +               goto err_crtc;
> +
> +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> +                                DRM_MODE_CONNECTOR_VIRTUAL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init connector\n");
> +               goto err_connector;
> +       }
> +
> +       drm_connector_helper_add(connector, &amdgpu_vkms_conn_helper_funcs);
> +
> +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init encoder\n");
> +               goto err_encoder;
> +       }
> +       encoder->possible_crtcs = 1 << index;
> +
> +       ret = drm_connector_attach_encoder(connector, encoder);
> +       if (ret) {
> +               DRM_ERROR("Failed to attach connector to encoder\n");
> +               goto err_attach;
> +       }
> +
> +       drm_mode_config_reset(dev);
> +
> +       return 0;
> +
> +err_attach:
> +       drm_encoder_cleanup(encoder);
> +
> +err_encoder:
> +       drm_connector_cleanup(connector);
> +
> +err_connector:
> +       drm_crtc_cleanup(crtc);
> +
> +err_crtc:
> +       drm_plane_cleanup(primary);
> +
> +       return ret;
> +}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> new file mode 100644
> index 000000000000..5dab51fbecf3
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +
> +#ifndef _AMDGPU_VKMS_H_
> +#define _AMDGPU_VKMS_H_
> +
> +#define XRES_DEF  1024
> +#define YRES_DEF   764

Squash in the 768 fix here.

> +
> +#define XRES_MAX  16384
> +#define YRES_MAX  16384
> +
> +#define drm_crtc_to_amdgpu_vkms_output(target) \
> +       container_of(target, struct amdgpu_vkms_output, crtc)
> +
> +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> +
> +struct amdgpu_vkms_output {
> +       struct drm_crtc crtc;
> +       struct drm_encoder encoder;
> +       struct drm_connector connector;
> +       struct hrtimer vblank_hrtimer;
> +       ktime_t period_ns;
> +       struct drm_pending_vblank_event *event;
> +};
> +
> +int amdgpu_vkms_output_init(struct drm_device *dev,
> +                           struct amdgpu_vkms_output *output, int index);
> +
> +#endif /* _AMDGPU_VKMS_H_ */
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> index 7e0d8c092c7e..642c77533157 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> @@ -22,6 +22,7 @@
>   */
>
>  #include <drm/drm_vblank.h>
> +#include <drm/drm_atomic_helper.h>
>
>  #include "amdgpu.h"
>  #include "amdgpu_pm.h"
> @@ -40,6 +41,7 @@
>  #include "dce_virtual.h"
>  #include "ivsrcid/ivsrcid_vislands30.h"
>  #include "amdgpu_display.h"
> +#include "amdgpu_vkms.h"
>
>  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
>
> @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
>         .force = dce_virtual_force,
>  };
>
> +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> +       .fb_create = amdgpu_display_user_framebuffer_create,
> +       .atomic_check = drm_atomic_helper_check,
> +       .atomic_commit = drm_atomic_helper_commit,
> +};
> +
>  static int dce_virtual_sw_init(void *handle)
>  {
>         int r, i;
> @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
>
>         adev_to_drm(adev)->max_vblank_count = 0;
>
> -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> +       adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
>
> -       adev_to_drm(adev)->mode_config.max_width = 16384;
> -       adev_to_drm(adev)->mode_config.max_height = 16384;
> +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
>
>         adev_to_drm(adev)->mode_config.preferred_depth = 24;
>         adev_to_drm(adev)->mode_config.prefer_shadow = 1;
> @@ -399,15 +407,11 @@ static int dce_virtual_sw_init(void *handle)
>         if (r)
>                 return r;
>
> -       adev_to_drm(adev)->mode_config.max_width = 16384;
> -       adev_to_drm(adev)->mode_config.max_height = 16384;
> +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);

You can use kcalloc here.

>
>         /* allocate crtcs, encoders, connectors */
>         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> -               r = dce_virtual_crtc_init(adev, i);
> -               if (r)
> -                       return r;
> -               r = dce_virtual_connector_encoder_init(adev, i);
> +               r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
>                 if (r)
>                         return r;
>         }
> @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
>                         hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
>
>         kfree(adev->mode_info.bios_hardcoded_edid);
> +       kfree(adev->amdgpu_vkms_output);
>
>         drm_kms_helper_poll_fini(adev_to_drm(adev));
>
> --
> 2.32.0
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* Re: [PATCH 3/3] drm/amdgpu: replace dce_virtual with amdgpu_vkms (v3)
  2021-07-21 17:07   ` Ryan Taylor
@ 2021-07-23 14:33     ` Alex Deucher
  -1 siblings, 0 replies; 24+ messages in thread
From: Alex Deucher @ 2021-07-23 14:33 UTC (permalink / raw)
  To: Ryan Taylor
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo,
	amd-gfx list, Melissa Wen, Maling list - DRI developers,
	Alex Deucher

On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
>
> Move dce_virtual into amdgpu_vkms and update all references to
> dce_virtual with amdgpu_vkms.
>
> v2: Removed more references to dce_virtual.
>
> v3: Restored display modes from previous implementation.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Suggested-by: Alex Deucher <Alexander.Deucher@amd.com>
> Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/Makefile      |   3 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 234 ++++++++++++++++++++++-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |   5 +-
>  drivers/gpu/drm/amd/amdgpu/cik.c         |  10 +-
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 223 ---------------------
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.h |  30 ---
>  drivers/gpu/drm/amd/amdgpu/nv.c          |  20 +-
>  drivers/gpu/drm/amd/amdgpu/si.c          |   8 +-
>  drivers/gpu/drm/amd/amdgpu/soc15.c       |  10 +-
>  drivers/gpu/drm/amd/amdgpu/vi.c          |  14 +-
>  10 files changed, 264 insertions(+), 293 deletions(-)
>  delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.c
>  delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
> index 30cbcd5ce1cc..0d814c957461 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -120,8 +120,7 @@ amdgpu-y += \
>  amdgpu-y += \
>         dce_v10_0.o \
>         dce_v11_0.o \
> -       amdgpu_vkms.o \
> -       dce_virtual.o
> +       amdgpu_vkms.o
>
>  # add GFX block
>  amdgpu-y += \
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> index d5c1f1c58f5f..538d41e6666a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> @@ -5,6 +5,15 @@
>  #include <drm/drm_vblank.h>
>
>  #include "amdgpu.h"
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +#include "dce_v6_0.h"
> +#endif
> +#ifdef CONFIG_DRM_AMDGPU_CIK
> +#include "dce_v8_0.h"
> +#endif
> +#include "dce_v10_0.h"
> +#include "dce_v11_0.h"
> +#include "ivsrcid/ivsrcid_vislands30.h"
>  #include "amdgpu_vkms.h"
>  #include "amdgpu_display.h"
>
> @@ -180,12 +189,45 @@ static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
>
>  static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
>  {
> -       int count;
> +       struct drm_device *dev = connector->dev;
> +       struct drm_display_mode *mode = NULL;
> +       unsigned i;
> +       static const struct mode_size {
> +               int w;
> +               int h;
> +       } common_modes[] = {
> +               { 640,  480},
> +               { 720,  480},
> +               { 800,  600},
> +               { 848,  480},
> +               {1024,  768},
> +               {1152,  768},
> +               {1280,  720},
> +               {1280,  800},
> +               {1280,  854},
> +               {1280,  960},
> +               {1280, 1024},
> +               {1440,  900},
> +               {1400, 1050},
> +               {1680, 1050},
> +               {1600, 1200},
> +               {1920, 1080},
> +               {1920, 1200},
> +               {2560, 1440},
> +               {4096, 3112},
> +               {3656, 2664},
> +               {3840, 2160},
> +               {4096, 2160},
> +       };
> +
> +       for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
> +               mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
> +               drm_mode_probed_add(connector, mode);
> +       }
>
> -       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
>         drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
>
> -       return count;
> +       return ARRAY_SIZE(common_modes);
>  }
>
>  static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> @@ -409,3 +451,189 @@ int amdgpu_vkms_output_init(struct drm_device *dev,
>
>         return ret;
>  }
> +
> +const struct drm_mode_config_funcs amdgpu_vkms_mode_funcs = {
> +       .fb_create = amdgpu_display_user_framebuffer_create,
> +       .atomic_check = drm_atomic_helper_check,
> +       .atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +static int amdgpu_vkms_sw_init(void *handle)
> +{
> +       int r, i;
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +       adev_to_drm(adev)->max_vblank_count = 0;
> +
> +       adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs;
> +
> +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> +
> +       adev_to_drm(adev)->mode_config.preferred_depth = 24;
> +       adev_to_drm(adev)->mode_config.prefer_shadow = 1;
> +
> +       adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
> +
> +       r = amdgpu_display_modeset_create_props(adev);
> +       if (r)
> +               return r;
> +
> +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> +
> +       /* allocate crtcs, encoders, connectors */
> +       for (i = 0; i < adev->mode_info.num_crtc; i++) {
> +               r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
> +               if (r)
> +                       return r;
> +       }
> +
> +       drm_kms_helper_poll_init(adev_to_drm(adev));
> +
> +       adev->mode_info.mode_config_initialized = true;
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_sw_fini(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int i = 0;
> +
> +       for (i = 0; i < adev->mode_info.num_crtc; i++)
> +               if (adev->mode_info.crtcs[i])
> +                       hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> +
> +       kfree(adev->mode_info.bios_hardcoded_edid);
> +       kfree(adev->amdgpu_vkms_output);
> +
> +       drm_kms_helper_poll_fini(adev_to_drm(adev));
> +
> +       adev->mode_info.mode_config_initialized = false;
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_hw_init(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +       switch (adev->asic_type) {
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +       case CHIP_TAHITI:
> +       case CHIP_PITCAIRN:
> +       case CHIP_VERDE:
> +       case CHIP_OLAND:
> +               dce_v6_0_disable_dce(adev);
> +               break;
> +#endif
> +#ifdef CONFIG_DRM_AMDGPU_CIK
> +       case CHIP_BONAIRE:
> +       case CHIP_HAWAII:
> +       case CHIP_KAVERI:
> +       case CHIP_KABINI:
> +       case CHIP_MULLINS:
> +               dce_v8_0_disable_dce(adev);
> +               break;
> +#endif
> +       case CHIP_FIJI:
> +       case CHIP_TONGA:
> +               dce_v10_0_disable_dce(adev);
> +               break;
> +       case CHIP_CARRIZO:
> +       case CHIP_STONEY:
> +       case CHIP_POLARIS10:
> +       case CHIP_POLARIS11:
> +       case CHIP_VEGAM:
> +               dce_v11_0_disable_dce(adev);
> +               break;
> +       case CHIP_TOPAZ:
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +       case CHIP_HAINAN:
> +#endif
> +               /* no DCE */
> +               break;
> +       default:
> +               break;
> +       }
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_hw_fini(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_suspend(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int r;
> +
> +       r = drm_mode_config_helper_suspend(adev_to_drm(adev));
> +       if (r)
> +               return r;
> +       return amdgpu_vkms_hw_fini(handle);
> +}
> +
> +static int amdgpu_vkms_resume(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int r;
> +
> +       r = amdgpu_vkms_hw_init(handle);
> +       if (r)
> +               return r;
> +       return drm_mode_config_helper_resume(adev_to_drm(adev));
> +}
> +
> +static bool amdgpu_vkms_is_idle(void *handle)
> +{
> +       return true;
> +}
> +
> +static int amdgpu_vkms_wait_for_idle(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_soft_reset(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_set_clockgating_state(void *handle,
> +                                         enum amd_clockgating_state state)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_set_powergating_state(void *handle,
> +                                         enum amd_powergating_state state)
> +{
> +       return 0;
> +}
> +
> +static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = {
> +       .name = "amdgpu_vkms",
> +       .early_init = NULL,
> +       .late_init = NULL,
> +       .sw_init = amdgpu_vkms_sw_init,
> +       .sw_fini = amdgpu_vkms_sw_fini,
> +       .hw_init = amdgpu_vkms_hw_init,
> +       .hw_fini = amdgpu_vkms_hw_fini,
> +       .suspend = amdgpu_vkms_suspend,
> +       .resume = amdgpu_vkms_resume,
> +       .is_idle = amdgpu_vkms_is_idle,
> +       .wait_for_idle = amdgpu_vkms_wait_for_idle,
> +       .soft_reset = amdgpu_vkms_soft_reset,
> +       .set_clockgating_state = amdgpu_vkms_set_clockgating_state,
> +       .set_powergating_state = amdgpu_vkms_set_powergating_state,
> +};
> +
> +const struct amdgpu_ip_block_version amdgpu_vkms_ip_block =
> +{
> +       .type = AMD_IP_BLOCK_TYPE_DCE,
> +       .major = 1,
> +       .minor = 0,
> +       .rev = 0,
> +       .funcs = &amdgpu_vkms_ip_funcs,
> +};
> +
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> index 5dab51fbecf3..97f1b79c0724 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> @@ -4,7 +4,7 @@
>  #define _AMDGPU_VKMS_H_
>
>  #define XRES_DEF  1024
> -#define YRES_DEF   764
> +#define YRES_DEF   768

Squash this fix into the original patch that added this macro.


>
>  #define XRES_MAX  16384
>  #define YRES_MAX  16384
> @@ -23,7 +23,4 @@ struct amdgpu_vkms_output {
>         struct drm_pending_vblank_event *event;
>  };
>
> -int amdgpu_vkms_output_init(struct drm_device *dev,
> -                           struct amdgpu_vkms_output *output, int index);
> -
>  #endif /* _AMDGPU_VKMS_H_ */
> diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
> index c0fcc41ee574..54f28c075f21 100644
> --- a/drivers/gpu/drm/amd/amdgpu/cik.c
> +++ b/drivers/gpu/drm/amd/amdgpu/cik.c
> @@ -70,7 +70,7 @@
>
>  #include "amdgpu_dm.h"
>  #include "amdgpu_amdkfd.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>
>  static const struct amdgpu_video_codec_info cik_video_codecs_encode_array[] =
>  {
> @@ -2259,7 +2259,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2277,7 +2277,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2295,7 +2295,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2315,7 +2315,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> deleted file mode 100644
> index 18369b47eac7..000000000000
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> +++ /dev/null
> @@ -1,223 +0,0 @@
> -/*
> - * Copyright 2014 Advanced Micro Devices, Inc.
> - *
> - * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
> - *
> - */
> -
> -#include <drm/drm_atomic_helper.h>
> -
> -#include "amdgpu.h"
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -#include "dce_v6_0.h"
> -#endif
> -#ifdef CONFIG_DRM_AMDGPU_CIK
> -#include "dce_v8_0.h"
> -#endif
> -#include "dce_v10_0.h"
> -#include "dce_v11_0.h"
> -#include "dce_virtual.h"
> -#include "ivsrcid/ivsrcid_vislands30.h"
> -#include "amdgpu_display.h"
> -#include "amdgpu_vkms.h"
> -
> -const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> -       .fb_create = amdgpu_display_user_framebuffer_create,
> -       .atomic_check = drm_atomic_helper_check,
> -       .atomic_commit = drm_atomic_helper_commit,
> -};
> -
> -static int dce_virtual_sw_init(void *handle)
> -{
> -       int r, i;
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -
> -       adev_to_drm(adev)->max_vblank_count = 0;
> -
> -       adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
> -
> -       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> -       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> -
> -       adev_to_drm(adev)->mode_config.preferred_depth = 24;
> -       adev_to_drm(adev)->mode_config.prefer_shadow = 1;
> -
> -       adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
> -
> -       r = amdgpu_display_modeset_create_props(adev);
> -       if (r)
> -               return r;
> -
> -       adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> -
> -       /* allocate crtcs, encoders, connectors */
> -       for (i = 0; i < adev->mode_info.num_crtc; i++) {
> -               r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
> -               if (r)
> -                       return r;
> -       }
> -
> -       drm_kms_helper_poll_init(adev_to_drm(adev));
> -
> -       adev->mode_info.mode_config_initialized = true;
> -       return 0;
> -}
> -
> -static int dce_virtual_sw_fini(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int i = 0;
> -
> -       for (i = 0; i < adev->mode_info.num_crtc; i++)
> -               if (adev->mode_info.crtcs[i])
> -                       hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> -
> -       kfree(adev->mode_info.bios_hardcoded_edid);
> -       kfree(adev->amdgpu_vkms_output);
> -
> -       drm_kms_helper_poll_fini(adev_to_drm(adev));
> -
> -       adev->mode_info.mode_config_initialized = false;
> -       return 0;
> -}
> -
> -static int dce_virtual_hw_init(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -
> -       switch (adev->asic_type) {
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -       case CHIP_TAHITI:
> -       case CHIP_PITCAIRN:
> -       case CHIP_VERDE:
> -       case CHIP_OLAND:
> -               dce_v6_0_disable_dce(adev);
> -               break;
> -#endif
> -#ifdef CONFIG_DRM_AMDGPU_CIK
> -       case CHIP_BONAIRE:
> -       case CHIP_HAWAII:
> -       case CHIP_KAVERI:
> -       case CHIP_KABINI:
> -       case CHIP_MULLINS:
> -               dce_v8_0_disable_dce(adev);
> -               break;
> -#endif
> -       case CHIP_FIJI:
> -       case CHIP_TONGA:
> -               dce_v10_0_disable_dce(adev);
> -               break;
> -       case CHIP_CARRIZO:
> -       case CHIP_STONEY:
> -       case CHIP_POLARIS10:
> -       case CHIP_POLARIS11:
> -       case CHIP_VEGAM:
> -               dce_v11_0_disable_dce(adev);
> -               break;
> -       case CHIP_TOPAZ:
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -       case CHIP_HAINAN:
> -#endif
> -               /* no DCE */
> -               break;
> -       default:
> -               break;
> -       }
> -       return 0;
> -}
> -
> -static int dce_virtual_hw_fini(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_suspend(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int r;
> -
> -       r = drm_mode_config_helper_suspend(adev_to_drm(adev));
> -       if (r)
> -               return r;
> -       return dce_virtual_hw_fini(handle);
> -}
> -
> -static int dce_virtual_resume(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int r;
> -
> -       r = dce_virtual_hw_init(handle);
> -       if (r)
> -               return r;
> -       return drm_mode_config_helper_resume(adev_to_drm(adev));
> -}
> -
> -static bool dce_virtual_is_idle(void *handle)
> -{
> -       return true;
> -}
> -
> -static int dce_virtual_wait_for_idle(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_soft_reset(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_set_clockgating_state(void *handle,
> -                                         enum amd_clockgating_state state)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_set_powergating_state(void *handle,
> -                                         enum amd_powergating_state state)
> -{
> -       return 0;
> -}
> -
> -static const struct amd_ip_funcs dce_virtual_ip_funcs = {
> -       .name = "dce_virtual",
> -       .early_init = NULL,
> -       .late_init = NULL,
> -       .sw_init = dce_virtual_sw_init,
> -       .sw_fini = dce_virtual_sw_fini,
> -       .hw_init = dce_virtual_hw_init,
> -       .hw_fini = dce_virtual_hw_fini,
> -       .suspend = dce_virtual_suspend,
> -       .resume = dce_virtual_resume,
> -       .is_idle = dce_virtual_is_idle,
> -       .wait_for_idle = dce_virtual_wait_for_idle,
> -       .soft_reset = dce_virtual_soft_reset,
> -       .set_clockgating_state = dce_virtual_set_clockgating_state,
> -       .set_powergating_state = dce_virtual_set_powergating_state,
> -};
> -
> -const struct amdgpu_ip_block_version dce_virtual_ip_block =
> -{
> -       .type = AMD_IP_BLOCK_TYPE_DCE,
> -       .major = 1,
> -       .minor = 0,
> -       .rev = 0,
> -       .funcs = &dce_virtual_ip_funcs,
> -};
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
> deleted file mode 100644
> index ed422012c8c6..000000000000
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
> +++ /dev/null
> @@ -1,30 +0,0 @@
> -/*
> - * Copyright 2014 Advanced Micro Devices, Inc.
> - *
> - * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
> - *
> - */
> -
> -#ifndef __DCE_VIRTUAL_H__
> -#define __DCE_VIRTUAL_H__
> -
> -extern const struct amdgpu_ip_block_version dce_virtual_ip_block;
> -
> -#endif
> -
> diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
> index 436fb13e32f0..696ecc1ccb28 100644
> --- a/drivers/gpu/drm/amd/amdgpu/nv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/nv.c
> @@ -58,7 +58,7 @@
>  #include "jpeg_v2_0.h"
>  #include "vcn_v3_0.h"
>  #include "jpeg_v3_0.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mes_v10_1.h"
>  #include "mxgpu_nv.h"
>  #include "smuio_v11_0.h"
> @@ -721,7 +721,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     !amdgpu_sriov_vf(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -749,7 +749,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -779,7 +779,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -802,7 +802,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -823,7 +823,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -843,7 +843,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                  else if (amdgpu_device_has_dc_support(adev))
>                          amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -865,7 +865,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -883,11 +883,11 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
> index 7cbc2bb03bc6..e6d2f74a7976 100644
> --- a/drivers/gpu/drm/amd/amdgpu/si.c
> +++ b/drivers/gpu/drm/amd/amdgpu/si.c
> @@ -44,7 +44,7 @@
>  #include "dce_v6_0.h"
>  #include "si.h"
>  #include "uvd_v3_1.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "gca/gfx_6_0_d.h"
>  #include "oss/oss_1_0_d.h"
>  #include "oss/oss_1_0_sh_mask.h"
> @@ -2759,7 +2759,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2777,7 +2777,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2795,7 +2795,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 break;
>         default:
>                 BUG();
> diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
> index a5e085e570f7..f7b56a746c15 100644
> --- a/drivers/gpu/drm/amd/amdgpu/soc15.c
> +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
> @@ -74,7 +74,7 @@
>  #include "smuio_v9_0.h"
>  #include "smuio_v11_0.h"
>  #include "smuio_v13_0.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mxgpu_ai.h"
>  #include "amdgpu_ras.h"
>  #include "amdgpu_xgmi.h"
> @@ -843,7 +843,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 }
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -863,7 +863,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -885,7 +885,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 }
>
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
> @@ -909,7 +909,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                  else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
> index 3d21c0799037..fe9a7cc8d9eb 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vi.c
> @@ -77,7 +77,7 @@
>  #if defined(CONFIG_DRM_AMD_ACP)
>  #include "amdgpu_acp.h"
>  #endif
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mxgpu_vi.h"
>  #include "amdgpu_dm.h"
>
> @@ -2102,7 +2102,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 break;
>         case CHIP_FIJI:
>                 amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
> @@ -2112,7 +2112,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2132,7 +2132,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2155,7 +2155,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2173,7 +2173,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2194,7 +2194,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> --
> 2.32.0
>

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

* Re: [PATCH 3/3] drm/amdgpu: replace dce_virtual with amdgpu_vkms (v3)
@ 2021-07-23 14:33     ` Alex Deucher
  0 siblings, 0 replies; 24+ messages in thread
From: Alex Deucher @ 2021-07-23 14:33 UTC (permalink / raw)
  To: Ryan Taylor
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo,
	amd-gfx list, Melissa Wen, Maling list - DRI developers,
	Alex Deucher

On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
>
> Move dce_virtual into amdgpu_vkms and update all references to
> dce_virtual with amdgpu_vkms.
>
> v2: Removed more references to dce_virtual.
>
> v3: Restored display modes from previous implementation.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Suggested-by: Alex Deucher <Alexander.Deucher@amd.com>
> Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/Makefile      |   3 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 234 ++++++++++++++++++++++-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |   5 +-
>  drivers/gpu/drm/amd/amdgpu/cik.c         |  10 +-
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 223 ---------------------
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.h |  30 ---
>  drivers/gpu/drm/amd/amdgpu/nv.c          |  20 +-
>  drivers/gpu/drm/amd/amdgpu/si.c          |   8 +-
>  drivers/gpu/drm/amd/amdgpu/soc15.c       |  10 +-
>  drivers/gpu/drm/amd/amdgpu/vi.c          |  14 +-
>  10 files changed, 264 insertions(+), 293 deletions(-)
>  delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.c
>  delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
> index 30cbcd5ce1cc..0d814c957461 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -120,8 +120,7 @@ amdgpu-y += \
>  amdgpu-y += \
>         dce_v10_0.o \
>         dce_v11_0.o \
> -       amdgpu_vkms.o \
> -       dce_virtual.o
> +       amdgpu_vkms.o
>
>  # add GFX block
>  amdgpu-y += \
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> index d5c1f1c58f5f..538d41e6666a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> @@ -5,6 +5,15 @@
>  #include <drm/drm_vblank.h>
>
>  #include "amdgpu.h"
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +#include "dce_v6_0.h"
> +#endif
> +#ifdef CONFIG_DRM_AMDGPU_CIK
> +#include "dce_v8_0.h"
> +#endif
> +#include "dce_v10_0.h"
> +#include "dce_v11_0.h"
> +#include "ivsrcid/ivsrcid_vislands30.h"
>  #include "amdgpu_vkms.h"
>  #include "amdgpu_display.h"
>
> @@ -180,12 +189,45 @@ static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
>
>  static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
>  {
> -       int count;
> +       struct drm_device *dev = connector->dev;
> +       struct drm_display_mode *mode = NULL;
> +       unsigned i;
> +       static const struct mode_size {
> +               int w;
> +               int h;
> +       } common_modes[] = {
> +               { 640,  480},
> +               { 720,  480},
> +               { 800,  600},
> +               { 848,  480},
> +               {1024,  768},
> +               {1152,  768},
> +               {1280,  720},
> +               {1280,  800},
> +               {1280,  854},
> +               {1280,  960},
> +               {1280, 1024},
> +               {1440,  900},
> +               {1400, 1050},
> +               {1680, 1050},
> +               {1600, 1200},
> +               {1920, 1080},
> +               {1920, 1200},
> +               {2560, 1440},
> +               {4096, 3112},
> +               {3656, 2664},
> +               {3840, 2160},
> +               {4096, 2160},
> +       };
> +
> +       for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
> +               mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
> +               drm_mode_probed_add(connector, mode);
> +       }
>
> -       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
>         drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
>
> -       return count;
> +       return ARRAY_SIZE(common_modes);
>  }
>
>  static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> @@ -409,3 +451,189 @@ int amdgpu_vkms_output_init(struct drm_device *dev,
>
>         return ret;
>  }
> +
> +const struct drm_mode_config_funcs amdgpu_vkms_mode_funcs = {
> +       .fb_create = amdgpu_display_user_framebuffer_create,
> +       .atomic_check = drm_atomic_helper_check,
> +       .atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +static int amdgpu_vkms_sw_init(void *handle)
> +{
> +       int r, i;
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +       adev_to_drm(adev)->max_vblank_count = 0;
> +
> +       adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs;
> +
> +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> +
> +       adev_to_drm(adev)->mode_config.preferred_depth = 24;
> +       adev_to_drm(adev)->mode_config.prefer_shadow = 1;
> +
> +       adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
> +
> +       r = amdgpu_display_modeset_create_props(adev);
> +       if (r)
> +               return r;
> +
> +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> +
> +       /* allocate crtcs, encoders, connectors */
> +       for (i = 0; i < adev->mode_info.num_crtc; i++) {
> +               r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
> +               if (r)
> +                       return r;
> +       }
> +
> +       drm_kms_helper_poll_init(adev_to_drm(adev));
> +
> +       adev->mode_info.mode_config_initialized = true;
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_sw_fini(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int i = 0;
> +
> +       for (i = 0; i < adev->mode_info.num_crtc; i++)
> +               if (adev->mode_info.crtcs[i])
> +                       hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> +
> +       kfree(adev->mode_info.bios_hardcoded_edid);
> +       kfree(adev->amdgpu_vkms_output);
> +
> +       drm_kms_helper_poll_fini(adev_to_drm(adev));
> +
> +       adev->mode_info.mode_config_initialized = false;
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_hw_init(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +       switch (adev->asic_type) {
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +       case CHIP_TAHITI:
> +       case CHIP_PITCAIRN:
> +       case CHIP_VERDE:
> +       case CHIP_OLAND:
> +               dce_v6_0_disable_dce(adev);
> +               break;
> +#endif
> +#ifdef CONFIG_DRM_AMDGPU_CIK
> +       case CHIP_BONAIRE:
> +       case CHIP_HAWAII:
> +       case CHIP_KAVERI:
> +       case CHIP_KABINI:
> +       case CHIP_MULLINS:
> +               dce_v8_0_disable_dce(adev);
> +               break;
> +#endif
> +       case CHIP_FIJI:
> +       case CHIP_TONGA:
> +               dce_v10_0_disable_dce(adev);
> +               break;
> +       case CHIP_CARRIZO:
> +       case CHIP_STONEY:
> +       case CHIP_POLARIS10:
> +       case CHIP_POLARIS11:
> +       case CHIP_VEGAM:
> +               dce_v11_0_disable_dce(adev);
> +               break;
> +       case CHIP_TOPAZ:
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +       case CHIP_HAINAN:
> +#endif
> +               /* no DCE */
> +               break;
> +       default:
> +               break;
> +       }
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_hw_fini(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_suspend(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int r;
> +
> +       r = drm_mode_config_helper_suspend(adev_to_drm(adev));
> +       if (r)
> +               return r;
> +       return amdgpu_vkms_hw_fini(handle);
> +}
> +
> +static int amdgpu_vkms_resume(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int r;
> +
> +       r = amdgpu_vkms_hw_init(handle);
> +       if (r)
> +               return r;
> +       return drm_mode_config_helper_resume(adev_to_drm(adev));
> +}
> +
> +static bool amdgpu_vkms_is_idle(void *handle)
> +{
> +       return true;
> +}
> +
> +static int amdgpu_vkms_wait_for_idle(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_soft_reset(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_set_clockgating_state(void *handle,
> +                                         enum amd_clockgating_state state)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_set_powergating_state(void *handle,
> +                                         enum amd_powergating_state state)
> +{
> +       return 0;
> +}
> +
> +static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = {
> +       .name = "amdgpu_vkms",
> +       .early_init = NULL,
> +       .late_init = NULL,
> +       .sw_init = amdgpu_vkms_sw_init,
> +       .sw_fini = amdgpu_vkms_sw_fini,
> +       .hw_init = amdgpu_vkms_hw_init,
> +       .hw_fini = amdgpu_vkms_hw_fini,
> +       .suspend = amdgpu_vkms_suspend,
> +       .resume = amdgpu_vkms_resume,
> +       .is_idle = amdgpu_vkms_is_idle,
> +       .wait_for_idle = amdgpu_vkms_wait_for_idle,
> +       .soft_reset = amdgpu_vkms_soft_reset,
> +       .set_clockgating_state = amdgpu_vkms_set_clockgating_state,
> +       .set_powergating_state = amdgpu_vkms_set_powergating_state,
> +};
> +
> +const struct amdgpu_ip_block_version amdgpu_vkms_ip_block =
> +{
> +       .type = AMD_IP_BLOCK_TYPE_DCE,
> +       .major = 1,
> +       .minor = 0,
> +       .rev = 0,
> +       .funcs = &amdgpu_vkms_ip_funcs,
> +};
> +
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> index 5dab51fbecf3..97f1b79c0724 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> @@ -4,7 +4,7 @@
>  #define _AMDGPU_VKMS_H_
>
>  #define XRES_DEF  1024
> -#define YRES_DEF   764
> +#define YRES_DEF   768

Squash this fix into the original patch that added this macro.


>
>  #define XRES_MAX  16384
>  #define YRES_MAX  16384
> @@ -23,7 +23,4 @@ struct amdgpu_vkms_output {
>         struct drm_pending_vblank_event *event;
>  };
>
> -int amdgpu_vkms_output_init(struct drm_device *dev,
> -                           struct amdgpu_vkms_output *output, int index);
> -
>  #endif /* _AMDGPU_VKMS_H_ */
> diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
> index c0fcc41ee574..54f28c075f21 100644
> --- a/drivers/gpu/drm/amd/amdgpu/cik.c
> +++ b/drivers/gpu/drm/amd/amdgpu/cik.c
> @@ -70,7 +70,7 @@
>
>  #include "amdgpu_dm.h"
>  #include "amdgpu_amdkfd.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>
>  static const struct amdgpu_video_codec_info cik_video_codecs_encode_array[] =
>  {
> @@ -2259,7 +2259,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2277,7 +2277,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2295,7 +2295,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2315,7 +2315,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> deleted file mode 100644
> index 18369b47eac7..000000000000
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> +++ /dev/null
> @@ -1,223 +0,0 @@
> -/*
> - * Copyright 2014 Advanced Micro Devices, Inc.
> - *
> - * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
> - *
> - */
> -
> -#include <drm/drm_atomic_helper.h>
> -
> -#include "amdgpu.h"
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -#include "dce_v6_0.h"
> -#endif
> -#ifdef CONFIG_DRM_AMDGPU_CIK
> -#include "dce_v8_0.h"
> -#endif
> -#include "dce_v10_0.h"
> -#include "dce_v11_0.h"
> -#include "dce_virtual.h"
> -#include "ivsrcid/ivsrcid_vislands30.h"
> -#include "amdgpu_display.h"
> -#include "amdgpu_vkms.h"
> -
> -const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> -       .fb_create = amdgpu_display_user_framebuffer_create,
> -       .atomic_check = drm_atomic_helper_check,
> -       .atomic_commit = drm_atomic_helper_commit,
> -};
> -
> -static int dce_virtual_sw_init(void *handle)
> -{
> -       int r, i;
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -
> -       adev_to_drm(adev)->max_vblank_count = 0;
> -
> -       adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
> -
> -       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> -       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> -
> -       adev_to_drm(adev)->mode_config.preferred_depth = 24;
> -       adev_to_drm(adev)->mode_config.prefer_shadow = 1;
> -
> -       adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
> -
> -       r = amdgpu_display_modeset_create_props(adev);
> -       if (r)
> -               return r;
> -
> -       adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> -
> -       /* allocate crtcs, encoders, connectors */
> -       for (i = 0; i < adev->mode_info.num_crtc; i++) {
> -               r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
> -               if (r)
> -                       return r;
> -       }
> -
> -       drm_kms_helper_poll_init(adev_to_drm(adev));
> -
> -       adev->mode_info.mode_config_initialized = true;
> -       return 0;
> -}
> -
> -static int dce_virtual_sw_fini(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int i = 0;
> -
> -       for (i = 0; i < adev->mode_info.num_crtc; i++)
> -               if (adev->mode_info.crtcs[i])
> -                       hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> -
> -       kfree(adev->mode_info.bios_hardcoded_edid);
> -       kfree(adev->amdgpu_vkms_output);
> -
> -       drm_kms_helper_poll_fini(adev_to_drm(adev));
> -
> -       adev->mode_info.mode_config_initialized = false;
> -       return 0;
> -}
> -
> -static int dce_virtual_hw_init(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -
> -       switch (adev->asic_type) {
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -       case CHIP_TAHITI:
> -       case CHIP_PITCAIRN:
> -       case CHIP_VERDE:
> -       case CHIP_OLAND:
> -               dce_v6_0_disable_dce(adev);
> -               break;
> -#endif
> -#ifdef CONFIG_DRM_AMDGPU_CIK
> -       case CHIP_BONAIRE:
> -       case CHIP_HAWAII:
> -       case CHIP_KAVERI:
> -       case CHIP_KABINI:
> -       case CHIP_MULLINS:
> -               dce_v8_0_disable_dce(adev);
> -               break;
> -#endif
> -       case CHIP_FIJI:
> -       case CHIP_TONGA:
> -               dce_v10_0_disable_dce(adev);
> -               break;
> -       case CHIP_CARRIZO:
> -       case CHIP_STONEY:
> -       case CHIP_POLARIS10:
> -       case CHIP_POLARIS11:
> -       case CHIP_VEGAM:
> -               dce_v11_0_disable_dce(adev);
> -               break;
> -       case CHIP_TOPAZ:
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -       case CHIP_HAINAN:
> -#endif
> -               /* no DCE */
> -               break;
> -       default:
> -               break;
> -       }
> -       return 0;
> -}
> -
> -static int dce_virtual_hw_fini(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_suspend(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int r;
> -
> -       r = drm_mode_config_helper_suspend(adev_to_drm(adev));
> -       if (r)
> -               return r;
> -       return dce_virtual_hw_fini(handle);
> -}
> -
> -static int dce_virtual_resume(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int r;
> -
> -       r = dce_virtual_hw_init(handle);
> -       if (r)
> -               return r;
> -       return drm_mode_config_helper_resume(adev_to_drm(adev));
> -}
> -
> -static bool dce_virtual_is_idle(void *handle)
> -{
> -       return true;
> -}
> -
> -static int dce_virtual_wait_for_idle(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_soft_reset(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_set_clockgating_state(void *handle,
> -                                         enum amd_clockgating_state state)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_set_powergating_state(void *handle,
> -                                         enum amd_powergating_state state)
> -{
> -       return 0;
> -}
> -
> -static const struct amd_ip_funcs dce_virtual_ip_funcs = {
> -       .name = "dce_virtual",
> -       .early_init = NULL,
> -       .late_init = NULL,
> -       .sw_init = dce_virtual_sw_init,
> -       .sw_fini = dce_virtual_sw_fini,
> -       .hw_init = dce_virtual_hw_init,
> -       .hw_fini = dce_virtual_hw_fini,
> -       .suspend = dce_virtual_suspend,
> -       .resume = dce_virtual_resume,
> -       .is_idle = dce_virtual_is_idle,
> -       .wait_for_idle = dce_virtual_wait_for_idle,
> -       .soft_reset = dce_virtual_soft_reset,
> -       .set_clockgating_state = dce_virtual_set_clockgating_state,
> -       .set_powergating_state = dce_virtual_set_powergating_state,
> -};
> -
> -const struct amdgpu_ip_block_version dce_virtual_ip_block =
> -{
> -       .type = AMD_IP_BLOCK_TYPE_DCE,
> -       .major = 1,
> -       .minor = 0,
> -       .rev = 0,
> -       .funcs = &dce_virtual_ip_funcs,
> -};
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
> deleted file mode 100644
> index ed422012c8c6..000000000000
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
> +++ /dev/null
> @@ -1,30 +0,0 @@
> -/*
> - * Copyright 2014 Advanced Micro Devices, Inc.
> - *
> - * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
> - *
> - */
> -
> -#ifndef __DCE_VIRTUAL_H__
> -#define __DCE_VIRTUAL_H__
> -
> -extern const struct amdgpu_ip_block_version dce_virtual_ip_block;
> -
> -#endif
> -
> diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
> index 436fb13e32f0..696ecc1ccb28 100644
> --- a/drivers/gpu/drm/amd/amdgpu/nv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/nv.c
> @@ -58,7 +58,7 @@
>  #include "jpeg_v2_0.h"
>  #include "vcn_v3_0.h"
>  #include "jpeg_v3_0.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mes_v10_1.h"
>  #include "mxgpu_nv.h"
>  #include "smuio_v11_0.h"
> @@ -721,7 +721,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     !amdgpu_sriov_vf(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -749,7 +749,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -779,7 +779,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -802,7 +802,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -823,7 +823,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -843,7 +843,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                  else if (amdgpu_device_has_dc_support(adev))
>                          amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -865,7 +865,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -883,11 +883,11 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
> index 7cbc2bb03bc6..e6d2f74a7976 100644
> --- a/drivers/gpu/drm/amd/amdgpu/si.c
> +++ b/drivers/gpu/drm/amd/amdgpu/si.c
> @@ -44,7 +44,7 @@
>  #include "dce_v6_0.h"
>  #include "si.h"
>  #include "uvd_v3_1.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "gca/gfx_6_0_d.h"
>  #include "oss/oss_1_0_d.h"
>  #include "oss/oss_1_0_sh_mask.h"
> @@ -2759,7 +2759,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2777,7 +2777,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2795,7 +2795,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 break;
>         default:
>                 BUG();
> diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
> index a5e085e570f7..f7b56a746c15 100644
> --- a/drivers/gpu/drm/amd/amdgpu/soc15.c
> +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
> @@ -74,7 +74,7 @@
>  #include "smuio_v9_0.h"
>  #include "smuio_v11_0.h"
>  #include "smuio_v13_0.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mxgpu_ai.h"
>  #include "amdgpu_ras.h"
>  #include "amdgpu_xgmi.h"
> @@ -843,7 +843,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 }
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -863,7 +863,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -885,7 +885,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 }
>
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
> @@ -909,7 +909,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                  else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
> index 3d21c0799037..fe9a7cc8d9eb 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vi.c
> @@ -77,7 +77,7 @@
>  #if defined(CONFIG_DRM_AMD_ACP)
>  #include "amdgpu_acp.h"
>  #endif
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mxgpu_vi.h"
>  #include "amdgpu_dm.h"
>
> @@ -2102,7 +2102,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 break;
>         case CHIP_FIJI:
>                 amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
> @@ -2112,7 +2112,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2132,7 +2132,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2155,7 +2155,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2173,7 +2173,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2194,7 +2194,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> --
> 2.32.0
>
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* Re: [PATCH 3/3] drm/amdgpu: replace dce_virtual with amdgpu_vkms (v3)
  2021-07-23 14:33     ` Alex Deucher
@ 2021-07-23 15:50       ` Taylor, Ryan
  -1 siblings, 0 replies; 24+ messages in thread
From: Taylor, Ryan @ 2021-07-23 15:50 UTC (permalink / raw)
  To: Alex Deucher
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo,
	amd-gfx list, Melissa Wen, Maling list - DRI developers, Deucher,
	 Alexander

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

[AMD Official Use Only]

Thanks Alex! I will make these changes.

Best,
Ryan
________________________________
From: Alex Deucher <alexdeucher@gmail.com>
Sent: Friday, July 23, 2021 7:33 AM
To: Taylor, Ryan <Ryan.Taylor@amd.com>
Cc: Maling list - DRI developers <dri-devel@lists.freedesktop.org>; amd-gfx list <amd-gfx@lists.freedesktop.org>; kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; Melissa Wen <melissa.srw@gmail.com>; Deucher, Alexander <Alexander.Deucher@amd.com>
Subject: Re: [PATCH 3/3] drm/amdgpu: replace dce_virtual with amdgpu_vkms (v3)

On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
>
> Move dce_virtual into amdgpu_vkms and update all references to
> dce_virtual with amdgpu_vkms.
>
> v2: Removed more references to dce_virtual.
>
> v3: Restored display modes from previous implementation.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Suggested-by: Alex Deucher <Alexander.Deucher@amd.com>
> Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/Makefile      |   3 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 234 ++++++++++++++++++++++-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |   5 +-
>  drivers/gpu/drm/amd/amdgpu/cik.c         |  10 +-
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 223 ---------------------
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.h |  30 ---
>  drivers/gpu/drm/amd/amdgpu/nv.c          |  20 +-
>  drivers/gpu/drm/amd/amdgpu/si.c          |   8 +-
>  drivers/gpu/drm/amd/amdgpu/soc15.c       |  10 +-
>  drivers/gpu/drm/amd/amdgpu/vi.c          |  14 +-
>  10 files changed, 264 insertions(+), 293 deletions(-)
>  delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.c
>  delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
> index 30cbcd5ce1cc..0d814c957461 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -120,8 +120,7 @@ amdgpu-y += \
>  amdgpu-y += \
>         dce_v10_0.o \
>         dce_v11_0.o \
> -       amdgpu_vkms.o \
> -       dce_virtual.o
> +       amdgpu_vkms.o
>
>  # add GFX block
>  amdgpu-y += \
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> index d5c1f1c58f5f..538d41e6666a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> @@ -5,6 +5,15 @@
>  #include <drm/drm_vblank.h>
>
>  #include "amdgpu.h"
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +#include "dce_v6_0.h"
> +#endif
> +#ifdef CONFIG_DRM_AMDGPU_CIK
> +#include "dce_v8_0.h"
> +#endif
> +#include "dce_v10_0.h"
> +#include "dce_v11_0.h"
> +#include "ivsrcid/ivsrcid_vislands30.h"
>  #include "amdgpu_vkms.h"
>  #include "amdgpu_display.h"
>
> @@ -180,12 +189,45 @@ static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
>
>  static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
>  {
> -       int count;
> +       struct drm_device *dev = connector->dev;
> +       struct drm_display_mode *mode = NULL;
> +       unsigned i;
> +       static const struct mode_size {
> +               int w;
> +               int h;
> +       } common_modes[] = {
> +               { 640,  480},
> +               { 720,  480},
> +               { 800,  600},
> +               { 848,  480},
> +               {1024,  768},
> +               {1152,  768},
> +               {1280,  720},
> +               {1280,  800},
> +               {1280,  854},
> +               {1280,  960},
> +               {1280, 1024},
> +               {1440,  900},
> +               {1400, 1050},
> +               {1680, 1050},
> +               {1600, 1200},
> +               {1920, 1080},
> +               {1920, 1200},
> +               {2560, 1440},
> +               {4096, 3112},
> +               {3656, 2664},
> +               {3840, 2160},
> +               {4096, 2160},
> +       };
> +
> +       for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
> +               mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
> +               drm_mode_probed_add(connector, mode);
> +       }
>
> -       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
>         drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
>
> -       return count;
> +       return ARRAY_SIZE(common_modes);
>  }
>
>  static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> @@ -409,3 +451,189 @@ int amdgpu_vkms_output_init(struct drm_device *dev,
>
>         return ret;
>  }
> +
> +const struct drm_mode_config_funcs amdgpu_vkms_mode_funcs = {
> +       .fb_create = amdgpu_display_user_framebuffer_create,
> +       .atomic_check = drm_atomic_helper_check,
> +       .atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +static int amdgpu_vkms_sw_init(void *handle)
> +{
> +       int r, i;
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +       adev_to_drm(adev)->max_vblank_count = 0;
> +
> +       adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs;
> +
> +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> +
> +       adev_to_drm(adev)->mode_config.preferred_depth = 24;
> +       adev_to_drm(adev)->mode_config.prefer_shadow = 1;
> +
> +       adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
> +
> +       r = amdgpu_display_modeset_create_props(adev);
> +       if (r)
> +               return r;
> +
> +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> +
> +       /* allocate crtcs, encoders, connectors */
> +       for (i = 0; i < adev->mode_info.num_crtc; i++) {
> +               r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
> +               if (r)
> +                       return r;
> +       }
> +
> +       drm_kms_helper_poll_init(adev_to_drm(adev));
> +
> +       adev->mode_info.mode_config_initialized = true;
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_sw_fini(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int i = 0;
> +
> +       for (i = 0; i < adev->mode_info.num_crtc; i++)
> +               if (adev->mode_info.crtcs[i])
> +                       hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> +
> +       kfree(adev->mode_info.bios_hardcoded_edid);
> +       kfree(adev->amdgpu_vkms_output);
> +
> +       drm_kms_helper_poll_fini(adev_to_drm(adev));
> +
> +       adev->mode_info.mode_config_initialized = false;
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_hw_init(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +       switch (adev->asic_type) {
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +       case CHIP_TAHITI:
> +       case CHIP_PITCAIRN:
> +       case CHIP_VERDE:
> +       case CHIP_OLAND:
> +               dce_v6_0_disable_dce(adev);
> +               break;
> +#endif
> +#ifdef CONFIG_DRM_AMDGPU_CIK
> +       case CHIP_BONAIRE:
> +       case CHIP_HAWAII:
> +       case CHIP_KAVERI:
> +       case CHIP_KABINI:
> +       case CHIP_MULLINS:
> +               dce_v8_0_disable_dce(adev);
> +               break;
> +#endif
> +       case CHIP_FIJI:
> +       case CHIP_TONGA:
> +               dce_v10_0_disable_dce(adev);
> +               break;
> +       case CHIP_CARRIZO:
> +       case CHIP_STONEY:
> +       case CHIP_POLARIS10:
> +       case CHIP_POLARIS11:
> +       case CHIP_VEGAM:
> +               dce_v11_0_disable_dce(adev);
> +               break;
> +       case CHIP_TOPAZ:
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +       case CHIP_HAINAN:
> +#endif
> +               /* no DCE */
> +               break;
> +       default:
> +               break;
> +       }
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_hw_fini(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_suspend(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int r;
> +
> +       r = drm_mode_config_helper_suspend(adev_to_drm(adev));
> +       if (r)
> +               return r;
> +       return amdgpu_vkms_hw_fini(handle);
> +}
> +
> +static int amdgpu_vkms_resume(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int r;
> +
> +       r = amdgpu_vkms_hw_init(handle);
> +       if (r)
> +               return r;
> +       return drm_mode_config_helper_resume(adev_to_drm(adev));
> +}
> +
> +static bool amdgpu_vkms_is_idle(void *handle)
> +{
> +       return true;
> +}
> +
> +static int amdgpu_vkms_wait_for_idle(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_soft_reset(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_set_clockgating_state(void *handle,
> +                                         enum amd_clockgating_state state)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_set_powergating_state(void *handle,
> +                                         enum amd_powergating_state state)
> +{
> +       return 0;
> +}
> +
> +static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = {
> +       .name = "amdgpu_vkms",
> +       .early_init = NULL,
> +       .late_init = NULL,
> +       .sw_init = amdgpu_vkms_sw_init,
> +       .sw_fini = amdgpu_vkms_sw_fini,
> +       .hw_init = amdgpu_vkms_hw_init,
> +       .hw_fini = amdgpu_vkms_hw_fini,
> +       .suspend = amdgpu_vkms_suspend,
> +       .resume = amdgpu_vkms_resume,
> +       .is_idle = amdgpu_vkms_is_idle,
> +       .wait_for_idle = amdgpu_vkms_wait_for_idle,
> +       .soft_reset = amdgpu_vkms_soft_reset,
> +       .set_clockgating_state = amdgpu_vkms_set_clockgating_state,
> +       .set_powergating_state = amdgpu_vkms_set_powergating_state,
> +};
> +
> +const struct amdgpu_ip_block_version amdgpu_vkms_ip_block =
> +{
> +       .type = AMD_IP_BLOCK_TYPE_DCE,
> +       .major = 1,
> +       .minor = 0,
> +       .rev = 0,
> +       .funcs = &amdgpu_vkms_ip_funcs,
> +};
> +
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> index 5dab51fbecf3..97f1b79c0724 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> @@ -4,7 +4,7 @@
>  #define _AMDGPU_VKMS_H_
>
>  #define XRES_DEF  1024
> -#define YRES_DEF   764
> +#define YRES_DEF   768

Squash this fix into the original patch that added this macro.


>
>  #define XRES_MAX  16384
>  #define YRES_MAX  16384
> @@ -23,7 +23,4 @@ struct amdgpu_vkms_output {
>         struct drm_pending_vblank_event *event;
>  };
>
> -int amdgpu_vkms_output_init(struct drm_device *dev,
> -                           struct amdgpu_vkms_output *output, int index);
> -
>  #endif /* _AMDGPU_VKMS_H_ */
> diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
> index c0fcc41ee574..54f28c075f21 100644
> --- a/drivers/gpu/drm/amd/amdgpu/cik.c
> +++ b/drivers/gpu/drm/amd/amdgpu/cik.c
> @@ -70,7 +70,7 @@
>
>  #include "amdgpu_dm.h"
>  #include "amdgpu_amdkfd.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>
>  static const struct amdgpu_video_codec_info cik_video_codecs_encode_array[] =
>  {
> @@ -2259,7 +2259,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2277,7 +2277,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2295,7 +2295,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2315,7 +2315,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> deleted file mode 100644
> index 18369b47eac7..000000000000
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> +++ /dev/null
> @@ -1,223 +0,0 @@
> -/*
> - * Copyright 2014 Advanced Micro Devices, Inc.
> - *
> - * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
> - *
> - */
> -
> -#include <drm/drm_atomic_helper.h>
> -
> -#include "amdgpu.h"
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -#include "dce_v6_0.h"
> -#endif
> -#ifdef CONFIG_DRM_AMDGPU_CIK
> -#include "dce_v8_0.h"
> -#endif
> -#include "dce_v10_0.h"
> -#include "dce_v11_0.h"
> -#include "dce_virtual.h"
> -#include "ivsrcid/ivsrcid_vislands30.h"
> -#include "amdgpu_display.h"
> -#include "amdgpu_vkms.h"
> -
> -const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> -       .fb_create = amdgpu_display_user_framebuffer_create,
> -       .atomic_check = drm_atomic_helper_check,
> -       .atomic_commit = drm_atomic_helper_commit,
> -};
> -
> -static int dce_virtual_sw_init(void *handle)
> -{
> -       int r, i;
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -
> -       adev_to_drm(adev)->max_vblank_count = 0;
> -
> -       adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
> -
> -       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> -       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> -
> -       adev_to_drm(adev)->mode_config.preferred_depth = 24;
> -       adev_to_drm(adev)->mode_config.prefer_shadow = 1;
> -
> -       adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
> -
> -       r = amdgpu_display_modeset_create_props(adev);
> -       if (r)
> -               return r;
> -
> -       adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> -
> -       /* allocate crtcs, encoders, connectors */
> -       for (i = 0; i < adev->mode_info.num_crtc; i++) {
> -               r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
> -               if (r)
> -                       return r;
> -       }
> -
> -       drm_kms_helper_poll_init(adev_to_drm(adev));
> -
> -       adev->mode_info.mode_config_initialized = true;
> -       return 0;
> -}
> -
> -static int dce_virtual_sw_fini(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int i = 0;
> -
> -       for (i = 0; i < adev->mode_info.num_crtc; i++)
> -               if (adev->mode_info.crtcs[i])
> -                       hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> -
> -       kfree(adev->mode_info.bios_hardcoded_edid);
> -       kfree(adev->amdgpu_vkms_output);
> -
> -       drm_kms_helper_poll_fini(adev_to_drm(adev));
> -
> -       adev->mode_info.mode_config_initialized = false;
> -       return 0;
> -}
> -
> -static int dce_virtual_hw_init(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -
> -       switch (adev->asic_type) {
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -       case CHIP_TAHITI:
> -       case CHIP_PITCAIRN:
> -       case CHIP_VERDE:
> -       case CHIP_OLAND:
> -               dce_v6_0_disable_dce(adev);
> -               break;
> -#endif
> -#ifdef CONFIG_DRM_AMDGPU_CIK
> -       case CHIP_BONAIRE:
> -       case CHIP_HAWAII:
> -       case CHIP_KAVERI:
> -       case CHIP_KABINI:
> -       case CHIP_MULLINS:
> -               dce_v8_0_disable_dce(adev);
> -               break;
> -#endif
> -       case CHIP_FIJI:
> -       case CHIP_TONGA:
> -               dce_v10_0_disable_dce(adev);
> -               break;
> -       case CHIP_CARRIZO:
> -       case CHIP_STONEY:
> -       case CHIP_POLARIS10:
> -       case CHIP_POLARIS11:
> -       case CHIP_VEGAM:
> -               dce_v11_0_disable_dce(adev);
> -               break;
> -       case CHIP_TOPAZ:
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -       case CHIP_HAINAN:
> -#endif
> -               /* no DCE */
> -               break;
> -       default:
> -               break;
> -       }
> -       return 0;
> -}
> -
> -static int dce_virtual_hw_fini(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_suspend(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int r;
> -
> -       r = drm_mode_config_helper_suspend(adev_to_drm(adev));
> -       if (r)
> -               return r;
> -       return dce_virtual_hw_fini(handle);
> -}
> -
> -static int dce_virtual_resume(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int r;
> -
> -       r = dce_virtual_hw_init(handle);
> -       if (r)
> -               return r;
> -       return drm_mode_config_helper_resume(adev_to_drm(adev));
> -}
> -
> -static bool dce_virtual_is_idle(void *handle)
> -{
> -       return true;
> -}
> -
> -static int dce_virtual_wait_for_idle(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_soft_reset(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_set_clockgating_state(void *handle,
> -                                         enum amd_clockgating_state state)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_set_powergating_state(void *handle,
> -                                         enum amd_powergating_state state)
> -{
> -       return 0;
> -}
> -
> -static const struct amd_ip_funcs dce_virtual_ip_funcs = {
> -       .name = "dce_virtual",
> -       .early_init = NULL,
> -       .late_init = NULL,
> -       .sw_init = dce_virtual_sw_init,
> -       .sw_fini = dce_virtual_sw_fini,
> -       .hw_init = dce_virtual_hw_init,
> -       .hw_fini = dce_virtual_hw_fini,
> -       .suspend = dce_virtual_suspend,
> -       .resume = dce_virtual_resume,
> -       .is_idle = dce_virtual_is_idle,
> -       .wait_for_idle = dce_virtual_wait_for_idle,
> -       .soft_reset = dce_virtual_soft_reset,
> -       .set_clockgating_state = dce_virtual_set_clockgating_state,
> -       .set_powergating_state = dce_virtual_set_powergating_state,
> -};
> -
> -const struct amdgpu_ip_block_version dce_virtual_ip_block =
> -{
> -       .type = AMD_IP_BLOCK_TYPE_DCE,
> -       .major = 1,
> -       .minor = 0,
> -       .rev = 0,
> -       .funcs = &dce_virtual_ip_funcs,
> -};
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
> deleted file mode 100644
> index ed422012c8c6..000000000000
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
> +++ /dev/null
> @@ -1,30 +0,0 @@
> -/*
> - * Copyright 2014 Advanced Micro Devices, Inc.
> - *
> - * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
> - *
> - */
> -
> -#ifndef __DCE_VIRTUAL_H__
> -#define __DCE_VIRTUAL_H__
> -
> -extern const struct amdgpu_ip_block_version dce_virtual_ip_block;
> -
> -#endif
> -
> diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
> index 436fb13e32f0..696ecc1ccb28 100644
> --- a/drivers/gpu/drm/amd/amdgpu/nv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/nv.c
> @@ -58,7 +58,7 @@
>  #include "jpeg_v2_0.h"
>  #include "vcn_v3_0.h"
>  #include "jpeg_v3_0.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mes_v10_1.h"
>  #include "mxgpu_nv.h"
>  #include "smuio_v11_0.h"
> @@ -721,7 +721,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     !amdgpu_sriov_vf(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -749,7 +749,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -779,7 +779,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -802,7 +802,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -823,7 +823,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -843,7 +843,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                  else if (amdgpu_device_has_dc_support(adev))
>                          amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -865,7 +865,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -883,11 +883,11 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
> index 7cbc2bb03bc6..e6d2f74a7976 100644
> --- a/drivers/gpu/drm/amd/amdgpu/si.c
> +++ b/drivers/gpu/drm/amd/amdgpu/si.c
> @@ -44,7 +44,7 @@
>  #include "dce_v6_0.h"
>  #include "si.h"
>  #include "uvd_v3_1.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "gca/gfx_6_0_d.h"
>  #include "oss/oss_1_0_d.h"
>  #include "oss/oss_1_0_sh_mask.h"
> @@ -2759,7 +2759,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2777,7 +2777,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2795,7 +2795,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 break;
>         default:
>                 BUG();
> diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
> index a5e085e570f7..f7b56a746c15 100644
> --- a/drivers/gpu/drm/amd/amdgpu/soc15.c
> +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
> @@ -74,7 +74,7 @@
>  #include "smuio_v9_0.h"
>  #include "smuio_v11_0.h"
>  #include "smuio_v13_0.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mxgpu_ai.h"
>  #include "amdgpu_ras.h"
>  #include "amdgpu_xgmi.h"
> @@ -843,7 +843,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 }
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -863,7 +863,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -885,7 +885,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 }
>
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
> @@ -909,7 +909,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                  else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
> index 3d21c0799037..fe9a7cc8d9eb 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vi.c
> @@ -77,7 +77,7 @@
>  #if defined(CONFIG_DRM_AMD_ACP)
>  #include "amdgpu_acp.h"
>  #endif
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mxgpu_vi.h"
>  #include "amdgpu_dm.h"
>
> @@ -2102,7 +2102,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 break;
>         case CHIP_FIJI:
>                 amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
> @@ -2112,7 +2112,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2132,7 +2132,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2155,7 +2155,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2173,7 +2173,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2194,7 +2194,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> --
> 2.32.0
>

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

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

* Re: [PATCH 3/3] drm/amdgpu: replace dce_virtual with amdgpu_vkms (v3)
@ 2021-07-23 15:50       ` Taylor, Ryan
  0 siblings, 0 replies; 24+ messages in thread
From: Taylor, Ryan @ 2021-07-23 15:50 UTC (permalink / raw)
  To: Alex Deucher
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo,
	amd-gfx list, Melissa Wen, Maling list - DRI developers, Deucher,
	 Alexander


[-- Attachment #1.1: Type: text/plain, Size: 38691 bytes --]

[AMD Official Use Only]

Thanks Alex! I will make these changes.

Best,
Ryan
________________________________
From: Alex Deucher <alexdeucher@gmail.com>
Sent: Friday, July 23, 2021 7:33 AM
To: Taylor, Ryan <Ryan.Taylor@amd.com>
Cc: Maling list - DRI developers <dri-devel@lists.freedesktop.org>; amd-gfx list <amd-gfx@lists.freedesktop.org>; kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; Melissa Wen <melissa.srw@gmail.com>; Deucher, Alexander <Alexander.Deucher@amd.com>
Subject: Re: [PATCH 3/3] drm/amdgpu: replace dce_virtual with amdgpu_vkms (v3)

On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
>
> Move dce_virtual into amdgpu_vkms and update all references to
> dce_virtual with amdgpu_vkms.
>
> v2: Removed more references to dce_virtual.
>
> v3: Restored display modes from previous implementation.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Suggested-by: Alex Deucher <Alexander.Deucher@amd.com>
> Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/Makefile      |   3 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 234 ++++++++++++++++++++++-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |   5 +-
>  drivers/gpu/drm/amd/amdgpu/cik.c         |  10 +-
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 223 ---------------------
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.h |  30 ---
>  drivers/gpu/drm/amd/amdgpu/nv.c          |  20 +-
>  drivers/gpu/drm/amd/amdgpu/si.c          |   8 +-
>  drivers/gpu/drm/amd/amdgpu/soc15.c       |  10 +-
>  drivers/gpu/drm/amd/amdgpu/vi.c          |  14 +-
>  10 files changed, 264 insertions(+), 293 deletions(-)
>  delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.c
>  delete mode 100644 drivers/gpu/drm/amd/amdgpu/dce_virtual.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
> index 30cbcd5ce1cc..0d814c957461 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -120,8 +120,7 @@ amdgpu-y += \
>  amdgpu-y += \
>         dce_v10_0.o \
>         dce_v11_0.o \
> -       amdgpu_vkms.o \
> -       dce_virtual.o
> +       amdgpu_vkms.o
>
>  # add GFX block
>  amdgpu-y += \
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> index d5c1f1c58f5f..538d41e6666a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> @@ -5,6 +5,15 @@
>  #include <drm/drm_vblank.h>
>
>  #include "amdgpu.h"
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +#include "dce_v6_0.h"
> +#endif
> +#ifdef CONFIG_DRM_AMDGPU_CIK
> +#include "dce_v8_0.h"
> +#endif
> +#include "dce_v10_0.h"
> +#include "dce_v11_0.h"
> +#include "ivsrcid/ivsrcid_vislands30.h"
>  #include "amdgpu_vkms.h"
>  #include "amdgpu_display.h"
>
> @@ -180,12 +189,45 @@ static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
>
>  static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
>  {
> -       int count;
> +       struct drm_device *dev = connector->dev;
> +       struct drm_display_mode *mode = NULL;
> +       unsigned i;
> +       static const struct mode_size {
> +               int w;
> +               int h;
> +       } common_modes[] = {
> +               { 640,  480},
> +               { 720,  480},
> +               { 800,  600},
> +               { 848,  480},
> +               {1024,  768},
> +               {1152,  768},
> +               {1280,  720},
> +               {1280,  800},
> +               {1280,  854},
> +               {1280,  960},
> +               {1280, 1024},
> +               {1440,  900},
> +               {1400, 1050},
> +               {1680, 1050},
> +               {1600, 1200},
> +               {1920, 1080},
> +               {1920, 1200},
> +               {2560, 1440},
> +               {4096, 3112},
> +               {3656, 2664},
> +               {3840, 2160},
> +               {4096, 2160},
> +       };
> +
> +       for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
> +               mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
> +               drm_mode_probed_add(connector, mode);
> +       }
>
> -       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
>         drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
>
> -       return count;
> +       return ARRAY_SIZE(common_modes);
>  }
>
>  static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> @@ -409,3 +451,189 @@ int amdgpu_vkms_output_init(struct drm_device *dev,
>
>         return ret;
>  }
> +
> +const struct drm_mode_config_funcs amdgpu_vkms_mode_funcs = {
> +       .fb_create = amdgpu_display_user_framebuffer_create,
> +       .atomic_check = drm_atomic_helper_check,
> +       .atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +static int amdgpu_vkms_sw_init(void *handle)
> +{
> +       int r, i;
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +       adev_to_drm(adev)->max_vblank_count = 0;
> +
> +       adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs;
> +
> +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> +
> +       adev_to_drm(adev)->mode_config.preferred_depth = 24;
> +       adev_to_drm(adev)->mode_config.prefer_shadow = 1;
> +
> +       adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
> +
> +       r = amdgpu_display_modeset_create_props(adev);
> +       if (r)
> +               return r;
> +
> +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> +
> +       /* allocate crtcs, encoders, connectors */
> +       for (i = 0; i < adev->mode_info.num_crtc; i++) {
> +               r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
> +               if (r)
> +                       return r;
> +       }
> +
> +       drm_kms_helper_poll_init(adev_to_drm(adev));
> +
> +       adev->mode_info.mode_config_initialized = true;
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_sw_fini(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int i = 0;
> +
> +       for (i = 0; i < adev->mode_info.num_crtc; i++)
> +               if (adev->mode_info.crtcs[i])
> +                       hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> +
> +       kfree(adev->mode_info.bios_hardcoded_edid);
> +       kfree(adev->amdgpu_vkms_output);
> +
> +       drm_kms_helper_poll_fini(adev_to_drm(adev));
> +
> +       adev->mode_info.mode_config_initialized = false;
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_hw_init(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +       switch (adev->asic_type) {
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +       case CHIP_TAHITI:
> +       case CHIP_PITCAIRN:
> +       case CHIP_VERDE:
> +       case CHIP_OLAND:
> +               dce_v6_0_disable_dce(adev);
> +               break;
> +#endif
> +#ifdef CONFIG_DRM_AMDGPU_CIK
> +       case CHIP_BONAIRE:
> +       case CHIP_HAWAII:
> +       case CHIP_KAVERI:
> +       case CHIP_KABINI:
> +       case CHIP_MULLINS:
> +               dce_v8_0_disable_dce(adev);
> +               break;
> +#endif
> +       case CHIP_FIJI:
> +       case CHIP_TONGA:
> +               dce_v10_0_disable_dce(adev);
> +               break;
> +       case CHIP_CARRIZO:
> +       case CHIP_STONEY:
> +       case CHIP_POLARIS10:
> +       case CHIP_POLARIS11:
> +       case CHIP_VEGAM:
> +               dce_v11_0_disable_dce(adev);
> +               break;
> +       case CHIP_TOPAZ:
> +#ifdef CONFIG_DRM_AMDGPU_SI
> +       case CHIP_HAINAN:
> +#endif
> +               /* no DCE */
> +               break;
> +       default:
> +               break;
> +       }
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_hw_fini(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_suspend(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int r;
> +
> +       r = drm_mode_config_helper_suspend(adev_to_drm(adev));
> +       if (r)
> +               return r;
> +       return amdgpu_vkms_hw_fini(handle);
> +}
> +
> +static int amdgpu_vkms_resume(void *handle)
> +{
> +       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +       int r;
> +
> +       r = amdgpu_vkms_hw_init(handle);
> +       if (r)
> +               return r;
> +       return drm_mode_config_helper_resume(adev_to_drm(adev));
> +}
> +
> +static bool amdgpu_vkms_is_idle(void *handle)
> +{
> +       return true;
> +}
> +
> +static int amdgpu_vkms_wait_for_idle(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_soft_reset(void *handle)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_set_clockgating_state(void *handle,
> +                                         enum amd_clockgating_state state)
> +{
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_set_powergating_state(void *handle,
> +                                         enum amd_powergating_state state)
> +{
> +       return 0;
> +}
> +
> +static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = {
> +       .name = "amdgpu_vkms",
> +       .early_init = NULL,
> +       .late_init = NULL,
> +       .sw_init = amdgpu_vkms_sw_init,
> +       .sw_fini = amdgpu_vkms_sw_fini,
> +       .hw_init = amdgpu_vkms_hw_init,
> +       .hw_fini = amdgpu_vkms_hw_fini,
> +       .suspend = amdgpu_vkms_suspend,
> +       .resume = amdgpu_vkms_resume,
> +       .is_idle = amdgpu_vkms_is_idle,
> +       .wait_for_idle = amdgpu_vkms_wait_for_idle,
> +       .soft_reset = amdgpu_vkms_soft_reset,
> +       .set_clockgating_state = amdgpu_vkms_set_clockgating_state,
> +       .set_powergating_state = amdgpu_vkms_set_powergating_state,
> +};
> +
> +const struct amdgpu_ip_block_version amdgpu_vkms_ip_block =
> +{
> +       .type = AMD_IP_BLOCK_TYPE_DCE,
> +       .major = 1,
> +       .minor = 0,
> +       .rev = 0,
> +       .funcs = &amdgpu_vkms_ip_funcs,
> +};
> +
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> index 5dab51fbecf3..97f1b79c0724 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> @@ -4,7 +4,7 @@
>  #define _AMDGPU_VKMS_H_
>
>  #define XRES_DEF  1024
> -#define YRES_DEF   764
> +#define YRES_DEF   768

Squash this fix into the original patch that added this macro.


>
>  #define XRES_MAX  16384
>  #define YRES_MAX  16384
> @@ -23,7 +23,4 @@ struct amdgpu_vkms_output {
>         struct drm_pending_vblank_event *event;
>  };
>
> -int amdgpu_vkms_output_init(struct drm_device *dev,
> -                           struct amdgpu_vkms_output *output, int index);
> -
>  #endif /* _AMDGPU_VKMS_H_ */
> diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
> index c0fcc41ee574..54f28c075f21 100644
> --- a/drivers/gpu/drm/amd/amdgpu/cik.c
> +++ b/drivers/gpu/drm/amd/amdgpu/cik.c
> @@ -70,7 +70,7 @@
>
>  #include "amdgpu_dm.h"
>  #include "amdgpu_amdkfd.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>
>  static const struct amdgpu_video_codec_info cik_video_codecs_encode_array[] =
>  {
> @@ -2259,7 +2259,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2277,7 +2277,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2295,7 +2295,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2315,7 +2315,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> deleted file mode 100644
> index 18369b47eac7..000000000000
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> +++ /dev/null
> @@ -1,223 +0,0 @@
> -/*
> - * Copyright 2014 Advanced Micro Devices, Inc.
> - *
> - * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
> - *
> - */
> -
> -#include <drm/drm_atomic_helper.h>
> -
> -#include "amdgpu.h"
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -#include "dce_v6_0.h"
> -#endif
> -#ifdef CONFIG_DRM_AMDGPU_CIK
> -#include "dce_v8_0.h"
> -#endif
> -#include "dce_v10_0.h"
> -#include "dce_v11_0.h"
> -#include "dce_virtual.h"
> -#include "ivsrcid/ivsrcid_vislands30.h"
> -#include "amdgpu_display.h"
> -#include "amdgpu_vkms.h"
> -
> -const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> -       .fb_create = amdgpu_display_user_framebuffer_create,
> -       .atomic_check = drm_atomic_helper_check,
> -       .atomic_commit = drm_atomic_helper_commit,
> -};
> -
> -static int dce_virtual_sw_init(void *handle)
> -{
> -       int r, i;
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -
> -       adev_to_drm(adev)->max_vblank_count = 0;
> -
> -       adev_to_drm(adev)->mode_config.funcs = &dce_virtual_mode_funcs;
> -
> -       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> -       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> -
> -       adev_to_drm(adev)->mode_config.preferred_depth = 24;
> -       adev_to_drm(adev)->mode_config.prefer_shadow = 1;
> -
> -       adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
> -
> -       r = amdgpu_display_modeset_create_props(adev);
> -       if (r)
> -               return r;
> -
> -       adev->amdgpu_vkms_output = kzalloc(sizeof(struct amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> -
> -       /* allocate crtcs, encoders, connectors */
> -       for (i = 0; i < adev->mode_info.num_crtc; i++) {
> -               r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
> -               if (r)
> -                       return r;
> -       }
> -
> -       drm_kms_helper_poll_init(adev_to_drm(adev));
> -
> -       adev->mode_info.mode_config_initialized = true;
> -       return 0;
> -}
> -
> -static int dce_virtual_sw_fini(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int i = 0;
> -
> -       for (i = 0; i < adev->mode_info.num_crtc; i++)
> -               if (adev->mode_info.crtcs[i])
> -                       hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> -
> -       kfree(adev->mode_info.bios_hardcoded_edid);
> -       kfree(adev->amdgpu_vkms_output);
> -
> -       drm_kms_helper_poll_fini(adev_to_drm(adev));
> -
> -       adev->mode_info.mode_config_initialized = false;
> -       return 0;
> -}
> -
> -static int dce_virtual_hw_init(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -
> -       switch (adev->asic_type) {
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -       case CHIP_TAHITI:
> -       case CHIP_PITCAIRN:
> -       case CHIP_VERDE:
> -       case CHIP_OLAND:
> -               dce_v6_0_disable_dce(adev);
> -               break;
> -#endif
> -#ifdef CONFIG_DRM_AMDGPU_CIK
> -       case CHIP_BONAIRE:
> -       case CHIP_HAWAII:
> -       case CHIP_KAVERI:
> -       case CHIP_KABINI:
> -       case CHIP_MULLINS:
> -               dce_v8_0_disable_dce(adev);
> -               break;
> -#endif
> -       case CHIP_FIJI:
> -       case CHIP_TONGA:
> -               dce_v10_0_disable_dce(adev);
> -               break;
> -       case CHIP_CARRIZO:
> -       case CHIP_STONEY:
> -       case CHIP_POLARIS10:
> -       case CHIP_POLARIS11:
> -       case CHIP_VEGAM:
> -               dce_v11_0_disable_dce(adev);
> -               break;
> -       case CHIP_TOPAZ:
> -#ifdef CONFIG_DRM_AMDGPU_SI
> -       case CHIP_HAINAN:
> -#endif
> -               /* no DCE */
> -               break;
> -       default:
> -               break;
> -       }
> -       return 0;
> -}
> -
> -static int dce_virtual_hw_fini(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_suspend(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int r;
> -
> -       r = drm_mode_config_helper_suspend(adev_to_drm(adev));
> -       if (r)
> -               return r;
> -       return dce_virtual_hw_fini(handle);
> -}
> -
> -static int dce_virtual_resume(void *handle)
> -{
> -       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> -       int r;
> -
> -       r = dce_virtual_hw_init(handle);
> -       if (r)
> -               return r;
> -       return drm_mode_config_helper_resume(adev_to_drm(adev));
> -}
> -
> -static bool dce_virtual_is_idle(void *handle)
> -{
> -       return true;
> -}
> -
> -static int dce_virtual_wait_for_idle(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_soft_reset(void *handle)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_set_clockgating_state(void *handle,
> -                                         enum amd_clockgating_state state)
> -{
> -       return 0;
> -}
> -
> -static int dce_virtual_set_powergating_state(void *handle,
> -                                         enum amd_powergating_state state)
> -{
> -       return 0;
> -}
> -
> -static const struct amd_ip_funcs dce_virtual_ip_funcs = {
> -       .name = "dce_virtual",
> -       .early_init = NULL,
> -       .late_init = NULL,
> -       .sw_init = dce_virtual_sw_init,
> -       .sw_fini = dce_virtual_sw_fini,
> -       .hw_init = dce_virtual_hw_init,
> -       .hw_fini = dce_virtual_hw_fini,
> -       .suspend = dce_virtual_suspend,
> -       .resume = dce_virtual_resume,
> -       .is_idle = dce_virtual_is_idle,
> -       .wait_for_idle = dce_virtual_wait_for_idle,
> -       .soft_reset = dce_virtual_soft_reset,
> -       .set_clockgating_state = dce_virtual_set_clockgating_state,
> -       .set_powergating_state = dce_virtual_set_powergating_state,
> -};
> -
> -const struct amdgpu_ip_block_version dce_virtual_ip_block =
> -{
> -       .type = AMD_IP_BLOCK_TYPE_DCE,
> -       .major = 1,
> -       .minor = 0,
> -       .rev = 0,
> -       .funcs = &dce_virtual_ip_funcs,
> -};
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h b/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
> deleted file mode 100644
> index ed422012c8c6..000000000000
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
> +++ /dev/null
> @@ -1,30 +0,0 @@
> -/*
> - * Copyright 2014 Advanced Micro Devices, Inc.
> - *
> - * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
> - *
> - */
> -
> -#ifndef __DCE_VIRTUAL_H__
> -#define __DCE_VIRTUAL_H__
> -
> -extern const struct amdgpu_ip_block_version dce_virtual_ip_block;
> -
> -#endif
> -
> diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
> index 436fb13e32f0..696ecc1ccb28 100644
> --- a/drivers/gpu/drm/amd/amdgpu/nv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/nv.c
> @@ -58,7 +58,7 @@
>  #include "jpeg_v2_0.h"
>  #include "vcn_v3_0.h"
>  #include "jpeg_v3_0.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mes_v10_1.h"
>  #include "mxgpu_nv.h"
>  #include "smuio_v11_0.h"
> @@ -721,7 +721,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     !amdgpu_sriov_vf(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -749,7 +749,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -779,7 +779,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -802,7 +802,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -823,7 +823,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -843,7 +843,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                     is_support_sw_smu(adev))
>                         amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                  else if (amdgpu_device_has_dc_support(adev))
>                          amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -865,7 +865,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -883,11 +883,11 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
> index 7cbc2bb03bc6..e6d2f74a7976 100644
> --- a/drivers/gpu/drm/amd/amdgpu/si.c
> +++ b/drivers/gpu/drm/amd/amdgpu/si.c
> @@ -44,7 +44,7 @@
>  #include "dce_v6_0.h"
>  #include "si.h"
>  #include "uvd_v3_1.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "gca/gfx_6_0_d.h"
>  #include "oss/oss_1_0_d.h"
>  #include "oss/oss_1_0_sh_mask.h"
> @@ -2759,7 +2759,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2777,7 +2777,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2795,7 +2795,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
>                 amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 break;
>         default:
>                 BUG();
> diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
> index a5e085e570f7..f7b56a746c15 100644
> --- a/drivers/gpu/drm/amd/amdgpu/soc15.c
> +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
> @@ -74,7 +74,7 @@
>  #include "smuio_v9_0.h"
>  #include "smuio_v11_0.h"
>  #include "smuio_v13_0.h"
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mxgpu_ai.h"
>  #include "amdgpu_ras.h"
>  #include "amdgpu_xgmi.h"
> @@ -843,7 +843,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                         amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 }
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -863,7 +863,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -885,7 +885,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 }
>
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
> @@ -909,7 +909,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                  else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
> index 3d21c0799037..fe9a7cc8d9eb 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vi.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vi.c
> @@ -77,7 +77,7 @@
>  #if defined(CONFIG_DRM_AMD_ACP)
>  #include "amdgpu_acp.h"
>  #endif
> -#include "dce_virtual.h"
> +#include "amdgpu_vkms.h"
>  #include "mxgpu_vi.h"
>  #include "amdgpu_dm.h"
>
> @@ -2102,7 +2102,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>                 break;
>         case CHIP_FIJI:
>                 amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
> @@ -2112,7 +2112,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2132,7 +2132,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2155,7 +2155,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2173,7 +2173,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> @@ -2194,7 +2194,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
>                 amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
>                 amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
>                 if (adev->enable_virtual_display)
> -                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
> +                       amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
>  #if defined(CONFIG_DRM_AMD_DC)
>                 else if (amdgpu_device_has_dc_support(adev))
>                         amdgpu_device_ip_block_add(adev, &dm_ip_block);
> --
> 2.32.0
>

[-- Attachment #1.2: Type: text/html, Size: 77181 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* RE: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
  2021-07-23 14:31     ` Alex Deucher
@ 2021-07-24  2:07       ` Chen, Guchun
  -1 siblings, 0 replies; 24+ messages in thread
From: Chen, Guchun @ 2021-07-24  2:07 UTC (permalink / raw)
  To: Alex Deucher, Taylor, Ryan
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo,
	Maling list - DRI developers, Melissa Wen, amd-gfx list

[Public]

Look copy right statement is missed in both amdgpu_vkms.c and amdgpu_vkms.h.

Regards,
Guchun

-----Original Message-----
From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Alex Deucher
Sent: Friday, July 23, 2021 10:32 PM
To: Taylor, Ryan <Ryan.Taylor@amd.com>
Cc: kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)

On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
>
> Modify the VKMS driver into an api that dce_virtual can use to create 
> virtual displays that obey drm's atomic modesetting api.
>
> v2: Made local functions static.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411 
> +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |  
> 29 ++  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
>  7 files changed, 458 insertions(+), 11 deletions(-)  create mode 
> 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
>  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile 
> b/drivers/gpu/drm/amd/amdgpu/Makefile
> index f089794bbdd5..30cbcd5ce1cc 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -120,6 +120,7 @@ amdgpu-y += \
>  amdgpu-y += \
>         dce_v10_0.o \
>         dce_v11_0.o \
> +       amdgpu_vkms.o \
>         dce_virtual.o
>
>  # add GFX block
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 54cf647bd018..d0a2f2ed433d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -919,6 +919,7 @@ struct amdgpu_device {
>
>         /* display */
>         bool                            enable_virtual_display;
> +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
>         struct amdgpu_mode_info         mode_info;
>         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
>         struct work_struct              hotplug_work;
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index d0c935cf4f0f..1b016e5bc75f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
>         int ret, retry = 0;
>         bool supports_atomic = false;
>
> -       if (!amdgpu_virtual_display &&
> +       if (amdgpu_virtual_display ||
>             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
>                 supports_atomic = true;
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> index 09b048647523..5a143ca02cf9 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
>         }
>
>         /* disable all the possible outputs/crtcs before entering KMS mode */
> -       if (!amdgpu_device_has_dc_support(adev))
> +       if (!amdgpu_device_has_dc_support(adev) && 
> + !amdgpu_virtual_display)
>                 
> drm_helper_disable_unused_functions(adev_to_drm(adev));
>
>         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); diff 
> --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> new file mode 100644
> index 000000000000..d5c1f1c58f5f
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> @@ -0,0 +1,411 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h>
> +
> +#include "amdgpu.h"
> +#include "amdgpu_vkms.h"
> +#include "amdgpu_display.h"
> +
> +/**
> + * DOC: amdgpu_vkms
> + *
> + * The amdgpu vkms interface provides a virtual KMS interface for 
> +several use
> + * cases: devices without display hardware, platforms where the 
> +actual display
> + * hardware is not useful (e.g., servers), SR-IOV virtual functions, 
> +device
> + * emulation/simulation, and device bring up prior to display 
> +hardware being
> + * usable. We previously emulated a legacy KMS interface, but there 
> +was a desire
> + * to move to the atomic KMS interface. The vkms driver did 
> +everything we
> + * needed, but we wanted KMS support natively in the driver without 
> +buffer
> + * sharing and the ability to support an instance of VKMS per device. 
> +We first
> + * looked at splitting vkms into a stub driver and a helper module 
> +that other
> + * drivers could use to implement a virtual display, but this 
> +strategy ended up
> + * being messy due to driver specific callbacks needed for buffer management.
> + * Ultimately, it proved easier to import the vkms code as it mostly 
> +used core
> + * drm helpers anyway.
> + */
> +
> +static const u32 amdgpu_vkms_formats[] = {
> +       DRM_FORMAT_XRGB8888,
> +};
> +
> +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct 
> +hrtimer *timer) {
> +       struct amdgpu_vkms_output *output = container_of(timer,
> +                                                        struct amdgpu_vkms_output,
> +                                                        vblank_hrtimer);
> +       struct drm_crtc *crtc = &output->crtc;
> +       u64 ret_overrun;
> +       bool ret;
> +
> +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> +                                         output->period_ns);
> +       WARN_ON(ret_overrun != 1);
> +
> +       ret = drm_crtc_handle_vblank(crtc);
> +       if (!ret)
> +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> +
> +       return HRTIMER_RESTART;
> +}
> +
> +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) {
> +       struct drm_device *dev = crtc->dev;
> +       unsigned int pipe = drm_crtc_index(crtc);
> +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +       struct amdgpu_vkms_output *out = 
> +drm_crtc_to_amdgpu_vkms_output(crtc);
> +
> +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> +
> +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> +       hrtimer_start(&out->vblank_hrtimer, out->period_ns, 
> + HRTIMER_MODE_REL);
> +
> +       return 0;
> +}
> +
> +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) {
> +       struct amdgpu_vkms_output *out = 
> +drm_crtc_to_amdgpu_vkms_output(crtc);
> +
> +       hrtimer_cancel(&out->vblank_hrtimer);
> +}
> +
> +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> +                                            int *max_error,
> +                                            ktime_t *vblank_time,
> +                                            bool in_vblank_irq) {
> +       struct drm_device *dev = crtc->dev;
> +       unsigned int pipe = crtc->index;
> +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +
> +       if (!READ_ONCE(vblank->enabled)) {
> +               *vblank_time = ktime_get();
> +               return true;
> +       }
> +
> +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> +
> +       if (WARN_ON(*vblank_time == vblank->time))
> +               return true;
> +
> +       /*
> +        * To prevent races we roll the hrtimer forward before we do any
> +        * interrupt processing - this is how real hw works (the interrupt is
> +        * only generated after all the vblank registers are updated) and what
> +        * the vblank core expects. Therefore we need to always correct the
> +        * timestampe by one frame.
> +        */
> +       *vblank_time -= output->period_ns;
> +
> +       return true;
> +}
> +
> +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> +       .set_config             = drm_atomic_helper_set_config,
> +       .destroy                = drm_crtc_cleanup,
> +       .page_flip              = drm_atomic_helper_page_flip,
> +       .reset                  = drm_atomic_helper_crtc_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> +};
> +
> +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> +                                          struct drm_atomic_state 
> +*state) {
> +       drm_crtc_vblank_on(crtc);
> +}
> +
> +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> +                                           struct drm_atomic_state 
> +*state) {
> +       drm_crtc_vblank_off(crtc);
> +}
> +
> +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> +                                         struct drm_atomic_state 
> +*state) {
> +       if (crtc->state->event) {
> +               spin_lock(&crtc->dev->event_lock);
> +
> +               if (drm_crtc_vblank_get(crtc) != 0)
> +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> +               else
> +                       drm_crtc_arm_vblank_event(crtc, 
> + crtc->state->event);
> +
> +               spin_unlock(&crtc->dev->event_lock);
> +
> +               crtc->state->event = NULL;
> +       }
> +}
> +
> +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable, };
> +
> +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> +                         struct drm_plane *primary, struct drm_plane 
> +*cursor) {
> +       int ret;
> +
> +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> +                                       &amdgpu_vkms_crtc_funcs, NULL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init CRTC\n");
> +               return ret;
> +       }
> +
> +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> +
> +       return ret;
> +}
> +
> +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> +       .fill_modes = drm_helper_probe_single_connector_modes,
> +       .destroy = drm_connector_cleanup,
> +       .reset = drm_atomic_helper_connector_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +       .atomic_destroy_state = 
> +drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int amdgpu_vkms_conn_get_modes(struct drm_connector 
> +*connector) {
> +       int count;
> +
> +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> +
> +       return count;
> +}
> +
> +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> +       .get_modes    = amdgpu_vkms_conn_get_modes,
> +};
> +
> +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> +       .update_plane           = drm_atomic_helper_update_plane,
> +       .disable_plane          = drm_atomic_helper_disable_plane,
> +       .destroy                = drm_plane_cleanup,
> +       .reset                  = drm_atomic_helper_plane_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> +};
> +
> +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> +                                           struct drm_plane_state 
> +*old_state) {
> +       return;
> +}
> +
> +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> +                                         struct drm_plane_state 
> +*state) {
> +       struct drm_crtc_state *crtc_state;
> +       bool can_position = false;
> +       int ret;
> +
> +       if (!state->fb || WARN_ON(!state->crtc))
> +               return 0;
> +
> +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> +       if (IS_ERR(crtc_state))
> +               return PTR_ERR(crtc_state);
> +
> +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> +                                                 DRM_PLANE_HELPER_NO_SCALING,
> +                                                 DRM_PLANE_HELPER_NO_SCALING,
> +                                                 can_position, true);
> +       if (ret != 0)
> +               return ret;
> +
> +       /* for now primary plane must be visible and full screen */
> +       if (!state->visible && !can_position)
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> +                                 struct drm_plane_state *new_state) {
> +       struct amdgpu_framebuffer *afb;
> +       struct drm_gem_object *obj;
> +       struct amdgpu_device *adev;
> +       struct amdgpu_bo *rbo;
> +       struct list_head list;
> +       struct ttm_validate_buffer tv;
> +       struct ww_acquire_ctx ticket;
> +       uint32_t domain;
> +       int r;
> +
> +       if (!new_state->fb) {
> +               DRM_DEBUG_KMS("No FB bound\n");
> +               return 0;
> +       }
> +       afb = to_amdgpu_framebuffer(new_state->fb);
> +       obj = new_state->fb->obj[0];
> +       rbo = gem_to_amdgpu_bo(obj);
> +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> +       INIT_LIST_HEAD(&list);
> +
> +       tv.bo = &rbo->tbo;
> +       tv.num_shared = 1;
> +       list_add(&tv.head, &list);
> +
> +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> +       if (r) {
> +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> +               return r;
> +       }
> +
> +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> +       else
> +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> +
> +       r = amdgpu_bo_pin(rbo, domain);
> +       if (unlikely(r != 0)) {
> +               if (r != -ERESTARTSYS)
> +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> +               ttm_eu_backoff_reservation(&ticket, &list);
> +               return r;
> +       }
> +
> +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> +       if (unlikely(r != 0)) {
> +               amdgpu_bo_unpin(rbo);
> +               ttm_eu_backoff_reservation(&ticket, &list);
> +               DRM_ERROR("%p bind failed\n", rbo);
> +               return r;
> +       }
> +
> +       ttm_eu_backoff_reservation(&ticket, &list);
> +
> +       afb->address = amdgpu_bo_gpu_offset(rbo);
> +
> +       amdgpu_bo_ref(rbo);
> +
> +       return 0;
> +}
> +
> +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> +                                  struct drm_plane_state *old_state) 
> +{
> +       struct amdgpu_bo *rbo;
> +       int r;
> +
> +       if (!old_state->fb)
> +               return;
> +
> +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> +       r = amdgpu_bo_reserve(rbo, false);
> +       if (unlikely(r)) {
> +               DRM_ERROR("failed to reserve rbo before unpin\n");
> +               return;
> +       }
> +
> +       amdgpu_bo_unpin(rbo);
> +       amdgpu_bo_unreserve(rbo);
> +       amdgpu_bo_unref(&rbo);
> +}
> +
> +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> +};
> +
> +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> +                                               enum drm_plane_type type,
> +                                               int index) {
> +       struct drm_plane *plane;
> +       int ret;
> +
> +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> +       if (!plane)
> +               return ERR_PTR(-ENOMEM);
> +
> +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> +                                      &amdgpu_vkms_plane_funcs,
> +                                      amdgpu_vkms_formats,
> +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> +                                      NULL, type, NULL);
> +       if (ret) {
> +               kfree(plane);
> +               return ERR_PTR(ret);
> +       }
> +
> +       drm_plane_helper_add(plane, 
> + &amdgpu_vkms_primary_helper_funcs);
> +
> +       return plane;
> +}
> +
> +int amdgpu_vkms_output_init(struct drm_device *dev,
> +                           struct amdgpu_vkms_output *output, int 
> +index) {
> +       struct drm_connector *connector = &output->connector;
> +       struct drm_encoder *encoder = &output->encoder;
> +       struct drm_crtc *crtc = &output->crtc;
> +       struct drm_plane *primary, *cursor = NULL;
> +       int ret;
> +
> +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> +       if (IS_ERR(primary))
> +               return PTR_ERR(primary);
> +
> +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> +       if (ret)
> +               goto err_crtc;
> +
> +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> +                                DRM_MODE_CONNECTOR_VIRTUAL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init connector\n");
> +               goto err_connector;
> +       }
> +
> +       drm_connector_helper_add(connector, 
> + &amdgpu_vkms_conn_helper_funcs);
> +
> +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init encoder\n");
> +               goto err_encoder;
> +       }
> +       encoder->possible_crtcs = 1 << index;
> +
> +       ret = drm_connector_attach_encoder(connector, encoder);
> +       if (ret) {
> +               DRM_ERROR("Failed to attach connector to encoder\n");
> +               goto err_attach;
> +       }
> +
> +       drm_mode_config_reset(dev);
> +
> +       return 0;
> +
> +err_attach:
> +       drm_encoder_cleanup(encoder);
> +
> +err_encoder:
> +       drm_connector_cleanup(connector);
> +
> +err_connector:
> +       drm_crtc_cleanup(crtc);
> +
> +err_crtc:
> +       drm_plane_cleanup(primary);
> +
> +       return ret;
> +}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> new file mode 100644
> index 000000000000..5dab51fbecf3
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +
> +#ifndef _AMDGPU_VKMS_H_
> +#define _AMDGPU_VKMS_H_
> +
> +#define XRES_DEF  1024
> +#define YRES_DEF   764

Squash in the 768 fix here.

> +
> +#define XRES_MAX  16384
> +#define YRES_MAX  16384
> +
> +#define drm_crtc_to_amdgpu_vkms_output(target) \
> +       container_of(target, struct amdgpu_vkms_output, crtc)
> +
> +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> +
> +struct amdgpu_vkms_output {
> +       struct drm_crtc crtc;
> +       struct drm_encoder encoder;
> +       struct drm_connector connector;
> +       struct hrtimer vblank_hrtimer;
> +       ktime_t period_ns;
> +       struct drm_pending_vblank_event *event; };
> +
> +int amdgpu_vkms_output_init(struct drm_device *dev,
> +                           struct amdgpu_vkms_output *output, int 
> +index);
> +
> +#endif /* _AMDGPU_VKMS_H_ */
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c 
> b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> index 7e0d8c092c7e..642c77533157 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> @@ -22,6 +22,7 @@
>   */
>
>  #include <drm/drm_vblank.h>
> +#include <drm/drm_atomic_helper.h>
>
>  #include "amdgpu.h"
>  #include "amdgpu_pm.h"
> @@ -40,6 +41,7 @@
>  #include "dce_virtual.h"
>  #include "ivsrcid/ivsrcid_vislands30.h"
>  #include "amdgpu_display.h"
> +#include "amdgpu_vkms.h"
>
>  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
>
> @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
>         .force = dce_virtual_force,
>  };
>
> +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> +       .fb_create = amdgpu_display_user_framebuffer_create,
> +       .atomic_check = drm_atomic_helper_check,
> +       .atomic_commit = drm_atomic_helper_commit, };
> +
>  static int dce_virtual_sw_init(void *handle)  {
>         int r, i;
> @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
>
>         adev_to_drm(adev)->max_vblank_count = 0;
>
> -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> +       adev_to_drm(adev)->mode_config.funcs = 
> + &dce_virtual_mode_funcs;
>
> -       adev_to_drm(adev)->mode_config.max_width = 16384;
> -       adev_to_drm(adev)->mode_config.max_height = 16384;
> +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
>
>         adev_to_drm(adev)->mode_config.preferred_depth = 24;
>         adev_to_drm(adev)->mode_config.prefer_shadow = 1; @@ -399,15 
> +407,11 @@ static int dce_virtual_sw_init(void *handle)
>         if (r)
>                 return r;
>
> -       adev_to_drm(adev)->mode_config.max_width = 16384;
> -       adev_to_drm(adev)->mode_config.max_height = 16384;
> +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct 
> + amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);

You can use kcalloc here.

>
>         /* allocate crtcs, encoders, connectors */
>         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> -               r = dce_virtual_crtc_init(adev, i);
> -               if (r)
> -                       return r;
> -               r = dce_virtual_connector_encoder_init(adev, i);
> +               r = amdgpu_vkms_output_init(adev_to_drm(adev), 
> + &adev->amdgpu_vkms_output[i], i);
>                 if (r)
>                         return r;
>         }
> @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
>                         
> hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
>
>         kfree(adev->mode_info.bios_hardcoded_edid);
> +       kfree(adev->amdgpu_vkms_output);
>
>         drm_kms_helper_poll_fini(adev_to_drm(adev));
>
> --
> 2.32.0
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flist
> s.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cgu
> chun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884
> e608e11a82d994e183d%7C0%7C0%7C637626475284480052%7CUnknown%7CTWFpbGZsb
> 3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%
> 7C1000&amp;sdata=0bbTKflaP2RPk%2BpboaNNiwffbEw1pW0zkqcxzPWjzmI%3D&amp;
> reserved=0
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cguchun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637626475284490043%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=VQ1liQG9OOsBA3NtjS93WNu6NhlLQ0fXQRbLwLmz95g%3D&amp;reserved=0

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

* RE: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
@ 2021-07-24  2:07       ` Chen, Guchun
  0 siblings, 0 replies; 24+ messages in thread
From: Chen, Guchun @ 2021-07-24  2:07 UTC (permalink / raw)
  To: Alex Deucher, Taylor, Ryan
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo,
	Maling list - DRI developers, Melissa Wen, amd-gfx list

[Public]

Look copy right statement is missed in both amdgpu_vkms.c and amdgpu_vkms.h.

Regards,
Guchun

-----Original Message-----
From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Alex Deucher
Sent: Friday, July 23, 2021 10:32 PM
To: Taylor, Ryan <Ryan.Taylor@amd.com>
Cc: kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)

On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
>
> Modify the VKMS driver into an api that dce_virtual can use to create 
> virtual displays that obey drm's atomic modesetting api.
>
> v2: Made local functions static.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411 
> +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |  
> 29 ++  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
>  7 files changed, 458 insertions(+), 11 deletions(-)  create mode 
> 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
>  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile 
> b/drivers/gpu/drm/amd/amdgpu/Makefile
> index f089794bbdd5..30cbcd5ce1cc 100644
> --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> @@ -120,6 +120,7 @@ amdgpu-y += \
>  amdgpu-y += \
>         dce_v10_0.o \
>         dce_v11_0.o \
> +       amdgpu_vkms.o \
>         dce_virtual.o
>
>  # add GFX block
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 54cf647bd018..d0a2f2ed433d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -919,6 +919,7 @@ struct amdgpu_device {
>
>         /* display */
>         bool                            enable_virtual_display;
> +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
>         struct amdgpu_mode_info         mode_info;
>         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
>         struct work_struct              hotplug_work;
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index d0c935cf4f0f..1b016e5bc75f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
>         int ret, retry = 0;
>         bool supports_atomic = false;
>
> -       if (!amdgpu_virtual_display &&
> +       if (amdgpu_virtual_display ||
>             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
>                 supports_atomic = true;
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> index 09b048647523..5a143ca02cf9 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
>         }
>
>         /* disable all the possible outputs/crtcs before entering KMS mode */
> -       if (!amdgpu_device_has_dc_support(adev))
> +       if (!amdgpu_device_has_dc_support(adev) && 
> + !amdgpu_virtual_display)
>                 
> drm_helper_disable_unused_functions(adev_to_drm(adev));
>
>         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); diff 
> --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> new file mode 100644
> index 000000000000..d5c1f1c58f5f
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> @@ -0,0 +1,411 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h>
> +
> +#include "amdgpu.h"
> +#include "amdgpu_vkms.h"
> +#include "amdgpu_display.h"
> +
> +/**
> + * DOC: amdgpu_vkms
> + *
> + * The amdgpu vkms interface provides a virtual KMS interface for 
> +several use
> + * cases: devices without display hardware, platforms where the 
> +actual display
> + * hardware is not useful (e.g., servers), SR-IOV virtual functions, 
> +device
> + * emulation/simulation, and device bring up prior to display 
> +hardware being
> + * usable. We previously emulated a legacy KMS interface, but there 
> +was a desire
> + * to move to the atomic KMS interface. The vkms driver did 
> +everything we
> + * needed, but we wanted KMS support natively in the driver without 
> +buffer
> + * sharing and the ability to support an instance of VKMS per device. 
> +We first
> + * looked at splitting vkms into a stub driver and a helper module 
> +that other
> + * drivers could use to implement a virtual display, but this 
> +strategy ended up
> + * being messy due to driver specific callbacks needed for buffer management.
> + * Ultimately, it proved easier to import the vkms code as it mostly 
> +used core
> + * drm helpers anyway.
> + */
> +
> +static const u32 amdgpu_vkms_formats[] = {
> +       DRM_FORMAT_XRGB8888,
> +};
> +
> +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct 
> +hrtimer *timer) {
> +       struct amdgpu_vkms_output *output = container_of(timer,
> +                                                        struct amdgpu_vkms_output,
> +                                                        vblank_hrtimer);
> +       struct drm_crtc *crtc = &output->crtc;
> +       u64 ret_overrun;
> +       bool ret;
> +
> +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> +                                         output->period_ns);
> +       WARN_ON(ret_overrun != 1);
> +
> +       ret = drm_crtc_handle_vblank(crtc);
> +       if (!ret)
> +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> +
> +       return HRTIMER_RESTART;
> +}
> +
> +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) {
> +       struct drm_device *dev = crtc->dev;
> +       unsigned int pipe = drm_crtc_index(crtc);
> +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +       struct amdgpu_vkms_output *out = 
> +drm_crtc_to_amdgpu_vkms_output(crtc);
> +
> +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> +
> +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> +       hrtimer_start(&out->vblank_hrtimer, out->period_ns, 
> + HRTIMER_MODE_REL);
> +
> +       return 0;
> +}
> +
> +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) {
> +       struct amdgpu_vkms_output *out = 
> +drm_crtc_to_amdgpu_vkms_output(crtc);
> +
> +       hrtimer_cancel(&out->vblank_hrtimer);
> +}
> +
> +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> +                                            int *max_error,
> +                                            ktime_t *vblank_time,
> +                                            bool in_vblank_irq) {
> +       struct drm_device *dev = crtc->dev;
> +       unsigned int pipe = crtc->index;
> +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +
> +       if (!READ_ONCE(vblank->enabled)) {
> +               *vblank_time = ktime_get();
> +               return true;
> +       }
> +
> +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> +
> +       if (WARN_ON(*vblank_time == vblank->time))
> +               return true;
> +
> +       /*
> +        * To prevent races we roll the hrtimer forward before we do any
> +        * interrupt processing - this is how real hw works (the interrupt is
> +        * only generated after all the vblank registers are updated) and what
> +        * the vblank core expects. Therefore we need to always correct the
> +        * timestampe by one frame.
> +        */
> +       *vblank_time -= output->period_ns;
> +
> +       return true;
> +}
> +
> +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> +       .set_config             = drm_atomic_helper_set_config,
> +       .destroy                = drm_crtc_cleanup,
> +       .page_flip              = drm_atomic_helper_page_flip,
> +       .reset                  = drm_atomic_helper_crtc_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> +};
> +
> +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> +                                          struct drm_atomic_state 
> +*state) {
> +       drm_crtc_vblank_on(crtc);
> +}
> +
> +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> +                                           struct drm_atomic_state 
> +*state) {
> +       drm_crtc_vblank_off(crtc);
> +}
> +
> +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> +                                         struct drm_atomic_state 
> +*state) {
> +       if (crtc->state->event) {
> +               spin_lock(&crtc->dev->event_lock);
> +
> +               if (drm_crtc_vblank_get(crtc) != 0)
> +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> +               else
> +                       drm_crtc_arm_vblank_event(crtc, 
> + crtc->state->event);
> +
> +               spin_unlock(&crtc->dev->event_lock);
> +
> +               crtc->state->event = NULL;
> +       }
> +}
> +
> +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable, };
> +
> +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> +                         struct drm_plane *primary, struct drm_plane 
> +*cursor) {
> +       int ret;
> +
> +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> +                                       &amdgpu_vkms_crtc_funcs, NULL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init CRTC\n");
> +               return ret;
> +       }
> +
> +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> +
> +       return ret;
> +}
> +
> +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> +       .fill_modes = drm_helper_probe_single_connector_modes,
> +       .destroy = drm_connector_cleanup,
> +       .reset = drm_atomic_helper_connector_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +       .atomic_destroy_state = 
> +drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int amdgpu_vkms_conn_get_modes(struct drm_connector 
> +*connector) {
> +       int count;
> +
> +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> +
> +       return count;
> +}
> +
> +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> +       .get_modes    = amdgpu_vkms_conn_get_modes,
> +};
> +
> +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> +       .update_plane           = drm_atomic_helper_update_plane,
> +       .disable_plane          = drm_atomic_helper_disable_plane,
> +       .destroy                = drm_plane_cleanup,
> +       .reset                  = drm_atomic_helper_plane_reset,
> +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> +};
> +
> +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> +                                           struct drm_plane_state 
> +*old_state) {
> +       return;
> +}
> +
> +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> +                                         struct drm_plane_state 
> +*state) {
> +       struct drm_crtc_state *crtc_state;
> +       bool can_position = false;
> +       int ret;
> +
> +       if (!state->fb || WARN_ON(!state->crtc))
> +               return 0;
> +
> +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> +       if (IS_ERR(crtc_state))
> +               return PTR_ERR(crtc_state);
> +
> +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> +                                                 DRM_PLANE_HELPER_NO_SCALING,
> +                                                 DRM_PLANE_HELPER_NO_SCALING,
> +                                                 can_position, true);
> +       if (ret != 0)
> +               return ret;
> +
> +       /* for now primary plane must be visible and full screen */
> +       if (!state->visible && !can_position)
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> +                                 struct drm_plane_state *new_state) {
> +       struct amdgpu_framebuffer *afb;
> +       struct drm_gem_object *obj;
> +       struct amdgpu_device *adev;
> +       struct amdgpu_bo *rbo;
> +       struct list_head list;
> +       struct ttm_validate_buffer tv;
> +       struct ww_acquire_ctx ticket;
> +       uint32_t domain;
> +       int r;
> +
> +       if (!new_state->fb) {
> +               DRM_DEBUG_KMS("No FB bound\n");
> +               return 0;
> +       }
> +       afb = to_amdgpu_framebuffer(new_state->fb);
> +       obj = new_state->fb->obj[0];
> +       rbo = gem_to_amdgpu_bo(obj);
> +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> +       INIT_LIST_HEAD(&list);
> +
> +       tv.bo = &rbo->tbo;
> +       tv.num_shared = 1;
> +       list_add(&tv.head, &list);
> +
> +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> +       if (r) {
> +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> +               return r;
> +       }
> +
> +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> +       else
> +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> +
> +       r = amdgpu_bo_pin(rbo, domain);
> +       if (unlikely(r != 0)) {
> +               if (r != -ERESTARTSYS)
> +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> +               ttm_eu_backoff_reservation(&ticket, &list);
> +               return r;
> +       }
> +
> +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> +       if (unlikely(r != 0)) {
> +               amdgpu_bo_unpin(rbo);
> +               ttm_eu_backoff_reservation(&ticket, &list);
> +               DRM_ERROR("%p bind failed\n", rbo);
> +               return r;
> +       }
> +
> +       ttm_eu_backoff_reservation(&ticket, &list);
> +
> +       afb->address = amdgpu_bo_gpu_offset(rbo);
> +
> +       amdgpu_bo_ref(rbo);
> +
> +       return 0;
> +}
> +
> +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> +                                  struct drm_plane_state *old_state) 
> +{
> +       struct amdgpu_bo *rbo;
> +       int r;
> +
> +       if (!old_state->fb)
> +               return;
> +
> +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> +       r = amdgpu_bo_reserve(rbo, false);
> +       if (unlikely(r)) {
> +               DRM_ERROR("failed to reserve rbo before unpin\n");
> +               return;
> +       }
> +
> +       amdgpu_bo_unpin(rbo);
> +       amdgpu_bo_unreserve(rbo);
> +       amdgpu_bo_unref(&rbo);
> +}
> +
> +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> +};
> +
> +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> +                                               enum drm_plane_type type,
> +                                               int index) {
> +       struct drm_plane *plane;
> +       int ret;
> +
> +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> +       if (!plane)
> +               return ERR_PTR(-ENOMEM);
> +
> +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> +                                      &amdgpu_vkms_plane_funcs,
> +                                      amdgpu_vkms_formats,
> +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> +                                      NULL, type, NULL);
> +       if (ret) {
> +               kfree(plane);
> +               return ERR_PTR(ret);
> +       }
> +
> +       drm_plane_helper_add(plane, 
> + &amdgpu_vkms_primary_helper_funcs);
> +
> +       return plane;
> +}
> +
> +int amdgpu_vkms_output_init(struct drm_device *dev,
> +                           struct amdgpu_vkms_output *output, int 
> +index) {
> +       struct drm_connector *connector = &output->connector;
> +       struct drm_encoder *encoder = &output->encoder;
> +       struct drm_crtc *crtc = &output->crtc;
> +       struct drm_plane *primary, *cursor = NULL;
> +       int ret;
> +
> +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> +       if (IS_ERR(primary))
> +               return PTR_ERR(primary);
> +
> +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> +       if (ret)
> +               goto err_crtc;
> +
> +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> +                                DRM_MODE_CONNECTOR_VIRTUAL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init connector\n");
> +               goto err_connector;
> +       }
> +
> +       drm_connector_helper_add(connector, 
> + &amdgpu_vkms_conn_helper_funcs);
> +
> +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> +       if (ret) {
> +               DRM_ERROR("Failed to init encoder\n");
> +               goto err_encoder;
> +       }
> +       encoder->possible_crtcs = 1 << index;
> +
> +       ret = drm_connector_attach_encoder(connector, encoder);
> +       if (ret) {
> +               DRM_ERROR("Failed to attach connector to encoder\n");
> +               goto err_attach;
> +       }
> +
> +       drm_mode_config_reset(dev);
> +
> +       return 0;
> +
> +err_attach:
> +       drm_encoder_cleanup(encoder);
> +
> +err_encoder:
> +       drm_connector_cleanup(connector);
> +
> +err_connector:
> +       drm_crtc_cleanup(crtc);
> +
> +err_crtc:
> +       drm_plane_cleanup(primary);
> +
> +       return ret;
> +}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> new file mode 100644
> index 000000000000..5dab51fbecf3
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +
> +#ifndef _AMDGPU_VKMS_H_
> +#define _AMDGPU_VKMS_H_
> +
> +#define XRES_DEF  1024
> +#define YRES_DEF   764

Squash in the 768 fix here.

> +
> +#define XRES_MAX  16384
> +#define YRES_MAX  16384
> +
> +#define drm_crtc_to_amdgpu_vkms_output(target) \
> +       container_of(target, struct amdgpu_vkms_output, crtc)
> +
> +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> +
> +struct amdgpu_vkms_output {
> +       struct drm_crtc crtc;
> +       struct drm_encoder encoder;
> +       struct drm_connector connector;
> +       struct hrtimer vblank_hrtimer;
> +       ktime_t period_ns;
> +       struct drm_pending_vblank_event *event; };
> +
> +int amdgpu_vkms_output_init(struct drm_device *dev,
> +                           struct amdgpu_vkms_output *output, int 
> +index);
> +
> +#endif /* _AMDGPU_VKMS_H_ */
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c 
> b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> index 7e0d8c092c7e..642c77533157 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> @@ -22,6 +22,7 @@
>   */
>
>  #include <drm/drm_vblank.h>
> +#include <drm/drm_atomic_helper.h>
>
>  #include "amdgpu.h"
>  #include "amdgpu_pm.h"
> @@ -40,6 +41,7 @@
>  #include "dce_virtual.h"
>  #include "ivsrcid/ivsrcid_vislands30.h"
>  #include "amdgpu_display.h"
> +#include "amdgpu_vkms.h"
>
>  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
>
> @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
>         .force = dce_virtual_force,
>  };
>
> +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> +       .fb_create = amdgpu_display_user_framebuffer_create,
> +       .atomic_check = drm_atomic_helper_check,
> +       .atomic_commit = drm_atomic_helper_commit, };
> +
>  static int dce_virtual_sw_init(void *handle)  {
>         int r, i;
> @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
>
>         adev_to_drm(adev)->max_vblank_count = 0;
>
> -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> +       adev_to_drm(adev)->mode_config.funcs = 
> + &dce_virtual_mode_funcs;
>
> -       adev_to_drm(adev)->mode_config.max_width = 16384;
> -       adev_to_drm(adev)->mode_config.max_height = 16384;
> +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
>
>         adev_to_drm(adev)->mode_config.preferred_depth = 24;
>         adev_to_drm(adev)->mode_config.prefer_shadow = 1; @@ -399,15 
> +407,11 @@ static int dce_virtual_sw_init(void *handle)
>         if (r)
>                 return r;
>
> -       adev_to_drm(adev)->mode_config.max_width = 16384;
> -       adev_to_drm(adev)->mode_config.max_height = 16384;
> +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct 
> + amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);

You can use kcalloc here.

>
>         /* allocate crtcs, encoders, connectors */
>         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> -               r = dce_virtual_crtc_init(adev, i);
> -               if (r)
> -                       return r;
> -               r = dce_virtual_connector_encoder_init(adev, i);
> +               r = amdgpu_vkms_output_init(adev_to_drm(adev), 
> + &adev->amdgpu_vkms_output[i], i);
>                 if (r)
>                         return r;
>         }
> @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
>                         
> hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
>
>         kfree(adev->mode_info.bios_hardcoded_edid);
> +       kfree(adev->amdgpu_vkms_output);
>
>         drm_kms_helper_poll_fini(adev_to_drm(adev));
>
> --
> 2.32.0
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flist
> s.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cgu
> chun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884
> e608e11a82d994e183d%7C0%7C0%7C637626475284480052%7CUnknown%7CTWFpbGZsb
> 3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%
> 7C1000&amp;sdata=0bbTKflaP2RPk%2BpboaNNiwffbEw1pW0zkqcxzPWjzmI%3D&amp;
> reserved=0
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cguchun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637626475284490043%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=VQ1liQG9OOsBA3NtjS93WNu6NhlLQ0fXQRbLwLmz95g%3D&amp;reserved=0
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
  2021-07-24  2:07       ` Chen, Guchun
@ 2021-07-26 16:21         ` Alex Deucher
  -1 siblings, 0 replies; 24+ messages in thread
From: Alex Deucher @ 2021-07-26 16:21 UTC (permalink / raw)
  To: Chen, Guchun
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo, Taylor,
	Ryan, amd-gfx list, Melissa Wen, Maling list - DRI developers

On Fri, Jul 23, 2021 at 10:07 PM Chen, Guchun <Guchun.Chen@amd.com> wrote:
>
> [Public]
>
> Look copy right statement is missed in both amdgpu_vkms.c and amdgpu_vkms.h.

It's there, it just uses the newer SPDX license identifier.

Alex


>
> Regards,
> Guchun
>
> -----Original Message-----
> From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Alex Deucher
> Sent: Friday, July 23, 2021 10:32 PM
> To: Taylor, Ryan <Ryan.Taylor@amd.com>
> Cc: kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
>
> On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
> >
> > Modify the VKMS driver into an api that dce_virtual can use to create
> > virtual displays that obey drm's atomic modesetting api.
> >
> > v2: Made local functions static.
> >
> > Reported-by: kernel test robot <lkp@intel.com>
> > Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> > ---
> >  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
> >  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411
> > +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |
> > 29 ++  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
> >  7 files changed, 458 insertions(+), 11 deletions(-)  create mode
> > 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> >  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile
> > b/drivers/gpu/drm/amd/amdgpu/Makefile
> > index f089794bbdd5..30cbcd5ce1cc 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> > +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> > @@ -120,6 +120,7 @@ amdgpu-y += \
> >  amdgpu-y += \
> >         dce_v10_0.o \
> >         dce_v11_0.o \
> > +       amdgpu_vkms.o \
> >         dce_virtual.o
> >
> >  # add GFX block
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > index 54cf647bd018..d0a2f2ed433d 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > @@ -919,6 +919,7 @@ struct amdgpu_device {
> >
> >         /* display */
> >         bool                            enable_virtual_display;
> > +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
> >         struct amdgpu_mode_info         mode_info;
> >         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
> >         struct work_struct              hotplug_work;
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > index d0c935cf4f0f..1b016e5bc75f 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
> >         int ret, retry = 0;
> >         bool supports_atomic = false;
> >
> > -       if (!amdgpu_virtual_display &&
> > +       if (amdgpu_virtual_display ||
> >             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
> >                 supports_atomic = true;
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > index 09b048647523..5a143ca02cf9 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
> >         }
> >
> >         /* disable all the possible outputs/crtcs before entering KMS mode */
> > -       if (!amdgpu_device_has_dc_support(adev))
> > +       if (!amdgpu_device_has_dc_support(adev) &&
> > + !amdgpu_virtual_display)
> >
> > drm_helper_disable_unused_functions(adev_to_drm(adev));
> >
> >         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); diff
> > --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > new file mode 100644
> > index 000000000000..d5c1f1c58f5f
> > --- /dev/null
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > @@ -0,0 +1,411 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h>
> > +
> > +#include "amdgpu.h"
> > +#include "amdgpu_vkms.h"
> > +#include "amdgpu_display.h"
> > +
> > +/**
> > + * DOC: amdgpu_vkms
> > + *
> > + * The amdgpu vkms interface provides a virtual KMS interface for
> > +several use
> > + * cases: devices without display hardware, platforms where the
> > +actual display
> > + * hardware is not useful (e.g., servers), SR-IOV virtual functions,
> > +device
> > + * emulation/simulation, and device bring up prior to display
> > +hardware being
> > + * usable. We previously emulated a legacy KMS interface, but there
> > +was a desire
> > + * to move to the atomic KMS interface. The vkms driver did
> > +everything we
> > + * needed, but we wanted KMS support natively in the driver without
> > +buffer
> > + * sharing and the ability to support an instance of VKMS per device.
> > +We first
> > + * looked at splitting vkms into a stub driver and a helper module
> > +that other
> > + * drivers could use to implement a virtual display, but this
> > +strategy ended up
> > + * being messy due to driver specific callbacks needed for buffer management.
> > + * Ultimately, it proved easier to import the vkms code as it mostly
> > +used core
> > + * drm helpers anyway.
> > + */
> > +
> > +static const u32 amdgpu_vkms_formats[] = {
> > +       DRM_FORMAT_XRGB8888,
> > +};
> > +
> > +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct
> > +hrtimer *timer) {
> > +       struct amdgpu_vkms_output *output = container_of(timer,
> > +                                                        struct amdgpu_vkms_output,
> > +                                                        vblank_hrtimer);
> > +       struct drm_crtc *crtc = &output->crtc;
> > +       u64 ret_overrun;
> > +       bool ret;
> > +
> > +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> > +                                         output->period_ns);
> > +       WARN_ON(ret_overrun != 1);
> > +
> > +       ret = drm_crtc_handle_vblank(crtc);
> > +       if (!ret)
> > +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> > +
> > +       return HRTIMER_RESTART;
> > +}
> > +
> > +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) {
> > +       struct drm_device *dev = crtc->dev;
> > +       unsigned int pipe = drm_crtc_index(crtc);
> > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > +       struct amdgpu_vkms_output *out =
> > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > +
> > +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> > +
> > +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> > +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> > +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> > +       hrtimer_start(&out->vblank_hrtimer, out->period_ns,
> > + HRTIMER_MODE_REL);
> > +
> > +       return 0;
> > +}
> > +
> > +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) {
> > +       struct amdgpu_vkms_output *out =
> > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > +
> > +       hrtimer_cancel(&out->vblank_hrtimer);
> > +}
> > +
> > +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> > +                                            int *max_error,
> > +                                            ktime_t *vblank_time,
> > +                                            bool in_vblank_irq) {
> > +       struct drm_device *dev = crtc->dev;
> > +       unsigned int pipe = crtc->index;
> > +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > +
> > +       if (!READ_ONCE(vblank->enabled)) {
> > +               *vblank_time = ktime_get();
> > +               return true;
> > +       }
> > +
> > +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> > +
> > +       if (WARN_ON(*vblank_time == vblank->time))
> > +               return true;
> > +
> > +       /*
> > +        * To prevent races we roll the hrtimer forward before we do any
> > +        * interrupt processing - this is how real hw works (the interrupt is
> > +        * only generated after all the vblank registers are updated) and what
> > +        * the vblank core expects. Therefore we need to always correct the
> > +        * timestampe by one frame.
> > +        */
> > +       *vblank_time -= output->period_ns;
> > +
> > +       return true;
> > +}
> > +
> > +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> > +       .set_config             = drm_atomic_helper_set_config,
> > +       .destroy                = drm_crtc_cleanup,
> > +       .page_flip              = drm_atomic_helper_page_flip,
> > +       .reset                  = drm_atomic_helper_crtc_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> > +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> > +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> > +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> > +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> > +};
> > +
> > +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> > +                                          struct drm_atomic_state
> > +*state) {
> > +       drm_crtc_vblank_on(crtc);
> > +}
> > +
> > +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> > +                                           struct drm_atomic_state
> > +*state) {
> > +       drm_crtc_vblank_off(crtc);
> > +}
> > +
> > +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> > +                                         struct drm_atomic_state
> > +*state) {
> > +       if (crtc->state->event) {
> > +               spin_lock(&crtc->dev->event_lock);
> > +
> > +               if (drm_crtc_vblank_get(crtc) != 0)
> > +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> > +               else
> > +                       drm_crtc_arm_vblank_event(crtc,
> > + crtc->state->event);
> > +
> > +               spin_unlock(&crtc->dev->event_lock);
> > +
> > +               crtc->state->event = NULL;
> > +       }
> > +}
> > +
> > +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> > +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> > +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> > +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable, };
> > +
> > +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> > +                         struct drm_plane *primary, struct drm_plane
> > +*cursor) {
> > +       int ret;
> > +
> > +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> > +                                       &amdgpu_vkms_crtc_funcs, NULL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init CRTC\n");
> > +               return ret;
> > +       }
> > +
> > +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> > +
> > +       return ret;
> > +}
> > +
> > +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> > +       .fill_modes = drm_helper_probe_single_connector_modes,
> > +       .destroy = drm_connector_cleanup,
> > +       .reset = drm_atomic_helper_connector_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> > +       .atomic_destroy_state =
> > +drm_atomic_helper_connector_destroy_state,
> > +};
> > +
> > +static int amdgpu_vkms_conn_get_modes(struct drm_connector
> > +*connector) {
> > +       int count;
> > +
> > +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> > +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> > +
> > +       return count;
> > +}
> > +
> > +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> > +       .get_modes    = amdgpu_vkms_conn_get_modes,
> > +};
> > +
> > +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> > +       .update_plane           = drm_atomic_helper_update_plane,
> > +       .disable_plane          = drm_atomic_helper_disable_plane,
> > +       .destroy                = drm_plane_cleanup,
> > +       .reset                  = drm_atomic_helper_plane_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> > +};
> > +
> > +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> > +                                           struct drm_plane_state
> > +*old_state) {
> > +       return;
> > +}
> > +
> > +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> > +                                         struct drm_plane_state
> > +*state) {
> > +       struct drm_crtc_state *crtc_state;
> > +       bool can_position = false;
> > +       int ret;
> > +
> > +       if (!state->fb || WARN_ON(!state->crtc))
> > +               return 0;
> > +
> > +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> > +       if (IS_ERR(crtc_state))
> > +               return PTR_ERR(crtc_state);
> > +
> > +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > +                                                 can_position, true);
> > +       if (ret != 0)
> > +               return ret;
> > +
> > +       /* for now primary plane must be visible and full screen */
> > +       if (!state->visible && !can_position)
> > +               return -EINVAL;
> > +
> > +       return 0;
> > +}
> > +
> > +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> > +                                 struct drm_plane_state *new_state) {
> > +       struct amdgpu_framebuffer *afb;
> > +       struct drm_gem_object *obj;
> > +       struct amdgpu_device *adev;
> > +       struct amdgpu_bo *rbo;
> > +       struct list_head list;
> > +       struct ttm_validate_buffer tv;
> > +       struct ww_acquire_ctx ticket;
> > +       uint32_t domain;
> > +       int r;
> > +
> > +       if (!new_state->fb) {
> > +               DRM_DEBUG_KMS("No FB bound\n");
> > +               return 0;
> > +       }
> > +       afb = to_amdgpu_framebuffer(new_state->fb);
> > +       obj = new_state->fb->obj[0];
> > +       rbo = gem_to_amdgpu_bo(obj);
> > +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> > +       INIT_LIST_HEAD(&list);
> > +
> > +       tv.bo = &rbo->tbo;
> > +       tv.num_shared = 1;
> > +       list_add(&tv.head, &list);
> > +
> > +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> > +       if (r) {
> > +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> > +               return r;
> > +       }
> > +
> > +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> > +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> > +       else
> > +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> > +
> > +       r = amdgpu_bo_pin(rbo, domain);
> > +       if (unlikely(r != 0)) {
> > +               if (r != -ERESTARTSYS)
> > +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> > +               ttm_eu_backoff_reservation(&ticket, &list);
> > +               return r;
> > +       }
> > +
> > +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> > +       if (unlikely(r != 0)) {
> > +               amdgpu_bo_unpin(rbo);
> > +               ttm_eu_backoff_reservation(&ticket, &list);
> > +               DRM_ERROR("%p bind failed\n", rbo);
> > +               return r;
> > +       }
> > +
> > +       ttm_eu_backoff_reservation(&ticket, &list);
> > +
> > +       afb->address = amdgpu_bo_gpu_offset(rbo);
> > +
> > +       amdgpu_bo_ref(rbo);
> > +
> > +       return 0;
> > +}
> > +
> > +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> > +                                  struct drm_plane_state *old_state)
> > +{
> > +       struct amdgpu_bo *rbo;
> > +       int r;
> > +
> > +       if (!old_state->fb)
> > +               return;
> > +
> > +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> > +       r = amdgpu_bo_reserve(rbo, false);
> > +       if (unlikely(r)) {
> > +               DRM_ERROR("failed to reserve rbo before unpin\n");
> > +               return;
> > +       }
> > +
> > +       amdgpu_bo_unpin(rbo);
> > +       amdgpu_bo_unreserve(rbo);
> > +       amdgpu_bo_unref(&rbo);
> > +}
> > +
> > +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> > +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> > +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> > +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> > +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> > +};
> > +
> > +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> > +                                               enum drm_plane_type type,
> > +                                               int index) {
> > +       struct drm_plane *plane;
> > +       int ret;
> > +
> > +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> > +       if (!plane)
> > +               return ERR_PTR(-ENOMEM);
> > +
> > +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> > +                                      &amdgpu_vkms_plane_funcs,
> > +                                      amdgpu_vkms_formats,
> > +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> > +                                      NULL, type, NULL);
> > +       if (ret) {
> > +               kfree(plane);
> > +               return ERR_PTR(ret);
> > +       }
> > +
> > +       drm_plane_helper_add(plane,
> > + &amdgpu_vkms_primary_helper_funcs);
> > +
> > +       return plane;
> > +}
> > +
> > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > +                           struct amdgpu_vkms_output *output, int
> > +index) {
> > +       struct drm_connector *connector = &output->connector;
> > +       struct drm_encoder *encoder = &output->encoder;
> > +       struct drm_crtc *crtc = &output->crtc;
> > +       struct drm_plane *primary, *cursor = NULL;
> > +       int ret;
> > +
> > +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> > +       if (IS_ERR(primary))
> > +               return PTR_ERR(primary);
> > +
> > +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> > +       if (ret)
> > +               goto err_crtc;
> > +
> > +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> > +                                DRM_MODE_CONNECTOR_VIRTUAL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init connector\n");
> > +               goto err_connector;
> > +       }
> > +
> > +       drm_connector_helper_add(connector,
> > + &amdgpu_vkms_conn_helper_funcs);
> > +
> > +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init encoder\n");
> > +               goto err_encoder;
> > +       }
> > +       encoder->possible_crtcs = 1 << index;
> > +
> > +       ret = drm_connector_attach_encoder(connector, encoder);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to attach connector to encoder\n");
> > +               goto err_attach;
> > +       }
> > +
> > +       drm_mode_config_reset(dev);
> > +
> > +       return 0;
> > +
> > +err_attach:
> > +       drm_encoder_cleanup(encoder);
> > +
> > +err_encoder:
> > +       drm_connector_cleanup(connector);
> > +
> > +err_connector:
> > +       drm_crtc_cleanup(crtc);
> > +
> > +err_crtc:
> > +       drm_plane_cleanup(primary);
> > +
> > +       return ret;
> > +}
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > new file mode 100644
> > index 000000000000..5dab51fbecf3
> > --- /dev/null
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > @@ -0,0 +1,29 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +
> > +#ifndef _AMDGPU_VKMS_H_
> > +#define _AMDGPU_VKMS_H_
> > +
> > +#define XRES_DEF  1024
> > +#define YRES_DEF   764
>
> Squash in the 768 fix here.
>
> > +
> > +#define XRES_MAX  16384
> > +#define YRES_MAX  16384
> > +
> > +#define drm_crtc_to_amdgpu_vkms_output(target) \
> > +       container_of(target, struct amdgpu_vkms_output, crtc)
> > +
> > +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> > +
> > +struct amdgpu_vkms_output {
> > +       struct drm_crtc crtc;
> > +       struct drm_encoder encoder;
> > +       struct drm_connector connector;
> > +       struct hrtimer vblank_hrtimer;
> > +       ktime_t period_ns;
> > +       struct drm_pending_vblank_event *event; };
> > +
> > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > +                           struct amdgpu_vkms_output *output, int
> > +index);
> > +
> > +#endif /* _AMDGPU_VKMS_H_ */
> > diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > index 7e0d8c092c7e..642c77533157 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > @@ -22,6 +22,7 @@
> >   */
> >
> >  #include <drm/drm_vblank.h>
> > +#include <drm/drm_atomic_helper.h>
> >
> >  #include "amdgpu.h"
> >  #include "amdgpu_pm.h"
> > @@ -40,6 +41,7 @@
> >  #include "dce_virtual.h"
> >  #include "ivsrcid/ivsrcid_vislands30.h"
> >  #include "amdgpu_display.h"
> > +#include "amdgpu_vkms.h"
> >
> >  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
> >
> > @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
> >         .force = dce_virtual_force,
> >  };
> >
> > +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> > +       .fb_create = amdgpu_display_user_framebuffer_create,
> > +       .atomic_check = drm_atomic_helper_check,
> > +       .atomic_commit = drm_atomic_helper_commit, };
> > +
> >  static int dce_virtual_sw_init(void *handle)  {
> >         int r, i;
> > @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
> >
> >         adev_to_drm(adev)->max_vblank_count = 0;
> >
> > -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> > +       adev_to_drm(adev)->mode_config.funcs =
> > + &dce_virtual_mode_funcs;
> >
> > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> > +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> >
> >         adev_to_drm(adev)->mode_config.preferred_depth = 24;
> >         adev_to_drm(adev)->mode_config.prefer_shadow = 1; @@ -399,15
> > +407,11 @@ static int dce_virtual_sw_init(void *handle)
> >         if (r)
> >                 return r;
> >
> > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct
> > + amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
>
> You can use kcalloc here.
>
> >
> >         /* allocate crtcs, encoders, connectors */
> >         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> > -               r = dce_virtual_crtc_init(adev, i);
> > -               if (r)
> > -                       return r;
> > -               r = dce_virtual_connector_encoder_init(adev, i);
> > +               r = amdgpu_vkms_output_init(adev_to_drm(adev),
> > + &adev->amdgpu_vkms_output[i], i);
> >                 if (r)
> >                         return r;
> >         }
> > @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
> >
> > hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> >
> >         kfree(adev->mode_info.bios_hardcoded_edid);
> > +       kfree(adev->amdgpu_vkms_output);
> >
> >         drm_kms_helper_poll_fini(adev_to_drm(adev));
> >
> > --
> > 2.32.0
> >
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flist
> > s.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cgu
> > chun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884
> > e608e11a82d994e183d%7C0%7C0%7C637626475284480052%7CUnknown%7CTWFpbGZsb
> > 3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%
> > 7C1000&amp;sdata=0bbTKflaP2RPk%2BpboaNNiwffbEw1pW0zkqcxzPWjzmI%3D&amp;
> > reserved=0
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cguchun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637626475284490043%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=VQ1liQG9OOsBA3NtjS93WNu6NhlLQ0fXQRbLwLmz95g%3D&amp;reserved=0

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

* Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
@ 2021-07-26 16:21         ` Alex Deucher
  0 siblings, 0 replies; 24+ messages in thread
From: Alex Deucher @ 2021-07-26 16:21 UTC (permalink / raw)
  To: Chen, Guchun
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo, Taylor,
	Ryan, amd-gfx list, Melissa Wen, Maling list - DRI developers

On Fri, Jul 23, 2021 at 10:07 PM Chen, Guchun <Guchun.Chen@amd.com> wrote:
>
> [Public]
>
> Look copy right statement is missed in both amdgpu_vkms.c and amdgpu_vkms.h.

It's there, it just uses the newer SPDX license identifier.

Alex


>
> Regards,
> Guchun
>
> -----Original Message-----
> From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Alex Deucher
> Sent: Friday, July 23, 2021 10:32 PM
> To: Taylor, Ryan <Ryan.Taylor@amd.com>
> Cc: kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
>
> On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
> >
> > Modify the VKMS driver into an api that dce_virtual can use to create
> > virtual displays that obey drm's atomic modesetting api.
> >
> > v2: Made local functions static.
> >
> > Reported-by: kernel test robot <lkp@intel.com>
> > Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> > ---
> >  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
> >  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411
> > +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |
> > 29 ++  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
> >  7 files changed, 458 insertions(+), 11 deletions(-)  create mode
> > 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> >  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile
> > b/drivers/gpu/drm/amd/amdgpu/Makefile
> > index f089794bbdd5..30cbcd5ce1cc 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> > +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> > @@ -120,6 +120,7 @@ amdgpu-y += \
> >  amdgpu-y += \
> >         dce_v10_0.o \
> >         dce_v11_0.o \
> > +       amdgpu_vkms.o \
> >         dce_virtual.o
> >
> >  # add GFX block
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > index 54cf647bd018..d0a2f2ed433d 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > @@ -919,6 +919,7 @@ struct amdgpu_device {
> >
> >         /* display */
> >         bool                            enable_virtual_display;
> > +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
> >         struct amdgpu_mode_info         mode_info;
> >         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
> >         struct work_struct              hotplug_work;
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > index d0c935cf4f0f..1b016e5bc75f 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
> >         int ret, retry = 0;
> >         bool supports_atomic = false;
> >
> > -       if (!amdgpu_virtual_display &&
> > +       if (amdgpu_virtual_display ||
> >             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
> >                 supports_atomic = true;
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > index 09b048647523..5a143ca02cf9 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
> >         }
> >
> >         /* disable all the possible outputs/crtcs before entering KMS mode */
> > -       if (!amdgpu_device_has_dc_support(adev))
> > +       if (!amdgpu_device_has_dc_support(adev) &&
> > + !amdgpu_virtual_display)
> >
> > drm_helper_disable_unused_functions(adev_to_drm(adev));
> >
> >         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); diff
> > --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > new file mode 100644
> > index 000000000000..d5c1f1c58f5f
> > --- /dev/null
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > @@ -0,0 +1,411 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h>
> > +
> > +#include "amdgpu.h"
> > +#include "amdgpu_vkms.h"
> > +#include "amdgpu_display.h"
> > +
> > +/**
> > + * DOC: amdgpu_vkms
> > + *
> > + * The amdgpu vkms interface provides a virtual KMS interface for
> > +several use
> > + * cases: devices without display hardware, platforms where the
> > +actual display
> > + * hardware is not useful (e.g., servers), SR-IOV virtual functions,
> > +device
> > + * emulation/simulation, and device bring up prior to display
> > +hardware being
> > + * usable. We previously emulated a legacy KMS interface, but there
> > +was a desire
> > + * to move to the atomic KMS interface. The vkms driver did
> > +everything we
> > + * needed, but we wanted KMS support natively in the driver without
> > +buffer
> > + * sharing and the ability to support an instance of VKMS per device.
> > +We first
> > + * looked at splitting vkms into a stub driver and a helper module
> > +that other
> > + * drivers could use to implement a virtual display, but this
> > +strategy ended up
> > + * being messy due to driver specific callbacks needed for buffer management.
> > + * Ultimately, it proved easier to import the vkms code as it mostly
> > +used core
> > + * drm helpers anyway.
> > + */
> > +
> > +static const u32 amdgpu_vkms_formats[] = {
> > +       DRM_FORMAT_XRGB8888,
> > +};
> > +
> > +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct
> > +hrtimer *timer) {
> > +       struct amdgpu_vkms_output *output = container_of(timer,
> > +                                                        struct amdgpu_vkms_output,
> > +                                                        vblank_hrtimer);
> > +       struct drm_crtc *crtc = &output->crtc;
> > +       u64 ret_overrun;
> > +       bool ret;
> > +
> > +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> > +                                         output->period_ns);
> > +       WARN_ON(ret_overrun != 1);
> > +
> > +       ret = drm_crtc_handle_vblank(crtc);
> > +       if (!ret)
> > +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> > +
> > +       return HRTIMER_RESTART;
> > +}
> > +
> > +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) {
> > +       struct drm_device *dev = crtc->dev;
> > +       unsigned int pipe = drm_crtc_index(crtc);
> > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > +       struct amdgpu_vkms_output *out =
> > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > +
> > +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> > +
> > +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> > +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> > +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> > +       hrtimer_start(&out->vblank_hrtimer, out->period_ns,
> > + HRTIMER_MODE_REL);
> > +
> > +       return 0;
> > +}
> > +
> > +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) {
> > +       struct amdgpu_vkms_output *out =
> > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > +
> > +       hrtimer_cancel(&out->vblank_hrtimer);
> > +}
> > +
> > +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> > +                                            int *max_error,
> > +                                            ktime_t *vblank_time,
> > +                                            bool in_vblank_irq) {
> > +       struct drm_device *dev = crtc->dev;
> > +       unsigned int pipe = crtc->index;
> > +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > +
> > +       if (!READ_ONCE(vblank->enabled)) {
> > +               *vblank_time = ktime_get();
> > +               return true;
> > +       }
> > +
> > +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> > +
> > +       if (WARN_ON(*vblank_time == vblank->time))
> > +               return true;
> > +
> > +       /*
> > +        * To prevent races we roll the hrtimer forward before we do any
> > +        * interrupt processing - this is how real hw works (the interrupt is
> > +        * only generated after all the vblank registers are updated) and what
> > +        * the vblank core expects. Therefore we need to always correct the
> > +        * timestampe by one frame.
> > +        */
> > +       *vblank_time -= output->period_ns;
> > +
> > +       return true;
> > +}
> > +
> > +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> > +       .set_config             = drm_atomic_helper_set_config,
> > +       .destroy                = drm_crtc_cleanup,
> > +       .page_flip              = drm_atomic_helper_page_flip,
> > +       .reset                  = drm_atomic_helper_crtc_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> > +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> > +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> > +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> > +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> > +};
> > +
> > +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> > +                                          struct drm_atomic_state
> > +*state) {
> > +       drm_crtc_vblank_on(crtc);
> > +}
> > +
> > +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> > +                                           struct drm_atomic_state
> > +*state) {
> > +       drm_crtc_vblank_off(crtc);
> > +}
> > +
> > +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> > +                                         struct drm_atomic_state
> > +*state) {
> > +       if (crtc->state->event) {
> > +               spin_lock(&crtc->dev->event_lock);
> > +
> > +               if (drm_crtc_vblank_get(crtc) != 0)
> > +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> > +               else
> > +                       drm_crtc_arm_vblank_event(crtc,
> > + crtc->state->event);
> > +
> > +               spin_unlock(&crtc->dev->event_lock);
> > +
> > +               crtc->state->event = NULL;
> > +       }
> > +}
> > +
> > +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> > +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> > +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> > +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable, };
> > +
> > +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> > +                         struct drm_plane *primary, struct drm_plane
> > +*cursor) {
> > +       int ret;
> > +
> > +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> > +                                       &amdgpu_vkms_crtc_funcs, NULL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init CRTC\n");
> > +               return ret;
> > +       }
> > +
> > +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> > +
> > +       return ret;
> > +}
> > +
> > +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> > +       .fill_modes = drm_helper_probe_single_connector_modes,
> > +       .destroy = drm_connector_cleanup,
> > +       .reset = drm_atomic_helper_connector_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> > +       .atomic_destroy_state =
> > +drm_atomic_helper_connector_destroy_state,
> > +};
> > +
> > +static int amdgpu_vkms_conn_get_modes(struct drm_connector
> > +*connector) {
> > +       int count;
> > +
> > +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> > +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> > +
> > +       return count;
> > +}
> > +
> > +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> > +       .get_modes    = amdgpu_vkms_conn_get_modes,
> > +};
> > +
> > +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> > +       .update_plane           = drm_atomic_helper_update_plane,
> > +       .disable_plane          = drm_atomic_helper_disable_plane,
> > +       .destroy                = drm_plane_cleanup,
> > +       .reset                  = drm_atomic_helper_plane_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> > +};
> > +
> > +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> > +                                           struct drm_plane_state
> > +*old_state) {
> > +       return;
> > +}
> > +
> > +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> > +                                         struct drm_plane_state
> > +*state) {
> > +       struct drm_crtc_state *crtc_state;
> > +       bool can_position = false;
> > +       int ret;
> > +
> > +       if (!state->fb || WARN_ON(!state->crtc))
> > +               return 0;
> > +
> > +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> > +       if (IS_ERR(crtc_state))
> > +               return PTR_ERR(crtc_state);
> > +
> > +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > +                                                 can_position, true);
> > +       if (ret != 0)
> > +               return ret;
> > +
> > +       /* for now primary plane must be visible and full screen */
> > +       if (!state->visible && !can_position)
> > +               return -EINVAL;
> > +
> > +       return 0;
> > +}
> > +
> > +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> > +                                 struct drm_plane_state *new_state) {
> > +       struct amdgpu_framebuffer *afb;
> > +       struct drm_gem_object *obj;
> > +       struct amdgpu_device *adev;
> > +       struct amdgpu_bo *rbo;
> > +       struct list_head list;
> > +       struct ttm_validate_buffer tv;
> > +       struct ww_acquire_ctx ticket;
> > +       uint32_t domain;
> > +       int r;
> > +
> > +       if (!new_state->fb) {
> > +               DRM_DEBUG_KMS("No FB bound\n");
> > +               return 0;
> > +       }
> > +       afb = to_amdgpu_framebuffer(new_state->fb);
> > +       obj = new_state->fb->obj[0];
> > +       rbo = gem_to_amdgpu_bo(obj);
> > +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> > +       INIT_LIST_HEAD(&list);
> > +
> > +       tv.bo = &rbo->tbo;
> > +       tv.num_shared = 1;
> > +       list_add(&tv.head, &list);
> > +
> > +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> > +       if (r) {
> > +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> > +               return r;
> > +       }
> > +
> > +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> > +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> > +       else
> > +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> > +
> > +       r = amdgpu_bo_pin(rbo, domain);
> > +       if (unlikely(r != 0)) {
> > +               if (r != -ERESTARTSYS)
> > +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> > +               ttm_eu_backoff_reservation(&ticket, &list);
> > +               return r;
> > +       }
> > +
> > +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> > +       if (unlikely(r != 0)) {
> > +               amdgpu_bo_unpin(rbo);
> > +               ttm_eu_backoff_reservation(&ticket, &list);
> > +               DRM_ERROR("%p bind failed\n", rbo);
> > +               return r;
> > +       }
> > +
> > +       ttm_eu_backoff_reservation(&ticket, &list);
> > +
> > +       afb->address = amdgpu_bo_gpu_offset(rbo);
> > +
> > +       amdgpu_bo_ref(rbo);
> > +
> > +       return 0;
> > +}
> > +
> > +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> > +                                  struct drm_plane_state *old_state)
> > +{
> > +       struct amdgpu_bo *rbo;
> > +       int r;
> > +
> > +       if (!old_state->fb)
> > +               return;
> > +
> > +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> > +       r = amdgpu_bo_reserve(rbo, false);
> > +       if (unlikely(r)) {
> > +               DRM_ERROR("failed to reserve rbo before unpin\n");
> > +               return;
> > +       }
> > +
> > +       amdgpu_bo_unpin(rbo);
> > +       amdgpu_bo_unreserve(rbo);
> > +       amdgpu_bo_unref(&rbo);
> > +}
> > +
> > +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> > +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> > +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> > +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> > +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> > +};
> > +
> > +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> > +                                               enum drm_plane_type type,
> > +                                               int index) {
> > +       struct drm_plane *plane;
> > +       int ret;
> > +
> > +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> > +       if (!plane)
> > +               return ERR_PTR(-ENOMEM);
> > +
> > +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> > +                                      &amdgpu_vkms_plane_funcs,
> > +                                      amdgpu_vkms_formats,
> > +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> > +                                      NULL, type, NULL);
> > +       if (ret) {
> > +               kfree(plane);
> > +               return ERR_PTR(ret);
> > +       }
> > +
> > +       drm_plane_helper_add(plane,
> > + &amdgpu_vkms_primary_helper_funcs);
> > +
> > +       return plane;
> > +}
> > +
> > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > +                           struct amdgpu_vkms_output *output, int
> > +index) {
> > +       struct drm_connector *connector = &output->connector;
> > +       struct drm_encoder *encoder = &output->encoder;
> > +       struct drm_crtc *crtc = &output->crtc;
> > +       struct drm_plane *primary, *cursor = NULL;
> > +       int ret;
> > +
> > +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> > +       if (IS_ERR(primary))
> > +               return PTR_ERR(primary);
> > +
> > +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> > +       if (ret)
> > +               goto err_crtc;
> > +
> > +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> > +                                DRM_MODE_CONNECTOR_VIRTUAL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init connector\n");
> > +               goto err_connector;
> > +       }
> > +
> > +       drm_connector_helper_add(connector,
> > + &amdgpu_vkms_conn_helper_funcs);
> > +
> > +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init encoder\n");
> > +               goto err_encoder;
> > +       }
> > +       encoder->possible_crtcs = 1 << index;
> > +
> > +       ret = drm_connector_attach_encoder(connector, encoder);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to attach connector to encoder\n");
> > +               goto err_attach;
> > +       }
> > +
> > +       drm_mode_config_reset(dev);
> > +
> > +       return 0;
> > +
> > +err_attach:
> > +       drm_encoder_cleanup(encoder);
> > +
> > +err_encoder:
> > +       drm_connector_cleanup(connector);
> > +
> > +err_connector:
> > +       drm_crtc_cleanup(crtc);
> > +
> > +err_crtc:
> > +       drm_plane_cleanup(primary);
> > +
> > +       return ret;
> > +}
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > new file mode 100644
> > index 000000000000..5dab51fbecf3
> > --- /dev/null
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > @@ -0,0 +1,29 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +
> > +#ifndef _AMDGPU_VKMS_H_
> > +#define _AMDGPU_VKMS_H_
> > +
> > +#define XRES_DEF  1024
> > +#define YRES_DEF   764
>
> Squash in the 768 fix here.
>
> > +
> > +#define XRES_MAX  16384
> > +#define YRES_MAX  16384
> > +
> > +#define drm_crtc_to_amdgpu_vkms_output(target) \
> > +       container_of(target, struct amdgpu_vkms_output, crtc)
> > +
> > +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> > +
> > +struct amdgpu_vkms_output {
> > +       struct drm_crtc crtc;
> > +       struct drm_encoder encoder;
> > +       struct drm_connector connector;
> > +       struct hrtimer vblank_hrtimer;
> > +       ktime_t period_ns;
> > +       struct drm_pending_vblank_event *event; };
> > +
> > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > +                           struct amdgpu_vkms_output *output, int
> > +index);
> > +
> > +#endif /* _AMDGPU_VKMS_H_ */
> > diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > index 7e0d8c092c7e..642c77533157 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > @@ -22,6 +22,7 @@
> >   */
> >
> >  #include <drm/drm_vblank.h>
> > +#include <drm/drm_atomic_helper.h>
> >
> >  #include "amdgpu.h"
> >  #include "amdgpu_pm.h"
> > @@ -40,6 +41,7 @@
> >  #include "dce_virtual.h"
> >  #include "ivsrcid/ivsrcid_vislands30.h"
> >  #include "amdgpu_display.h"
> > +#include "amdgpu_vkms.h"
> >
> >  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
> >
> > @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
> >         .force = dce_virtual_force,
> >  };
> >
> > +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> > +       .fb_create = amdgpu_display_user_framebuffer_create,
> > +       .atomic_check = drm_atomic_helper_check,
> > +       .atomic_commit = drm_atomic_helper_commit, };
> > +
> >  static int dce_virtual_sw_init(void *handle)  {
> >         int r, i;
> > @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
> >
> >         adev_to_drm(adev)->max_vblank_count = 0;
> >
> > -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> > +       adev_to_drm(adev)->mode_config.funcs =
> > + &dce_virtual_mode_funcs;
> >
> > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> > +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> >
> >         adev_to_drm(adev)->mode_config.preferred_depth = 24;
> >         adev_to_drm(adev)->mode_config.prefer_shadow = 1; @@ -399,15
> > +407,11 @@ static int dce_virtual_sw_init(void *handle)
> >         if (r)
> >                 return r;
> >
> > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct
> > + amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
>
> You can use kcalloc here.
>
> >
> >         /* allocate crtcs, encoders, connectors */
> >         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> > -               r = dce_virtual_crtc_init(adev, i);
> > -               if (r)
> > -                       return r;
> > -               r = dce_virtual_connector_encoder_init(adev, i);
> > +               r = amdgpu_vkms_output_init(adev_to_drm(adev),
> > + &adev->amdgpu_vkms_output[i], i);
> >                 if (r)
> >                         return r;
> >         }
> > @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
> >
> > hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> >
> >         kfree(adev->mode_info.bios_hardcoded_edid);
> > +       kfree(adev->amdgpu_vkms_output);
> >
> >         drm_kms_helper_poll_fini(adev_to_drm(adev));
> >
> > --
> > 2.32.0
> >
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flist
> > s.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cgu
> > chun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884
> > e608e11a82d994e183d%7C0%7C0%7C637626475284480052%7CUnknown%7CTWFpbGZsb
> > 3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%
> > 7C1000&amp;sdata=0bbTKflaP2RPk%2BpboaNNiwffbEw1pW0zkqcxzPWjzmI%3D&amp;
> > reserved=0
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cguchun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637626475284490043%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=VQ1liQG9OOsBA3NtjS93WNu6NhlLQ0fXQRbLwLmz95g%3D&amp;reserved=0
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
  2021-07-26 16:21         ` Alex Deucher
@ 2021-07-26 16:39           ` Taylor, Ryan
  -1 siblings, 0 replies; 24+ messages in thread
From: Taylor, Ryan @ 2021-07-26 16:39 UTC (permalink / raw)
  To: Alex Deucher, Chen, Guchun
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo,
	Maling list - DRI developers, Melissa Wen, amd-gfx list

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

[AMD Official Use Only]

Given that amdgpu_vkms contains code from both dce_virtual and vkms should the identifier be changed to GPL-2.0+ OR MIT like in amdgpu_res_cursor.h?

Best,
Ryan
________________________________
From: Alex Deucher <alexdeucher@gmail.com>
Sent: Monday, July 26, 2021 9:21 AM
To: Chen, Guchun <Guchun.Chen@amd.com>
Cc: Taylor, Ryan <Ryan.Taylor@amd.com>; kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)

On Fri, Jul 23, 2021 at 10:07 PM Chen, Guchun <Guchun.Chen@amd.com> wrote:
>
> [Public]
>
> Look copy right statement is missed in both amdgpu_vkms.c and amdgpu_vkms.h.

It's there, it just uses the newer SPDX license identifier.

Alex


>
> Regards,
> Guchun
>
> -----Original Message-----
> From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Alex Deucher
> Sent: Friday, July 23, 2021 10:32 PM
> To: Taylor, Ryan <Ryan.Taylor@amd.com>
> Cc: kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
>
> On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
> >
> > Modify the VKMS driver into an api that dce_virtual can use to create
> > virtual displays that obey drm's atomic modesetting api.
> >
> > v2: Made local functions static.
> >
> > Reported-by: kernel test robot <lkp@intel.com>
> > Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> > ---
> >  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
> >  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411
> > +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |
> > 29 ++  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
> >  7 files changed, 458 insertions(+), 11 deletions(-)  create mode
> > 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> >  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile
> > b/drivers/gpu/drm/amd/amdgpu/Makefile
> > index f089794bbdd5..30cbcd5ce1cc 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> > +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> > @@ -120,6 +120,7 @@ amdgpu-y += \
> >  amdgpu-y += \
> >         dce_v10_0.o \
> >         dce_v11_0.o \
> > +       amdgpu_vkms.o \
> >         dce_virtual.o
> >
> >  # add GFX block
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > index 54cf647bd018..d0a2f2ed433d 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > @@ -919,6 +919,7 @@ struct amdgpu_device {
> >
> >         /* display */
> >         bool                            enable_virtual_display;
> > +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
> >         struct amdgpu_mode_info         mode_info;
> >         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
> >         struct work_struct              hotplug_work;
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > index d0c935cf4f0f..1b016e5bc75f 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
> >         int ret, retry = 0;
> >         bool supports_atomic = false;
> >
> > -       if (!amdgpu_virtual_display &&
> > +       if (amdgpu_virtual_display ||
> >             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
> >                 supports_atomic = true;
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > index 09b048647523..5a143ca02cf9 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
> >         }
> >
> >         /* disable all the possible outputs/crtcs before entering KMS mode */
> > -       if (!amdgpu_device_has_dc_support(adev))
> > +       if (!amdgpu_device_has_dc_support(adev) &&
> > + !amdgpu_virtual_display)
> >
> > drm_helper_disable_unused_functions(adev_to_drm(adev));
> >
> >         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); diff
> > --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > new file mode 100644
> > index 000000000000..d5c1f1c58f5f
> > --- /dev/null
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > @@ -0,0 +1,411 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h>
> > +
> > +#include "amdgpu.h"
> > +#include "amdgpu_vkms.h"
> > +#include "amdgpu_display.h"
> > +
> > +/**
> > + * DOC: amdgpu_vkms
> > + *
> > + * The amdgpu vkms interface provides a virtual KMS interface for
> > +several use
> > + * cases: devices without display hardware, platforms where the
> > +actual display
> > + * hardware is not useful (e.g., servers), SR-IOV virtual functions,
> > +device
> > + * emulation/simulation, and device bring up prior to display
> > +hardware being
> > + * usable. We previously emulated a legacy KMS interface, but there
> > +was a desire
> > + * to move to the atomic KMS interface. The vkms driver did
> > +everything we
> > + * needed, but we wanted KMS support natively in the driver without
> > +buffer
> > + * sharing and the ability to support an instance of VKMS per device.
> > +We first
> > + * looked at splitting vkms into a stub driver and a helper module
> > +that other
> > + * drivers could use to implement a virtual display, but this
> > +strategy ended up
> > + * being messy due to driver specific callbacks needed for buffer management.
> > + * Ultimately, it proved easier to import the vkms code as it mostly
> > +used core
> > + * drm helpers anyway.
> > + */
> > +
> > +static const u32 amdgpu_vkms_formats[] = {
> > +       DRM_FORMAT_XRGB8888,
> > +};
> > +
> > +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct
> > +hrtimer *timer) {
> > +       struct amdgpu_vkms_output *output = container_of(timer,
> > +                                                        struct amdgpu_vkms_output,
> > +                                                        vblank_hrtimer);
> > +       struct drm_crtc *crtc = &output->crtc;
> > +       u64 ret_overrun;
> > +       bool ret;
> > +
> > +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> > +                                         output->period_ns);
> > +       WARN_ON(ret_overrun != 1);
> > +
> > +       ret = drm_crtc_handle_vblank(crtc);
> > +       if (!ret)
> > +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> > +
> > +       return HRTIMER_RESTART;
> > +}
> > +
> > +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) {
> > +       struct drm_device *dev = crtc->dev;
> > +       unsigned int pipe = drm_crtc_index(crtc);
> > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > +       struct amdgpu_vkms_output *out =
> > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > +
> > +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> > +
> > +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> > +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> > +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> > +       hrtimer_start(&out->vblank_hrtimer, out->period_ns,
> > + HRTIMER_MODE_REL);
> > +
> > +       return 0;
> > +}
> > +
> > +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) {
> > +       struct amdgpu_vkms_output *out =
> > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > +
> > +       hrtimer_cancel(&out->vblank_hrtimer);
> > +}
> > +
> > +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> > +                                            int *max_error,
> > +                                            ktime_t *vblank_time,
> > +                                            bool in_vblank_irq) {
> > +       struct drm_device *dev = crtc->dev;
> > +       unsigned int pipe = crtc->index;
> > +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > +
> > +       if (!READ_ONCE(vblank->enabled)) {
> > +               *vblank_time = ktime_get();
> > +               return true;
> > +       }
> > +
> > +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> > +
> > +       if (WARN_ON(*vblank_time == vblank->time))
> > +               return true;
> > +
> > +       /*
> > +        * To prevent races we roll the hrtimer forward before we do any
> > +        * interrupt processing - this is how real hw works (the interrupt is
> > +        * only generated after all the vblank registers are updated) and what
> > +        * the vblank core expects. Therefore we need to always correct the
> > +        * timestampe by one frame.
> > +        */
> > +       *vblank_time -= output->period_ns;
> > +
> > +       return true;
> > +}
> > +
> > +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> > +       .set_config             = drm_atomic_helper_set_config,
> > +       .destroy                = drm_crtc_cleanup,
> > +       .page_flip              = drm_atomic_helper_page_flip,
> > +       .reset                  = drm_atomic_helper_crtc_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> > +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> > +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> > +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> > +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> > +};
> > +
> > +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> > +                                          struct drm_atomic_state
> > +*state) {
> > +       drm_crtc_vblank_on(crtc);
> > +}
> > +
> > +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> > +                                           struct drm_atomic_state
> > +*state) {
> > +       drm_crtc_vblank_off(crtc);
> > +}
> > +
> > +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> > +                                         struct drm_atomic_state
> > +*state) {
> > +       if (crtc->state->event) {
> > +               spin_lock(&crtc->dev->event_lock);
> > +
> > +               if (drm_crtc_vblank_get(crtc) != 0)
> > +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> > +               else
> > +                       drm_crtc_arm_vblank_event(crtc,
> > + crtc->state->event);
> > +
> > +               spin_unlock(&crtc->dev->event_lock);
> > +
> > +               crtc->state->event = NULL;
> > +       }
> > +}
> > +
> > +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> > +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> > +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> > +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable, };
> > +
> > +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> > +                         struct drm_plane *primary, struct drm_plane
> > +*cursor) {
> > +       int ret;
> > +
> > +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> > +                                       &amdgpu_vkms_crtc_funcs, NULL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init CRTC\n");
> > +               return ret;
> > +       }
> > +
> > +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> > +
> > +       return ret;
> > +}
> > +
> > +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> > +       .fill_modes = drm_helper_probe_single_connector_modes,
> > +       .destroy = drm_connector_cleanup,
> > +       .reset = drm_atomic_helper_connector_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> > +       .atomic_destroy_state =
> > +drm_atomic_helper_connector_destroy_state,
> > +};
> > +
> > +static int amdgpu_vkms_conn_get_modes(struct drm_connector
> > +*connector) {
> > +       int count;
> > +
> > +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> > +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> > +
> > +       return count;
> > +}
> > +
> > +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> > +       .get_modes    = amdgpu_vkms_conn_get_modes,
> > +};
> > +
> > +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> > +       .update_plane           = drm_atomic_helper_update_plane,
> > +       .disable_plane          = drm_atomic_helper_disable_plane,
> > +       .destroy                = drm_plane_cleanup,
> > +       .reset                  = drm_atomic_helper_plane_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> > +};
> > +
> > +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> > +                                           struct drm_plane_state
> > +*old_state) {
> > +       return;
> > +}
> > +
> > +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> > +                                         struct drm_plane_state
> > +*state) {
> > +       struct drm_crtc_state *crtc_state;
> > +       bool can_position = false;
> > +       int ret;
> > +
> > +       if (!state->fb || WARN_ON(!state->crtc))
> > +               return 0;
> > +
> > +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> > +       if (IS_ERR(crtc_state))
> > +               return PTR_ERR(crtc_state);
> > +
> > +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > +                                                 can_position, true);
> > +       if (ret != 0)
> > +               return ret;
> > +
> > +       /* for now primary plane must be visible and full screen */
> > +       if (!state->visible && !can_position)
> > +               return -EINVAL;
> > +
> > +       return 0;
> > +}
> > +
> > +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> > +                                 struct drm_plane_state *new_state) {
> > +       struct amdgpu_framebuffer *afb;
> > +       struct drm_gem_object *obj;
> > +       struct amdgpu_device *adev;
> > +       struct amdgpu_bo *rbo;
> > +       struct list_head list;
> > +       struct ttm_validate_buffer tv;
> > +       struct ww_acquire_ctx ticket;
> > +       uint32_t domain;
> > +       int r;
> > +
> > +       if (!new_state->fb) {
> > +               DRM_DEBUG_KMS("No FB bound\n");
> > +               return 0;
> > +       }
> > +       afb = to_amdgpu_framebuffer(new_state->fb);
> > +       obj = new_state->fb->obj[0];
> > +       rbo = gem_to_amdgpu_bo(obj);
> > +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> > +       INIT_LIST_HEAD(&list);
> > +
> > +       tv.bo = &rbo->tbo;
> > +       tv.num_shared = 1;
> > +       list_add(&tv.head, &list);
> > +
> > +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> > +       if (r) {
> > +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> > +               return r;
> > +       }
> > +
> > +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> > +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> > +       else
> > +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> > +
> > +       r = amdgpu_bo_pin(rbo, domain);
> > +       if (unlikely(r != 0)) {
> > +               if (r != -ERESTARTSYS)
> > +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> > +               ttm_eu_backoff_reservation(&ticket, &list);
> > +               return r;
> > +       }
> > +
> > +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> > +       if (unlikely(r != 0)) {
> > +               amdgpu_bo_unpin(rbo);
> > +               ttm_eu_backoff_reservation(&ticket, &list);
> > +               DRM_ERROR("%p bind failed\n", rbo);
> > +               return r;
> > +       }
> > +
> > +       ttm_eu_backoff_reservation(&ticket, &list);
> > +
> > +       afb->address = amdgpu_bo_gpu_offset(rbo);
> > +
> > +       amdgpu_bo_ref(rbo);
> > +
> > +       return 0;
> > +}
> > +
> > +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> > +                                  struct drm_plane_state *old_state)
> > +{
> > +       struct amdgpu_bo *rbo;
> > +       int r;
> > +
> > +       if (!old_state->fb)
> > +               return;
> > +
> > +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> > +       r = amdgpu_bo_reserve(rbo, false);
> > +       if (unlikely(r)) {
> > +               DRM_ERROR("failed to reserve rbo before unpin\n");
> > +               return;
> > +       }
> > +
> > +       amdgpu_bo_unpin(rbo);
> > +       amdgpu_bo_unreserve(rbo);
> > +       amdgpu_bo_unref(&rbo);
> > +}
> > +
> > +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> > +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> > +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> > +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> > +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> > +};
> > +
> > +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> > +                                               enum drm_plane_type type,
> > +                                               int index) {
> > +       struct drm_plane *plane;
> > +       int ret;
> > +
> > +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> > +       if (!plane)
> > +               return ERR_PTR(-ENOMEM);
> > +
> > +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> > +                                      &amdgpu_vkms_plane_funcs,
> > +                                      amdgpu_vkms_formats,
> > +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> > +                                      NULL, type, NULL);
> > +       if (ret) {
> > +               kfree(plane);
> > +               return ERR_PTR(ret);
> > +       }
> > +
> > +       drm_plane_helper_add(plane,
> > + &amdgpu_vkms_primary_helper_funcs);
> > +
> > +       return plane;
> > +}
> > +
> > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > +                           struct amdgpu_vkms_output *output, int
> > +index) {
> > +       struct drm_connector *connector = &output->connector;
> > +       struct drm_encoder *encoder = &output->encoder;
> > +       struct drm_crtc *crtc = &output->crtc;
> > +       struct drm_plane *primary, *cursor = NULL;
> > +       int ret;
> > +
> > +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> > +       if (IS_ERR(primary))
> > +               return PTR_ERR(primary);
> > +
> > +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> > +       if (ret)
> > +               goto err_crtc;
> > +
> > +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> > +                                DRM_MODE_CONNECTOR_VIRTUAL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init connector\n");
> > +               goto err_connector;
> > +       }
> > +
> > +       drm_connector_helper_add(connector,
> > + &amdgpu_vkms_conn_helper_funcs);
> > +
> > +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init encoder\n");
> > +               goto err_encoder;
> > +       }
> > +       encoder->possible_crtcs = 1 << index;
> > +
> > +       ret = drm_connector_attach_encoder(connector, encoder);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to attach connector to encoder\n");
> > +               goto err_attach;
> > +       }
> > +
> > +       drm_mode_config_reset(dev);
> > +
> > +       return 0;
> > +
> > +err_attach:
> > +       drm_encoder_cleanup(encoder);
> > +
> > +err_encoder:
> > +       drm_connector_cleanup(connector);
> > +
> > +err_connector:
> > +       drm_crtc_cleanup(crtc);
> > +
> > +err_crtc:
> > +       drm_plane_cleanup(primary);
> > +
> > +       return ret;
> > +}
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > new file mode 100644
> > index 000000000000..5dab51fbecf3
> > --- /dev/null
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > @@ -0,0 +1,29 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +
> > +#ifndef _AMDGPU_VKMS_H_
> > +#define _AMDGPU_VKMS_H_
> > +
> > +#define XRES_DEF  1024
> > +#define YRES_DEF   764
>
> Squash in the 768 fix here.
>
> > +
> > +#define XRES_MAX  16384
> > +#define YRES_MAX  16384
> > +
> > +#define drm_crtc_to_amdgpu_vkms_output(target) \
> > +       container_of(target, struct amdgpu_vkms_output, crtc)
> > +
> > +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> > +
> > +struct amdgpu_vkms_output {
> > +       struct drm_crtc crtc;
> > +       struct drm_encoder encoder;
> > +       struct drm_connector connector;
> > +       struct hrtimer vblank_hrtimer;
> > +       ktime_t period_ns;
> > +       struct drm_pending_vblank_event *event; };
> > +
> > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > +                           struct amdgpu_vkms_output *output, int
> > +index);
> > +
> > +#endif /* _AMDGPU_VKMS_H_ */
> > diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > index 7e0d8c092c7e..642c77533157 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > @@ -22,6 +22,7 @@
> >   */
> >
> >  #include <drm/drm_vblank.h>
> > +#include <drm/drm_atomic_helper.h>
> >
> >  #include "amdgpu.h"
> >  #include "amdgpu_pm.h"
> > @@ -40,6 +41,7 @@
> >  #include "dce_virtual.h"
> >  #include "ivsrcid/ivsrcid_vislands30.h"
> >  #include "amdgpu_display.h"
> > +#include "amdgpu_vkms.h"
> >
> >  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
> >
> > @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
> >         .force = dce_virtual_force,
> >  };
> >
> > +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> > +       .fb_create = amdgpu_display_user_framebuffer_create,
> > +       .atomic_check = drm_atomic_helper_check,
> > +       .atomic_commit = drm_atomic_helper_commit, };
> > +
> >  static int dce_virtual_sw_init(void *handle)  {
> >         int r, i;
> > @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
> >
> >         adev_to_drm(adev)->max_vblank_count = 0;
> >
> > -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> > +       adev_to_drm(adev)->mode_config.funcs =
> > + &dce_virtual_mode_funcs;
> >
> > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> > +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> >
> >         adev_to_drm(adev)->mode_config.preferred_depth = 24;
> >         adev_to_drm(adev)->mode_config.prefer_shadow = 1; @@ -399,15
> > +407,11 @@ static int dce_virtual_sw_init(void *handle)
> >         if (r)
> >                 return r;
> >
> > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct
> > + amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
>
> You can use kcalloc here.
>
> >
> >         /* allocate crtcs, encoders, connectors */
> >         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> > -               r = dce_virtual_crtc_init(adev, i);
> > -               if (r)
> > -                       return r;
> > -               r = dce_virtual_connector_encoder_init(adev, i);
> > +               r = amdgpu_vkms_output_init(adev_to_drm(adev),
> > + &adev->amdgpu_vkms_output[i], i);
> >                 if (r)
> >                         return r;
> >         }
> > @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
> >
> > hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> >
> >         kfree(adev->mode_info.bios_hardcoded_edid);
> > +       kfree(adev->amdgpu_vkms_output);
> >
> >         drm_kms_helper_poll_fini(adev_to_drm(adev));
> >
> > --
> > 2.32.0
> >
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flist
> > s.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cgu
> > chun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884
> > e608e11a82d994e183d%7C0%7C0%7C637626475284480052%7CUnknown%7CTWFpbGZsb
> > 3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%
> > 7C1000&amp;sdata=0bbTKflaP2RPk%2BpboaNNiwffbEw1pW0zkqcxzPWjzmI%3D&amp;
> > reserved=0
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7CRyan.Taylor%40amd.com%7Ce0a16eb27da04a035cb608d950516493%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637629133975706919%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=KCe92Ic79b8lkS6h4GoZhRdhwehzleQrSH8OKlinX8I%3D&amp;reserved=0

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

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

* Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
@ 2021-07-26 16:39           ` Taylor, Ryan
  0 siblings, 0 replies; 24+ messages in thread
From: Taylor, Ryan @ 2021-07-26 16:39 UTC (permalink / raw)
  To: Alex Deucher, Chen, Guchun
  Cc: kernel test robot, Daniel Vetter, Siqueira, Rodrigo,
	Maling list - DRI developers, Melissa Wen, amd-gfx list


[-- Attachment #1.1: Type: text/plain, Size: 27144 bytes --]

[AMD Official Use Only]

Given that amdgpu_vkms contains code from both dce_virtual and vkms should the identifier be changed to GPL-2.0+ OR MIT like in amdgpu_res_cursor.h?

Best,
Ryan
________________________________
From: Alex Deucher <alexdeucher@gmail.com>
Sent: Monday, July 26, 2021 9:21 AM
To: Chen, Guchun <Guchun.Chen@amd.com>
Cc: Taylor, Ryan <Ryan.Taylor@amd.com>; kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)

On Fri, Jul 23, 2021 at 10:07 PM Chen, Guchun <Guchun.Chen@amd.com> wrote:
>
> [Public]
>
> Look copy right statement is missed in both amdgpu_vkms.c and amdgpu_vkms.h.

It's there, it just uses the newer SPDX license identifier.

Alex


>
> Regards,
> Guchun
>
> -----Original Message-----
> From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Alex Deucher
> Sent: Friday, July 23, 2021 10:32 PM
> To: Taylor, Ryan <Ryan.Taylor@amd.com>
> Cc: kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
>
> On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
> >
> > Modify the VKMS driver into an api that dce_virtual can use to create
> > virtual displays that obey drm's atomic modesetting api.
> >
> > v2: Made local functions static.
> >
> > Reported-by: kernel test robot <lkp@intel.com>
> > Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> > ---
> >  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
> >  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411
> > +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |
> > 29 ++  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
> >  7 files changed, 458 insertions(+), 11 deletions(-)  create mode
> > 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> >  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile
> > b/drivers/gpu/drm/amd/amdgpu/Makefile
> > index f089794bbdd5..30cbcd5ce1cc 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> > +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> > @@ -120,6 +120,7 @@ amdgpu-y += \
> >  amdgpu-y += \
> >         dce_v10_0.o \
> >         dce_v11_0.o \
> > +       amdgpu_vkms.o \
> >         dce_virtual.o
> >
> >  # add GFX block
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > index 54cf647bd018..d0a2f2ed433d 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > @@ -919,6 +919,7 @@ struct amdgpu_device {
> >
> >         /* display */
> >         bool                            enable_virtual_display;
> > +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
> >         struct amdgpu_mode_info         mode_info;
> >         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
> >         struct work_struct              hotplug_work;
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > index d0c935cf4f0f..1b016e5bc75f 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
> >         int ret, retry = 0;
> >         bool supports_atomic = false;
> >
> > -       if (!amdgpu_virtual_display &&
> > +       if (amdgpu_virtual_display ||
> >             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
> >                 supports_atomic = true;
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > index 09b048647523..5a143ca02cf9 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
> >         }
> >
> >         /* disable all the possible outputs/crtcs before entering KMS mode */
> > -       if (!amdgpu_device_has_dc_support(adev))
> > +       if (!amdgpu_device_has_dc_support(adev) &&
> > + !amdgpu_virtual_display)
> >
> > drm_helper_disable_unused_functions(adev_to_drm(adev));
> >
> >         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); diff
> > --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > new file mode 100644
> > index 000000000000..d5c1f1c58f5f
> > --- /dev/null
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > @@ -0,0 +1,411 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +
> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h>
> > +
> > +#include "amdgpu.h"
> > +#include "amdgpu_vkms.h"
> > +#include "amdgpu_display.h"
> > +
> > +/**
> > + * DOC: amdgpu_vkms
> > + *
> > + * The amdgpu vkms interface provides a virtual KMS interface for
> > +several use
> > + * cases: devices without display hardware, platforms where the
> > +actual display
> > + * hardware is not useful (e.g., servers), SR-IOV virtual functions,
> > +device
> > + * emulation/simulation, and device bring up prior to display
> > +hardware being
> > + * usable. We previously emulated a legacy KMS interface, but there
> > +was a desire
> > + * to move to the atomic KMS interface. The vkms driver did
> > +everything we
> > + * needed, but we wanted KMS support natively in the driver without
> > +buffer
> > + * sharing and the ability to support an instance of VKMS per device.
> > +We first
> > + * looked at splitting vkms into a stub driver and a helper module
> > +that other
> > + * drivers could use to implement a virtual display, but this
> > +strategy ended up
> > + * being messy due to driver specific callbacks needed for buffer management.
> > + * Ultimately, it proved easier to import the vkms code as it mostly
> > +used core
> > + * drm helpers anyway.
> > + */
> > +
> > +static const u32 amdgpu_vkms_formats[] = {
> > +       DRM_FORMAT_XRGB8888,
> > +};
> > +
> > +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct
> > +hrtimer *timer) {
> > +       struct amdgpu_vkms_output *output = container_of(timer,
> > +                                                        struct amdgpu_vkms_output,
> > +                                                        vblank_hrtimer);
> > +       struct drm_crtc *crtc = &output->crtc;
> > +       u64 ret_overrun;
> > +       bool ret;
> > +
> > +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> > +                                         output->period_ns);
> > +       WARN_ON(ret_overrun != 1);
> > +
> > +       ret = drm_crtc_handle_vblank(crtc);
> > +       if (!ret)
> > +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> > +
> > +       return HRTIMER_RESTART;
> > +}
> > +
> > +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) {
> > +       struct drm_device *dev = crtc->dev;
> > +       unsigned int pipe = drm_crtc_index(crtc);
> > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > +       struct amdgpu_vkms_output *out =
> > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > +
> > +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> > +
> > +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> > +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> > +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> > +       hrtimer_start(&out->vblank_hrtimer, out->period_ns,
> > + HRTIMER_MODE_REL);
> > +
> > +       return 0;
> > +}
> > +
> > +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) {
> > +       struct amdgpu_vkms_output *out =
> > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > +
> > +       hrtimer_cancel(&out->vblank_hrtimer);
> > +}
> > +
> > +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> > +                                            int *max_error,
> > +                                            ktime_t *vblank_time,
> > +                                            bool in_vblank_irq) {
> > +       struct drm_device *dev = crtc->dev;
> > +       unsigned int pipe = crtc->index;
> > +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > +
> > +       if (!READ_ONCE(vblank->enabled)) {
> > +               *vblank_time = ktime_get();
> > +               return true;
> > +       }
> > +
> > +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> > +
> > +       if (WARN_ON(*vblank_time == vblank->time))
> > +               return true;
> > +
> > +       /*
> > +        * To prevent races we roll the hrtimer forward before we do any
> > +        * interrupt processing - this is how real hw works (the interrupt is
> > +        * only generated after all the vblank registers are updated) and what
> > +        * the vblank core expects. Therefore we need to always correct the
> > +        * timestampe by one frame.
> > +        */
> > +       *vblank_time -= output->period_ns;
> > +
> > +       return true;
> > +}
> > +
> > +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> > +       .set_config             = drm_atomic_helper_set_config,
> > +       .destroy                = drm_crtc_cleanup,
> > +       .page_flip              = drm_atomic_helper_page_flip,
> > +       .reset                  = drm_atomic_helper_crtc_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> > +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> > +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> > +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> > +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> > +};
> > +
> > +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> > +                                          struct drm_atomic_state
> > +*state) {
> > +       drm_crtc_vblank_on(crtc);
> > +}
> > +
> > +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> > +                                           struct drm_atomic_state
> > +*state) {
> > +       drm_crtc_vblank_off(crtc);
> > +}
> > +
> > +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> > +                                         struct drm_atomic_state
> > +*state) {
> > +       if (crtc->state->event) {
> > +               spin_lock(&crtc->dev->event_lock);
> > +
> > +               if (drm_crtc_vblank_get(crtc) != 0)
> > +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> > +               else
> > +                       drm_crtc_arm_vblank_event(crtc,
> > + crtc->state->event);
> > +
> > +               spin_unlock(&crtc->dev->event_lock);
> > +
> > +               crtc->state->event = NULL;
> > +       }
> > +}
> > +
> > +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> > +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> > +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> > +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable, };
> > +
> > +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> > +                         struct drm_plane *primary, struct drm_plane
> > +*cursor) {
> > +       int ret;
> > +
> > +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> > +                                       &amdgpu_vkms_crtc_funcs, NULL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init CRTC\n");
> > +               return ret;
> > +       }
> > +
> > +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> > +
> > +       return ret;
> > +}
> > +
> > +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> > +       .fill_modes = drm_helper_probe_single_connector_modes,
> > +       .destroy = drm_connector_cleanup,
> > +       .reset = drm_atomic_helper_connector_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> > +       .atomic_destroy_state =
> > +drm_atomic_helper_connector_destroy_state,
> > +};
> > +
> > +static int amdgpu_vkms_conn_get_modes(struct drm_connector
> > +*connector) {
> > +       int count;
> > +
> > +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> > +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> > +
> > +       return count;
> > +}
> > +
> > +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> > +       .get_modes    = amdgpu_vkms_conn_get_modes,
> > +};
> > +
> > +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> > +       .update_plane           = drm_atomic_helper_update_plane,
> > +       .disable_plane          = drm_atomic_helper_disable_plane,
> > +       .destroy                = drm_plane_cleanup,
> > +       .reset                  = drm_atomic_helper_plane_reset,
> > +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> > +};
> > +
> > +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> > +                                           struct drm_plane_state
> > +*old_state) {
> > +       return;
> > +}
> > +
> > +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> > +                                         struct drm_plane_state
> > +*state) {
> > +       struct drm_crtc_state *crtc_state;
> > +       bool can_position = false;
> > +       int ret;
> > +
> > +       if (!state->fb || WARN_ON(!state->crtc))
> > +               return 0;
> > +
> > +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> > +       if (IS_ERR(crtc_state))
> > +               return PTR_ERR(crtc_state);
> > +
> > +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > +                                                 can_position, true);
> > +       if (ret != 0)
> > +               return ret;
> > +
> > +       /* for now primary plane must be visible and full screen */
> > +       if (!state->visible && !can_position)
> > +               return -EINVAL;
> > +
> > +       return 0;
> > +}
> > +
> > +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> > +                                 struct drm_plane_state *new_state) {
> > +       struct amdgpu_framebuffer *afb;
> > +       struct drm_gem_object *obj;
> > +       struct amdgpu_device *adev;
> > +       struct amdgpu_bo *rbo;
> > +       struct list_head list;
> > +       struct ttm_validate_buffer tv;
> > +       struct ww_acquire_ctx ticket;
> > +       uint32_t domain;
> > +       int r;
> > +
> > +       if (!new_state->fb) {
> > +               DRM_DEBUG_KMS("No FB bound\n");
> > +               return 0;
> > +       }
> > +       afb = to_amdgpu_framebuffer(new_state->fb);
> > +       obj = new_state->fb->obj[0];
> > +       rbo = gem_to_amdgpu_bo(obj);
> > +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> > +       INIT_LIST_HEAD(&list);
> > +
> > +       tv.bo = &rbo->tbo;
> > +       tv.num_shared = 1;
> > +       list_add(&tv.head, &list);
> > +
> > +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> > +       if (r) {
> > +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> > +               return r;
> > +       }
> > +
> > +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> > +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> > +       else
> > +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> > +
> > +       r = amdgpu_bo_pin(rbo, domain);
> > +       if (unlikely(r != 0)) {
> > +               if (r != -ERESTARTSYS)
> > +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> > +               ttm_eu_backoff_reservation(&ticket, &list);
> > +               return r;
> > +       }
> > +
> > +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> > +       if (unlikely(r != 0)) {
> > +               amdgpu_bo_unpin(rbo);
> > +               ttm_eu_backoff_reservation(&ticket, &list);
> > +               DRM_ERROR("%p bind failed\n", rbo);
> > +               return r;
> > +       }
> > +
> > +       ttm_eu_backoff_reservation(&ticket, &list);
> > +
> > +       afb->address = amdgpu_bo_gpu_offset(rbo);
> > +
> > +       amdgpu_bo_ref(rbo);
> > +
> > +       return 0;
> > +}
> > +
> > +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> > +                                  struct drm_plane_state *old_state)
> > +{
> > +       struct amdgpu_bo *rbo;
> > +       int r;
> > +
> > +       if (!old_state->fb)
> > +               return;
> > +
> > +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> > +       r = amdgpu_bo_reserve(rbo, false);
> > +       if (unlikely(r)) {
> > +               DRM_ERROR("failed to reserve rbo before unpin\n");
> > +               return;
> > +       }
> > +
> > +       amdgpu_bo_unpin(rbo);
> > +       amdgpu_bo_unreserve(rbo);
> > +       amdgpu_bo_unref(&rbo);
> > +}
> > +
> > +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> > +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> > +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> > +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> > +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> > +};
> > +
> > +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> > +                                               enum drm_plane_type type,
> > +                                               int index) {
> > +       struct drm_plane *plane;
> > +       int ret;
> > +
> > +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> > +       if (!plane)
> > +               return ERR_PTR(-ENOMEM);
> > +
> > +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> > +                                      &amdgpu_vkms_plane_funcs,
> > +                                      amdgpu_vkms_formats,
> > +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> > +                                      NULL, type, NULL);
> > +       if (ret) {
> > +               kfree(plane);
> > +               return ERR_PTR(ret);
> > +       }
> > +
> > +       drm_plane_helper_add(plane,
> > + &amdgpu_vkms_primary_helper_funcs);
> > +
> > +       return plane;
> > +}
> > +
> > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > +                           struct amdgpu_vkms_output *output, int
> > +index) {
> > +       struct drm_connector *connector = &output->connector;
> > +       struct drm_encoder *encoder = &output->encoder;
> > +       struct drm_crtc *crtc = &output->crtc;
> > +       struct drm_plane *primary, *cursor = NULL;
> > +       int ret;
> > +
> > +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> > +       if (IS_ERR(primary))
> > +               return PTR_ERR(primary);
> > +
> > +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> > +       if (ret)
> > +               goto err_crtc;
> > +
> > +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> > +                                DRM_MODE_CONNECTOR_VIRTUAL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init connector\n");
> > +               goto err_connector;
> > +       }
> > +
> > +       drm_connector_helper_add(connector,
> > + &amdgpu_vkms_conn_helper_funcs);
> > +
> > +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to init encoder\n");
> > +               goto err_encoder;
> > +       }
> > +       encoder->possible_crtcs = 1 << index;
> > +
> > +       ret = drm_connector_attach_encoder(connector, encoder);
> > +       if (ret) {
> > +               DRM_ERROR("Failed to attach connector to encoder\n");
> > +               goto err_attach;
> > +       }
> > +
> > +       drm_mode_config_reset(dev);
> > +
> > +       return 0;
> > +
> > +err_attach:
> > +       drm_encoder_cleanup(encoder);
> > +
> > +err_encoder:
> > +       drm_connector_cleanup(connector);
> > +
> > +err_connector:
> > +       drm_crtc_cleanup(crtc);
> > +
> > +err_crtc:
> > +       drm_plane_cleanup(primary);
> > +
> > +       return ret;
> > +}
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > new file mode 100644
> > index 000000000000..5dab51fbecf3
> > --- /dev/null
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > @@ -0,0 +1,29 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +
> > +#ifndef _AMDGPU_VKMS_H_
> > +#define _AMDGPU_VKMS_H_
> > +
> > +#define XRES_DEF  1024
> > +#define YRES_DEF   764
>
> Squash in the 768 fix here.
>
> > +
> > +#define XRES_MAX  16384
> > +#define YRES_MAX  16384
> > +
> > +#define drm_crtc_to_amdgpu_vkms_output(target) \
> > +       container_of(target, struct amdgpu_vkms_output, crtc)
> > +
> > +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> > +
> > +struct amdgpu_vkms_output {
> > +       struct drm_crtc crtc;
> > +       struct drm_encoder encoder;
> > +       struct drm_connector connector;
> > +       struct hrtimer vblank_hrtimer;
> > +       ktime_t period_ns;
> > +       struct drm_pending_vblank_event *event; };
> > +
> > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > +                           struct amdgpu_vkms_output *output, int
> > +index);
> > +
> > +#endif /* _AMDGPU_VKMS_H_ */
> > diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > index 7e0d8c092c7e..642c77533157 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > @@ -22,6 +22,7 @@
> >   */
> >
> >  #include <drm/drm_vblank.h>
> > +#include <drm/drm_atomic_helper.h>
> >
> >  #include "amdgpu.h"
> >  #include "amdgpu_pm.h"
> > @@ -40,6 +41,7 @@
> >  #include "dce_virtual.h"
> >  #include "ivsrcid/ivsrcid_vislands30.h"
> >  #include "amdgpu_display.h"
> > +#include "amdgpu_vkms.h"
> >
> >  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
> >
> > @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
> >         .force = dce_virtual_force,
> >  };
> >
> > +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> > +       .fb_create = amdgpu_display_user_framebuffer_create,
> > +       .atomic_check = drm_atomic_helper_check,
> > +       .atomic_commit = drm_atomic_helper_commit, };
> > +
> >  static int dce_virtual_sw_init(void *handle)  {
> >         int r, i;
> > @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
> >
> >         adev_to_drm(adev)->max_vblank_count = 0;
> >
> > -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> > +       adev_to_drm(adev)->mode_config.funcs =
> > + &dce_virtual_mode_funcs;
> >
> > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> > +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> >
> >         adev_to_drm(adev)->mode_config.preferred_depth = 24;
> >         adev_to_drm(adev)->mode_config.prefer_shadow = 1; @@ -399,15
> > +407,11 @@ static int dce_virtual_sw_init(void *handle)
> >         if (r)
> >                 return r;
> >
> > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct
> > + amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
>
> You can use kcalloc here.
>
> >
> >         /* allocate crtcs, encoders, connectors */
> >         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> > -               r = dce_virtual_crtc_init(adev, i);
> > -               if (r)
> > -                       return r;
> > -               r = dce_virtual_connector_encoder_init(adev, i);
> > +               r = amdgpu_vkms_output_init(adev_to_drm(adev),
> > + &adev->amdgpu_vkms_output[i], i);
> >                 if (r)
> >                         return r;
> >         }
> > @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
> >
> > hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> >
> >         kfree(adev->mode_info.bios_hardcoded_edid);
> > +       kfree(adev->amdgpu_vkms_output);
> >
> >         drm_kms_helper_poll_fini(adev_to_drm(adev));
> >
> > --
> > 2.32.0
> >
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flist
> > s.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cgu
> > chun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884
> > e608e11a82d994e183d%7C0%7C0%7C637626475284480052%7CUnknown%7CTWFpbGZsb
> > 3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%
> > 7C1000&amp;sdata=0bbTKflaP2RPk%2BpboaNNiwffbEw1pW0zkqcxzPWjzmI%3D&amp;
> > reserved=0
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7CRyan.Taylor%40amd.com%7Ce0a16eb27da04a035cb608d950516493%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637629133975706919%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=KCe92Ic79b8lkS6h4GoZhRdhwehzleQrSH8OKlinX8I%3D&amp;reserved=0

[-- Attachment #1.2: Type: text/html, Size: 54178 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
  2021-07-26 16:39           ` Taylor, Ryan
@ 2021-07-26 16:58             ` Alex Deucher
  -1 siblings, 0 replies; 24+ messages in thread
From: Alex Deucher @ 2021-07-26 16:58 UTC (permalink / raw)
  To: Taylor, Ryan
  Cc: kernel test robot, Chen, Guchun, Daniel Vetter, Siqueira,
	Rodrigo, amd-gfx list, Melissa Wen, Maling list - DRI developers

On Mon, Jul 26, 2021 at 12:39 PM Taylor, Ryan <Ryan.Taylor@amd.com> wrote:
>
> [AMD Official Use Only]
>
>
> Given that amdgpu_vkms contains code from both dce_virtual and vkms should the identifier be changed to GPL-2.0+ OR MIT like in amdgpu_res_cursor.h?

Most of the code is from vkms so match vkms.

Alex


>
> Best,
> Ryan
> ________________________________
> From: Alex Deucher <alexdeucher@gmail.com>
> Sent: Monday, July 26, 2021 9:21 AM
> To: Chen, Guchun <Guchun.Chen@amd.com>
> Cc: Taylor, Ryan <Ryan.Taylor@amd.com>; kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
>
> On Fri, Jul 23, 2021 at 10:07 PM Chen, Guchun <Guchun.Chen@amd.com> wrote:
> >
> > [Public]
> >
> > Look copy right statement is missed in both amdgpu_vkms.c and amdgpu_vkms.h.
>
> It's there, it just uses the newer SPDX license identifier.
>
> Alex
>
>
> >
> > Regards,
> > Guchun
> >
> > -----Original Message-----
> > From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Alex Deucher
> > Sent: Friday, July 23, 2021 10:32 PM
> > To: Taylor, Ryan <Ryan.Taylor@amd.com>
> > Cc: kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> > Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
> >
> > On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
> > >
> > > Modify the VKMS driver into an api that dce_virtual can use to create
> > > virtual displays that obey drm's atomic modesetting api.
> > >
> > > v2: Made local functions static.
> > >
> > > Reported-by: kernel test robot <lkp@intel.com>
> > > Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> > > ---
> > >  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411
> > > +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |
> > > 29 ++  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
> > >  7 files changed, 458 insertions(+), 11 deletions(-)  create mode
> > > 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > >  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > >
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile
> > > b/drivers/gpu/drm/amd/amdgpu/Makefile
> > > index f089794bbdd5..30cbcd5ce1cc 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> > > +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> > > @@ -120,6 +120,7 @@ amdgpu-y += \
> > >  amdgpu-y += \
> > >         dce_v10_0.o \
> > >         dce_v11_0.o \
> > > +       amdgpu_vkms.o \
> > >         dce_virtual.o
> > >
> > >  # add GFX block
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > index 54cf647bd018..d0a2f2ed433d 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > @@ -919,6 +919,7 @@ struct amdgpu_device {
> > >
> > >         /* display */
> > >         bool                            enable_virtual_display;
> > > +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
> > >         struct amdgpu_mode_info         mode_info;
> > >         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
> > >         struct work_struct              hotplug_work;
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > index d0c935cf4f0f..1b016e5bc75f 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
> > >         int ret, retry = 0;
> > >         bool supports_atomic = false;
> > >
> > > -       if (!amdgpu_virtual_display &&
> > > +       if (amdgpu_virtual_display ||
> > >             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
> > >                 supports_atomic = true;
> > >
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > index 09b048647523..5a143ca02cf9 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
> > >         }
> > >
> > >         /* disable all the possible outputs/crtcs before entering KMS mode */
> > > -       if (!amdgpu_device_has_dc_support(adev))
> > > +       if (!amdgpu_device_has_dc_support(adev) &&
> > > + !amdgpu_virtual_display)
> > >
> > > drm_helper_disable_unused_functions(adev_to_drm(adev));
> > >
> > >         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); diff
> > > --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > new file mode 100644
> > > index 000000000000..d5c1f1c58f5f
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > @@ -0,0 +1,411 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +
> > > +#include <drm/drm_atomic_helper.h>
> > > +#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h>
> > > +
> > > +#include "amdgpu.h"
> > > +#include "amdgpu_vkms.h"
> > > +#include "amdgpu_display.h"
> > > +
> > > +/**
> > > + * DOC: amdgpu_vkms
> > > + *
> > > + * The amdgpu vkms interface provides a virtual KMS interface for
> > > +several use
> > > + * cases: devices without display hardware, platforms where the
> > > +actual display
> > > + * hardware is not useful (e.g., servers), SR-IOV virtual functions,
> > > +device
> > > + * emulation/simulation, and device bring up prior to display
> > > +hardware being
> > > + * usable. We previously emulated a legacy KMS interface, but there
> > > +was a desire
> > > + * to move to the atomic KMS interface. The vkms driver did
> > > +everything we
> > > + * needed, but we wanted KMS support natively in the driver without
> > > +buffer
> > > + * sharing and the ability to support an instance of VKMS per device.
> > > +We first
> > > + * looked at splitting vkms into a stub driver and a helper module
> > > +that other
> > > + * drivers could use to implement a virtual display, but this
> > > +strategy ended up
> > > + * being messy due to driver specific callbacks needed for buffer management.
> > > + * Ultimately, it proved easier to import the vkms code as it mostly
> > > +used core
> > > + * drm helpers anyway.
> > > + */
> > > +
> > > +static const u32 amdgpu_vkms_formats[] = {
> > > +       DRM_FORMAT_XRGB8888,
> > > +};
> > > +
> > > +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct
> > > +hrtimer *timer) {
> > > +       struct amdgpu_vkms_output *output = container_of(timer,
> > > +                                                        struct amdgpu_vkms_output,
> > > +                                                        vblank_hrtimer);
> > > +       struct drm_crtc *crtc = &output->crtc;
> > > +       u64 ret_overrun;
> > > +       bool ret;
> > > +
> > > +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> > > +                                         output->period_ns);
> > > +       WARN_ON(ret_overrun != 1);
> > > +
> > > +       ret = drm_crtc_handle_vblank(crtc);
> > > +       if (!ret)
> > > +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> > > +
> > > +       return HRTIMER_RESTART;
> > > +}
> > > +
> > > +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) {
> > > +       struct drm_device *dev = crtc->dev;
> > > +       unsigned int pipe = drm_crtc_index(crtc);
> > > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > > +       struct amdgpu_vkms_output *out =
> > > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +
> > > +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> > > +
> > > +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> > > +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> > > +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> > > +       hrtimer_start(&out->vblank_hrtimer, out->period_ns,
> > > + HRTIMER_MODE_REL);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) {
> > > +       struct amdgpu_vkms_output *out =
> > > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +
> > > +       hrtimer_cancel(&out->vblank_hrtimer);
> > > +}
> > > +
> > > +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> > > +                                            int *max_error,
> > > +                                            ktime_t *vblank_time,
> > > +                                            bool in_vblank_irq) {
> > > +       struct drm_device *dev = crtc->dev;
> > > +       unsigned int pipe = crtc->index;
> > > +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > > +
> > > +       if (!READ_ONCE(vblank->enabled)) {
> > > +               *vblank_time = ktime_get();
> > > +               return true;
> > > +       }
> > > +
> > > +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> > > +
> > > +       if (WARN_ON(*vblank_time == vblank->time))
> > > +               return true;
> > > +
> > > +       /*
> > > +        * To prevent races we roll the hrtimer forward before we do any
> > > +        * interrupt processing - this is how real hw works (the interrupt is
> > > +        * only generated after all the vblank registers are updated) and what
> > > +        * the vblank core expects. Therefore we need to always correct the
> > > +        * timestampe by one frame.
> > > +        */
> > > +       *vblank_time -= output->period_ns;
> > > +
> > > +       return true;
> > > +}
> > > +
> > > +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> > > +       .set_config             = drm_atomic_helper_set_config,
> > > +       .destroy                = drm_crtc_cleanup,
> > > +       .page_flip              = drm_atomic_helper_page_flip,
> > > +       .reset                  = drm_atomic_helper_crtc_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> > > +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> > > +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> > > +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> > > +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> > > +};
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> > > +                                          struct drm_atomic_state
> > > +*state) {
> > > +       drm_crtc_vblank_on(crtc);
> > > +}
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> > > +                                           struct drm_atomic_state
> > > +*state) {
> > > +       drm_crtc_vblank_off(crtc);
> > > +}
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> > > +                                         struct drm_atomic_state
> > > +*state) {
> > > +       if (crtc->state->event) {
> > > +               spin_lock(&crtc->dev->event_lock);
> > > +
> > > +               if (drm_crtc_vblank_get(crtc) != 0)
> > > +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> > > +               else
> > > +                       drm_crtc_arm_vblank_event(crtc,
> > > + crtc->state->event);
> > > +
> > > +               spin_unlock(&crtc->dev->event_lock);
> > > +
> > > +               crtc->state->event = NULL;
> > > +       }
> > > +}
> > > +
> > > +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> > > +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> > > +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> > > +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable, };
> > > +
> > > +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> > > +                         struct drm_plane *primary, struct drm_plane
> > > +*cursor) {
> > > +       int ret;
> > > +
> > > +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> > > +                                       &amdgpu_vkms_crtc_funcs, NULL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init CRTC\n");
> > > +               return ret;
> > > +       }
> > > +
> > > +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> > > +
> > > +       return ret;
> > > +}
> > > +
> > > +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> > > +       .fill_modes = drm_helper_probe_single_connector_modes,
> > > +       .destroy = drm_connector_cleanup,
> > > +       .reset = drm_atomic_helper_connector_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> > > +       .atomic_destroy_state =
> > > +drm_atomic_helper_connector_destroy_state,
> > > +};
> > > +
> > > +static int amdgpu_vkms_conn_get_modes(struct drm_connector
> > > +*connector) {
> > > +       int count;
> > > +
> > > +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> > > +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> > > +
> > > +       return count;
> > > +}
> > > +
> > > +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> > > +       .get_modes    = amdgpu_vkms_conn_get_modes,
> > > +};
> > > +
> > > +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> > > +       .update_plane           = drm_atomic_helper_update_plane,
> > > +       .disable_plane          = drm_atomic_helper_disable_plane,
> > > +       .destroy                = drm_plane_cleanup,
> > > +       .reset                  = drm_atomic_helper_plane_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > > +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> > > +};
> > > +
> > > +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> > > +                                           struct drm_plane_state
> > > +*old_state) {
> > > +       return;
> > > +}
> > > +
> > > +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> > > +                                         struct drm_plane_state
> > > +*state) {
> > > +       struct drm_crtc_state *crtc_state;
> > > +       bool can_position = false;
> > > +       int ret;
> > > +
> > > +       if (!state->fb || WARN_ON(!state->crtc))
> > > +               return 0;
> > > +
> > > +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> > > +       if (IS_ERR(crtc_state))
> > > +               return PTR_ERR(crtc_state);
> > > +
> > > +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> > > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > > +                                                 can_position, true);
> > > +       if (ret != 0)
> > > +               return ret;
> > > +
> > > +       /* for now primary plane must be visible and full screen */
> > > +       if (!state->visible && !can_position)
> > > +               return -EINVAL;
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> > > +                                 struct drm_plane_state *new_state) {
> > > +       struct amdgpu_framebuffer *afb;
> > > +       struct drm_gem_object *obj;
> > > +       struct amdgpu_device *adev;
> > > +       struct amdgpu_bo *rbo;
> > > +       struct list_head list;
> > > +       struct ttm_validate_buffer tv;
> > > +       struct ww_acquire_ctx ticket;
> > > +       uint32_t domain;
> > > +       int r;
> > > +
> > > +       if (!new_state->fb) {
> > > +               DRM_DEBUG_KMS("No FB bound\n");
> > > +               return 0;
> > > +       }
> > > +       afb = to_amdgpu_framebuffer(new_state->fb);
> > > +       obj = new_state->fb->obj[0];
> > > +       rbo = gem_to_amdgpu_bo(obj);
> > > +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> > > +       INIT_LIST_HEAD(&list);
> > > +
> > > +       tv.bo = &rbo->tbo;
> > > +       tv.num_shared = 1;
> > > +       list_add(&tv.head, &list);
> > > +
> > > +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> > > +       if (r) {
> > > +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> > > +               return r;
> > > +       }
> > > +
> > > +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> > > +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> > > +       else
> > > +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> > > +
> > > +       r = amdgpu_bo_pin(rbo, domain);
> > > +       if (unlikely(r != 0)) {
> > > +               if (r != -ERESTARTSYS)
> > > +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> > > +               ttm_eu_backoff_reservation(&ticket, &list);
> > > +               return r;
> > > +       }
> > > +
> > > +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> > > +       if (unlikely(r != 0)) {
> > > +               amdgpu_bo_unpin(rbo);
> > > +               ttm_eu_backoff_reservation(&ticket, &list);
> > > +               DRM_ERROR("%p bind failed\n", rbo);
> > > +               return r;
> > > +       }
> > > +
> > > +       ttm_eu_backoff_reservation(&ticket, &list);
> > > +
> > > +       afb->address = amdgpu_bo_gpu_offset(rbo);
> > > +
> > > +       amdgpu_bo_ref(rbo);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> > > +                                  struct drm_plane_state *old_state)
> > > +{
> > > +       struct amdgpu_bo *rbo;
> > > +       int r;
> > > +
> > > +       if (!old_state->fb)
> > > +               return;
> > > +
> > > +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> > > +       r = amdgpu_bo_reserve(rbo, false);
> > > +       if (unlikely(r)) {
> > > +               DRM_ERROR("failed to reserve rbo before unpin\n");
> > > +               return;
> > > +       }
> > > +
> > > +       amdgpu_bo_unpin(rbo);
> > > +       amdgpu_bo_unreserve(rbo);
> > > +       amdgpu_bo_unref(&rbo);
> > > +}
> > > +
> > > +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> > > +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> > > +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> > > +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> > > +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> > > +};
> > > +
> > > +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> > > +                                               enum drm_plane_type type,
> > > +                                               int index) {
> > > +       struct drm_plane *plane;
> > > +       int ret;
> > > +
> > > +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> > > +       if (!plane)
> > > +               return ERR_PTR(-ENOMEM);
> > > +
> > > +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> > > +                                      &amdgpu_vkms_plane_funcs,
> > > +                                      amdgpu_vkms_formats,
> > > +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> > > +                                      NULL, type, NULL);
> > > +       if (ret) {
> > > +               kfree(plane);
> > > +               return ERR_PTR(ret);
> > > +       }
> > > +
> > > +       drm_plane_helper_add(plane,
> > > + &amdgpu_vkms_primary_helper_funcs);
> > > +
> > > +       return plane;
> > > +}
> > > +
> > > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > > +                           struct amdgpu_vkms_output *output, int
> > > +index) {
> > > +       struct drm_connector *connector = &output->connector;
> > > +       struct drm_encoder *encoder = &output->encoder;
> > > +       struct drm_crtc *crtc = &output->crtc;
> > > +       struct drm_plane *primary, *cursor = NULL;
> > > +       int ret;
> > > +
> > > +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> > > +       if (IS_ERR(primary))
> > > +               return PTR_ERR(primary);
> > > +
> > > +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> > > +       if (ret)
> > > +               goto err_crtc;
> > > +
> > > +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> > > +                                DRM_MODE_CONNECTOR_VIRTUAL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init connector\n");
> > > +               goto err_connector;
> > > +       }
> > > +
> > > +       drm_connector_helper_add(connector,
> > > + &amdgpu_vkms_conn_helper_funcs);
> > > +
> > > +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init encoder\n");
> > > +               goto err_encoder;
> > > +       }
> > > +       encoder->possible_crtcs = 1 << index;
> > > +
> > > +       ret = drm_connector_attach_encoder(connector, encoder);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to attach connector to encoder\n");
> > > +               goto err_attach;
> > > +       }
> > > +
> > > +       drm_mode_config_reset(dev);
> > > +
> > > +       return 0;
> > > +
> > > +err_attach:
> > > +       drm_encoder_cleanup(encoder);
> > > +
> > > +err_encoder:
> > > +       drm_connector_cleanup(connector);
> > > +
> > > +err_connector:
> > > +       drm_crtc_cleanup(crtc);
> > > +
> > > +err_crtc:
> > > +       drm_plane_cleanup(primary);
> > > +
> > > +       return ret;
> > > +}
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > new file mode 100644
> > > index 000000000000..5dab51fbecf3
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > @@ -0,0 +1,29 @@
> > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > +
> > > +#ifndef _AMDGPU_VKMS_H_
> > > +#define _AMDGPU_VKMS_H_
> > > +
> > > +#define XRES_DEF  1024
> > > +#define YRES_DEF   764
> >
> > Squash in the 768 fix here.
> >
> > > +
> > > +#define XRES_MAX  16384
> > > +#define YRES_MAX  16384
> > > +
> > > +#define drm_crtc_to_amdgpu_vkms_output(target) \
> > > +       container_of(target, struct amdgpu_vkms_output, crtc)
> > > +
> > > +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> > > +
> > > +struct amdgpu_vkms_output {
> > > +       struct drm_crtc crtc;
> > > +       struct drm_encoder encoder;
> > > +       struct drm_connector connector;
> > > +       struct hrtimer vblank_hrtimer;
> > > +       ktime_t period_ns;
> > > +       struct drm_pending_vblank_event *event; };
> > > +
> > > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > > +                           struct amdgpu_vkms_output *output, int
> > > +index);
> > > +
> > > +#endif /* _AMDGPU_VKMS_H_ */
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > index 7e0d8c092c7e..642c77533157 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > @@ -22,6 +22,7 @@
> > >   */
> > >
> > >  #include <drm/drm_vblank.h>
> > > +#include <drm/drm_atomic_helper.h>
> > >
> > >  #include "amdgpu.h"
> > >  #include "amdgpu_pm.h"
> > > @@ -40,6 +41,7 @@
> > >  #include "dce_virtual.h"
> > >  #include "ivsrcid/ivsrcid_vislands30.h"
> > >  #include "amdgpu_display.h"
> > > +#include "amdgpu_vkms.h"
> > >
> > >  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
> > >
> > > @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
> > >         .force = dce_virtual_force,
> > >  };
> > >
> > > +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> > > +       .fb_create = amdgpu_display_user_framebuffer_create,
> > > +       .atomic_check = drm_atomic_helper_check,
> > > +       .atomic_commit = drm_atomic_helper_commit, };
> > > +
> > >  static int dce_virtual_sw_init(void *handle)  {
> > >         int r, i;
> > > @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
> > >
> > >         adev_to_drm(adev)->max_vblank_count = 0;
> > >
> > > -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> > > +       adev_to_drm(adev)->mode_config.funcs =
> > > + &dce_virtual_mode_funcs;
> > >
> > > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > > +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> > > +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> > >
> > >         adev_to_drm(adev)->mode_config.preferred_depth = 24;
> > >         adev_to_drm(adev)->mode_config.prefer_shadow = 1; @@ -399,15
> > > +407,11 @@ static int dce_virtual_sw_init(void *handle)
> > >         if (r)
> > >                 return r;
> > >
> > > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > > +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct
> > > + amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> >
> > You can use kcalloc here.
> >
> > >
> > >         /* allocate crtcs, encoders, connectors */
> > >         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> > > -               r = dce_virtual_crtc_init(adev, i);
> > > -               if (r)
> > > -                       return r;
> > > -               r = dce_virtual_connector_encoder_init(adev, i);
> > > +               r = amdgpu_vkms_output_init(adev_to_drm(adev),
> > > + &adev->amdgpu_vkms_output[i], i);
> > >                 if (r)
> > >                         return r;
> > >         }
> > > @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
> > >
> > > hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> > >
> > >         kfree(adev->mode_info.bios_hardcoded_edid);
> > > +       kfree(adev->amdgpu_vkms_output);
> > >
> > >         drm_kms_helper_poll_fini(adev_to_drm(adev));
> > >
> > > --
> > > 2.32.0
> > >
> > > _______________________________________________
> > > amd-gfx mailing list
> > > amd-gfx@lists.freedesktop.org
> > > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flist
> > > s.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cgu
> > > chun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884
> > > e608e11a82d994e183d%7C0%7C0%7C637626475284480052%7CUnknown%7CTWFpbGZsb
> > > 3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%
> > > 7C1000&amp;sdata=0bbTKflaP2RPk%2BpboaNNiwffbEw1pW0zkqcxzPWjzmI%3D&amp;
> > > reserved=0
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7CRyan.Taylor%40amd.com%7Ce0a16eb27da04a035cb608d950516493%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637629133975706919%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=KCe92Ic79b8lkS6h4GoZhRdhwehzleQrSH8OKlinX8I%3D&amp;reserved=0

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

* Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
@ 2021-07-26 16:58             ` Alex Deucher
  0 siblings, 0 replies; 24+ messages in thread
From: Alex Deucher @ 2021-07-26 16:58 UTC (permalink / raw)
  To: Taylor, Ryan
  Cc: kernel test robot, Chen, Guchun, Daniel Vetter, Siqueira,
	Rodrigo, amd-gfx list, Melissa Wen, Maling list - DRI developers

On Mon, Jul 26, 2021 at 12:39 PM Taylor, Ryan <Ryan.Taylor@amd.com> wrote:
>
> [AMD Official Use Only]
>
>
> Given that amdgpu_vkms contains code from both dce_virtual and vkms should the identifier be changed to GPL-2.0+ OR MIT like in amdgpu_res_cursor.h?

Most of the code is from vkms so match vkms.

Alex


>
> Best,
> Ryan
> ________________________________
> From: Alex Deucher <alexdeucher@gmail.com>
> Sent: Monday, July 26, 2021 9:21 AM
> To: Chen, Guchun <Guchun.Chen@amd.com>
> Cc: Taylor, Ryan <Ryan.Taylor@amd.com>; kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
>
> On Fri, Jul 23, 2021 at 10:07 PM Chen, Guchun <Guchun.Chen@amd.com> wrote:
> >
> > [Public]
> >
> > Look copy right statement is missed in both amdgpu_vkms.c and amdgpu_vkms.h.
>
> It's there, it just uses the newer SPDX license identifier.
>
> Alex
>
>
> >
> > Regards,
> > Guchun
> >
> > -----Original Message-----
> > From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Alex Deucher
> > Sent: Friday, July 23, 2021 10:32 PM
> > To: Taylor, Ryan <Ryan.Taylor@amd.com>
> > Cc: kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> > Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
> >
> > On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
> > >
> > > Modify the VKMS driver into an api that dce_virtual can use to create
> > > virtual displays that obey drm's atomic modesetting api.
> > >
> > > v2: Made local functions static.
> > >
> > > Reported-by: kernel test robot <lkp@intel.com>
> > > Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> > > ---
> > >  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411
> > > +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |
> > > 29 ++  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
> > >  7 files changed, 458 insertions(+), 11 deletions(-)  create mode
> > > 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > >  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > >
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile
> > > b/drivers/gpu/drm/amd/amdgpu/Makefile
> > > index f089794bbdd5..30cbcd5ce1cc 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> > > +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> > > @@ -120,6 +120,7 @@ amdgpu-y += \
> > >  amdgpu-y += \
> > >         dce_v10_0.o \
> > >         dce_v11_0.o \
> > > +       amdgpu_vkms.o \
> > >         dce_virtual.o
> > >
> > >  # add GFX block
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > index 54cf647bd018..d0a2f2ed433d 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > @@ -919,6 +919,7 @@ struct amdgpu_device {
> > >
> > >         /* display */
> > >         bool                            enable_virtual_display;
> > > +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
> > >         struct amdgpu_mode_info         mode_info;
> > >         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
> > >         struct work_struct              hotplug_work;
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > index d0c935cf4f0f..1b016e5bc75f 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
> > >         int ret, retry = 0;
> > >         bool supports_atomic = false;
> > >
> > > -       if (!amdgpu_virtual_display &&
> > > +       if (amdgpu_virtual_display ||
> > >             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
> > >                 supports_atomic = true;
> > >
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > index 09b048647523..5a143ca02cf9 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
> > >         }
> > >
> > >         /* disable all the possible outputs/crtcs before entering KMS mode */
> > > -       if (!amdgpu_device_has_dc_support(adev))
> > > +       if (!amdgpu_device_has_dc_support(adev) &&
> > > + !amdgpu_virtual_display)
> > >
> > > drm_helper_disable_unused_functions(adev_to_drm(adev));
> > >
> > >         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); diff
> > > --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > new file mode 100644
> > > index 000000000000..d5c1f1c58f5f
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > @@ -0,0 +1,411 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +
> > > +#include <drm/drm_atomic_helper.h>
> > > +#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h>
> > > +
> > > +#include "amdgpu.h"
> > > +#include "amdgpu_vkms.h"
> > > +#include "amdgpu_display.h"
> > > +
> > > +/**
> > > + * DOC: amdgpu_vkms
> > > + *
> > > + * The amdgpu vkms interface provides a virtual KMS interface for
> > > +several use
> > > + * cases: devices without display hardware, platforms where the
> > > +actual display
> > > + * hardware is not useful (e.g., servers), SR-IOV virtual functions,
> > > +device
> > > + * emulation/simulation, and device bring up prior to display
> > > +hardware being
> > > + * usable. We previously emulated a legacy KMS interface, but there
> > > +was a desire
> > > + * to move to the atomic KMS interface. The vkms driver did
> > > +everything we
> > > + * needed, but we wanted KMS support natively in the driver without
> > > +buffer
> > > + * sharing and the ability to support an instance of VKMS per device.
> > > +We first
> > > + * looked at splitting vkms into a stub driver and a helper module
> > > +that other
> > > + * drivers could use to implement a virtual display, but this
> > > +strategy ended up
> > > + * being messy due to driver specific callbacks needed for buffer management.
> > > + * Ultimately, it proved easier to import the vkms code as it mostly
> > > +used core
> > > + * drm helpers anyway.
> > > + */
> > > +
> > > +static const u32 amdgpu_vkms_formats[] = {
> > > +       DRM_FORMAT_XRGB8888,
> > > +};
> > > +
> > > +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct
> > > +hrtimer *timer) {
> > > +       struct amdgpu_vkms_output *output = container_of(timer,
> > > +                                                        struct amdgpu_vkms_output,
> > > +                                                        vblank_hrtimer);
> > > +       struct drm_crtc *crtc = &output->crtc;
> > > +       u64 ret_overrun;
> > > +       bool ret;
> > > +
> > > +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> > > +                                         output->period_ns);
> > > +       WARN_ON(ret_overrun != 1);
> > > +
> > > +       ret = drm_crtc_handle_vblank(crtc);
> > > +       if (!ret)
> > > +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> > > +
> > > +       return HRTIMER_RESTART;
> > > +}
> > > +
> > > +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) {
> > > +       struct drm_device *dev = crtc->dev;
> > > +       unsigned int pipe = drm_crtc_index(crtc);
> > > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > > +       struct amdgpu_vkms_output *out =
> > > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +
> > > +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> > > +
> > > +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> > > +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> > > +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> > > +       hrtimer_start(&out->vblank_hrtimer, out->period_ns,
> > > + HRTIMER_MODE_REL);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) {
> > > +       struct amdgpu_vkms_output *out =
> > > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +
> > > +       hrtimer_cancel(&out->vblank_hrtimer);
> > > +}
> > > +
> > > +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> > > +                                            int *max_error,
> > > +                                            ktime_t *vblank_time,
> > > +                                            bool in_vblank_irq) {
> > > +       struct drm_device *dev = crtc->dev;
> > > +       unsigned int pipe = crtc->index;
> > > +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > > +
> > > +       if (!READ_ONCE(vblank->enabled)) {
> > > +               *vblank_time = ktime_get();
> > > +               return true;
> > > +       }
> > > +
> > > +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> > > +
> > > +       if (WARN_ON(*vblank_time == vblank->time))
> > > +               return true;
> > > +
> > > +       /*
> > > +        * To prevent races we roll the hrtimer forward before we do any
> > > +        * interrupt processing - this is how real hw works (the interrupt is
> > > +        * only generated after all the vblank registers are updated) and what
> > > +        * the vblank core expects. Therefore we need to always correct the
> > > +        * timestampe by one frame.
> > > +        */
> > > +       *vblank_time -= output->period_ns;
> > > +
> > > +       return true;
> > > +}
> > > +
> > > +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> > > +       .set_config             = drm_atomic_helper_set_config,
> > > +       .destroy                = drm_crtc_cleanup,
> > > +       .page_flip              = drm_atomic_helper_page_flip,
> > > +       .reset                  = drm_atomic_helper_crtc_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> > > +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> > > +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> > > +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> > > +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> > > +};
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> > > +                                          struct drm_atomic_state
> > > +*state) {
> > > +       drm_crtc_vblank_on(crtc);
> > > +}
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> > > +                                           struct drm_atomic_state
> > > +*state) {
> > > +       drm_crtc_vblank_off(crtc);
> > > +}
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> > > +                                         struct drm_atomic_state
> > > +*state) {
> > > +       if (crtc->state->event) {
> > > +               spin_lock(&crtc->dev->event_lock);
> > > +
> > > +               if (drm_crtc_vblank_get(crtc) != 0)
> > > +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> > > +               else
> > > +                       drm_crtc_arm_vblank_event(crtc,
> > > + crtc->state->event);
> > > +
> > > +               spin_unlock(&crtc->dev->event_lock);
> > > +
> > > +               crtc->state->event = NULL;
> > > +       }
> > > +}
> > > +
> > > +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> > > +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> > > +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> > > +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable, };
> > > +
> > > +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> > > +                         struct drm_plane *primary, struct drm_plane
> > > +*cursor) {
> > > +       int ret;
> > > +
> > > +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> > > +                                       &amdgpu_vkms_crtc_funcs, NULL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init CRTC\n");
> > > +               return ret;
> > > +       }
> > > +
> > > +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> > > +
> > > +       return ret;
> > > +}
> > > +
> > > +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> > > +       .fill_modes = drm_helper_probe_single_connector_modes,
> > > +       .destroy = drm_connector_cleanup,
> > > +       .reset = drm_atomic_helper_connector_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> > > +       .atomic_destroy_state =
> > > +drm_atomic_helper_connector_destroy_state,
> > > +};
> > > +
> > > +static int amdgpu_vkms_conn_get_modes(struct drm_connector
> > > +*connector) {
> > > +       int count;
> > > +
> > > +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> > > +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> > > +
> > > +       return count;
> > > +}
> > > +
> > > +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> > > +       .get_modes    = amdgpu_vkms_conn_get_modes,
> > > +};
> > > +
> > > +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> > > +       .update_plane           = drm_atomic_helper_update_plane,
> > > +       .disable_plane          = drm_atomic_helper_disable_plane,
> > > +       .destroy                = drm_plane_cleanup,
> > > +       .reset                  = drm_atomic_helper_plane_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > > +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> > > +};
> > > +
> > > +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> > > +                                           struct drm_plane_state
> > > +*old_state) {
> > > +       return;
> > > +}
> > > +
> > > +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> > > +                                         struct drm_plane_state
> > > +*state) {
> > > +       struct drm_crtc_state *crtc_state;
> > > +       bool can_position = false;
> > > +       int ret;
> > > +
> > > +       if (!state->fb || WARN_ON(!state->crtc))
> > > +               return 0;
> > > +
> > > +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> > > +       if (IS_ERR(crtc_state))
> > > +               return PTR_ERR(crtc_state);
> > > +
> > > +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> > > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > > +                                                 can_position, true);
> > > +       if (ret != 0)
> > > +               return ret;
> > > +
> > > +       /* for now primary plane must be visible and full screen */
> > > +       if (!state->visible && !can_position)
> > > +               return -EINVAL;
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> > > +                                 struct drm_plane_state *new_state) {
> > > +       struct amdgpu_framebuffer *afb;
> > > +       struct drm_gem_object *obj;
> > > +       struct amdgpu_device *adev;
> > > +       struct amdgpu_bo *rbo;
> > > +       struct list_head list;
> > > +       struct ttm_validate_buffer tv;
> > > +       struct ww_acquire_ctx ticket;
> > > +       uint32_t domain;
> > > +       int r;
> > > +
> > > +       if (!new_state->fb) {
> > > +               DRM_DEBUG_KMS("No FB bound\n");
> > > +               return 0;
> > > +       }
> > > +       afb = to_amdgpu_framebuffer(new_state->fb);
> > > +       obj = new_state->fb->obj[0];
> > > +       rbo = gem_to_amdgpu_bo(obj);
> > > +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> > > +       INIT_LIST_HEAD(&list);
> > > +
> > > +       tv.bo = &rbo->tbo;
> > > +       tv.num_shared = 1;
> > > +       list_add(&tv.head, &list);
> > > +
> > > +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> > > +       if (r) {
> > > +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> > > +               return r;
> > > +       }
> > > +
> > > +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> > > +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> > > +       else
> > > +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> > > +
> > > +       r = amdgpu_bo_pin(rbo, domain);
> > > +       if (unlikely(r != 0)) {
> > > +               if (r != -ERESTARTSYS)
> > > +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> > > +               ttm_eu_backoff_reservation(&ticket, &list);
> > > +               return r;
> > > +       }
> > > +
> > > +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> > > +       if (unlikely(r != 0)) {
> > > +               amdgpu_bo_unpin(rbo);
> > > +               ttm_eu_backoff_reservation(&ticket, &list);
> > > +               DRM_ERROR("%p bind failed\n", rbo);
> > > +               return r;
> > > +       }
> > > +
> > > +       ttm_eu_backoff_reservation(&ticket, &list);
> > > +
> > > +       afb->address = amdgpu_bo_gpu_offset(rbo);
> > > +
> > > +       amdgpu_bo_ref(rbo);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> > > +                                  struct drm_plane_state *old_state)
> > > +{
> > > +       struct amdgpu_bo *rbo;
> > > +       int r;
> > > +
> > > +       if (!old_state->fb)
> > > +               return;
> > > +
> > > +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> > > +       r = amdgpu_bo_reserve(rbo, false);
> > > +       if (unlikely(r)) {
> > > +               DRM_ERROR("failed to reserve rbo before unpin\n");
> > > +               return;
> > > +       }
> > > +
> > > +       amdgpu_bo_unpin(rbo);
> > > +       amdgpu_bo_unreserve(rbo);
> > > +       amdgpu_bo_unref(&rbo);
> > > +}
> > > +
> > > +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> > > +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> > > +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> > > +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> > > +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> > > +};
> > > +
> > > +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> > > +                                               enum drm_plane_type type,
> > > +                                               int index) {
> > > +       struct drm_plane *plane;
> > > +       int ret;
> > > +
> > > +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> > > +       if (!plane)
> > > +               return ERR_PTR(-ENOMEM);
> > > +
> > > +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> > > +                                      &amdgpu_vkms_plane_funcs,
> > > +                                      amdgpu_vkms_formats,
> > > +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> > > +                                      NULL, type, NULL);
> > > +       if (ret) {
> > > +               kfree(plane);
> > > +               return ERR_PTR(ret);
> > > +       }
> > > +
> > > +       drm_plane_helper_add(plane,
> > > + &amdgpu_vkms_primary_helper_funcs);
> > > +
> > > +       return plane;
> > > +}
> > > +
> > > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > > +                           struct amdgpu_vkms_output *output, int
> > > +index) {
> > > +       struct drm_connector *connector = &output->connector;
> > > +       struct drm_encoder *encoder = &output->encoder;
> > > +       struct drm_crtc *crtc = &output->crtc;
> > > +       struct drm_plane *primary, *cursor = NULL;
> > > +       int ret;
> > > +
> > > +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> > > +       if (IS_ERR(primary))
> > > +               return PTR_ERR(primary);
> > > +
> > > +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> > > +       if (ret)
> > > +               goto err_crtc;
> > > +
> > > +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> > > +                                DRM_MODE_CONNECTOR_VIRTUAL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init connector\n");
> > > +               goto err_connector;
> > > +       }
> > > +
> > > +       drm_connector_helper_add(connector,
> > > + &amdgpu_vkms_conn_helper_funcs);
> > > +
> > > +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init encoder\n");
> > > +               goto err_encoder;
> > > +       }
> > > +       encoder->possible_crtcs = 1 << index;
> > > +
> > > +       ret = drm_connector_attach_encoder(connector, encoder);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to attach connector to encoder\n");
> > > +               goto err_attach;
> > > +       }
> > > +
> > > +       drm_mode_config_reset(dev);
> > > +
> > > +       return 0;
> > > +
> > > +err_attach:
> > > +       drm_encoder_cleanup(encoder);
> > > +
> > > +err_encoder:
> > > +       drm_connector_cleanup(connector);
> > > +
> > > +err_connector:
> > > +       drm_crtc_cleanup(crtc);
> > > +
> > > +err_crtc:
> > > +       drm_plane_cleanup(primary);
> > > +
> > > +       return ret;
> > > +}
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > new file mode 100644
> > > index 000000000000..5dab51fbecf3
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > @@ -0,0 +1,29 @@
> > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > +
> > > +#ifndef _AMDGPU_VKMS_H_
> > > +#define _AMDGPU_VKMS_H_
> > > +
> > > +#define XRES_DEF  1024
> > > +#define YRES_DEF   764
> >
> > Squash in the 768 fix here.
> >
> > > +
> > > +#define XRES_MAX  16384
> > > +#define YRES_MAX  16384
> > > +
> > > +#define drm_crtc_to_amdgpu_vkms_output(target) \
> > > +       container_of(target, struct amdgpu_vkms_output, crtc)
> > > +
> > > +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> > > +
> > > +struct amdgpu_vkms_output {
> > > +       struct drm_crtc crtc;
> > > +       struct drm_encoder encoder;
> > > +       struct drm_connector connector;
> > > +       struct hrtimer vblank_hrtimer;
> > > +       ktime_t period_ns;
> > > +       struct drm_pending_vblank_event *event; };
> > > +
> > > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > > +                           struct amdgpu_vkms_output *output, int
> > > +index);
> > > +
> > > +#endif /* _AMDGPU_VKMS_H_ */
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > index 7e0d8c092c7e..642c77533157 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > @@ -22,6 +22,7 @@
> > >   */
> > >
> > >  #include <drm/drm_vblank.h>
> > > +#include <drm/drm_atomic_helper.h>
> > >
> > >  #include "amdgpu.h"
> > >  #include "amdgpu_pm.h"
> > > @@ -40,6 +41,7 @@
> > >  #include "dce_virtual.h"
> > >  #include "ivsrcid/ivsrcid_vislands30.h"
> > >  #include "amdgpu_display.h"
> > > +#include "amdgpu_vkms.h"
> > >
> > >  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
> > >
> > > @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
> > >         .force = dce_virtual_force,
> > >  };
> > >
> > > +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> > > +       .fb_create = amdgpu_display_user_framebuffer_create,
> > > +       .atomic_check = drm_atomic_helper_check,
> > > +       .atomic_commit = drm_atomic_helper_commit, };
> > > +
> > >  static int dce_virtual_sw_init(void *handle)  {
> > >         int r, i;
> > > @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
> > >
> > >         adev_to_drm(adev)->max_vblank_count = 0;
> > >
> > > -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> > > +       adev_to_drm(adev)->mode_config.funcs =
> > > + &dce_virtual_mode_funcs;
> > >
> > > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > > +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> > > +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> > >
> > >         adev_to_drm(adev)->mode_config.preferred_depth = 24;
> > >         adev_to_drm(adev)->mode_config.prefer_shadow = 1; @@ -399,15
> > > +407,11 @@ static int dce_virtual_sw_init(void *handle)
> > >         if (r)
> > >                 return r;
> > >
> > > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > > +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct
> > > + amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> >
> > You can use kcalloc here.
> >
> > >
> > >         /* allocate crtcs, encoders, connectors */
> > >         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> > > -               r = dce_virtual_crtc_init(adev, i);
> > > -               if (r)
> > > -                       return r;
> > > -               r = dce_virtual_connector_encoder_init(adev, i);
> > > +               r = amdgpu_vkms_output_init(adev_to_drm(adev),
> > > + &adev->amdgpu_vkms_output[i], i);
> > >                 if (r)
> > >                         return r;
> > >         }
> > > @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
> > >
> > > hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> > >
> > >         kfree(adev->mode_info.bios_hardcoded_edid);
> > > +       kfree(adev->amdgpu_vkms_output);
> > >
> > >         drm_kms_helper_poll_fini(adev_to_drm(adev));
> > >
> > > --
> > > 2.32.0
> > >
> > > _______________________________________________
> > > amd-gfx mailing list
> > > amd-gfx@lists.freedesktop.org
> > > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flist
> > > s.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cgu
> > > chun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884
> > > e608e11a82d994e183d%7C0%7C0%7C637626475284480052%7CUnknown%7CTWFpbGZsb
> > > 3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%
> > > 7C1000&amp;sdata=0bbTKflaP2RPk%2BpboaNNiwffbEw1pW0zkqcxzPWjzmI%3D&amp;
> > > reserved=0
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7CRyan.Taylor%40amd.com%7Ce0a16eb27da04a035cb608d950516493%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637629133975706919%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=KCe92Ic79b8lkS6h4GoZhRdhwehzleQrSH8OKlinX8I%3D&amp;reserved=0
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

* Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
  2021-07-26 16:58             ` Alex Deucher
@ 2021-07-26 17:02               ` Taylor, Ryan
  -1 siblings, 0 replies; 24+ messages in thread
From: Taylor, Ryan @ 2021-07-26 17:02 UTC (permalink / raw)
  To: Alex Deucher
  Cc: kernel test robot, Chen, Guchun, Daniel Vetter, Siqueira,
	Rodrigo, amd-gfx list, Melissa Wen, Maling list - DRI developers

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

[AMD Official Use Only]

Sounds good, Thanks for clarifying. Thanks for the input Guchun.

Best,
Ryan
________________________________
From: Alex Deucher <alexdeucher@gmail.com>
Sent: Monday, July 26, 2021 9:58 AM
To: Taylor, Ryan <Ryan.Taylor@amd.com>
Cc: Chen, Guchun <Guchun.Chen@amd.com>; kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)

On Mon, Jul 26, 2021 at 12:39 PM Taylor, Ryan <Ryan.Taylor@amd.com> wrote:
>
> [AMD Official Use Only]
>
>
> Given that amdgpu_vkms contains code from both dce_virtual and vkms should the identifier be changed to GPL-2.0+ OR MIT like in amdgpu_res_cursor.h?

Most of the code is from vkms so match vkms.

Alex


>
> Best,
> Ryan
> ________________________________
> From: Alex Deucher <alexdeucher@gmail.com>
> Sent: Monday, July 26, 2021 9:21 AM
> To: Chen, Guchun <Guchun.Chen@amd.com>
> Cc: Taylor, Ryan <Ryan.Taylor@amd.com>; kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
>
> On Fri, Jul 23, 2021 at 10:07 PM Chen, Guchun <Guchun.Chen@amd.com> wrote:
> >
> > [Public]
> >
> > Look copy right statement is missed in both amdgpu_vkms.c and amdgpu_vkms.h.
>
> It's there, it just uses the newer SPDX license identifier.
>
> Alex
>
>
> >
> > Regards,
> > Guchun
> >
> > -----Original Message-----
> > From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Alex Deucher
> > Sent: Friday, July 23, 2021 10:32 PM
> > To: Taylor, Ryan <Ryan.Taylor@amd.com>
> > Cc: kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> > Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
> >
> > On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
> > >
> > > Modify the VKMS driver into an api that dce_virtual can use to create
> > > virtual displays that obey drm's atomic modesetting api.
> > >
> > > v2: Made local functions static.
> > >
> > > Reported-by: kernel test robot <lkp@intel.com>
> > > Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> > > ---
> > >  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411
> > > +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |
> > > 29 ++  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
> > >  7 files changed, 458 insertions(+), 11 deletions(-)  create mode
> > > 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > >  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > >
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile
> > > b/drivers/gpu/drm/amd/amdgpu/Makefile
> > > index f089794bbdd5..30cbcd5ce1cc 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> > > +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> > > @@ -120,6 +120,7 @@ amdgpu-y += \
> > >  amdgpu-y += \
> > >         dce_v10_0.o \
> > >         dce_v11_0.o \
> > > +       amdgpu_vkms.o \
> > >         dce_virtual.o
> > >
> > >  # add GFX block
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > index 54cf647bd018..d0a2f2ed433d 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > @@ -919,6 +919,7 @@ struct amdgpu_device {
> > >
> > >         /* display */
> > >         bool                            enable_virtual_display;
> > > +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
> > >         struct amdgpu_mode_info         mode_info;
> > >         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
> > >         struct work_struct              hotplug_work;
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > index d0c935cf4f0f..1b016e5bc75f 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
> > >         int ret, retry = 0;
> > >         bool supports_atomic = false;
> > >
> > > -       if (!amdgpu_virtual_display &&
> > > +       if (amdgpu_virtual_display ||
> > >             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
> > >                 supports_atomic = true;
> > >
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > index 09b048647523..5a143ca02cf9 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
> > >         }
> > >
> > >         /* disable all the possible outputs/crtcs before entering KMS mode */
> > > -       if (!amdgpu_device_has_dc_support(adev))
> > > +       if (!amdgpu_device_has_dc_support(adev) &&
> > > + !amdgpu_virtual_display)
> > >
> > > drm_helper_disable_unused_functions(adev_to_drm(adev));
> > >
> > >         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); diff
> > > --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > new file mode 100644
> > > index 000000000000..d5c1f1c58f5f
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > @@ -0,0 +1,411 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +
> > > +#include <drm/drm_atomic_helper.h>
> > > +#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h>
> > > +
> > > +#include "amdgpu.h"
> > > +#include "amdgpu_vkms.h"
> > > +#include "amdgpu_display.h"
> > > +
> > > +/**
> > > + * DOC: amdgpu_vkms
> > > + *
> > > + * The amdgpu vkms interface provides a virtual KMS interface for
> > > +several use
> > > + * cases: devices without display hardware, platforms where the
> > > +actual display
> > > + * hardware is not useful (e.g., servers), SR-IOV virtual functions,
> > > +device
> > > + * emulation/simulation, and device bring up prior to display
> > > +hardware being
> > > + * usable. We previously emulated a legacy KMS interface, but there
> > > +was a desire
> > > + * to move to the atomic KMS interface. The vkms driver did
> > > +everything we
> > > + * needed, but we wanted KMS support natively in the driver without
> > > +buffer
> > > + * sharing and the ability to support an instance of VKMS per device.
> > > +We first
> > > + * looked at splitting vkms into a stub driver and a helper module
> > > +that other
> > > + * drivers could use to implement a virtual display, but this
> > > +strategy ended up
> > > + * being messy due to driver specific callbacks needed for buffer management.
> > > + * Ultimately, it proved easier to import the vkms code as it mostly
> > > +used core
> > > + * drm helpers anyway.
> > > + */
> > > +
> > > +static const u32 amdgpu_vkms_formats[] = {
> > > +       DRM_FORMAT_XRGB8888,
> > > +};
> > > +
> > > +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct
> > > +hrtimer *timer) {
> > > +       struct amdgpu_vkms_output *output = container_of(timer,
> > > +                                                        struct amdgpu_vkms_output,
> > > +                                                        vblank_hrtimer);
> > > +       struct drm_crtc *crtc = &output->crtc;
> > > +       u64 ret_overrun;
> > > +       bool ret;
> > > +
> > > +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> > > +                                         output->period_ns);
> > > +       WARN_ON(ret_overrun != 1);
> > > +
> > > +       ret = drm_crtc_handle_vblank(crtc);
> > > +       if (!ret)
> > > +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> > > +
> > > +       return HRTIMER_RESTART;
> > > +}
> > > +
> > > +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) {
> > > +       struct drm_device *dev = crtc->dev;
> > > +       unsigned int pipe = drm_crtc_index(crtc);
> > > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > > +       struct amdgpu_vkms_output *out =
> > > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +
> > > +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> > > +
> > > +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> > > +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> > > +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> > > +       hrtimer_start(&out->vblank_hrtimer, out->period_ns,
> > > + HRTIMER_MODE_REL);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) {
> > > +       struct amdgpu_vkms_output *out =
> > > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +
> > > +       hrtimer_cancel(&out->vblank_hrtimer);
> > > +}
> > > +
> > > +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> > > +                                            int *max_error,
> > > +                                            ktime_t *vblank_time,
> > > +                                            bool in_vblank_irq) {
> > > +       struct drm_device *dev = crtc->dev;
> > > +       unsigned int pipe = crtc->index;
> > > +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > > +
> > > +       if (!READ_ONCE(vblank->enabled)) {
> > > +               *vblank_time = ktime_get();
> > > +               return true;
> > > +       }
> > > +
> > > +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> > > +
> > > +       if (WARN_ON(*vblank_time == vblank->time))
> > > +               return true;
> > > +
> > > +       /*
> > > +        * To prevent races we roll the hrtimer forward before we do any
> > > +        * interrupt processing - this is how real hw works (the interrupt is
> > > +        * only generated after all the vblank registers are updated) and what
> > > +        * the vblank core expects. Therefore we need to always correct the
> > > +        * timestampe by one frame.
> > > +        */
> > > +       *vblank_time -= output->period_ns;
> > > +
> > > +       return true;
> > > +}
> > > +
> > > +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> > > +       .set_config             = drm_atomic_helper_set_config,
> > > +       .destroy                = drm_crtc_cleanup,
> > > +       .page_flip              = drm_atomic_helper_page_flip,
> > > +       .reset                  = drm_atomic_helper_crtc_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> > > +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> > > +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> > > +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> > > +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> > > +};
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> > > +                                          struct drm_atomic_state
> > > +*state) {
> > > +       drm_crtc_vblank_on(crtc);
> > > +}
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> > > +                                           struct drm_atomic_state
> > > +*state) {
> > > +       drm_crtc_vblank_off(crtc);
> > > +}
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> > > +                                         struct drm_atomic_state
> > > +*state) {
> > > +       if (crtc->state->event) {
> > > +               spin_lock(&crtc->dev->event_lock);
> > > +
> > > +               if (drm_crtc_vblank_get(crtc) != 0)
> > > +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> > > +               else
> > > +                       drm_crtc_arm_vblank_event(crtc,
> > > + crtc->state->event);
> > > +
> > > +               spin_unlock(&crtc->dev->event_lock);
> > > +
> > > +               crtc->state->event = NULL;
> > > +       }
> > > +}
> > > +
> > > +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> > > +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> > > +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> > > +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable, };
> > > +
> > > +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> > > +                         struct drm_plane *primary, struct drm_plane
> > > +*cursor) {
> > > +       int ret;
> > > +
> > > +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> > > +                                       &amdgpu_vkms_crtc_funcs, NULL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init CRTC\n");
> > > +               return ret;
> > > +       }
> > > +
> > > +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> > > +
> > > +       return ret;
> > > +}
> > > +
> > > +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> > > +       .fill_modes = drm_helper_probe_single_connector_modes,
> > > +       .destroy = drm_connector_cleanup,
> > > +       .reset = drm_atomic_helper_connector_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> > > +       .atomic_destroy_state =
> > > +drm_atomic_helper_connector_destroy_state,
> > > +};
> > > +
> > > +static int amdgpu_vkms_conn_get_modes(struct drm_connector
> > > +*connector) {
> > > +       int count;
> > > +
> > > +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> > > +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> > > +
> > > +       return count;
> > > +}
> > > +
> > > +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> > > +       .get_modes    = amdgpu_vkms_conn_get_modes,
> > > +};
> > > +
> > > +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> > > +       .update_plane           = drm_atomic_helper_update_plane,
> > > +       .disable_plane          = drm_atomic_helper_disable_plane,
> > > +       .destroy                = drm_plane_cleanup,
> > > +       .reset                  = drm_atomic_helper_plane_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > > +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> > > +};
> > > +
> > > +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> > > +                                           struct drm_plane_state
> > > +*old_state) {
> > > +       return;
> > > +}
> > > +
> > > +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> > > +                                         struct drm_plane_state
> > > +*state) {
> > > +       struct drm_crtc_state *crtc_state;
> > > +       bool can_position = false;
> > > +       int ret;
> > > +
> > > +       if (!state->fb || WARN_ON(!state->crtc))
> > > +               return 0;
> > > +
> > > +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> > > +       if (IS_ERR(crtc_state))
> > > +               return PTR_ERR(crtc_state);
> > > +
> > > +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> > > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > > +                                                 can_position, true);
> > > +       if (ret != 0)
> > > +               return ret;
> > > +
> > > +       /* for now primary plane must be visible and full screen */
> > > +       if (!state->visible && !can_position)
> > > +               return -EINVAL;
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> > > +                                 struct drm_plane_state *new_state) {
> > > +       struct amdgpu_framebuffer *afb;
> > > +       struct drm_gem_object *obj;
> > > +       struct amdgpu_device *adev;
> > > +       struct amdgpu_bo *rbo;
> > > +       struct list_head list;
> > > +       struct ttm_validate_buffer tv;
> > > +       struct ww_acquire_ctx ticket;
> > > +       uint32_t domain;
> > > +       int r;
> > > +
> > > +       if (!new_state->fb) {
> > > +               DRM_DEBUG_KMS("No FB bound\n");
> > > +               return 0;
> > > +       }
> > > +       afb = to_amdgpu_framebuffer(new_state->fb);
> > > +       obj = new_state->fb->obj[0];
> > > +       rbo = gem_to_amdgpu_bo(obj);
> > > +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> > > +       INIT_LIST_HEAD(&list);
> > > +
> > > +       tv.bo = &rbo->tbo;
> > > +       tv.num_shared = 1;
> > > +       list_add(&tv.head, &list);
> > > +
> > > +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> > > +       if (r) {
> > > +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> > > +               return r;
> > > +       }
> > > +
> > > +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> > > +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> > > +       else
> > > +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> > > +
> > > +       r = amdgpu_bo_pin(rbo, domain);
> > > +       if (unlikely(r != 0)) {
> > > +               if (r != -ERESTARTSYS)
> > > +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> > > +               ttm_eu_backoff_reservation(&ticket, &list);
> > > +               return r;
> > > +       }
> > > +
> > > +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> > > +       if (unlikely(r != 0)) {
> > > +               amdgpu_bo_unpin(rbo);
> > > +               ttm_eu_backoff_reservation(&ticket, &list);
> > > +               DRM_ERROR("%p bind failed\n", rbo);
> > > +               return r;
> > > +       }
> > > +
> > > +       ttm_eu_backoff_reservation(&ticket, &list);
> > > +
> > > +       afb->address = amdgpu_bo_gpu_offset(rbo);
> > > +
> > > +       amdgpu_bo_ref(rbo);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> > > +                                  struct drm_plane_state *old_state)
> > > +{
> > > +       struct amdgpu_bo *rbo;
> > > +       int r;
> > > +
> > > +       if (!old_state->fb)
> > > +               return;
> > > +
> > > +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> > > +       r = amdgpu_bo_reserve(rbo, false);
> > > +       if (unlikely(r)) {
> > > +               DRM_ERROR("failed to reserve rbo before unpin\n");
> > > +               return;
> > > +       }
> > > +
> > > +       amdgpu_bo_unpin(rbo);
> > > +       amdgpu_bo_unreserve(rbo);
> > > +       amdgpu_bo_unref(&rbo);
> > > +}
> > > +
> > > +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> > > +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> > > +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> > > +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> > > +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> > > +};
> > > +
> > > +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> > > +                                               enum drm_plane_type type,
> > > +                                               int index) {
> > > +       struct drm_plane *plane;
> > > +       int ret;
> > > +
> > > +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> > > +       if (!plane)
> > > +               return ERR_PTR(-ENOMEM);
> > > +
> > > +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> > > +                                      &amdgpu_vkms_plane_funcs,
> > > +                                      amdgpu_vkms_formats,
> > > +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> > > +                                      NULL, type, NULL);
> > > +       if (ret) {
> > > +               kfree(plane);
> > > +               return ERR_PTR(ret);
> > > +       }
> > > +
> > > +       drm_plane_helper_add(plane,
> > > + &amdgpu_vkms_primary_helper_funcs);
> > > +
> > > +       return plane;
> > > +}
> > > +
> > > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > > +                           struct amdgpu_vkms_output *output, int
> > > +index) {
> > > +       struct drm_connector *connector = &output->connector;
> > > +       struct drm_encoder *encoder = &output->encoder;
> > > +       struct drm_crtc *crtc = &output->crtc;
> > > +       struct drm_plane *primary, *cursor = NULL;
> > > +       int ret;
> > > +
> > > +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> > > +       if (IS_ERR(primary))
> > > +               return PTR_ERR(primary);
> > > +
> > > +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> > > +       if (ret)
> > > +               goto err_crtc;
> > > +
> > > +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> > > +                                DRM_MODE_CONNECTOR_VIRTUAL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init connector\n");
> > > +               goto err_connector;
> > > +       }
> > > +
> > > +       drm_connector_helper_add(connector,
> > > + &amdgpu_vkms_conn_helper_funcs);
> > > +
> > > +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init encoder\n");
> > > +               goto err_encoder;
> > > +       }
> > > +       encoder->possible_crtcs = 1 << index;
> > > +
> > > +       ret = drm_connector_attach_encoder(connector, encoder);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to attach connector to encoder\n");
> > > +               goto err_attach;
> > > +       }
> > > +
> > > +       drm_mode_config_reset(dev);
> > > +
> > > +       return 0;
> > > +
> > > +err_attach:
> > > +       drm_encoder_cleanup(encoder);
> > > +
> > > +err_encoder:
> > > +       drm_connector_cleanup(connector);
> > > +
> > > +err_connector:
> > > +       drm_crtc_cleanup(crtc);
> > > +
> > > +err_crtc:
> > > +       drm_plane_cleanup(primary);
> > > +
> > > +       return ret;
> > > +}
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > new file mode 100644
> > > index 000000000000..5dab51fbecf3
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > @@ -0,0 +1,29 @@
> > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > +
> > > +#ifndef _AMDGPU_VKMS_H_
> > > +#define _AMDGPU_VKMS_H_
> > > +
> > > +#define XRES_DEF  1024
> > > +#define YRES_DEF   764
> >
> > Squash in the 768 fix here.
> >
> > > +
> > > +#define XRES_MAX  16384
> > > +#define YRES_MAX  16384
> > > +
> > > +#define drm_crtc_to_amdgpu_vkms_output(target) \
> > > +       container_of(target, struct amdgpu_vkms_output, crtc)
> > > +
> > > +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> > > +
> > > +struct amdgpu_vkms_output {
> > > +       struct drm_crtc crtc;
> > > +       struct drm_encoder encoder;
> > > +       struct drm_connector connector;
> > > +       struct hrtimer vblank_hrtimer;
> > > +       ktime_t period_ns;
> > > +       struct drm_pending_vblank_event *event; };
> > > +
> > > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > > +                           struct amdgpu_vkms_output *output, int
> > > +index);
> > > +
> > > +#endif /* _AMDGPU_VKMS_H_ */
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > index 7e0d8c092c7e..642c77533157 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > @@ -22,6 +22,7 @@
> > >   */
> > >
> > >  #include <drm/drm_vblank.h>
> > > +#include <drm/drm_atomic_helper.h>
> > >
> > >  #include "amdgpu.h"
> > >  #include "amdgpu_pm.h"
> > > @@ -40,6 +41,7 @@
> > >  #include "dce_virtual.h"
> > >  #include "ivsrcid/ivsrcid_vislands30.h"
> > >  #include "amdgpu_display.h"
> > > +#include "amdgpu_vkms.h"
> > >
> > >  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
> > >
> > > @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
> > >         .force = dce_virtual_force,
> > >  };
> > >
> > > +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> > > +       .fb_create = amdgpu_display_user_framebuffer_create,
> > > +       .atomic_check = drm_atomic_helper_check,
> > > +       .atomic_commit = drm_atomic_helper_commit, };
> > > +
> > >  static int dce_virtual_sw_init(void *handle)  {
> > >         int r, i;
> > > @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
> > >
> > >         adev_to_drm(adev)->max_vblank_count = 0;
> > >
> > > -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> > > +       adev_to_drm(adev)->mode_config.funcs =
> > > + &dce_virtual_mode_funcs;
> > >
> > > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > > +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> > > +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> > >
> > >         adev_to_drm(adev)->mode_config.preferred_depth = 24;
> > >         adev_to_drm(adev)->mode_config.prefer_shadow = 1; @@ -399,15
> > > +407,11 @@ static int dce_virtual_sw_init(void *handle)
> > >         if (r)
> > >                 return r;
> > >
> > > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > > +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct
> > > + amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> >
> > You can use kcalloc here.
> >
> > >
> > >         /* allocate crtcs, encoders, connectors */
> > >         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> > > -               r = dce_virtual_crtc_init(adev, i);
> > > -               if (r)
> > > -                       return r;
> > > -               r = dce_virtual_connector_encoder_init(adev, i);
> > > +               r = amdgpu_vkms_output_init(adev_to_drm(adev),
> > > + &adev->amdgpu_vkms_output[i], i);
> > >                 if (r)
> > >                         return r;
> > >         }
> > > @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
> > >
> > > hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> > >
> > >         kfree(adev->mode_info.bios_hardcoded_edid);
> > > +       kfree(adev->amdgpu_vkms_output);
> > >
> > >         drm_kms_helper_poll_fini(adev_to_drm(adev));
> > >
> > > --
> > > 2.32.0
> > >
> > > _______________________________________________
> > > amd-gfx mailing list
> > > amd-gfx@lists.freedesktop.org
> > > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flist
> > > s.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cgu
> > > chun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884
> > > e608e11a82d994e183d%7C0%7C0%7C637626475284480052%7CUnknown%7CTWFpbGZsb
> > > 3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%
> > > 7C1000&amp;sdata=0bbTKflaP2RPk%2BpboaNNiwffbEw1pW0zkqcxzPWjzmI%3D&amp;
> > > reserved=0
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7CRyan.Taylor%40amd.com%7Cbaa2d803835b411fdc0408d95056aa89%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637629155949319404%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=gqJcTtUbjxhBYg2k5rg1KunDoCJxPi%2BrrLOKrLb10RM%3D&amp;reserved=0

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

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

* Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
@ 2021-07-26 17:02               ` Taylor, Ryan
  0 siblings, 0 replies; 24+ messages in thread
From: Taylor, Ryan @ 2021-07-26 17:02 UTC (permalink / raw)
  To: Alex Deucher
  Cc: kernel test robot, Chen, Guchun, Daniel Vetter, Siqueira,
	Rodrigo, amd-gfx list, Melissa Wen, Maling list - DRI developers


[-- Attachment #1.1: Type: text/plain, Size: 29268 bytes --]

[AMD Official Use Only]

Sounds good, Thanks for clarifying. Thanks for the input Guchun.

Best,
Ryan
________________________________
From: Alex Deucher <alexdeucher@gmail.com>
Sent: Monday, July 26, 2021 9:58 AM
To: Taylor, Ryan <Ryan.Taylor@amd.com>
Cc: Chen, Guchun <Guchun.Chen@amd.com>; kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)

On Mon, Jul 26, 2021 at 12:39 PM Taylor, Ryan <Ryan.Taylor@amd.com> wrote:
>
> [AMD Official Use Only]
>
>
> Given that amdgpu_vkms contains code from both dce_virtual and vkms should the identifier be changed to GPL-2.0+ OR MIT like in amdgpu_res_cursor.h?

Most of the code is from vkms so match vkms.

Alex


>
> Best,
> Ryan
> ________________________________
> From: Alex Deucher <alexdeucher@gmail.com>
> Sent: Monday, July 26, 2021 9:21 AM
> To: Chen, Guchun <Guchun.Chen@amd.com>
> Cc: Taylor, Ryan <Ryan.Taylor@amd.com>; kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
>
> On Fri, Jul 23, 2021 at 10:07 PM Chen, Guchun <Guchun.Chen@amd.com> wrote:
> >
> > [Public]
> >
> > Look copy right statement is missed in both amdgpu_vkms.c and amdgpu_vkms.h.
>
> It's there, it just uses the newer SPDX license identifier.
>
> Alex
>
>
> >
> > Regards,
> > Guchun
> >
> > -----Original Message-----
> > From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Alex Deucher
> > Sent: Friday, July 23, 2021 10:32 PM
> > To: Taylor, Ryan <Ryan.Taylor@amd.com>
> > Cc: kernel test robot <lkp@intel.com>; Daniel Vetter <daniel.vetter@ffwll.ch>; Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; amd-gfx list <amd-gfx@lists.freedesktop.org>; Melissa Wen <melissa.srw@gmail.com>; Maling list - DRI developers <dri-devel@lists.freedesktop.org>
> > Subject: Re: [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2)
> >
> > On Wed, Jul 21, 2021 at 1:07 PM Ryan Taylor <Ryan.Taylor@amd.com> wrote:
> > >
> > > Modify the VKMS driver into an api that dce_virtual can use to create
> > > virtual displays that obey drm's atomic modesetting api.
> > >
> > > v2: Made local functions static.
> > >
> > > Reported-by: kernel test robot <lkp@intel.com>
> > > Signed-off-by: Ryan Taylor <Ryan.Taylor@amd.com>
> > > ---
> > >  drivers/gpu/drm/amd/amdgpu/Makefile      |   1 +
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu.h      |   1 +
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |   2 +-
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c   |   2 +-
> > >  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 411
> > > +++++++++++++++++++++++  drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h |
> > > 29 ++  drivers/gpu/drm/amd/amdgpu/dce_virtual.c |  23 +-
> > >  7 files changed, 458 insertions(+), 11 deletions(-)  create mode
> > > 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > >  create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > >
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile
> > > b/drivers/gpu/drm/amd/amdgpu/Makefile
> > > index f089794bbdd5..30cbcd5ce1cc 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/Makefile
> > > +++ b/drivers/gpu/drm/amd/amdgpu/Makefile
> > > @@ -120,6 +120,7 @@ amdgpu-y += \
> > >  amdgpu-y += \
> > >         dce_v10_0.o \
> > >         dce_v11_0.o \
> > > +       amdgpu_vkms.o \
> > >         dce_virtual.o
> > >
> > >  # add GFX block
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > index 54cf647bd018..d0a2f2ed433d 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> > > @@ -919,6 +919,7 @@ struct amdgpu_device {
> > >
> > >         /* display */
> > >         bool                            enable_virtual_display;
> > > +       struct amdgpu_vkms_output       *amdgpu_vkms_output;
> > >         struct amdgpu_mode_info         mode_info;
> > >         /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
> > >         struct work_struct              hotplug_work;
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > index d0c935cf4f0f..1b016e5bc75f 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > > @@ -1230,7 +1230,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
> > >         int ret, retry = 0;
> > >         bool supports_atomic = false;
> > >
> > > -       if (!amdgpu_virtual_display &&
> > > +       if (amdgpu_virtual_display ||
> > >             amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
> > >                 supports_atomic = true;
> > >
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > index 09b048647523..5a143ca02cf9 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
> > > @@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
> > >         }
> > >
> > >         /* disable all the possible outputs/crtcs before entering KMS mode */
> > > -       if (!amdgpu_device_has_dc_support(adev))
> > > +       if (!amdgpu_device_has_dc_support(adev) &&
> > > + !amdgpu_virtual_display)
> > >
> > > drm_helper_disable_unused_functions(adev_to_drm(adev));
> > >
> > >         drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); diff
> > > --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > new file mode 100644
> > > index 000000000000..d5c1f1c58f5f
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
> > > @@ -0,0 +1,411 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +
> > > +#include <drm/drm_atomic_helper.h>
> > > +#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h>
> > > +
> > > +#include "amdgpu.h"
> > > +#include "amdgpu_vkms.h"
> > > +#include "amdgpu_display.h"
> > > +
> > > +/**
> > > + * DOC: amdgpu_vkms
> > > + *
> > > + * The amdgpu vkms interface provides a virtual KMS interface for
> > > +several use
> > > + * cases: devices without display hardware, platforms where the
> > > +actual display
> > > + * hardware is not useful (e.g., servers), SR-IOV virtual functions,
> > > +device
> > > + * emulation/simulation, and device bring up prior to display
> > > +hardware being
> > > + * usable. We previously emulated a legacy KMS interface, but there
> > > +was a desire
> > > + * to move to the atomic KMS interface. The vkms driver did
> > > +everything we
> > > + * needed, but we wanted KMS support natively in the driver without
> > > +buffer
> > > + * sharing and the ability to support an instance of VKMS per device.
> > > +We first
> > > + * looked at splitting vkms into a stub driver and a helper module
> > > +that other
> > > + * drivers could use to implement a virtual display, but this
> > > +strategy ended up
> > > + * being messy due to driver specific callbacks needed for buffer management.
> > > + * Ultimately, it proved easier to import the vkms code as it mostly
> > > +used core
> > > + * drm helpers anyway.
> > > + */
> > > +
> > > +static const u32 amdgpu_vkms_formats[] = {
> > > +       DRM_FORMAT_XRGB8888,
> > > +};
> > > +
> > > +static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct
> > > +hrtimer *timer) {
> > > +       struct amdgpu_vkms_output *output = container_of(timer,
> > > +                                                        struct amdgpu_vkms_output,
> > > +                                                        vblank_hrtimer);
> > > +       struct drm_crtc *crtc = &output->crtc;
> > > +       u64 ret_overrun;
> > > +       bool ret;
> > > +
> > > +       ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
> > > +                                         output->period_ns);
> > > +       WARN_ON(ret_overrun != 1);
> > > +
> > > +       ret = drm_crtc_handle_vblank(crtc);
> > > +       if (!ret)
> > > +               DRM_ERROR("amdgpu_vkms failure on handling vblank");
> > > +
> > > +       return HRTIMER_RESTART;
> > > +}
> > > +
> > > +static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc) {
> > > +       struct drm_device *dev = crtc->dev;
> > > +       unsigned int pipe = drm_crtc_index(crtc);
> > > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > > +       struct amdgpu_vkms_output *out =
> > > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +
> > > +       drm_calc_timestamping_constants(crtc, &crtc->mode);
> > > +
> > > +       hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> > > +       out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
> > > +       out->period_ns = ktime_set(0, vblank->framedur_ns);
> > > +       hrtimer_start(&out->vblank_hrtimer, out->period_ns,
> > > + HRTIMER_MODE_REL);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc) {
> > > +       struct amdgpu_vkms_output *out =
> > > +drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +
> > > +       hrtimer_cancel(&out->vblank_hrtimer);
> > > +}
> > > +
> > > +static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
> > > +                                            int *max_error,
> > > +                                            ktime_t *vblank_time,
> > > +                                            bool in_vblank_irq) {
> > > +       struct drm_device *dev = crtc->dev;
> > > +       unsigned int pipe = crtc->index;
> > > +       struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
> > > +       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> > > +
> > > +       if (!READ_ONCE(vblank->enabled)) {
> > > +               *vblank_time = ktime_get();
> > > +               return true;
> > > +       }
> > > +
> > > +       *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
> > > +
> > > +       if (WARN_ON(*vblank_time == vblank->time))
> > > +               return true;
> > > +
> > > +       /*
> > > +        * To prevent races we roll the hrtimer forward before we do any
> > > +        * interrupt processing - this is how real hw works (the interrupt is
> > > +        * only generated after all the vblank registers are updated) and what
> > > +        * the vblank core expects. Therefore we need to always correct the
> > > +        * timestampe by one frame.
> > > +        */
> > > +       *vblank_time -= output->period_ns;
> > > +
> > > +       return true;
> > > +}
> > > +
> > > +static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
> > > +       .set_config             = drm_atomic_helper_set_config,
> > > +       .destroy                = drm_crtc_cleanup,
> > > +       .page_flip              = drm_atomic_helper_page_flip,
> > > +       .reset                  = drm_atomic_helper_crtc_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> > > +       .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
> > > +       .enable_vblank          = amdgpu_vkms_enable_vblank,
> > > +       .disable_vblank         = amdgpu_vkms_disable_vblank,
> > > +       .get_vblank_timestamp   = amdgpu_vkms_get_vblank_timestamp,
> > > +};
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
> > > +                                          struct drm_atomic_state
> > > +*state) {
> > > +       drm_crtc_vblank_on(crtc);
> > > +}
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
> > > +                                           struct drm_atomic_state
> > > +*state) {
> > > +       drm_crtc_vblank_off(crtc);
> > > +}
> > > +
> > > +static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
> > > +                                         struct drm_atomic_state
> > > +*state) {
> > > +       if (crtc->state->event) {
> > > +               spin_lock(&crtc->dev->event_lock);
> > > +
> > > +               if (drm_crtc_vblank_get(crtc) != 0)
> > > +                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
> > > +               else
> > > +                       drm_crtc_arm_vblank_event(crtc,
> > > + crtc->state->event);
> > > +
> > > +               spin_unlock(&crtc->dev->event_lock);
> > > +
> > > +               crtc->state->event = NULL;
> > > +       }
> > > +}
> > > +
> > > +static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
> > > +       .atomic_flush   = amdgpu_vkms_crtc_atomic_flush,
> > > +       .atomic_enable  = amdgpu_vkms_crtc_atomic_enable,
> > > +       .atomic_disable = amdgpu_vkms_crtc_atomic_disable, };
> > > +
> > > +static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> > > +                         struct drm_plane *primary, struct drm_plane
> > > +*cursor) {
> > > +       int ret;
> > > +
> > > +       ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
> > > +                                       &amdgpu_vkms_crtc_funcs, NULL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init CRTC\n");
> > > +               return ret;
> > > +       }
> > > +
> > > +       drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
> > > +
> > > +       return ret;
> > > +}
> > > +
> > > +static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
> > > +       .fill_modes = drm_helper_probe_single_connector_modes,
> > > +       .destroy = drm_connector_cleanup,
> > > +       .reset = drm_atomic_helper_connector_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> > > +       .atomic_destroy_state =
> > > +drm_atomic_helper_connector_destroy_state,
> > > +};
> > > +
> > > +static int amdgpu_vkms_conn_get_modes(struct drm_connector
> > > +*connector) {
> > > +       int count;
> > > +
> > > +       count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
> > > +       drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
> > > +
> > > +       return count;
> > > +}
> > > +
> > > +static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
> > > +       .get_modes    = amdgpu_vkms_conn_get_modes,
> > > +};
> > > +
> > > +static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
> > > +       .update_plane           = drm_atomic_helper_update_plane,
> > > +       .disable_plane          = drm_atomic_helper_disable_plane,
> > > +       .destroy                = drm_plane_cleanup,
> > > +       .reset                  = drm_atomic_helper_plane_reset,
> > > +       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> > > +       .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
> > > +};
> > > +
> > > +static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
> > > +                                           struct drm_plane_state
> > > +*old_state) {
> > > +       return;
> > > +}
> > > +
> > > +static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
> > > +                                         struct drm_plane_state
> > > +*state) {
> > > +       struct drm_crtc_state *crtc_state;
> > > +       bool can_position = false;
> > > +       int ret;
> > > +
> > > +       if (!state->fb || WARN_ON(!state->crtc))
> > > +               return 0;
> > > +
> > > +       crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> > > +       if (IS_ERR(crtc_state))
> > > +               return PTR_ERR(crtc_state);
> > > +
> > > +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
> > > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > > +                                                 DRM_PLANE_HELPER_NO_SCALING,
> > > +                                                 can_position, true);
> > > +       if (ret != 0)
> > > +               return ret;
> > > +
> > > +       /* for now primary plane must be visible and full screen */
> > > +       if (!state->visible && !can_position)
> > > +               return -EINVAL;
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
> > > +                                 struct drm_plane_state *new_state) {
> > > +       struct amdgpu_framebuffer *afb;
> > > +       struct drm_gem_object *obj;
> > > +       struct amdgpu_device *adev;
> > > +       struct amdgpu_bo *rbo;
> > > +       struct list_head list;
> > > +       struct ttm_validate_buffer tv;
> > > +       struct ww_acquire_ctx ticket;
> > > +       uint32_t domain;
> > > +       int r;
> > > +
> > > +       if (!new_state->fb) {
> > > +               DRM_DEBUG_KMS("No FB bound\n");
> > > +               return 0;
> > > +       }
> > > +       afb = to_amdgpu_framebuffer(new_state->fb);
> > > +       obj = new_state->fb->obj[0];
> > > +       rbo = gem_to_amdgpu_bo(obj);
> > > +       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
> > > +       INIT_LIST_HEAD(&list);
> > > +
> > > +       tv.bo = &rbo->tbo;
> > > +       tv.num_shared = 1;
> > > +       list_add(&tv.head, &list);
> > > +
> > > +       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
> > > +       if (r) {
> > > +               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
> > > +               return r;
> > > +       }
> > > +
> > > +       if (plane->type != DRM_PLANE_TYPE_CURSOR)
> > > +               domain = amdgpu_display_supported_domains(adev, rbo->flags);
> > > +       else
> > > +               domain = AMDGPU_GEM_DOMAIN_VRAM;
> > > +
> > > +       r = amdgpu_bo_pin(rbo, domain);
> > > +       if (unlikely(r != 0)) {
> > > +               if (r != -ERESTARTSYS)
> > > +                       DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
> > > +               ttm_eu_backoff_reservation(&ticket, &list);
> > > +               return r;
> > > +       }
> > > +
> > > +       r = amdgpu_ttm_alloc_gart(&rbo->tbo);
> > > +       if (unlikely(r != 0)) {
> > > +               amdgpu_bo_unpin(rbo);
> > > +               ttm_eu_backoff_reservation(&ticket, &list);
> > > +               DRM_ERROR("%p bind failed\n", rbo);
> > > +               return r;
> > > +       }
> > > +
> > > +       ttm_eu_backoff_reservation(&ticket, &list);
> > > +
> > > +       afb->address = amdgpu_bo_gpu_offset(rbo);
> > > +
> > > +       amdgpu_bo_ref(rbo);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
> > > +                                  struct drm_plane_state *old_state)
> > > +{
> > > +       struct amdgpu_bo *rbo;
> > > +       int r;
> > > +
> > > +       if (!old_state->fb)
> > > +               return;
> > > +
> > > +       rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
> > > +       r = amdgpu_bo_reserve(rbo, false);
> > > +       if (unlikely(r)) {
> > > +               DRM_ERROR("failed to reserve rbo before unpin\n");
> > > +               return;
> > > +       }
> > > +
> > > +       amdgpu_bo_unpin(rbo);
> > > +       amdgpu_bo_unreserve(rbo);
> > > +       amdgpu_bo_unref(&rbo);
> > > +}
> > > +
> > > +static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
> > > +       .atomic_update          = amdgpu_vkms_plane_atomic_update,
> > > +       .atomic_check           = amdgpu_vkms_plane_atomic_check,
> > > +       .prepare_fb             = amdgpu_vkms_prepare_fb,
> > > +       .cleanup_fb             = amdgpu_vkms_cleanup_fb,
> > > +};
> > > +
> > > +static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
> > > +                                               enum drm_plane_type type,
> > > +                                               int index) {
> > > +       struct drm_plane *plane;
> > > +       int ret;
> > > +
> > > +       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
> > > +       if (!plane)
> > > +               return ERR_PTR(-ENOMEM);
> > > +
> > > +       ret = drm_universal_plane_init(dev, plane, 1 << index,
> > > +                                      &amdgpu_vkms_plane_funcs,
> > > +                                      amdgpu_vkms_formats,
> > > +                                      ARRAY_SIZE(amdgpu_vkms_formats),
> > > +                                      NULL, type, NULL);
> > > +       if (ret) {
> > > +               kfree(plane);
> > > +               return ERR_PTR(ret);
> > > +       }
> > > +
> > > +       drm_plane_helper_add(plane,
> > > + &amdgpu_vkms_primary_helper_funcs);
> > > +
> > > +       return plane;
> > > +}
> > > +
> > > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > > +                           struct amdgpu_vkms_output *output, int
> > > +index) {
> > > +       struct drm_connector *connector = &output->connector;
> > > +       struct drm_encoder *encoder = &output->encoder;
> > > +       struct drm_crtc *crtc = &output->crtc;
> > > +       struct drm_plane *primary, *cursor = NULL;
> > > +       int ret;
> > > +
> > > +       primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
> > > +       if (IS_ERR(primary))
> > > +               return PTR_ERR(primary);
> > > +
> > > +       ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
> > > +       if (ret)
> > > +               goto err_crtc;
> > > +
> > > +       ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
> > > +                                DRM_MODE_CONNECTOR_VIRTUAL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init connector\n");
> > > +               goto err_connector;
> > > +       }
> > > +
> > > +       drm_connector_helper_add(connector,
> > > + &amdgpu_vkms_conn_helper_funcs);
> > > +
> > > +       ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to init encoder\n");
> > > +               goto err_encoder;
> > > +       }
> > > +       encoder->possible_crtcs = 1 << index;
> > > +
> > > +       ret = drm_connector_attach_encoder(connector, encoder);
> > > +       if (ret) {
> > > +               DRM_ERROR("Failed to attach connector to encoder\n");
> > > +               goto err_attach;
> > > +       }
> > > +
> > > +       drm_mode_config_reset(dev);
> > > +
> > > +       return 0;
> > > +
> > > +err_attach:
> > > +       drm_encoder_cleanup(encoder);
> > > +
> > > +err_encoder:
> > > +       drm_connector_cleanup(connector);
> > > +
> > > +err_connector:
> > > +       drm_crtc_cleanup(crtc);
> > > +
> > > +err_crtc:
> > > +       drm_plane_cleanup(primary);
> > > +
> > > +       return ret;
> > > +}
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > new file mode 100644
> > > index 000000000000..5dab51fbecf3
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.h
> > > @@ -0,0 +1,29 @@
> > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > +
> > > +#ifndef _AMDGPU_VKMS_H_
> > > +#define _AMDGPU_VKMS_H_
> > > +
> > > +#define XRES_DEF  1024
> > > +#define YRES_DEF   764
> >
> > Squash in the 768 fix here.
> >
> > > +
> > > +#define XRES_MAX  16384
> > > +#define YRES_MAX  16384
> > > +
> > > +#define drm_crtc_to_amdgpu_vkms_output(target) \
> > > +       container_of(target, struct amdgpu_vkms_output, crtc)
> > > +
> > > +extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
> > > +
> > > +struct amdgpu_vkms_output {
> > > +       struct drm_crtc crtc;
> > > +       struct drm_encoder encoder;
> > > +       struct drm_connector connector;
> > > +       struct hrtimer vblank_hrtimer;
> > > +       ktime_t period_ns;
> > > +       struct drm_pending_vblank_event *event; };
> > > +
> > > +int amdgpu_vkms_output_init(struct drm_device *dev,
> > > +                           struct amdgpu_vkms_output *output, int
> > > +index);
> > > +
> > > +#endif /* _AMDGPU_VKMS_H_ */
> > > diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > index 7e0d8c092c7e..642c77533157 100644
> > > --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> > > @@ -22,6 +22,7 @@
> > >   */
> > >
> > >  #include <drm/drm_vblank.h>
> > > +#include <drm/drm_atomic_helper.h>
> > >
> > >  #include "amdgpu.h"
> > >  #include "amdgpu_pm.h"
> > > @@ -40,6 +41,7 @@
> > >  #include "dce_virtual.h"
> > >  #include "ivsrcid/ivsrcid_vislands30.h"
> > >  #include "amdgpu_display.h"
> > > +#include "amdgpu_vkms.h"
> > >
> > >  #define DCE_VIRTUAL_VBLANK_PERIOD 16666666
> > >
> > > @@ -374,6 +376,12 @@ static const struct drm_connector_funcs dce_virtual_connector_funcs = {
> > >         .force = dce_virtual_force,
> > >  };
> > >
> > > +const struct drm_mode_config_funcs dce_virtual_mode_funcs = {
> > > +       .fb_create = amdgpu_display_user_framebuffer_create,
> > > +       .atomic_check = drm_atomic_helper_check,
> > > +       .atomic_commit = drm_atomic_helper_commit, };
> > > +
> > >  static int dce_virtual_sw_init(void *handle)  {
> > >         int r, i;
> > > @@ -385,10 +393,10 @@ static int dce_virtual_sw_init(void *handle)
> > >
> > >         adev_to_drm(adev)->max_vblank_count = 0;
> > >
> > > -       adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
> > > +       adev_to_drm(adev)->mode_config.funcs =
> > > + &dce_virtual_mode_funcs;
> > >
> > > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > > +       adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
> > > +       adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
> > >
> > >         adev_to_drm(adev)->mode_config.preferred_depth = 24;
> > >         adev_to_drm(adev)->mode_config.prefer_shadow = 1; @@ -399,15
> > > +407,11 @@ static int dce_virtual_sw_init(void *handle)
> > >         if (r)
> > >                 return r;
> > >
> > > -       adev_to_drm(adev)->mode_config.max_width = 16384;
> > > -       adev_to_drm(adev)->mode_config.max_height = 16384;
> > > +       adev->amdgpu_vkms_output = kzalloc(sizeof(struct
> > > + amdgpu_vkms_output) * adev->mode_info.num_crtc, GFP_KERNEL);
> >
> > You can use kcalloc here.
> >
> > >
> > >         /* allocate crtcs, encoders, connectors */
> > >         for (i = 0; i < adev->mode_info.num_crtc; i++) {
> > > -               r = dce_virtual_crtc_init(adev, i);
> > > -               if (r)
> > > -                       return r;
> > > -               r = dce_virtual_connector_encoder_init(adev, i);
> > > +               r = amdgpu_vkms_output_init(adev_to_drm(adev),
> > > + &adev->amdgpu_vkms_output[i], i);
> > >                 if (r)
> > >                         return r;
> > >         }
> > > @@ -428,6 +432,7 @@ static int dce_virtual_sw_fini(void *handle)
> > >
> > > hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
> > >
> > >         kfree(adev->mode_info.bios_hardcoded_edid);
> > > +       kfree(adev->amdgpu_vkms_output);
> > >
> > >         drm_kms_helper_poll_fini(adev_to_drm(adev));
> > >
> > > --
> > > 2.32.0
> > >
> > > _______________________________________________
> > > amd-gfx mailing list
> > > amd-gfx@lists.freedesktop.org
> > > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flist
> > > s.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cgu
> > > chun.chen%40amd.com%7Ce4b064b3485c4865df8608d94de6a58e%7C3dd8961fe4884
> > > e608e11a82d994e183d%7C0%7C0%7C637626475284480052%7CUnknown%7CTWFpbGZsb
> > > 3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%
> > > 7C1000&amp;sdata=0bbTKflaP2RPk%2BpboaNNiwffbEw1pW0zkqcxzPWjzmI%3D&amp;
> > > reserved=0
> > _______________________________________________
> > amd-gfx mailing list
> > amd-gfx@lists.freedesktop.org
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7CRyan.Taylor%40amd.com%7Cbaa2d803835b411fdc0408d95056aa89%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637629155949319404%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=gqJcTtUbjxhBYg2k5rg1KunDoCJxPi%2BrrLOKrLb10RM%3D&amp;reserved=0

[-- Attachment #1.2: Type: text/html, Size: 58488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

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

end of thread, other threads:[~2021-07-26 17:02 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-21 17:07 [PATCH 0/3] drm/amdgpu: modernize virtual display feature Ryan Taylor
2021-07-21 17:07 ` Ryan Taylor
2021-07-21 17:07 ` [PATCH 1/3] drm/amdgpu: create amdgpu_vkms (v2) Ryan Taylor
2021-07-21 17:07   ` Ryan Taylor
2021-07-23 14:31   ` Alex Deucher
2021-07-23 14:31     ` Alex Deucher
2021-07-24  2:07     ` Chen, Guchun
2021-07-24  2:07       ` Chen, Guchun
2021-07-26 16:21       ` Alex Deucher
2021-07-26 16:21         ` Alex Deucher
2021-07-26 16:39         ` Taylor, Ryan
2021-07-26 16:39           ` Taylor, Ryan
2021-07-26 16:58           ` Alex Deucher
2021-07-26 16:58             ` Alex Deucher
2021-07-26 17:02             ` Taylor, Ryan
2021-07-26 17:02               ` Taylor, Ryan
2021-07-21 17:07 ` [PATCH 2/3] drm/amdgpu: cleanup dce_virtual Ryan Taylor
2021-07-21 17:07   ` Ryan Taylor
2021-07-21 17:07 ` [PATCH 3/3] drm/amdgpu: replace dce_virtual with amdgpu_vkms (v3) Ryan Taylor
2021-07-21 17:07   ` Ryan Taylor
2021-07-23 14:33   ` Alex Deucher
2021-07-23 14:33     ` Alex Deucher
2021-07-23 15:50     ` Taylor, Ryan
2021-07-23 15:50       ` Taylor, Ryan

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.