From d0c4fc5a4814e431c15272935c8dc973c18073aa Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 14 Nov 2019 13:51:04 +0100 Subject: drm/udl: Replace fbdev code with generic emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The udl driver can use the generic fbdev implementation. Convert it. v5: * initialize console after registering device v4: * hardcode console bpp to 16 v3: * remove module parameter fb_bpp in favor of fbdev's video * call drm_fbdev_generic_setup() directly; remove udl_fbdev_init() * use default for struct drm_mode_config_funcs.output_poll_changed * use default for struct drm_driver.lastclose Signed-off-by: Thomas Zimmermann Reviewed-by: Noralf Trønnes Link: https://patchwork.freedesktop.org/patch/msgid/20191114125106.28347-2-tzimmermann@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/udl/udl_modeset.c') diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index bc1ab6060dc6..6582c9d27a87 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -422,7 +422,6 @@ static int udl_crtc_init(struct drm_device *dev) static const struct drm_mode_config_funcs udl_mode_funcs = { .fb_create = udl_fb_user_fb_create, - .output_poll_changed = NULL, }; int udl_modeset_init(struct drm_device *dev) -- cgit From ba59b015a0145330e2bf7ab20d504bc624fd618a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 14 Nov 2019 15:10:23 +0100 Subject: drm/udl: Store active framebuffer in device structure The framebuffer's 'active_16' flag signals which framebuffer to flush to device memory. Moving the 'active_16' state from struct udl_framebuffer into struct udl_device prepares for using the generic GEM framebuffer. Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20191114141025.32198-4-tzimmermann@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/udl/udl_modeset.c') diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 6582c9d27a87..44a741f463c9 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -332,11 +332,9 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc, wrptr = udl_dummy_render(wrptr); - if (old_fb) { - struct udl_framebuffer *uold_fb = to_udl_fb(old_fb); - uold_fb->active_16 = false; - } - ufb->active_16 = true; + spin_lock(&udl->active_fb_16_lock); + udl->active_fb_16 = &ufb->base; + spin_unlock(&udl->active_fb_16_lock); udl->mode_buf_len = wrptr - buf; /* damage all of it */ @@ -364,13 +362,11 @@ static int udl_crtc_page_flip(struct drm_crtc *crtc, { struct udl_framebuffer *ufb = to_udl_fb(fb); struct drm_device *dev = crtc->dev; + struct udl_device *udl = dev->dev_private; - struct drm_framebuffer *old_fb = crtc->primary->fb; - if (old_fb) { - struct udl_framebuffer *uold_fb = to_udl_fb(old_fb); - uold_fb->active_16 = false; - } - ufb->active_16 = true; + spin_lock(&udl->active_fb_16_lock); + udl->active_fb_16 = fb; + spin_unlock(&udl->active_fb_16_lock); udl_handle_damage(ufb, 0, 0, fb->width, fb->height); -- cgit From 8344603534e17f9926253a65088f59b787222bc5 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 14 Nov 2019 15:10:24 +0100 Subject: drm/udl: Call udl_handle_damage() with DRM framebuffer Simplifying the udl code before replacing struct udl_framebuffer. Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20191114141025.32198-5-tzimmermann@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/udl/udl_modeset.c') diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 44a741f463c9..91af25caed64 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -301,7 +301,7 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; - struct udl_framebuffer *ufb = to_udl_fb(crtc->primary->fb); + struct drm_framebuffer *fb = crtc->primary->fb; struct udl_device *udl = dev->dev_private; char *buf; char *wrptr; @@ -333,12 +333,12 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc, wrptr = udl_dummy_render(wrptr); spin_lock(&udl->active_fb_16_lock); - udl->active_fb_16 = &ufb->base; + udl->active_fb_16 = fb; spin_unlock(&udl->active_fb_16_lock); udl->mode_buf_len = wrptr - buf; /* damage all of it */ - udl_handle_damage(ufb, 0, 0, ufb->base.width, ufb->base.height); + udl_handle_damage(fb, 0, 0, fb->width, fb->height); return 0; } @@ -360,7 +360,6 @@ static int udl_crtc_page_flip(struct drm_crtc *crtc, uint32_t page_flip_flags, struct drm_modeset_acquire_ctx *ctx) { - struct udl_framebuffer *ufb = to_udl_fb(fb); struct drm_device *dev = crtc->dev; struct udl_device *udl = dev->dev_private; @@ -368,7 +367,7 @@ static int udl_crtc_page_flip(struct drm_crtc *crtc, udl->active_fb_16 = fb; spin_unlock(&udl->active_fb_16_lock); - udl_handle_damage(ufb, 0, 0, fb->width, fb->height); + udl_handle_damage(fb, 0, 0, fb->width, fb->height); spin_lock_irq(&dev->event_lock); if (event) @@ -448,13 +447,13 @@ int udl_modeset_init(struct drm_device *dev) void udl_modeset_restore(struct drm_device *dev) { struct udl_device *udl = dev->dev_private; - struct udl_framebuffer *ufb; + struct drm_framebuffer *fb; if (!udl->crtc || !udl->crtc->primary->fb) return; udl_crtc_commit(udl->crtc); - ufb = to_udl_fb(udl->crtc->primary->fb); - udl_handle_damage(ufb, 0, 0, ufb->base.width, ufb->base.height); + fb = udl->crtc->primary->fb; + udl_handle_damage(fb, 0, 0, fb->width, fb->height); } void udl_modeset_cleanup(struct drm_device *dev) -- cgit From e829cf0b30b4b55c9fa212cef1e116df91e0d80b Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 10 Dec 2019 09:48:57 +0100 Subject: drm/udl: Init connector before encoder and CRTC To mimic simple-pipe, we initialize the connector before the rest of the display pipeline. v2: * remove unnecessary calls to drm_connector_{register,unregister}() Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/20191210084905.5570-2-tzimmermann@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/udl/udl_modeset.c') diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 91af25caed64..5bb1522036c7 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -421,7 +421,10 @@ static const struct drm_mode_config_funcs udl_mode_funcs = { int udl_modeset_init(struct drm_device *dev) { + struct drm_connector *connector; struct drm_encoder *encoder; + int ret; + drm_mode_config_init(dev); dev->mode_config.min_width = 640; @@ -435,13 +438,22 @@ int udl_modeset_init(struct drm_device *dev) dev->mode_config.funcs = &udl_mode_funcs; + connector = udl_connector_init(dev); + if (IS_ERR(connector)) { + ret = PTR_ERR(connector); + goto err_drm_mode_config_cleanup; + } + udl_crtc_init(dev); encoder = udl_encoder_init(dev); - - udl_connector_init(dev, encoder); + drm_connector_attach_encoder(connector, encoder); return 0; + +err_drm_mode_config_cleanup: + drm_mode_config_cleanup(dev); + return ret; } void udl_modeset_restore(struct drm_device *dev) -- cgit From 9fda81e00e060e3ab9a56d77552d2d5e296f1007 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 10 Dec 2019 09:48:58 +0100 Subject: drm/udl: Convert to struct drm_simple_display_pipe Udl has a single display pipeline with a primary 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. v3: * remove unused field crtc from struct udl_device * set crtc_state->no_vblank at beginning of enable() v2: * move suspend/resume changes into separate patch * remove non-atomic code Signed-off-by: Thomas Zimmermann Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/20191210084905.5570-3-tzimmermann@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 170 +++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 93 deletions(-) (limited to 'drivers/gpu/drm/udl/udl_modeset.c') diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 5bb1522036c7..36b7844e8cf4 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -9,12 +9,16 @@ */ +#include #include +#include #include #include #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 @@ -277,48 +281,44 @@ static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) } -#if 0 -static int -udl_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y, enum mode_set_atomic state) -{ - return 0; -} +/* + * Simple display pipeline + */ -static int -udl_pipe_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) +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 0; + return MODE_OK; } -#endif - -static int udl_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) +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 = crtc->primary->fb; + 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 = 0; + int color_depth = UDL_COLOR_DEPTH_16BPP; - udl->crtc = crtc; + crtc_state->no_vblank = true; buf = (char *)udl->mode_buf; - /* for now we just clip 24 -> 16 - if we fix that fix this */ - /*if (crtc->fb->bits_per_pixel != 16) - color_depth = 1; */ - /* 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. - */ + * 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 */ @@ -326,7 +326,7 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc, /* 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, adjusted_mode); + wrptr = udl_set_vid_cmds(wrptr, mode); wrptr = udl_set_blank(wrptr, DRM_MODE_DPMS_ON); wrptr = udl_vidreg_unlock(wrptr); @@ -337,92 +337,68 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc, spin_unlock(&udl->active_fb_16_lock); udl->mode_buf_len = wrptr - buf; - /* damage all of it */ udl_handle_damage(fb, 0, 0, fb->width, fb->height); - return 0; -} + udl_crtc_dpms(&pipe->crtc, DRM_MODE_DPMS_ON); +} -static void udl_crtc_disable(struct drm_crtc *crtc) +static void +udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) { - udl_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + udl_crtc_dpms(&pipe->crtc, DRM_MODE_DPMS_OFF); } -static void udl_crtc_destroy(struct drm_crtc *crtc) +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) { - drm_crtc_cleanup(crtc); - kfree(crtc); + return 0; } -static int udl_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, - struct drm_modeset_acquire_ctx *ctx) +static void +udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_plane_state) { - struct drm_device *dev = crtc->dev; + 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); - udl_handle_damage(fb, 0, 0, fb->width, fb->height); - - spin_lock_irq(&dev->event_lock); - if (event) - drm_crtc_send_vblank_event(crtc, event); - spin_unlock_irq(&dev->event_lock); - crtc->primary->fb = fb; - - return 0; -} - -static void udl_crtc_prepare(struct drm_crtc *crtc) -{ -} + if (!fb) + return; -static void udl_crtc_commit(struct drm_crtc *crtc) -{ - udl_crtc_dpms(crtc, DRM_MODE_DPMS_ON); + udl_handle_damage(fb, 0, 0, fb->width, fb->height); } -static const struct drm_crtc_helper_funcs udl_helper_funcs = { - .dpms = udl_crtc_dpms, - .mode_set = udl_crtc_mode_set, - .prepare = udl_crtc_prepare, - .commit = udl_crtc_commit, - .disable = udl_crtc_disable, -}; - -static const struct drm_crtc_funcs udl_crtc_funcs = { - .set_config = drm_crtc_helper_set_config, - .destroy = udl_crtc_destroy, - .page_flip = udl_crtc_page_flip, +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, }; -static int udl_crtc_init(struct drm_device *dev) -{ - struct drm_crtc *crtc; - - crtc = kzalloc(sizeof(struct drm_crtc) + sizeof(struct drm_connector *), GFP_KERNEL); - if (crtc == NULL) - return -ENOMEM; - - drm_crtc_init(dev, crtc, &udl_crtc_funcs); - drm_crtc_helper_add(crtc, &udl_helper_funcs); - - return 0; -} +/* + * 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 +420,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); + + 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; - encoder = udl_encoder_init(dev); - drm_connector_attach_encoder(connector, encoder); + drm_mode_config_reset(dev); return 0; @@ -459,12 +441,14 @@ err_drm_mode_config_cleanup: void udl_modeset_restore(struct drm_device *dev) { struct udl_device *udl = dev->dev_private; - struct drm_framebuffer *fb; + struct drm_crtc *crtc = &udl->display_pipe.crtc; + struct drm_plane *primary = &udl->display_pipe.plane; + struct drm_framebuffer *fb = primary->fb; - if (!udl->crtc || !udl->crtc->primary->fb) + if (!fb) return; - udl_crtc_commit(udl->crtc); - fb = udl->crtc->primary->fb; + + udl_crtc_dpms(crtc, DRM_MODE_DPMS_ON); udl_handle_damage(fb, 0, 0, fb->width, fb->height); } -- cgit From ae08b88aea6b8094c8163b753b626329542146ee Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 10 Dec 2019 09:48:59 +0100 Subject: drm/udl: Switch to atomic suspend/resume helpers We can use the generic suspend/resume helpers for atomic modesetting. Switch udl over. Signed-off-by: Thomas Zimmermann Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/20191210084905.5570-4-tzimmermann@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/gpu/drm/udl/udl_modeset.c') diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 36b7844e8cf4..cde6b7ff9599 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -438,20 +438,6 @@ err_drm_mode_config_cleanup: return ret; } -void udl_modeset_restore(struct drm_device *dev) -{ - struct udl_device *udl = dev->dev_private; - struct drm_crtc *crtc = &udl->display_pipe.crtc; - struct drm_plane *primary = &udl->display_pipe.plane; - struct drm_framebuffer *fb = primary->fb; - - if (!fb) - return; - - udl_crtc_dpms(crtc, DRM_MODE_DPMS_ON); - udl_handle_damage(fb, 0, 0, fb->width, fb->height); -} - void udl_modeset_cleanup(struct drm_device *dev) { drm_mode_config_cleanup(dev); -- cgit From 997d33c35618f12e311734b9fcd03a9945950c2b Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 10 Dec 2019 09:49:00 +0100 Subject: drm/udl: Inline DPMS code into CRTC enable and disable functions DPMS functionality is only used by the CRTC's enable and disable functions. Inline the code. The patch also adds symbolic constants for the blank register and constants; according to udlfb, which is a bit more detailed than DRM's udl. v3: * use symbolic constants for blank, according to udlfb driver Signed-off-by: Thomas Zimmermann Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/20191210084905.5570-5-tzimmermann@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 88 +++++++++++++-------------------------- 1 file changed, 29 insertions(+), 59 deletions(-) (limited to 'drivers/gpu/drm/udl/udl_modeset.c') diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index cde6b7ff9599..381caf553542 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -42,31 +42,9 @@ static char *udl_vidreg_unlock(char *buf) return udl_set_register(buf, 0xFF, 0xFF); } -/* - * On/Off for driving the DisplayLink framebuffer to the display - * 0x00 H and V sync on - * 0x01 H and V sync off (screen blank but powered) - * 0x07 DPMS powerdown (requires modeset to come back) - */ -static char *udl_set_blank(char *buf, int dpms_mode) +static char *udl_set_blank_mode(char *buf, u8 mode) { - u8 reg; - switch (dpms_mode) { - case DRM_MODE_DPMS_OFF: - reg = 0x07; - break; - case DRM_MODE_DPMS_STANDBY: - reg = 0x05; - break; - case DRM_MODE_DPMS_SUSPEND: - reg = 0x01; - break; - case DRM_MODE_DPMS_ON: - reg = 0x00; - break; - } - - return udl_set_register(buf, 0x1f, reg); + return udl_set_register(buf, UDL_REG_BLANK_MODE, mode); } static char *udl_set_color_depth(char *buf, u8 selection) @@ -237,6 +215,11 @@ static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc) char *buf; int retval; + if (udl->mode_buf_len == 0) { + DRM_ERROR("No mode set\n"); + return -EINVAL; + } + urb = udl_get_urb(dev); if (!urb) return -ENOMEM; @@ -249,38 +232,6 @@ static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc) return retval; } - -static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) -{ - struct drm_device *dev = crtc->dev; - struct udl_device *udl = dev->dev_private; - int retval; - - if (mode == DRM_MODE_DPMS_OFF) { - char *buf; - struct urb *urb; - urb = udl_get_urb(dev); - if (!urb) - return; - - buf = (char *)urb->transfer_buffer; - buf = udl_vidreg_lock(buf); - buf = udl_set_blank(buf, mode); - buf = udl_vidreg_unlock(buf); - - buf = udl_dummy_render(buf); - retval = udl_submit_urb(dev, urb, buf - (char *) - urb->transfer_buffer); - } else { - if (udl->mode_buf_len == 0) { - DRM_ERROR("Trying to enable DPMS with no mode\n"); - return; - } - udl_crtc_write_mode_to_hw(crtc); - } - -} - /* * Simple display pipeline */ @@ -327,7 +278,7 @@ udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, 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_set_blank_mode(wrptr, UDL_BLANK_MODE_ON); wrptr = udl_vidreg_unlock(wrptr); wrptr = udl_dummy_render(wrptr); @@ -339,13 +290,32 @@ udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, udl_handle_damage(fb, 0, 0, fb->width, fb->height); - udl_crtc_dpms(&pipe->crtc, DRM_MODE_DPMS_ON); + if (!crtc_state->mode_changed) + return; + + /* enable display */ + udl_crtc_write_mode_to_hw(crtc); } static void udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe) { - udl_crtc_dpms(&pipe->crtc, DRM_MODE_DPMS_OFF); + struct drm_crtc *crtc = &pipe->crtc; + struct drm_device *dev = crtc->dev; + struct urb *urb; + char *buf; + + urb = udl_get_urb(dev); + if (!urb) + return; + + buf = (char *)urb->transfer_buffer; + buf = udl_vidreg_lock(buf); + buf = udl_set_blank_mode(buf, UDL_BLANK_MODE_POWERDOWN); + buf = udl_vidreg_unlock(buf); + buf = udl_dummy_render(buf); + + udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer); } static int -- cgit From d8177841aa8a5d32767a5a18413c30b40234a4e5 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 10 Dec 2019 09:49:01 +0100 Subject: drm/udl: Set preferred color depth to 16 bpp The current default color depth of 24 bpp is not even supported by the driver. Being the native format for communicating with the adapter, 16 bpp is the correct choice. Signed-off-by: Thomas Zimmermann Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/20191210084905.5570-6-tzimmermann@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/udl/udl_modeset.c') diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 381caf553542..067f626bb65b 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -380,7 +380,7 @@ int udl_modeset_init(struct drm_device *dev) dev->mode_config.max_height = 2048; dev->mode_config.prefer_shadow = 0; - dev->mode_config.preferred_depth = 24; + dev->mode_config.preferred_depth = 16; dev->mode_config.funcs = &udl_mode_funcs; -- cgit From 230b8b04d74958ebc5892510475e510b1284f14f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 10 Dec 2019 09:49:02 +0100 Subject: drm/udl: Convert to drm_atomic_helper_dirtyfb() The infrastruture for atomic modesetting allows us to use the generic code for dirty-FB and damage handling. Switch over udl and remove the driver's implementation. The simple-pipe's update function now picks up the primary plane's damage and updates a minimal region of the screen. Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/20191210084905.5570-7-tzimmermann@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/udl/udl_modeset.c') diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 067f626bb65b..c02e383afabe 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -332,7 +333,9 @@ udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, { struct drm_device *dev = pipe->crtc.dev; struct udl_device *udl = dev->dev_private; - struct drm_framebuffer *fb = pipe->plane.state->fb; + struct drm_plane_state *state = pipe->plane.state; + struct drm_framebuffer *fb = state->fb; + struct drm_rect rect; spin_lock(&udl->active_fb_16_lock); udl->active_fb_16 = fb; @@ -341,7 +344,9 @@ udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, if (!fb) return; - udl_handle_damage(fb, 0, 0, fb->width, fb->height); + if (drm_atomic_helper_damage_merged(old_plane_state, state, &rect)) + udl_handle_damage(fb, rect.x1, rect.y1, rect.x2 - rect.x1, + rect.y2 - rect.y1); } static const @@ -359,7 +364,7 @@ struct drm_simple_display_pipe_funcs udl_simple_display_pipe_funcs = { */ static const struct drm_mode_config_funcs udl_mode_funcs = { - .fb_create = udl_fb_user_fb_create, + .fb_create = drm_gem_fb_create_with_dirty, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, }; -- cgit From eb3deeceaa5d066a5819fb45876de4d262a8f210 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 10 Dec 2019 09:49:03 +0100 Subject: drm/udl: Remove struct udl_device.active_fb_16 The udl driver stores the currently active framebuffer to know from where to accept damage updates. With the conversion to plane-state damage handling, this is not necessary any longer. The currently active framebuffer and damaged area are always stored in the plane state. Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/20191210084905.5570-8-tzimmermann@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/gpu/drm/udl/udl_modeset.c') diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index c02e383afabe..35fa7b11c681 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -284,9 +284,6 @@ udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, 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); @@ -331,16 +328,10 @@ 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_plane_state *state = pipe->plane.state; struct drm_framebuffer *fb = state->fb; struct drm_rect rect; - spin_lock(&udl->active_fb_16_lock); - udl->active_fb_16 = fb; - spin_unlock(&udl->active_fb_16_lock); - if (!fb) return; -- cgit From a8109f5bc4bd6dc037bd15651c6c7f1ac00ed235 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 10 Dec 2019 09:49:04 +0100 Subject: drm/udl: Move udl_handle_damage() into udl_modeset.c The only caller of udl_handle_damage() in the plane-update function in udl_modeset.c. Move udl_handle_damage() there. v2: * remove udl_fb.c in a separate patch Signed-off-by: Thomas Zimmermann Reviewed-by: Daniel Vetter Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/20191210084905.5570-9-tzimmermann@suse.de --- drivers/gpu/drm/udl/udl_modeset.c | 112 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) (limited to 'drivers/gpu/drm/udl/udl_modeset.c') diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 35fa7b11c681..22af17959053 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -9,10 +9,14 @@ */ +#include + #include #include #include +#include #include +#include #include #include @@ -233,6 +237,114 @@ static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc) return retval; } +static long udl_log_cpp(unsigned int cpp) +{ + if (WARN_ON(!is_power_of_2(cpp))) + return -EINVAL; + return __ffs(cpp); +} + +static int udl_aligned_damage_clip(struct drm_rect *clip, int x, int y, + int width, int height) +{ + int x1, x2; + + if (WARN_ON_ONCE(x < 0) || + WARN_ON_ONCE(y < 0) || + WARN_ON_ONCE(width < 0) || + WARN_ON_ONCE(height < 0)) + return -EINVAL; + + x1 = ALIGN_DOWN(x, sizeof(unsigned long)); + x2 = ALIGN(width + (x - x1), sizeof(unsigned long)) + x1; + + clip->x1 = x1; + clip->y1 = y; + clip->x2 = x2; + clip->y2 = y + height; + + return 0; +} + +int udl_handle_damage(struct drm_framebuffer *fb, int x, int y, + int width, int height) +{ + struct drm_device *dev = fb->dev; + struct dma_buf_attachment *import_attach = fb->obj[0]->import_attach; + int i, ret, tmp_ret; + char *cmd; + struct urb *urb; + struct drm_rect clip; + int log_bpp; + void *vaddr; + + ret = udl_log_cpp(fb->format->cpp[0]); + if (ret < 0) + return ret; + log_bpp = ret; + + ret = udl_aligned_damage_clip(&clip, x, y, width, height); + if (ret) + return ret; + else if ((clip.x2 > fb->width) || (clip.y2 > fb->height)) + return -EINVAL; + + if (import_attach) { + ret = dma_buf_begin_cpu_access(import_attach->dmabuf, + DMA_FROM_DEVICE); + if (ret) + return ret; + } + + vaddr = drm_gem_shmem_vmap(fb->obj[0]); + if (IS_ERR(vaddr)) { + DRM_ERROR("failed to vmap fb\n"); + goto out_dma_buf_end_cpu_access; + } + + urb = udl_get_urb(dev); + if (!urb) + goto out_drm_gem_shmem_vunmap; + cmd = urb->transfer_buffer; + + for (i = clip.y1; i < clip.y2; i++) { + const int line_offset = fb->pitches[0] * i; + const int byte_offset = line_offset + (clip.x1 << log_bpp); + const int dev_byte_offset = (fb->width * i + clip.x1) << log_bpp; + const int byte_width = (clip.x2 - clip.x1) << log_bpp; + ret = udl_render_hline(dev, log_bpp, &urb, (char *)vaddr, + &cmd, byte_offset, dev_byte_offset, + byte_width); + if (ret) + goto out_drm_gem_shmem_vunmap; + } + + if (cmd > (char *)urb->transfer_buffer) { + /* Send partial buffer remaining before exiting */ + int len; + if (cmd < (char *)urb->transfer_buffer + urb->transfer_buffer_length) + *cmd++ = 0xAF; + len = cmd - (char *)urb->transfer_buffer; + ret = udl_submit_urb(dev, urb, len); + } else { + udl_urb_completion(urb); + } + + ret = 0; + +out_drm_gem_shmem_vunmap: + drm_gem_shmem_vunmap(fb->obj[0], vaddr); +out_dma_buf_end_cpu_access: + if (import_attach) { + tmp_ret = dma_buf_end_cpu_access(import_attach->dmabuf, + DMA_FROM_DEVICE); + if (tmp_ret && !ret) + ret = tmp_ret; /* only update ret if not set yet */ + } + + return ret; +} + /* * Simple display pipeline */ -- cgit