[PATCH 2/7] drm/udl: Convert to struct drm_simple_display_pipe
Daniel Vetter
daniel at ffwll.ch
Thu Nov 28 14:09:18 UTC 2019
On Tue, Nov 26, 2019 at 02:47:02PM +0100, Thomas Zimmermann wrote:
> 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 at suse.de>
> ---
> 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 at plugable.com>
> */
>
> +#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);
Please mention in the commit message that you're also switching over to
the atomic-based generic suspend/resume helpers. Might even want to split
that out as a separate patch (but will require minor adjustements in
udl_modeset_restore).
> }
>
> 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);
Having a _dpms() function is very much legacy-modeset style. I think much
cleaner if you'd just inline the relevant part of the function here and
below.
> +
> + 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);
Where's all the deleted code that removes the udl crtc and encoder
code/structs?
Cheers, Daniel
> --
> 2.23.0
>
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the dri-devel
mailing list