[PATCH 2/7] drm/udl: Convert to struct drm_simple_display_pipe

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Udl has a single display pipeline with aprimary plane; perfect for
simple-pipe helpers. Convert it over. The old encoder and CRTC code
becomes unused and obsolete.

Exported formats for the primary plane are RGB565 and XRGB8888, with
the latter being emulated. The 16-bit format is the default and what
is used when communicating with the device.

This patch enables atomic modesetting for udl devices.

Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx>
---
 drivers/gpu/drm/udl/udl_connector.c |  12 +--
 drivers/gpu/drm/udl/udl_drv.c       |   9 +-
 drivers/gpu/drm/udl/udl_drv.h       |   4 +-
 drivers/gpu/drm/udl/udl_modeset.c   | 142 ++++++++++++++++++++++++----
 4 files changed, 136 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index 68e113ae44f7..47ab8d150f1a 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -7,6 +7,7 @@
  * Copyright (C) 2009 Bernie Thompson <bernie@xxxxxxxxxxxx>
  */
 
+#include <drm/drm_atomic_state_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_probe_helper.h>
 
@@ -90,13 +91,6 @@ udl_detect(struct drm_connector *connector, bool force)
 	return connector_status_connected;
 }
 
-static int udl_connector_set_property(struct drm_connector *connector,
-				      struct drm_property *property,
-				      uint64_t val)
-{
-	return 0;
-}
-
 static void udl_connector_destroy(struct drm_connector *connector)
 {
 	struct udl_drm_connector *udl_connector =
@@ -117,10 +111,12 @@ static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
 
 static const struct drm_connector_funcs udl_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
 	.detect = udl_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = udl_connector_destroy,
-	.set_property = udl_connector_set_property,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
 };
 
 struct drm_connector *udl_connector_init(struct drm_device *dev)
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index d5783fa32c5b..b3fa6bf41acc 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -21,17 +21,14 @@ static int udl_usb_suspend(struct usb_interface *interface,
 {
 	struct drm_device *dev = usb_get_intfdata(interface);
 
-	drm_kms_helper_poll_disable(dev);
-	return 0;
+	return drm_mode_config_helper_suspend(dev);
 }
 
 static int udl_usb_resume(struct usb_interface *interface)
 {
 	struct drm_device *dev = usb_get_intfdata(interface);
 
-	drm_kms_helper_poll_enable(dev);
-	udl_modeset_restore(dev);
-	return 0;
+	return drm_mode_config_helper_resume(dev);
 }
 
 DEFINE_DRM_GEM_FOPS(udl_driver_fops);
@@ -45,7 +42,7 @@ static void udl_driver_release(struct drm_device *dev)
 }
 
 static struct drm_driver driver = {
-	.driver_features = DRIVER_MODESET | DRIVER_GEM,
+	.driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
 	.release = udl_driver_release,
 
 	/* gem hooks */
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index 8dc04717abac..23346bdc74bc 100644
--- a/drivers/gpu/drm/udl/udl_drv.h
+++ b/drivers/gpu/drm/udl/udl_drv.h
@@ -17,6 +17,7 @@
 #include <drm/drm_device.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem.h>
+#include <drm/drm_simple_kms_helper.h>
 
 struct drm_encoder;
 struct drm_mode_create_dumb;
@@ -53,6 +54,8 @@ struct udl_device {
 	struct usb_device *udev;
 	struct drm_crtc *crtc;
 
+	struct drm_simple_display_pipe display_pipe;
+
 	/* active framebuffer on the 16-bit channel */
 	const struct drm_framebuffer *active_fb_16;
 	spinlock_t active_fb_16_lock;
@@ -76,7 +79,6 @@ struct udl_device {
 
 /* modeset */
 int udl_modeset_init(struct drm_device *dev);
-void udl_modeset_restore(struct drm_device *dev);
 void udl_modeset_cleanup(struct drm_device *dev);
 struct drm_connector *udl_connector_init(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index 5bb1522036c7..c8bd438de6e9 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -9,12 +9,16 @@
 
  */
 
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_vblank.h>
 
 #include "udl_drv.h"
 
+#define UDL_COLOR_DEPTH_16BPP	0
+
 /*
  * All DisplayLink bulk operations start with 0xAF, followed by specific code
  * All operations are written to buffers which then later get sent to device
@@ -415,14 +419,126 @@ static int udl_crtc_init(struct drm_device *dev)
 	return 0;
 }
 
+/*
+ * Simple display pipeline
+ */
+
+static const uint32_t udl_simple_display_pipe_formats[] = {
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+};
+
+static enum drm_mode_status
+udl_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
+				   const struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static void
+udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
+			       struct drm_crtc_state *crtc_state,
+			       struct drm_plane_state *plane_state)
+{
+	struct drm_crtc *crtc = &pipe->crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_framebuffer *fb = plane_state->fb;
+	struct udl_device *udl = dev->dev_private;
+	struct drm_display_mode *mode = &crtc_state->mode;
+	char *buf;
+	char *wrptr;
+	int color_depth = UDL_COLOR_DEPTH_16BPP;
+
+	udl->crtc = crtc;
+
+	buf = (char *)udl->mode_buf;
+
+	/* This first section has to do with setting the base address on the
+	 * controller associated with the display. There are 2 base
+	 * pointers, currently, we only use the 16 bpp segment.
+	 */
+	wrptr = udl_vidreg_lock(buf);
+	wrptr = udl_set_color_depth(wrptr, color_depth);
+	/* set base for 16bpp segment to 0 */
+	wrptr = udl_set_base16bpp(wrptr, 0);
+	/* set base for 8bpp segment to end of fb */
+	wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay);
+
+	wrptr = udl_set_vid_cmds(wrptr, mode);
+	wrptr = udl_set_blank(wrptr, DRM_MODE_DPMS_ON);
+	wrptr = udl_vidreg_unlock(wrptr);
+
+	wrptr = udl_dummy_render(wrptr);
+
+	spin_lock(&udl->active_fb_16_lock);
+	udl->active_fb_16 = fb;
+	spin_unlock(&udl->active_fb_16_lock);
+	udl->mode_buf_len = wrptr - buf;
+
+	udl_handle_damage(fb, 0, 0, fb->width, fb->height);
+
+	udl_crtc_dpms(&pipe->crtc, DRM_MODE_DPMS_ON);
+
+	crtc_state->no_vblank = true;
+}
+
+static void
+udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+	udl_crtc_dpms(&pipe->crtc, DRM_MODE_DPMS_OFF);
+}
+
+static int
+udl_simple_display_pipe_check(struct drm_simple_display_pipe *pipe,
+			      struct drm_plane_state *plane_state,
+			      struct drm_crtc_state *crtc_state)
+{
+	return 0;
+}
+
+static void
+udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
+			       struct drm_plane_state *old_plane_state)
+{
+	struct drm_device *dev = pipe->crtc.dev;
+	struct udl_device *udl = dev->dev_private;
+	struct drm_framebuffer *fb = pipe->plane.state->fb;
+
+	spin_lock(&udl->active_fb_16_lock);
+	udl->active_fb_16 = fb;
+	spin_unlock(&udl->active_fb_16_lock);
+
+	if (!fb)
+		return;
+
+	udl_handle_damage(fb, 0, 0, fb->width, fb->height);
+}
+
+static const
+struct drm_simple_display_pipe_funcs udl_simple_display_pipe_funcs = {
+	.mode_valid = udl_simple_display_pipe_mode_valid,
+	.enable = udl_simple_display_pipe_enable,
+	.disable = udl_simple_display_pipe_disable,
+	.check = udl_simple_display_pipe_check,
+	.update = udl_simple_display_pipe_update,
+	.prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+/*
+ * Modesetting
+ */
+
 static const struct drm_mode_config_funcs udl_mode_funcs = {
 	.fb_create = udl_fb_user_fb_create,
+	.atomic_check  = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
 };
 
 int udl_modeset_init(struct drm_device *dev)
 {
+	size_t format_count = ARRAY_SIZE(udl_simple_display_pipe_formats);
+	struct udl_device *udl = dev->dev_private;
 	struct drm_connector *connector;
-	struct drm_encoder *encoder;
 	int ret;
 
 	drm_mode_config_init(dev);
@@ -444,10 +560,16 @@ int udl_modeset_init(struct drm_device *dev)
 		goto err_drm_mode_config_cleanup;
 	}
 
-	udl_crtc_init(dev);
+	format_count = ARRAY_SIZE(udl_simple_display_pipe_formats);
 
-	encoder = udl_encoder_init(dev);
-	drm_connector_attach_encoder(connector, encoder);
+	ret = drm_simple_display_pipe_init(dev, &udl->display_pipe,
+					   &udl_simple_display_pipe_funcs,
+					   udl_simple_display_pipe_formats,
+					   format_count, NULL, connector);
+	if (ret)
+		goto err_drm_mode_config_cleanup;
+
+	drm_mode_config_reset(dev);
 
 	return 0;
 
@@ -456,18 +578,6 @@ int udl_modeset_init(struct drm_device *dev)
 	return ret;
 }
 
-void udl_modeset_restore(struct drm_device *dev)
-{
-	struct udl_device *udl = dev->dev_private;
-	struct drm_framebuffer *fb;
-
-	if (!udl->crtc || !udl->crtc->primary->fb)
-		return;
-	udl_crtc_commit(udl->crtc);
-	fb = udl->crtc->primary->fb;
-	udl_handle_damage(fb, 0, 0, fb->width, fb->height);
-}
-
 void udl_modeset_cleanup(struct drm_device *dev)
 {
 	drm_mode_config_cleanup(dev);
-- 
2.23.0

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




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux