diff options
Diffstat (limited to 'drivers/gpu/drm/udl')
-rw-r--r-- | drivers/gpu/drm/udl/udl_drv.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/udl/udl_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/udl/udl_main.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/udl/udl_modeset.c | 34 |
4 files changed, 41 insertions, 21 deletions
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 9269092697d8..5703277c6f52 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -32,6 +32,22 @@ static int udl_usb_resume(struct usb_interface *interface) return drm_mode_config_helper_resume(dev); } +/* + * FIXME: Dma-buf sharing requires DMA support by the importing device. + * This function is a workaround to make USB devices work as well. + * See todo.rst for how to fix the issue in the dma-buf framework. + */ +static struct drm_gem_object *udl_driver_gem_prime_import(struct drm_device *dev, + struct dma_buf *dma_buf) +{ + struct udl_device *udl = to_udl(dev); + + if (!udl->dmadev) + return ERR_PTR(-ENODEV); + + return drm_gem_prime_import_dev(dev, dma_buf, udl->dmadev); +} + DEFINE_DRM_GEM_FOPS(udl_driver_fops); static const struct drm_driver driver = { @@ -40,6 +56,7 @@ static const struct drm_driver driver = { /* GEM hooks */ .fops = &udl_driver_fops, DRM_GEM_SHMEM_DRIVER_OPS, + .gem_prime_import = udl_driver_gem_prime_import, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 875e73551ae9..cc16a13316e4 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -50,6 +50,7 @@ struct urb_list { struct udl_device { struct drm_device drm; struct device *dev; + struct device *dmadev; struct drm_simple_display_pipe display_pipe; diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 0e2a376cb075..853f147036f6 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -315,6 +315,10 @@ int udl_init(struct udl_device *udl) DRM_DEBUG("\n"); + udl->dmadev = usb_intf_get_dma_device(to_usb_interface(dev->dev)); + if (!udl->dmadev) + drm_warn(dev, "buffer sharing not supported"); /* not an error */ + mutex_init(&udl->gem_lock); if (!udl_parse_vendor_descriptor(udl)) { @@ -343,12 +347,18 @@ int udl_init(struct udl_device *udl) err: if (udl->urbs.count) udl_free_urb_list(dev); + put_device(udl->dmadev); DRM_ERROR("%d\n", ret); return ret; } int udl_drop_usb(struct drm_device *dev) { + struct udl_device *udl = to_udl(dev); + udl_free_urb_list(dev); + put_device(udl->dmadev); + udl->dmadev = NULL; + return 0; } diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 9d34ec9d03f6..8d98bf69d075 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -15,6 +15,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_shmem_helper.h> #include <drm/drm_modeset_helper_vtables.h> @@ -266,18 +267,17 @@ static int udl_aligned_damage_clip(struct drm_rect *clip, int x, int y, return 0; } -static int udl_handle_damage(struct drm_framebuffer *fb, int x, int y, - int width, int height) +static int udl_handle_damage(struct drm_framebuffer *fb, const struct dma_buf_map *map, + 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; + void *vaddr = map->vaddr; /* TODO: Use mapping abstraction properly */ int i, ret, tmp_ret; char *cmd; struct urb *urb; struct drm_rect clip; int log_bpp; - struct dma_buf_map map; - void *vaddr; ret = udl_log_cpp(fb->format->cpp[0]); if (ret < 0) @@ -297,17 +297,10 @@ static int udl_handle_damage(struct drm_framebuffer *fb, int x, int y, return ret; } - ret = drm_gem_shmem_vmap(fb->obj[0], &map); - if (ret) { - DRM_ERROR("failed to vmap fb\n"); - goto out_dma_buf_end_cpu_access; - } - vaddr = map.vaddr; /* TODO: Use mapping abstraction properly */ - urb = udl_get_urb(dev); if (!urb) { ret = -ENOMEM; - goto out_drm_gem_shmem_vunmap; + goto out_dma_buf_end_cpu_access; } cmd = urb->transfer_buffer; @@ -320,7 +313,7 @@ static int udl_handle_damage(struct drm_framebuffer *fb, int x, int y, &cmd, byte_offset, dev_byte_offset, byte_width); if (ret) - goto out_drm_gem_shmem_vunmap; + goto out_dma_buf_end_cpu_access; } if (cmd > (char *)urb->transfer_buffer) { @@ -336,8 +329,6 @@ static int udl_handle_damage(struct drm_framebuffer *fb, int x, int y, ret = 0; -out_drm_gem_shmem_vunmap: - drm_gem_shmem_vunmap(fb->obj[0], &map); out_dma_buf_end_cpu_access: if (import_attach) { tmp_ret = dma_buf_end_cpu_access(import_attach->dmabuf, @@ -375,6 +366,7 @@ udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_framebuffer *fb = plane_state->fb; struct udl_device *udl = to_udl(dev); struct drm_display_mode *mode = &crtc_state->mode; + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); char *buf; char *wrptr; int color_depth = UDL_COLOR_DEPTH_16BPP; @@ -400,7 +392,7 @@ udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe, udl->mode_buf_len = wrptr - buf; - udl_handle_damage(fb, 0, 0, fb->width, fb->height); + udl_handle_damage(fb, &shadow_plane_state->map[0], 0, 0, fb->width, fb->height); if (!crtc_state->mode_changed) return; @@ -435,6 +427,7 @@ udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_plane_state *old_plane_state) { struct drm_plane_state *state = pipe->plane.state; + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state); struct drm_framebuffer *fb = state->fb; struct drm_rect rect; @@ -442,17 +435,16 @@ udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, return; 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); + udl_handle_damage(fb, &shadow_plane_state->map[0], rect.x1, rect.y1, + rect.x2 - rect.x1, rect.y2 - rect.y1); } -static const -struct drm_simple_display_pipe_funcs udl_simple_display_pipe_funcs = { +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, .update = udl_simple_display_pipe_update, - .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, + DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS, }; /* |