depends on USB_SUPPORT
depends on USB_ARCH_HAS_HCD
select USB
+ select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER
help
This is a KMS driver for the USB displaylink video adapters.
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
+#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_print.h>
return 0;
}
-static const struct vm_operations_struct udl_gem_vm_ops = {
- .fault = udl_gem_fault,
- .open = drm_gem_vm_open,
- .close = drm_gem_vm_close,
-};
-
-static const struct file_operations udl_driver_fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .mmap = udl_drm_gem_mmap,
- .poll = drm_poll,
- .read = drm_read,
- .unlocked_ioctl = drm_ioctl,
- .release = drm_release,
- .compat_ioctl = drm_compat_ioctl,
- .llseek = noop_llseek,
-};
+DEFINE_DRM_GEM_FOPS(udl_driver_fops);
static void udl_driver_release(struct drm_device *dev)
{
.release = udl_driver_release,
/* gem hooks */
- .gem_free_object_unlocked = udl_gem_free_object,
.gem_create_object = udl_driver_gem_create_object,
- .gem_vm_ops = &udl_gem_vm_ops,
- .dumb_create = udl_dumb_create,
- .dumb_map_offset = udl_gem_mmap,
.fops = &udl_driver_fops,
-
- .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
- .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
- .gem_prime_export = udl_gem_prime_export,
- .gem_prime_import = udl_gem_prime_import,
+ DRM_GEM_SHMEM_DRIVER_OPS,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
struct udl_framebuffer {
struct drm_framebuffer base;
struct udl_gem_object *obj;
+ struct drm_gem_shmem_object *shmem;
bool active_16; /* active on the 16-bit channel */
};
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_modeset_helper.h>
#include "udl_drv.h"
if (!fb->active_16)
return 0;
- if (!fb->obj->vmapping) {
- ret = udl_gem_vmap(fb->obj);
- if (ret == -ENOMEM) {
+ if (!fb->shmem->vaddr) {
+ void *vaddr;
+
+ vaddr = drm_gem_shmem_vmap(&fb->shmem->base);
+ if (IS_ERR(vaddr)) {
DRM_ERROR("failed to vmap fb\n");
return 0;
}
- if (!fb->obj->vmapping) {
- DRM_ERROR("failed to vmapping\n");
- return 0;
- }
}
aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
const int byte_offset = line_offset + (x << log_bpp);
const int dev_byte_offset = (fb->base.width * i + x) << log_bpp;
if (udl_render_hline(dev, log_bpp, &urb,
- (char *) fb->obj->vmapping,
+ (char *) fb->shmem->vaddr,
&cmd, byte_offset, dev_byte_offset,
width << log_bpp,
&bytes_identical, &bytes_sent))
unsigned num_clips)
{
struct udl_framebuffer *ufb = to_udl_fb(fb);
+ struct dma_buf_attachment *import_attach;
int i;
int ret = 0;
if (!ufb->active_16)
goto unlock;
- if (ufb->obj->base.import_attach) {
- ret = dma_buf_begin_cpu_access(ufb->obj->base.import_attach->dmabuf,
+ import_attach = ufb->shmem->base.import_attach;
+
+ if (import_attach) {
+ ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
DMA_FROM_DEVICE);
if (ret)
goto unlock;
break;
}
- if (ufb->obj->base.import_attach) {
- ret = dma_buf_end_cpu_access(ufb->obj->base.import_attach->dmabuf,
+ if (import_attach)
+ ret = dma_buf_end_cpu_access(import_attach->dmabuf,
DMA_FROM_DEVICE);
- }
unlock:
drm_modeset_unlock_all(fb->dev);
{
struct udl_framebuffer *ufb = to_udl_fb(fb);
- if (ufb->obj)
- drm_gem_object_put_unlocked(&ufb->obj->base);
+ if (ufb->shmem)
+ drm_gem_object_put_unlocked(&ufb->shmem->base);
drm_framebuffer_cleanup(fb);
kfree(ufb);
udl_framebuffer_init(struct drm_device *dev,
struct udl_framebuffer *ufb,
const struct drm_mode_fb_cmd2 *mode_cmd,
- struct udl_gem_object *obj)
+ struct drm_gem_shmem_object *shmem)
{
int ret;
- ufb->obj = obj;
+ ufb->shmem = shmem;
drm_helper_mode_fill_fb_struct(dev, &ufb->base, mode_cmd);
ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs);
return ret;
struct fb_info *info;
struct drm_framebuffer *fb;
struct drm_mode_fb_cmd2 mode_cmd;
- struct udl_gem_object *obj;
+ struct drm_gem_shmem_object *shmem;
+ void *vaddr;
uint32_t size;
int ret = 0;
size = mode_cmd.pitches[0] * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE);
- obj = udl_gem_alloc_object(dev, size);
- if (!obj)
+ shmem = drm_gem_shmem_create(dev, size);
+ if (IS_ERR(shmem)) {
+ ret = PTR_ERR(shmem);
goto out;
+ }
- ret = udl_gem_vmap(obj);
- if (ret) {
+ vaddr = drm_gem_shmem_vmap(&shmem->base);
+ if (IS_ERR(vaddr)) {
+ ret = PTR_ERR(vaddr);
DRM_ERROR("failed to vmap fb\n");
goto out_gfree;
}
goto out_gfree;
}
- ret = udl_framebuffer_init(dev, &ufbdev->ufb, &mode_cmd, obj);
+ ret = udl_framebuffer_init(dev, &ufbdev->ufb, &mode_cmd, shmem);
if (ret)
goto out_gfree;
ufbdev->helper.fb = fb;
- info->screen_base = ufbdev->ufb.obj->vmapping;
+ info->screen_base = vaddr;
info->fix.smem_len = size;
- info->fix.smem_start = (unsigned long)ufbdev->ufb.obj->vmapping;
+ info->fix.smem_start = (unsigned long)vaddr;
info->fbops = &udlfb_ops;
drm_fb_helper_fill_info(info, &ufbdev->helper, sizes);
DRM_DEBUG_KMS("allocated %dx%d vmal %p\n",
fb->width, fb->height,
- ufbdev->ufb.obj->vmapping);
+ ufbdev->ufb.shmem->vaddr);
return ret;
out_gfree:
- drm_gem_object_put_unlocked(&ufbdev->ufb.obj->base);
+ drm_gem_object_put_unlocked(&ufbdev->ufb.shmem->base);
out:
return ret;
}
{
drm_fb_helper_unregister_fbi(&ufbdev->helper);
drm_fb_helper_fini(&ufbdev->helper);
- if (ufbdev->ufb.obj) {
+ if (ufbdev->ufb.shmem) {
drm_framebuffer_unregister_private(&ufbdev->ufb.base);
drm_framebuffer_cleanup(&ufbdev->ufb.base);
- drm_gem_object_put_unlocked(&ufbdev->ufb.obj->base);
+ drm_gem_object_put_unlocked(&ufbdev->ufb.shmem->base);
}
}
if (ufb == NULL)
return ERR_PTR(-ENOMEM);
- ret = udl_framebuffer_init(dev, ufb, mode_cmd, to_udl_bo(obj));
+ ret = udl_framebuffer_init(dev, ufb, mode_cmd,
+ to_drm_gem_shmem_obj(obj));
if (ret) {
kfree(ufb);
return ERR_PTR(-EINVAL);
#include <linux/vmalloc.h>
#include <drm/drm_drv.h>
+#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_mode.h>
#include <drm/drm_prime.h>
#include "udl_drv.h"
+/*
+ * GEM object funcs
+ */
+
+static void udl_gem_object_free_object(struct drm_gem_object *obj)
+{
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+
+ /* Fbdev emulation vmaps the buffer. Unmap it here for consistency
+ * with the original udl GEM code.
+ *
+ * TODO: Switch to generic fbdev emulation and release the
+ * GEM object with drm_gem_shmem_free_object().
+ */
+ if (shmem->vaddr)
+ drm_gem_shmem_vunmap(obj, shmem->vaddr);
+
+ drm_gem_shmem_free_object(obj);
+}
+
+static int udl_gem_object_mmap(struct drm_gem_object *obj,
+ struct vm_area_struct *vma)
+{
+ int ret;
+
+ ret = drm_gem_shmem_mmap(obj, vma);
+ if (ret)
+ return ret;
+
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+ if (obj->import_attach)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
+
+ return 0;
+}
+
+static void *udl_gem_object_vmap(struct drm_gem_object *obj)
+{
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+ int ret;
+
+ ret = mutex_lock_interruptible(&shmem->vmap_lock);
+ if (ret)
+ return ERR_PTR(ret);
+
+ if (shmem->vmap_use_count++ > 0)
+ goto out;
+
+ ret = drm_gem_shmem_get_pages(shmem);
+ if (ret)
+ goto err_zero_use;
+
+ if (obj->import_attach)
+ shmem->vaddr = dma_buf_vmap(obj->import_attach->dmabuf);
+ else
+ shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT,
+ VM_MAP, PAGE_KERNEL);
+
+ if (!shmem->vaddr) {
+ DRM_DEBUG_KMS("Failed to vmap pages\n");
+ ret = -ENOMEM;
+ goto err_put_pages;
+ }
+
+out:
+ mutex_unlock(&shmem->vmap_lock);
+ return shmem->vaddr;
+
+err_put_pages:
+ drm_gem_shmem_put_pages(shmem);
+err_zero_use:
+ shmem->vmap_use_count = 0;
+ mutex_unlock(&shmem->vmap_lock);
+ return ERR_PTR(ret);
+}
+
+static const struct drm_gem_object_funcs udl_gem_object_funcs = {
+ .free = udl_gem_object_free_object,
+ .print_info = drm_gem_shmem_print_info,
+ .pin = drm_gem_shmem_pin,
+ .unpin = drm_gem_shmem_unpin,
+ .get_sg_table = drm_gem_shmem_get_sg_table,
+ .vmap = udl_gem_object_vmap,
+ .vunmap = drm_gem_shmem_vunmap,
+ .mmap = udl_gem_object_mmap,
+};
+
/*
* Helpers for struct drm_driver
*/
struct drm_gem_object *udl_driver_gem_create_object(struct drm_device *dev,
size_t size)
{
- struct udl_gem_object *obj;
+ struct drm_gem_shmem_object *shmem;
+ struct drm_gem_object *obj;
- obj = kzalloc(sizeof(*obj), GFP_KERNEL);
- if (!obj)
+ shmem = kzalloc(sizeof(*shmem), GFP_KERNEL);
+ if (!shmem)
return NULL;
- return &obj->base;
+ obj = &shmem->base;
+ obj->funcs = &udl_gem_object_funcs;
+
+ return obj;
}
struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev,