diff options
Diffstat (limited to 'drivers/gpu/drm')
139 files changed, 1113 insertions, 1209 deletions
diff --git a/drivers/gpu/drm/armada/armada_gem.h b/drivers/gpu/drm/armada/armada_gem.h index 00b6cd461a03..b000ea3a829a 100644 --- a/drivers/gpu/drm/armada/armada_gem.h +++ b/drivers/gpu/drm/armada/armada_gem.h @@ -8,6 +8,8 @@ #ifndef ARMADA_GEM_H #define ARMADA_GEM_H +#include <drm/drm_gem.h> + /* GEM */ struct armada_gem_object { struct drm_gem_object obj; diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 7485ff945ca9..86205a28e56b 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -36,6 +36,8 @@ #include <drm/ttm/ttm_memory.h> #include <drm/ttm/ttm_module.h> +#include <drm/drm_gem.h> + #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index cba45c774552..5c60ae524c45 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -186,7 +186,8 @@ static int astfb_create_object(struct ast_fbdev *afbdev, static int astfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { - struct ast_fbdev *afbdev = (struct ast_fbdev *)helper; + struct ast_fbdev *afbdev = + container_of(helper, struct ast_fbdev, helper); struct drm_device *dev = afbdev->helper.dev; struct drm_mode_fb_cmd2 mode_cmd; struct drm_framebuffer *fb; diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c index 5098c7dd435c..08f82eae6939 100644 --- a/drivers/gpu/drm/ast/ast_ttm.c +++ b/drivers/gpu/drm/ast/ast_ttm.c @@ -339,7 +339,7 @@ int ast_bo_create(struct drm_device *dev, int size, int align, ret = ttm_bo_init(&ast->ttm.bdev, &astbo->bo, size, ttm_bo_type_device, &astbo->placement, align >> PAGE_SHIFT, false, NULL, acc_size, - NULL, ast_bo_ttm_destroy); + NULL, NULL, ast_bo_ttm_destroy); if (ret) return ret; @@ -427,7 +427,7 @@ int ast_mmap(struct file *filp, struct vm_area_struct *vma) struct ast_private *ast; if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) - return drm_mmap(filp, vma); + return -EINVAL; file_priv = filp->private_data; ast = file_priv->minor->dev->dev_private; diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index 4f6e7b3a3635..71f2687fc3cc 100644 --- a/drivers/gpu/drm/bochs/bochs.h +++ b/drivers/gpu/drm/bochs/bochs.h @@ -7,6 +7,8 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_gem.h> + #include <ttm/ttm_bo_driver.h> #include <ttm/ttm_page_alloc.h> diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c index 2af30e7607d7..66286ff518d4 100644 --- a/drivers/gpu/drm/bochs/bochs_mm.c +++ b/drivers/gpu/drm/bochs/bochs_mm.c @@ -339,7 +339,7 @@ int bochs_mmap(struct file *filp, struct vm_area_struct *vma) struct bochs_device *bochs; if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) - return drm_mmap(filp, vma); + return -EINVAL; file_priv = filp->private_data; bochs = file_priv->minor->dev->dev_private; @@ -377,7 +377,7 @@ static int bochs_bo_create(struct drm_device *dev, int size, int align, ret = ttm_bo_init(&bochs->ttm.bdev, &bochsbo->bo, size, ttm_bo_type_device, &bochsbo->placement, align >> PAGE_SHIFT, false, NULL, acc_size, - NULL, bochs_bo_ttm_destroy); + NULL, NULL, bochs_bo_ttm_destroy); if (ret) return ret; diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h index dd2cfc9024aa..d44e69daa239 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.h +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h @@ -21,6 +21,8 @@ #include <drm/ttm/ttm_memory.h> #include <drm/ttm/ttm_module.h> +#include <drm/drm_gem.h> + #define DRIVER_AUTHOR "Matthew Garrett" #define DRIVER_NAME "cirrus" diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index 2a135f253e29..d231b1c317af 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -160,7 +160,8 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev, static int cirrusfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { - struct cirrus_fbdev *gfbdev = (struct cirrus_fbdev *)helper; + struct cirrus_fbdev *gfbdev = + container_of(helper, struct cirrus_fbdev, helper); struct drm_device *dev = gfbdev->helper.dev; struct cirrus_device *cdev = gfbdev->helper.dev->dev_private; struct fb_info *info; diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c b/drivers/gpu/drm/cirrus/cirrus_ttm.c index 3e7d758330a9..dfffd528517a 100644 --- a/drivers/gpu/drm/cirrus/cirrus_ttm.c +++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c @@ -343,7 +343,7 @@ int cirrus_bo_create(struct drm_device *dev, int size, int align, ret = ttm_bo_init(&cirrus->ttm.bdev, &cirrusbo->bo, size, ttm_bo_type_device, &cirrusbo->placement, align >> PAGE_SHIFT, false, NULL, acc_size, - NULL, cirrus_bo_ttm_destroy); + NULL, NULL, cirrus_bo_ttm_destroy); if (ret) return ret; @@ -411,7 +411,7 @@ int cirrus_mmap(struct file *filp, struct vm_area_struct *vma) struct cirrus_device *cirrus; if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) - return drm_mmap(filp, vma); + return -EINVAL; file_priv = filp->private_data; cirrus = file_priv->minor->dev->dev_private; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index ecd4e0b4c525..e79c8d3700d8 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2263,21 +2263,19 @@ out: * * src_{x,y,w,h} are provided in 16.16 fixed point format */ -static int setplane_internal(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int32_t crtc_x, int32_t crtc_y, - uint32_t crtc_w, uint32_t crtc_h, - /* src_{x,y,w,h} values are 16.16 fixed point */ - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) +static int __setplane_internal(struct drm_plane *plane, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int32_t crtc_x, int32_t crtc_y, + uint32_t crtc_w, uint32_t crtc_h, + /* src_{x,y,w,h} values are 16.16 fixed point */ + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) { - struct drm_device *dev = plane->dev; int ret = 0; unsigned int fb_width, fb_height; int i; - drm_modeset_lock_all(dev); /* No fb means shut it down */ if (!fb) { plane->old_fb = plane->fb; @@ -2345,10 +2343,28 @@ out: if (plane->old_fb) drm_framebuffer_unreference(plane->old_fb); plane->old_fb = NULL; - drm_modeset_unlock_all(dev); return ret; +} + +static int setplane_internal(struct drm_plane *plane, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int32_t crtc_x, int32_t crtc_y, + uint32_t crtc_w, uint32_t crtc_h, + /* src_{x,y,w,h} values are 16.16 fixed point */ + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) +{ + int ret; + + drm_modeset_lock_all(plane->dev); + ret = __setplane_internal(plane, crtc, fb, + crtc_x, crtc_y, crtc_w, crtc_h, + src_x, src_y, src_w, src_h); + drm_modeset_unlock_all(plane->dev); + return ret; } /** @@ -2714,6 +2730,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, int ret = 0; BUG_ON(!crtc->cursor); + WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL); /* * Obtain fb we'll be using (either new or existing) and take an extra @@ -2733,11 +2750,9 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, fb = NULL; } } else { - mutex_lock(&dev->mode_config.mutex); fb = crtc->cursor->fb; if (fb) drm_framebuffer_reference(fb); - mutex_unlock(&dev->mode_config.mutex); } if (req->flags & DRM_MODE_CURSOR_MOVE) { @@ -2759,7 +2774,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, * setplane_internal will take care of deref'ing either the old or new * framebuffer depending on success. */ - ret = setplane_internal(crtc->cursor, crtc, fb, + ret = __setplane_internal(crtc->cursor, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, 0, 0, src_w, src_h); @@ -2795,10 +2810,12 @@ static int drm_mode_cursor_common(struct drm_device *dev, * If this crtc has a universal cursor plane, call that plane's update * handler rather than using legacy cursor handlers. */ - if (crtc->cursor) - return drm_mode_cursor_universal(crtc, req, file_priv); - drm_modeset_lock_crtc(crtc); + if (crtc->cursor) { + ret = drm_mode_cursor_universal(crtc, req, file_priv); + goto out; + } + if (req->flags & DRM_MODE_CURSOR_BO) { if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { ret = -ENXIO; @@ -3383,7 +3400,16 @@ void drm_fb_release(struct drm_file *priv) struct drm_device *dev = priv->minor->dev; struct drm_framebuffer *fb, *tfb; - mutex_lock(&priv->fbs_lock); + /* + * When the file gets released that means no one else can access the fb + * list any more, so no need to grab fpriv->fbs_lock. And we need to to + * avoid upsetting lockdep since the universal cursor code adds a + * framebuffer while holding mutex locks. + * + * Note that a real deadlock between fpriv->fbs_lock and the modeset + * locks is impossible here since no one else but this function can get + * at it any more. + */ list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { mutex_lock(&dev->mode_config.fb_lock); @@ -3396,7 +3422,6 @@ void drm_fb_release(struct drm_file *priv) /* This will also drop the fpriv->fbs reference. */ drm_framebuffer_remove(fb); } - mutex_unlock(&priv->fbs_lock); } /** diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 6a119026a76b..8889f8ec50ab 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -56,22 +56,19 @@ static struct idr drm_minors_idr; struct class *drm_class; static struct dentry *drm_debugfs_root; -int drm_err(const char *func, const char *format, ...) +void drm_err(const char *func, const char *format, ...) { struct va_format vaf; va_list args; - int r; va_start(args, format); vaf.fmt = format; vaf.va = &args; - r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf); + printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf); va_end(args); - - return r; } EXPORT_SYMBOL(drm_err); diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index eb5dd67153e4..cd45e45e2cce 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -38,6 +38,7 @@ #include <linux/dma-buf.h> #include <drm/drmP.h> #include <drm/drm_vma_manager.h> +#include <drm/drm_gem.h> #include "drm_internal.h" /** @file drm_gem.c @@ -888,7 +889,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) vma_pages(vma)); if (!node) { mutex_unlock(&dev->struct_mutex); - return drm_mmap(filp, vma); + return -EINVAL; } else if (!drm_vma_node_is_allowed(node, filp)) { mutex_unlock(&dev->struct_mutex); return -EACCES; diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c index e467e67af6e7..0316310e2cc4 100644 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/drivers/gpu/drm/drm_gem_cma_helper.c @@ -316,7 +316,8 @@ out: EXPORT_SYMBOL_GPL(drm_gem_cma_prime_get_sg_table); struct drm_gem_object * -drm_gem_cma_prime_import_sg_table(struct drm_device *dev, size_t size, +drm_gem_cma_prime_import_sg_table(struct drm_device *dev, + struct dma_buf_attachment *attach, struct sg_table *sgt) { struct drm_gem_cma_object *cma_obj; @@ -325,14 +326,14 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev, size_t size, return ERR_PTR(-EINVAL); /* Create a CMA GEM buffer. */ - cma_obj = __drm_gem_cma_create(dev, size); + cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size); if (IS_ERR(cma_obj)) return ERR_CAST(cma_obj); cma_obj->paddr = sg_dma_address(sgt->sgl); cma_obj->sgt = sgt; - DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &cma_obj->paddr, size); + DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &cma_obj->paddr, attach->dmabuf->size); return &cma_obj->base; } diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 0780541f7935..51efebd434f3 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -35,6 +35,8 @@ #include <linux/seq_file.h> #include <drm/drmP.h> +#include <drm/drm_gem.h> + #include "drm_legacy.h" /** diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 7e459bf38c26..7cc0a3516871 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -37,7 +37,7 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, /* drm_vm.c */ int drm_vma_info(struct seq_file *m, void *data); -int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma); +void drm_vm_open_locked(struct drm_device *dev, struct vm_area_struct *vma); void drm_vm_close_locked(struct drm_device *dev, struct vm_area_struct *vma); /* drm_prime.c */ @@ -62,6 +62,8 @@ int drm_gem_name_info(struct seq_file *m, void *data); /* drm_irq.c */ int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv); +int drm_modeset_ctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); /* drm_auth.c */ int drm_getmagic(struct drm_device *dev, void *data, @@ -93,3 +95,38 @@ int drm_gem_open_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); void drm_gem_open(struct drm_device *dev, struct drm_file *file_private); void drm_gem_release(struct drm_device *dev, struct drm_file *file_private); + +/* drm_drv.c */ +int drm_setmaster_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int drm_dropmaster_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +struct drm_master *drm_master_create(struct drm_minor *minor); + +/* drm_debugfs.c */ +#if defined(CONFIG_DEBUG_FS) +int drm_debugfs_init(struct drm_minor *minor, int minor_id, + struct dentry *root); +int drm_debugfs_cleanup(struct drm_minor *minor); +int drm_debugfs_connector_add(struct drm_connector *connector); +void drm_debugfs_connector_remove(struct drm_connector *connector); +#else +static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id, + struct dentry *root) +{ + return 0; +} + +static inline int drm_debugfs_cleanup(struct drm_minor *minor) +{ + return 0; +} + +static inline int drm_debugfs_connector_add(struct drm_connector *connector) +{ + return 0; +} +static inline void drm_debugfs_connector_remove(struct drm_connector *connector) +{ +} +#endif diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 80ff94ada75e..5ef03c216a27 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -126,6 +126,9 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) DRM_DEBUG("updating vblank count on crtc %d, missed %d\n", crtc, diff); + if (diff == 0) + return; + /* Reinitialize corresponding vblank timestamp if high-precision query * available. Skip this step if query unsupported or failed. Will * reinitialize delayed at next vblank interrupt in that case. @@ -1074,7 +1077,7 @@ void drm_wait_one_vblank(struct drm_device *dev, int crtc) u32 last; ret = drm_vblank_get(dev, crtc); - if (WARN_ON(ret)) + if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", crtc, ret)) return; last = drm_vblank_count(dev, crtc); @@ -1083,7 +1086,7 @@ void drm_wait_one_vblank(struct drm_device *dev, int crtc) last != drm_vblank_count(dev, crtc), msecs_to_jiffies(100)); - WARN_ON(ret == 0); + WARN(ret == 0, "vblank wait timed out on crtc %i\n", crtc); drm_vblank_put(dev, crtc); } diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 6aa6a9e95570..eb6dfe52cab2 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -231,6 +231,9 @@ ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, const void *data, break; } + if (dsi->mode_flags & MIPI_DSI_MODE_LPM) + msg.flags = MIPI_DSI_MSG_USE_LPM; + return ops->transfer(dsi->host, &msg); } EXPORT_SYMBOL(mipi_dsi_dcs_write); @@ -260,6 +263,9 @@ ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data, if (!ops || !ops->transfer) return -ENOSYS; + if (dsi->mode_flags & MIPI_DSI_MODE_LPM) + msg.flags = MIPI_DSI_MSG_USE_LPM; + return ops->transfer(dsi->host, &msg); } EXPORT_SYMBOL(mipi_dsi_dcs_read); diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 2807a771f505..78ca30808422 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -29,6 +29,8 @@ #include <linux/export.h> #include <linux/dma-buf.h> #include <drm/drmP.h> +#include <drm/drm_gem.h> + #include "drm_internal.h" /* @@ -523,7 +525,7 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, goto fail_detach; } - obj = dev->driver->gem_prime_import_sg_table(dev, dma_buf->size, sgt); + obj = dev->driver->gem_prime_import_sg_table(dev, attach, sgt); if (IS_ERR(obj)) { ret = PTR_ERR(obj); goto fail_unmap; diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 06cad0323699..4a2c328959e5 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -57,15 +57,11 @@ static pgprot_t drm_io_prot(struct drm_local_map *map, { pgprot_t tmp = vm_get_page_prot(vma->vm_flags); -#if defined(__i386__) || defined(__x86_64__) +#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) if (map->type == _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING)) tmp = pgprot_noncached(tmp); else tmp = pgprot_writecombine(tmp); -#elif defined(__powerpc__) - pgprot_val(tmp) |= _PAGE_NO_CACHE; - if (map->type == _DRM_REGISTERS) - pgprot_val(tmp) |= _PAGE_GUARDED; #elif defined(__ia64__) if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start)) @@ -421,7 +417,6 @@ void drm_vm_open_locked(struct drm_device *dev, list_add(&vma_entry->head, &dev->vmalist); } } -EXPORT_SYMBOL_GPL(drm_vm_open_locked); static void drm_vm_open(struct vm_area_struct *vma) { @@ -541,7 +536,7 @@ static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev) * according to the mapping type and remaps the pages. Finally sets the file * pointer and calls vm_open(). */ -int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) +static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) { struct drm_file *priv = filp->private_data; struct drm_device *dev = priv->minor->dev; @@ -655,7 +650,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) return 0; } -int drm_mmap(struct file *filp, struct vm_area_struct *vma) +int drm_legacy_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *priv = filp->private_data; struct drm_device *dev = priv->minor->dev; @@ -670,7 +665,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) return ret; } -EXPORT_SYMBOL(drm_mmap); +EXPORT_SYMBOL(drm_legacy_mmap); void drm_legacy_vma_flush(struct drm_device *dev) { diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 02602a8254c4..cd50ece31601 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -937,6 +937,8 @@ static enum drm_connector_status exynos_dp_detect( static void exynos_dp_connector_destroy(struct drm_connector *connector) { + drm_connector_unregister(connector); + drm_connector_cleanup(connector); } static struct drm_connector_funcs exynos_dp_connector_funcs = { @@ -1358,8 +1360,8 @@ static void exynos_dp_unbind(struct device *dev, struct device *master, exynos_dp_dpms(display, DRM_MODE_DPMS_OFF); + exynos_dp_connector_destroy(&dp->connector); encoder->funcs->destroy(encoder); - drm_connector_cleanup(&dp->connector); } static const struct component_ops exynos_dp_ops = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index b68e58f78cd1..8e38e9f8e542 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -32,7 +32,6 @@ enum exynos_crtc_mode { * Exynos specific crtc structure. * * @drm_crtc: crtc object. - * @drm_plane: pointer of private plane object for this crtc * @manager: the manager associated with this crtc * @pipe: a crtc index created at load() with a new crtc object creation * and the crtc object would be set to private->crtc array @@ -46,7 +45,6 @@ enum exynos_crtc_mode { */ struct exynos_drm_crtc { struct drm_crtc drm_crtc; - struct drm_plane *plane; struct exynos_drm_manager *manager; unsigned int pipe; unsigned int dpms; @@ -94,12 +92,12 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc) exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON); - exynos_plane_commit(exynos_crtc->plane); + exynos_plane_commit(crtc->primary); if (manager->ops->commit) manager->ops->commit(manager); - exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON); + exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON); } static bool @@ -123,10 +121,9 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct exynos_drm_manager *manager = exynos_crtc->manager; - struct drm_plane *plane = exynos_crtc->plane; + struct drm_framebuffer *fb = crtc->primary->fb; unsigned int crtc_w; unsigned int crtc_h; - int ret; /* * copy the mode data adjusted by mode_fixup() into crtc->mode @@ -134,29 +131,21 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, */ memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode)); - crtc_w = crtc->primary->fb->width - x; - crtc_h = crtc->primary->fb->height - y; + crtc_w = fb->width - x; + crtc_h = fb->height - y; if (manager->ops->mode_set) manager->ops->mode_set(manager, &crtc->mode); - ret = exynos_plane_mode_set(plane, crtc, crtc->primary->fb, 0, 0, crtc_w, crtc_h, - x, y, crtc_w, crtc_h); - if (ret) - return ret; - - plane->crtc = crtc; - plane->fb = crtc->primary->fb; - drm_framebuffer_reference(plane->fb); - - return 0; + return exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0, + crtc_w, crtc_h, x, y, crtc_w, crtc_h); } static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct drm_plane *plane = exynos_crtc->plane; + struct drm_framebuffer *fb = crtc->primary->fb; unsigned int crtc_w; unsigned int crtc_h; int ret; @@ -167,11 +156,11 @@ static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y, return -EPERM; } - crtc_w = crtc->primary->fb->width - x; - crtc_h = crtc->primary->fb->height - y; + crtc_w = fb->width - x; + crtc_h = fb->height - y; - ret = exynos_plane_mode_set(plane, crtc, crtc->primary->fb, 0, 0, crtc_w, crtc_h, - x, y, crtc_w, crtc_h); + ret = exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0, + crtc_w, crtc_h, x, y, crtc_w, crtc_h); if (ret) return ret; @@ -304,8 +293,7 @@ static int exynos_drm_crtc_set_property(struct drm_crtc *crtc, exynos_drm_crtc_commit(crtc); break; case CRTC_MODE_BLANK: - exynos_plane_dpms(exynos_crtc->plane, - DRM_MODE_DPMS_OFF); + exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_OFF); break; default: break; @@ -351,8 +339,10 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc) int exynos_drm_crtc_create(struct exynos_drm_manager *manager) { struct exynos_drm_crtc *exynos_crtc; + struct drm_plane *plane; struct exynos_drm_private *private = manager->drm_dev->dev_private; struct drm_crtc *crtc; + int ret; exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); if (!exynos_crtc) @@ -364,11 +354,11 @@ int exynos_drm_crtc_create(struct exynos_drm_manager *manager) exynos_crtc->dpms = DRM_MODE_DPMS_OFF; exynos_crtc->manager = manager; exynos_crtc->pipe = manager->pipe; - exynos_crtc->plane = exynos_plane_init(manager->drm_dev, - 1 << manager->pipe, true); - if (!exynos_crtc->plane) { - kfree(exynos_crtc); - return -ENOMEM; + plane = exynos_plane_init(manager->drm_dev, 1 << manager->pipe, + DRM_PLANE_TYPE_PRIMARY); + if (IS_ERR(plane)) { + ret = PTR_ERR(plane); + goto err_plane; } manager->crtc = &exynos_crtc->drm_crtc; @@ -376,12 +366,22 @@ int exynos_drm_crtc_create(struct exynos_drm_manager *manager) private->crtc[manager->pipe] = crtc; - drm_crtc_init(manager->drm_dev, crtc, &exynos_crtc_funcs); + ret = drm_crtc_init_with_planes(manager->drm_dev, crtc, plane, NULL, + &exynos_crtc_funcs); + if (ret < 0) + goto err_crtc; + drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs); exynos_drm_crtc_attach_mode_property(crtc); return 0; + +err_crtc: + plane->funcs->destroy(plane); +err_plane: + kfree(exynos_crtc); + return ret; } int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c index fa08f05e3e34..96c87db388fb 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c @@ -342,8 +342,12 @@ int exynos_dpi_remove(struct device *dev) struct exynos_dpi *ctx = exynos_dpi_display.ctx; exynos_dpi_dpms(&exynos_dpi_display, DRM_MODE_DPMS_OFF); + + exynos_dpi_connector_destroy(&ctx->connector); encoder->funcs->destroy(encoder); - drm_connector_cleanup(&ctx->connector); + + if (ctx->panel) + drm_panel_detach(ctx->panel); exynos_drm_component_del(dev, EXYNOS_DEVICE_TYPE_CONNECTOR); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 5aae95cf5b23..443a2069858a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -15,7 +15,6 @@ #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> -#include <linux/anon_inodes.h> #include <linux/component.h> #include <drm/exynos_drm.h> @@ -86,8 +85,9 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) struct drm_plane *plane; unsigned long possible_crtcs = (1 << MAX_CRTC) - 1; - plane = exynos_plane_init(dev, possible_crtcs, false); - if (!plane) + plane = exynos_plane_init(dev, possible_crtcs, + DRM_PLANE_TYPE_OVERLAY); + if (IS_ERR(plane)) goto err_mode_config_cleanup; } @@ -116,6 +116,23 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) /* force connectors detection */ drm_helper_hpd_irq_event(dev); + /* + * enable drm irq mode. + * - with irq_enabled = true, we can use the vblank feature. + * + * P.S. note that we wouldn't use drm irq handler but + * just specific driver own one instead because + * drm framework supports only one irq handler. + */ + dev->irq_enabled = true; + + /* + * with vblank_disable_allowed = true, vblank interrupt will be disabled + * by drm timer once a current process gives up ownership of + * vblank event.(after drm_vblank_put function is called) + */ + dev->vblank_disable_allowed = true; + return 0; err_unbind_all: @@ -136,23 +153,19 @@ static int exynos_drm_unload(struct drm_device *dev) exynos_drm_device_subdrv_remove(dev); exynos_drm_fbdev_fini(dev); - drm_vblank_cleanup(dev); drm_kms_helper_poll_fini(dev); - drm_mode_config_cleanup(dev); + component_unbind_all(dev->dev, dev); + drm_vblank_cleanup(dev); + drm_mode_config_cleanup(dev); drm_release_iommu_mapping(dev); - kfree(dev->dev_private); - component_unbind_all(dev->dev, dev); + kfree(dev->dev_private); dev->dev_private = NULL; return 0; } -static const struct file_operations exynos_drm_gem_fops = { - .mmap = exynos_drm_gem_mmap_buffer, -}; - static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state) { struct drm_connector *connector; @@ -191,7 +204,6 @@ static int exynos_drm_resume(struct drm_device *dev) static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) { struct drm_exynos_file_private *file_priv; - struct file *anon_filp; int ret; file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); @@ -204,21 +216,8 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) if (ret) goto err_file_priv_free; - anon_filp = anon_inode_getfile("exynos_gem", &exynos_drm_gem_fops, - NULL, 0); - if (IS_ERR(anon_filp)) { - ret = PTR_ERR(anon_filp); - goto err_subdrv_close; - } - - anon_filp->f_mode = FMODE_READ | FMODE_WRITE; - file_priv->anon_filp = anon_filp; - return ret; -err_subdrv_close: - exynos_drm_subdrv_close(dev, file); - err_file_priv_free: kfree(file_priv); file->driver_priv = NULL; @@ -234,7 +233,6 @@ static void exynos_drm_preclose(struct drm_device *dev, static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) { struct exynos_drm_private *private = dev->dev_private; - struct drm_exynos_file_private *file_priv; struct drm_pending_vblank_event *v, *vt; struct drm_pending_event *e, *et; unsigned long flags; @@ -260,10 +258,6 @@ static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) } spin_unlock_irqrestore(&dev->event_lock, flags); - file_priv = file->driver_priv; - if (file_priv->anon_filp) - fput(file_priv->anon_filp); - kfree(file->driver_priv); file->driver_priv = NULL; } @@ -282,11 +276,6 @@ static const struct vm_operations_struct exynos_drm_gem_vm_ops = { static const struct drm_ioctl_desc exynos_ioctls[] = { DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl, DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET, - exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED | - DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP, - exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH), DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, exynos_drm_gem_get_ioctl, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, @@ -486,21 +475,20 @@ void exynos_drm_component_del(struct device *dev, mutex_unlock(&drm_component_lock); } -static int compare_of(struct device *dev, void *data) +static int compare_dev(struct device *dev, void *data) { return dev == (struct device *)data; } -static int exynos_drm_add_components(struct device *dev, struct master *m) +static struct component_match *exynos_drm_match_add(struct device *dev) { + struct component_match *match = NULL; struct component_dev *cdev; unsigned int attach_cnt = 0; mutex_lock(&drm_component_lock); list_for_each_entry(cdev, &drm_component_list, list) { - int ret; - /* * Add components to master only in case that crtc and * encoder/connector device objects exist. @@ -515,16 +503,10 @@ static int exynos_drm_add_components(struct device *dev, struct master *m) /* * fimd and dpi modules have same device object so add * only crtc device object in this case. - * - * TODO. if dpi module follows driver-model driver then - * below codes can be removed. */ if (cdev->crtc_dev == cdev->conn_dev) { - ret = component_master_add_child(m, compare_of, - cdev->crtc_dev); - if (ret < 0) - return ret; - + component_match_add(dev, &match, compare_dev, + cdev->crtc_dev); goto out_lock; } @@ -534,11 +516,8 @@ static int exynos_drm_add_components(struct device *dev, struct master *m) * connector/encoder need pipe number of crtc when they * are created. */ - ret = component_master_add_child(m, compare_of, cdev->crtc_dev); - ret |= component_master_add_child(m, compare_of, - cdev->conn_dev); - if (ret < 0) - return ret; + component_match_add(dev, &match, compare_dev, cdev->crtc_dev); + component_match_add(dev, &match, compare_dev, cdev->conn_dev); out_lock: mutex_lock(&drm_component_lock); @@ -546,7 +525,7 @@ out_lock: mutex_unlock(&drm_component_lock); - return attach_cnt ? 0 : -ENODEV; + return attach_cnt ? match : ERR_PTR(-EPROBE_DEFER); } static int exynos_drm_bind(struct device *dev) @@ -560,13 +539,13 @@ static void exynos_drm_unbind(struct device *dev) } static const struct component_master_ops exynos_drm_ops = { - .add_components = exynos_drm_add_components, .bind = exynos_drm_bind, .unbind = exynos_drm_unbind, }; static int exynos_drm_platform_probe(struct platform_device *pdev) { + struct component_match *match; int ret; pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); @@ -633,13 +612,23 @@ static int exynos_drm_platform_probe(struct platform_device *pdev) goto err_unregister_ipp_drv; #endif - ret = component_master_add(&pdev->dev, &exynos_drm_ops); + match = exynos_drm_match_add(&pdev->dev); + if (IS_ERR(match)) { + ret = PTR_ERR(match); + goto err_unregister_resources; + } + + ret = component_master_add_with_match(&pdev->dev, &exynos_drm_ops, + match); if (ret < 0) - DRM_DEBUG_KMS("re-tried by last sub driver probed later.\n"); + goto err_unregister_resources; - return 0; + return ret; + +err_unregister_resources: #ifdef CONFIG_DRM_EXYNOS_IPP + exynos_platform_device_ipp_unregister(); err_unregister_ipp_drv: platform_driver_unregister(&ipp_driver); err_unregister_gsc_drv: diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 69a6fa397d75..d22e640f59a0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -240,7 +240,6 @@ struct exynos_drm_g2d_private { struct drm_exynos_file_private { struct exynos_drm_g2d_private *g2d_priv; struct device *ipp_dev; - struct file *anon_filp; }; /* diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 442aa2d00132..24741d8758e8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -114,6 +114,8 @@ #define DSIM_SYNC_INFORM (1 << 27) #define DSIM_EOT_DISABLE (1 << 28) #define DSIM_MFLUSH_VS (1 << 29) +/* This flag is valid only for exynos3250/3472/4415/5260/5430 */ +#define DSIM_CLKLANE_STOP (1 << 30) /* DSIM_ESCMODE */ #define DSIM_TX_TRIGGER_RST (1 << 4) @@ -262,6 +264,7 @@ struct exynos_dsi_driver_data { unsigned int plltmr_reg; unsigned int has_freqband:1; + unsigned int has_clklane_stop:1; }; struct exynos_dsi { @@ -301,9 +304,16 @@ struct exynos_dsi { #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector) +static struct exynos_dsi_driver_data exynos3_dsi_driver_data = { + .plltmr_reg = 0x50, + .has_freqband = 1, + .has_clklane_stop = 1, +}; + static struct exynos_dsi_driver_data exynos4_dsi_driver_data = { .plltmr_reg = 0x50, .has_freqband = 1, + .has_clklane_stop = 1, }; static struct exynos_dsi_driver_data exynos5_dsi_driver_data = { @@ -311,6 +321,8 @@ static struct exynos_dsi_driver_data exynos5_dsi_driver_data = { }; static struct of_device_id exynos_dsi_of_match[] = { + { .compatible = "samsung,exynos3250-mipi-dsi", + .data = &exynos3_dsi_driver_data }, { .compatible = "samsung,exynos4210-mipi-dsi", .data = &exynos4_dsi_driver_data }, { .compatible = "samsung,exynos5410-mipi-dsi", @@ -421,7 +433,7 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, if (!fout) { dev_err(dsi->dev, "failed to find PLL PMS for requested frequency\n"); - return -EFAULT; + return 0; } dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d)\n", fout, p, m, s); @@ -453,7 +465,7 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, do { if (timeout-- == 0) { dev_err(dsi->dev, "PLL failed to stabilize\n"); - return -EFAULT; + return 0; } reg = readl(dsi->reg_base + DSIM_STATUS_REG); } while ((reg & DSIM_PLL_STABLE) == 0); @@ -569,6 +581,7 @@ static void exynos_dsi_disable_clock(struct exynos_dsi *dsi) static int exynos_dsi_init_link(struct exynos_dsi *dsi) { + struct exynos_dsi_driver_data *driver_data = dsi->driver_data; int timeout; u32 reg; u32 lanes_mask; @@ -650,6 +663,20 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) reg |= DSIM_LANE_EN(lanes_mask); writel(reg, dsi->reg_base + DSIM_CONFIG_REG); + /* + * Use non-continuous clock mode if the periparal wants and + * host controller supports + * + * In non-continous clock mode, host controller will turn off + * the HS clock between high-speed transmissions to reduce + * power consumption. + */ + if (driver_data->has_clklane_stop && + dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { + reg |= DSIM_CLKLANE_STOP; + writel(reg, dsi->reg_base + DSIM_CONFIG_REG); + } + /* Check clock and data lane state are stop state */ timeout = 100; do { @@ -1414,6 +1441,9 @@ exynos_dsi_detect(struct drm_connector *connector, bool force) static void exynos_dsi_connector_destroy(struct drm_connector *connector) { + drm_connector_unregister(connector); + drm_connector_cleanup(connector); + connector->dev = NULL; } static struct drm_connector_funcs exynos_dsi_connector_funcs = { @@ -1634,10 +1664,10 @@ static void exynos_dsi_unbind(struct device *dev, struct device *master, exynos_dsi_dpms(&exynos_dsi_display, DRM_MODE_DPMS_OFF); - mipi_dsi_host_unregister(&dsi->dsi_host); - + exynos_dsi_connector_destroy(&dsi->connector); encoder->funcs->destroy(encoder); - drm_connector_cleanup(&dsi->connector); + + mipi_dsi_host_unregister(&dsi->dsi_host); } static const struct component_ops exynos_dsi_component_ops = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 65a22cad7b36..d346d1e6eda0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -165,6 +165,7 @@ exynos_drm_framebuffer_init(struct drm_device *dev, ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); if (ret) { + kfree(exynos_fb); DRM_ERROR("failed to initialize framebuffer\n"); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 32e63f60e1d1..e12ea90c6237 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -123,6 +123,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, fbi->screen_base = buffer->kvaddr + offset; fbi->screen_size = size; + fbi->fix.smem_len = size; return 0; } @@ -353,9 +354,6 @@ void exynos_drm_fbdev_fini(struct drm_device *dev) fbdev = to_exynos_fbdev(private->fb_helper); - if (fbdev->exynos_gem_obj) - exynos_drm_gem_destroy(fbdev->exynos_gem_obj); - exynos_drm_fbdev_destroy(dev, private->fb_helper); kfree(fbdev); private->fb_helper = NULL; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index ec7cc9ea50df..68d38eb6774d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -336,9 +336,6 @@ static bool fimc_check_ovf(struct fimc_context *ctx) fimc_set_bits(ctx, EXYNOS_CIWDOFST, EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB | EXYNOS_CIWDOFST_CLROVFICR); - fimc_clear_bits(ctx, EXYNOS_CIWDOFST, - EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB | - EXYNOS_CIWDOFST_CLROVFICR); dev_err(ippdrv->dev, "occurred overflow at %d, status 0x%x.\n", ctx->id, status); @@ -718,24 +715,24 @@ static int fimc_src_set_addr(struct device *dev, case IPP_BUF_ENQUEUE: config = &property->config[EXYNOS_DRM_OPS_SRC]; fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_Y], - EXYNOS_CIIYSA(buf_id)); + EXYNOS_CIIYSA0); if (config->fmt == DRM_FORMAT_YVU420) { fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CR], - EXYNOS_CIICBSA(buf_id)); + EXYNOS_CIICBSA0); fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CB], - EXYNOS_CIICRSA(buf_id)); + EXYNOS_CIICRSA0); } else { fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CB], - EXYNOS_CIICBSA(buf_id)); + EXYNOS_CIICBSA0); fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CR], - EXYNOS_CIICRSA(buf_id)); + EXYNOS_CIICRSA0); } break; case IPP_BUF_DEQUEUE: - fimc_write(ctx, 0x0, EXYNOS_CIIYSA(buf_id)); - fimc_write(ctx, 0x0, EXYNOS_CIICBSA(buf_id)); - fimc_write(ctx, 0x0, EXYNOS_CIICRSA(buf_id)); + fimc_write(ctx, 0x0, EXYNOS_CIIYSA0); + fimc_write(ctx, 0x0, EXYNOS_CIICBSA0); + fimc_write(ctx, 0x0, EXYNOS_CIICRSA0); break; default: /* bypass */ @@ -1122,67 +1119,34 @@ static int fimc_dst_set_size(struct device *dev, int swap, return 0; } -static int fimc_dst_get_buf_count(struct fimc_context *ctx) -{ - u32 cfg, buf_num; - - cfg = fimc_read(ctx, EXYNOS_CIFCNTSEQ); - - buf_num = hweight32(cfg); - - DRM_DEBUG_KMS("buf_num[%d]\n", buf_num); - - return buf_num; -} - -static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id, +static void fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id, enum drm_exynos_ipp_buf_type buf_type) { - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - bool enable; - u32 cfg; - u32 mask = 0x00000001 << buf_id; - int ret = 0; unsigned long flags; + u32 buf_num; + u32 cfg; DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type); spin_lock_irqsave(&ctx->lock, flags); - /* mask register set */ cfg = fimc_read(ctx, EXYNOS_CIFCNTSEQ); - switch (buf_type) { - case IPP_BUF_ENQUEUE: - enable = true; - break; - case IPP_BUF_DEQUEUE: - enable = false; - break; - default: - dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n"); - ret = -EINVAL; - goto err_unlock; - } + if (buf_type == IPP_BUF_ENQUEUE) + cfg |= (1 << buf_id); + else + cfg &= ~(1 << buf_id); - /* sequence id */ - cfg &= ~mask; - cfg |= (enable << buf_id); fimc_write(ctx, cfg, EXYNOS_CIFCNTSEQ); - /* interrupt enable */ - if (buf_type == IPP_BUF_ENQUEUE && - fimc_dst_get_buf_count(ctx) >= FIMC_BUF_START) - fimc_mask_irq(ctx, true); + buf_num = hweight32(cfg); - /* interrupt disable */ - if (buf_type == IPP_BUF_DEQUEUE && - fimc_dst_get_buf_count(ctx) <= FIMC_BUF_STOP) + if (buf_type == IPP_BUF_ENQUEUE && buf_num >= FIMC_BUF_START) + fimc_mask_irq(ctx, true); + else if (buf_type == IPP_BUF_DEQUEUE && buf_num <= FIMC_BUF_STOP) fimc_mask_irq(ctx, false); -err_unlock: spin_unlock_irqrestore(&ctx->lock, flags); - return ret; } static int fimc_dst_set_addr(struct device *dev, @@ -1240,7 +1204,9 @@ static int fimc_dst_set_addr(struct device *dev, break; } - return fimc_dst_set_buf_seq(ctx, buf_id, buf_type); + fimc_dst_set_buf_seq(ctx, buf_id, buf_type); + + return 0; } static struct exynos_drm_ipp_ops fimc_dst_ops = { @@ -1291,14 +1257,11 @@ static irqreturn_t fimc_irq_handler(int irq, void *dev_id) DRM_DEBUG_KMS("buf_id[%d]\n", buf_id); - if (fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE) < 0) { - DRM_ERROR("failed to dequeue.\n"); - return IRQ_HANDLED; - } + fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE); event_work->ippdrv = ippdrv; event_work->buf_id[EXYNOS_DRM_OPS_DST] = buf_id; - queue_work(ippdrv->event_workq, (struct work_struct *)event_work); + queue_work(ippdrv->event_workq, &event_work->work); return IRQ_HANDLED; } @@ -1590,11 +1553,8 @@ static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd) fimc_clear_bits(ctx, EXYNOS_CIOCTRL, EXYNOS_CIOCTRL_WEAVE_MASK); - if (cmd == IPP_CMD_M2M) { - fimc_set_bits(ctx, EXYNOS_MSCTRL, EXYNOS_MSCTRL_ENVID); - + if (cmd == IPP_CMD_M2M) fimc_set_bits(ctx, EXYNOS_MSCTRL, EXYNOS_MSCTRL_ENVID); - } return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 5d09e33fef87..085b066a9993 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -104,6 +104,14 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = { .has_limited_fmt = 1, }; +static struct fimd_driver_data exynos3_fimd_driver_data = { + .timing_base = 0x20000, + .lcdblk_offset = 0x210, + .lcdblk_bypass_shift = 1, + .has_shadowcon = 1, + .has_vidoutcon = 1, +}; + static struct fimd_driver_data exynos4_fimd_driver_data = { .timing_base = 0x0, .lcdblk_offset = 0x210, @@ -168,6 +176,8 @@ struct fimd_context { static const struct of_device_id fimd_driver_dt_match[] = { { .compatible = "samsung,s3c6400-fimd", .data = &s3c64xx_fimd_driver_data }, + { .compatible = "samsung,exynos3250-fimd", + .data = &exynos3_fimd_driver_data }, { .compatible = "samsung,exynos4210-fimd", .data = &exynos4_fimd_driver_data }, { .compatible = "samsung,exynos5250-fimd", @@ -204,7 +214,6 @@ static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr) DRM_DEBUG_KMS("vblank wait timed out.\n"); } - static void fimd_clear_channel(struct exynos_drm_manager *mgr) { struct fimd_context *ctx = mgr->ctx; @@ -214,17 +223,31 @@ static void fimd_clear_channel(struct exynos_drm_manager *mgr) /* Check if any channel is enabled. */ for (win = 0; win < WINDOWS_NR; win++) { - u32 val = readl(ctx->regs + SHADOWCON); - if (val & SHADOWCON_CHx_ENABLE(win)) { - val &= ~SHADOWCON_CHx_ENABLE(win); - writel(val, ctx->regs + SHADOWCON); + u32 val = readl(ctx->regs + WINCON(win)); + + if (val & WINCONx_ENWIN) { + /* wincon */ + val &= ~WINCONx_ENWIN; + writel(val, ctx->regs + WINCON(win)); + + /* unprotect windows */ + if (ctx->driver_data->has_shadowcon) { + val = readl(ctx->regs + SHADOWCON); + val &= ~SHADOWCON_CHx_ENABLE(win); + writel(val, ctx->regs + SHADOWCON); + } ch_enabled = 1; } } /* Wait for vsync, as disable channel takes effect at next vsync */ - if (ch_enabled) + if (ch_enabled) { + unsigned int state = ctx->suspended; + + ctx->suspended = 0; fimd_wait_for_vblank(mgr); + ctx->suspended = state; + } } static int fimd_mgr_initialize(struct exynos_drm_manager *mgr, @@ -237,23 +260,6 @@ static int fimd_mgr_initialize(struct exynos_drm_manager *mgr, mgr->drm_dev = ctx->drm_dev = drm_dev; mgr->pipe = ctx->pipe = priv->pipe++; - /* - * enable drm irq mode. - * - with irq_enabled = true, we can use the vblank feature. - * - * P.S. note that we wouldn't use drm irq handler but - * just specific driver own one instead because - * drm framework supports only one irq handler. - */ - drm_dev->irq_enabled = true; - - /* - * with vblank_disable_allowed = true, vblank interrupt will be disabled - * by drm timer once a current process gives up ownership of - * vblank event.(after drm_vblank_put function is called) - */ - drm_dev->vblank_disable_allowed = true; - /* attach this sub driver to iommu mapping if supported. */ if (is_drm_iommu_supported(ctx->drm_dev)) { /* @@ -1051,7 +1057,6 @@ static void fimd_unbind(struct device *dev, struct device *master, { struct exynos_drm_manager *mgr = dev_get_drvdata(dev); struct fimd_context *ctx = fimd_manager.ctx; - struct drm_crtc *crtc = mgr->crtc; fimd_dpms(mgr, DRM_MODE_DPMS_OFF); @@ -1059,8 +1064,6 @@ static void fimd_unbind(struct device *dev, struct device *master, exynos_dpi_remove(dev); fimd_mgr_remove(mgr); - - crtc->funcs->destroy(crtc); } static const struct component_ops fimd_component_ops = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 15db80138382..0d5b9698d384 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -318,40 +318,16 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev, drm_gem_object_unreference_unlocked(obj); } -int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_exynos_gem_map_off *args = data; - - DRM_DEBUG_KMS("handle = 0x%x, offset = 0x%lx\n", - args->handle, (unsigned long)args->offset); - - if (!(dev->driver->driver_features & DRIVER_GEM)) { - DRM_ERROR("does not support GEM.\n"); - return -ENODEV; - } - - return exynos_drm_gem_dumb_map_offset(file_priv, dev, args->handle, - &args->offset); -} - -int exynos_drm_gem_mmap_buffer(struct file *filp, +int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj, struct vm_area_struct *vma) { - struct drm_gem_object *obj = filp->private_data; - struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); - struct drm_device *drm_dev = obj->dev; + struct drm_device *drm_dev = exynos_gem_obj->base.dev; struct exynos_drm_gem_buf *buffer; unsigned long vm_size; int ret; - WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); - - vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; - vma->vm_private_data = obj; - vma->vm_ops = drm_dev->driver->gem_vm_ops; - - update_vm_cache_attr(exynos_gem_obj, vma); + vma->vm_flags &= ~VM_PFNMAP; + vma->vm_pgoff = 0; vm_size = vma->vm_end - vma->vm_start; @@ -373,60 +349,6 @@ int exynos_drm_gem_mmap_buffer(struct file *filp, return ret; } - /* - * take a reference to this mapping of the object. And this reference - * is unreferenced by the corresponding vm_close call. - */ - drm_gem_object_reference(obj); - - drm_vm_open_locked(drm_dev, vma); - - return 0; -} - -int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_exynos_file_private *exynos_file_priv; - struct drm_exynos_gem_mmap *args = data; - struct drm_gem_object *obj; - struct file *anon_filp; - unsigned long addr; - - if (!(dev->driver->driver_features & DRIVER_GEM)) { - DRM_ERROR("does not support GEM.\n"); - return -ENODEV; - } - - mutex_lock(&dev->struct_mutex); - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - mutex_unlock(&dev->struct_mutex); - return -EINVAL; - } - - exynos_file_priv = file_priv->driver_priv; - anon_filp = exynos_file_priv->anon_filp; - anon_filp->private_data = obj; - - addr = vm_mmap(anon_filp, 0, args->size, PROT_READ | PROT_WRITE, - MAP_SHARED, 0); - - drm_gem_object_unreference(obj); - - if (IS_ERR_VALUE(addr)) { - mutex_unlock(&dev->struct_mutex); - return (int)addr; - } - - mutex_unlock(&dev->struct_mutex); - - args->mapped = addr; - - DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped); - return 0; } @@ -710,16 +632,20 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) exynos_gem_obj = to_exynos_gem_obj(obj); ret = check_gem_flags(exynos_gem_obj->flags); - if (ret) { - drm_gem_vm_close(vma); - drm_gem_free_mmap_offset(obj); - return ret; - } - - vma->vm_flags &= ~VM_PFNMAP; - vma->vm_flags |= VM_MIXEDMAP; + if (ret) + goto err_close_vm; update_vm_cache_attr(exynos_gem_obj, vma); + ret = exynos_drm_gem_mmap_buffer(exynos_gem_obj, vma); + if (ret) + goto err_close_vm; + + return ret; + +err_close_vm: + drm_gem_vm_close(vma); + drm_gem_free_mmap_offset(obj); + return ret; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index 1592c0ba7de8..ec58fe9c40df 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h @@ -12,6 +12,8 @@ #ifndef _EXYNOS_DRM_GEM_H_ #define _EXYNOS_DRM_GEM_H_ +#include <drm/drm_gem.h> + #define to_exynos_gem_obj(x) container_of(x,\ struct exynos_drm_gem_obj, base) @@ -111,20 +113,6 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev, unsigned int gem_handle, struct drm_file *filp); -/* get buffer offset to map to user space. */ -int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* - * mmap the physically continuous memory that a gem object contains - * to user space. - */ -int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -int exynos_drm_gem_mmap_buffer(struct file *filp, - struct vm_area_struct *vma); - /* map user space allocated by malloc to pages. */ int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index 9e3ff1672965..c6a013fc321c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -1326,8 +1326,7 @@ static irqreturn_t gsc_irq_handler(int irq, void *dev_id) buf_id[EXYNOS_DRM_OPS_SRC]; event_work->buf_id[EXYNOS_DRM_OPS_DST] = buf_id[EXYNOS_DRM_OPS_DST]; - queue_work(ippdrv->event_workq, - (struct work_struct *)event_work); + queue_work(ippdrv->event_workq, &event_work->work); } return IRQ_HANDLED; diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index c411399070d6..00d74b18f7cb 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -75,7 +75,6 @@ struct drm_exynos_ipp_mem_node { u32 prop_id; u32 buf_id; struct drm_exynos_ipp_buf_info buf_info; - struct drm_file *filp; }; /* @@ -319,44 +318,6 @@ static void ipp_print_property(struct drm_exynos_ipp_property *property, sz->hsize, sz->vsize, config->flip, config->degree); } -static int ipp_find_and_set_property(struct drm_exynos_ipp_property *property) -{ - struct exynos_drm_ippdrv *ippdrv; - struct drm_exynos_ipp_cmd_node *c_node; - u32 prop_id = property->prop_id; - - DRM_DEBUG_KMS("prop_id[%d]\n", prop_id); - - ippdrv = ipp_find_drv_by_handle(prop_id); - if (IS_ERR(ippdrv)) { - DRM_ERROR("failed to get ipp driver.\n"); - return -EINVAL; - } - - /* - * Find command node using command list in ippdrv. - * when we find this command no using prop_id. - * return property information set in this command node. - */ - mutex_lock(&ippdrv->cmd_lock); - list_for_each_entry(c_node, &ippdrv->cmd_list, list) { - if ((c_node->property.prop_id == prop_id) && - (c_node->state == IPP_STATE_STOP)) { - mutex_unlock(&ippdrv->cmd_lock); - DRM_DEBUG_KMS("found cmd[%d]ippdrv[0x%x]\n", - property->cmd, (int)ippdrv); - - c_node->property = *property; - return 0; - } - } - mutex_unlock(&ippdrv->cmd_lock); - - DRM_ERROR("failed to search property.\n"); - - return -EINVAL; -} - static struct drm_exynos_ipp_cmd_work *ipp_create_cmd_work(void) { struct drm_exynos_ipp_cmd_work *cmd_work; @@ -392,6 +353,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, struct drm_exynos_ipp_property *property = data; struct exynos_drm_ippdrv *ippdrv; struct drm_exynos_ipp_cmd_node *c_node; + u32 prop_id; int ret, i; if (!ctx) { @@ -404,6 +366,8 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, return -EINVAL; } + prop_id = property->prop_id; + /* * This is log print for user application property. * user application set various property. @@ -412,14 +376,24 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, ipp_print_property(property, i); /* - * set property ioctl generated new prop_id. - * but in this case already asigned prop_id using old set property. - * e.g PAUSE state. this case supports find current prop_id and use it - * instead of allocation. + * In case prop_id is not zero try to set existing property. */ - if (property->prop_id) { - DRM_DEBUG_KMS("prop_id[%d]\n", property->prop_id); - return ipp_find_and_set_property(property); + if (prop_id) { + c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock, prop_id); + + if (!c_node || c_node->filp != file) { + DRM_DEBUG_KMS("prop_id[%d] not found\n", prop_id); + return -EINVAL; + } + + if (c_node->state != IPP_STATE_STOP) { + DRM_DEBUG_KMS("prop_id[%d] not stopped\n", prop_id); + return -EINVAL; + } + + c_node->property = *property; + + return 0; } /* find ipp driver using ipp id */ @@ -445,9 +419,9 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, property->prop_id, property->cmd, (int)ippdrv); /* stored property information and ippdrv in private data */ - c_node->dev = dev; c_node->property = *property; c_node->state = IPP_STATE_IDLE; + c_node->filp = file; c_node->start_work = ipp_create_cmd_work(); if (IS_ERR(c_node->start_work)) { @@ -499,105 +473,37 @@ err_clear: return ret; } -static void ipp_clean_cmd_node(struct ipp_context *ctx, - struct drm_exynos_ipp_cmd_node *c_node) -{ - /* delete list */ - list_del(&c_node->list); - - ipp_remove_id(&ctx->prop_idr, &ctx->prop_lock, - c_node->property.prop_id); - - /* destroy mutex */ - mutex_destroy(&c_node->lock); - mutex_destroy(&c_node->mem_lock); - mutex_destroy(&c_node->event_lock); - - /* free command node */ - kfree(c_node->start_work); - kfree(c_node->stop_work); - kfree(c_node->event_work); - kfree(c_node); -} - -static bool ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node) -{ - switch (c_node->property.cmd) { - case IPP_CMD_WB: - return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_DST]); - case IPP_CMD_OUTPUT: - return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_SRC]); - case IPP_CMD_M2M: - default: - return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_SRC]) && - !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_DST]); - } -} - -static struct drm_exynos_ipp_mem_node - *ipp_find_mem_node(struct drm_exynos_ipp_cmd_node *c_node, - struct drm_exynos_ipp_queue_buf *qbuf) -{ - struct drm_exynos_ipp_mem_node *m_node; - struct list_head *head; - int count = 0; - - DRM_DEBUG_KMS("buf_id[%d]\n", qbuf->buf_id); - - /* source/destination memory list */ - head = &c_node->mem_list[qbuf->ops_id]; - - /* find memory node from memory list */ - list_for_each_entry(m_node, head, list) { - DRM_DEBUG_KMS("count[%d]m_node[0x%x]\n", count++, (int)m_node); - - /* compare buffer id */ - if (m_node->buf_id == qbuf->buf_id) - return m_node; - } - - return NULL; -} - -static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv, +static int ipp_put_mem_node(struct drm_device *drm_dev, struct drm_exynos_ipp_cmd_node *c_node, struct drm_exynos_ipp_mem_node *m_node) { - struct exynos_drm_ipp_ops *ops = NULL; - int ret = 0; + int i; DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node); if (!m_node) { - DRM_ERROR("invalid queue node.\n"); + DRM_ERROR("invalid dequeue node.\n"); return -EFAULT; } DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id); - /* get operations callback */ - ops = ippdrv->ops[m_node->ops_id]; - if (!ops) { - DRM_ERROR("not support ops.\n"); - return -EFAULT; + /* put gem buffer */ + for_each_ipp_planar(i) { + unsigned long handle = m_node->buf_info.handles[i]; + if (handle) + exynos_drm_gem_put_dma_addr(drm_dev, handle, + c_node->filp); } - /* set address and enable irq */ - if (ops->set_addr) { - ret = ops->set_addr(ippdrv->dev, &m_node->buf_info, - m_node->buf_id, IPP_BUF_ENQUEUE); - if (ret) { - DRM_ERROR("failed to set addr.\n"); - return ret; - } - } + list_del(&m_node->list); + kfree(m_node); - return ret; + return 0; } static struct drm_exynos_ipp_mem_node *ipp_get_mem_node(struct drm_device *drm_dev, - struct drm_file *file, struct drm_exynos_ipp_cmd_node *c_node, struct drm_exynos_ipp_queue_buf *qbuf) { @@ -615,6 +521,7 @@ static struct drm_exynos_ipp_mem_node m_node->ops_id = qbuf->ops_id; m_node->prop_id = qbuf->prop_id; m_node->buf_id = qbuf->buf_id; + INIT_LIST_HEAD(&m_node->list); DRM_DEBUG_KMS("m_node[0x%x]ops_id[%d]\n", (int)m_node, qbuf->ops_id); DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]\n", qbuf->prop_id, m_node->buf_id); @@ -627,10 +534,11 @@ static struct drm_exynos_ipp_mem_node dma_addr_t *addr; addr = exynos_drm_gem_get_dma_addr(drm_dev, - qbuf->handle[i], file); + qbuf->handle[i], c_node->filp); if (IS_ERR(addr)) { DRM_ERROR("failed to get addr.\n"); - goto err_clear; + ipp_put_mem_node(drm_dev, c_node, m_node); + return ERR_PTR(-EFAULT); } buf_info->handles[i] = qbuf->handle[i]; @@ -640,46 +548,30 @@ static struct drm_exynos_ipp_mem_node } } - m_node->filp = file; mutex_lock(&c_node->mem_lock); list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]); mutex_unlock(&c_node->mem_lock); return m_node; - -err_clear: - kfree(m_node); - return ERR_PTR(-EFAULT); } -static int ipp_put_mem_node(struct drm_device *drm_dev, - struct drm_exynos_ipp_cmd_node *c_node, - struct drm_exynos_ipp_mem_node *m_node) +static void ipp_clean_mem_nodes(struct drm_device *drm_dev, + struct drm_exynos_ipp_cmd_node *c_node, int ops) { - int i; - - DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node); + struct drm_exynos_ipp_mem_node *m_node, *tm_node; + struct list_head *head = &c_node->mem_list[ops]; - if (!m_node) { - DRM_ERROR("invalid dequeue node.\n"); - return -EFAULT; - } + mutex_lock(&c_node->mem_lock); - DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id); + list_for_each_entry_safe(m_node, tm_node, head, list) { + int ret; - /* put gem buffer */ - for_each_ipp_planar(i) { - unsigned long handle = m_node->buf_info.handles[i]; - if (handle) - exynos_drm_gem_put_dma_addr(drm_dev, handle, - m_node->filp); + ret = ipp_put_mem_node(drm_dev, c_node, m_node); + if (ret) + DRM_ERROR("failed to put m_node.\n"); } - /* delete list in queue */ - list_del(&m_node->list); - kfree(m_node); - - return 0; + mutex_unlock(&c_node->mem_lock); } static void ipp_free_event(struct drm_pending_event *event) @@ -688,7 +580,6 @@ static void ipp_free_event(struct drm_pending_event *event) } static int ipp_get_event(struct drm_device *drm_dev, - struct drm_file *file, struct drm_exynos_ipp_cmd_node *c_node, struct drm_exynos_ipp_queue_buf *qbuf) { @@ -700,7 +591,7 @@ static int ipp_get_event(struct drm_device *drm_dev, e = kzalloc(sizeof(*e), GFP_KERNEL); if (!e) { spin_lock_irqsave(&drm_dev->event_lock, flags); - file->event_space += sizeof(e->event); + c_node->filp->event_space += sizeof(e->event); spin_unlock_irqrestore(&drm_dev->event_lock, flags); return -ENOMEM; } @@ -712,7 +603,7 @@ static int ipp_get_event(struct drm_device *drm_dev, e->event.prop_id = qbuf->prop_id; e->event.buf_id[EXYNOS_DRM_OPS_DST] = qbuf->buf_id; e->base.event = &e->event.base; - e->base.file_priv = file; + e->base.file_priv = c_node->filp; e->base.destroy = ipp_free_event; mutex_lock(&c_node->event_lock); list_add_tail(&e->base.link, &c_node->event_list); @@ -757,6 +648,115 @@ out_unlock: return; } +static void ipp_clean_cmd_node(struct ipp_context *ctx, + struct drm_exynos_ipp_cmd_node *c_node) +{ + int i; + + /* cancel works */ + cancel_work_sync(&c_node->start_work->work); + cancel_work_sync(&c_node->stop_work->work); + cancel_work_sync(&c_node->event_work->work); + + /* put event */ + ipp_put_event(c_node, NULL); + + for_each_ipp_ops(i) + ipp_clean_mem_nodes(ctx->subdrv.drm_dev, c_node, i); + + /* delete list */ + list_del(&c_node->list); + + ipp_remove_id(&ctx->prop_idr, &ctx->prop_lock, + c_node->property.prop_id); + + /* destroy mutex */ + mutex_destroy(&c_node->lock); + mutex_destroy(&c_node->mem_lock); + mutex_destroy(&c_node->event_lock); + + /* free command node */ + kfree(c_node->start_work); + kfree(c_node->stop_work); + kfree(c_node->event_work); + kfree(c_node); +} + +static bool ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node) +{ + switch (c_node->property.cmd) { + case IPP_CMD_WB: + return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_DST]); + case IPP_CMD_OUTPUT: + return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_SRC]); + case IPP_CMD_M2M: + default: + return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_SRC]) && + !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_DST]); + } +} + +static struct drm_exynos_ipp_mem_node + *ipp_find_mem_node(struct drm_exynos_ipp_cmd_node *c_node, + struct drm_exynos_ipp_queue_buf *qbuf) +{ + struct drm_exynos_ipp_mem_node *m_node; + struct list_head *head; + int count = 0; + + DRM_DEBUG_KMS("buf_id[%d]\n", qbuf->buf_id); + + /* source/destination memory list */ + head = &c_node->mem_list[qbuf->ops_id]; + + /* find memory node from memory list */ + list_for_each_entry(m_node, head, list) { + DRM_DEBUG_KMS("count[%d]m_node[0x%x]\n", count++, (int)m_node); + + /* compare buffer id */ + if (m_node->buf_id == qbuf->buf_id) + return m_node; + } + + return NULL; +} + +static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv, + struct drm_exynos_ipp_cmd_node *c_node, + struct drm_exynos_ipp_mem_node *m_node) +{ + struct exynos_drm_ipp_ops *ops = NULL; + int ret = 0; + + DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node); + + if (!m_node) { + DRM_ERROR("invalid queue node.\n"); + return -EFAULT; + } + + DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id); + + /* get operations callback */ + ops = ippdrv->ops[m_node->ops_id]; + if (!ops) { + DRM_ERROR("not support ops.\n"); + return -EFAULT; + } + + /* set address and enable irq */ + if (ops->set_addr) { + ret = ops->set_addr(ippdrv->dev, &m_node->buf_info, + m_node->buf_id, IPP_BUF_ENQUEUE); + if (ret) { + DRM_ERROR("failed to set addr.\n"); + return ret; + } + } + + return ret; +} + static void ipp_handle_cmd_work(struct device *dev, struct exynos_drm_ippdrv *ippdrv, struct drm_exynos_ipp_cmd_work *cmd_work, @@ -766,7 +766,7 @@ static void ipp_handle_cmd_work(struct device *dev, cmd_work->ippdrv = ippdrv; cmd_work->c_node = c_node; - queue_work(ctx->cmd_workq, (struct work_struct *)cmd_work); + queue_work(ctx->cmd_workq, &cmd_work->work); } static int ipp_queue_buf_with_run(struct device *dev, @@ -872,7 +872,7 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data, /* find command node */ c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock, qbuf->prop_id); - if (!c_node) { + if (!c_node || c_node->filp != file) { DRM_ERROR("failed to get command node.\n"); return -ENODEV; } @@ -881,7 +881,7 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data, switch (qbuf->buf_type) { case IPP_BUF_ENQUEUE: /* get memory node */ - m_node = ipp_get_mem_node(drm_dev, file, c_node, qbuf); + m_node = ipp_get_mem_node(drm_dev, c_node, qbuf); if (IS_ERR(m_node)) { DRM_ERROR("failed to get m_node.\n"); return PTR_ERR(m_node); @@ -894,7 +894,7 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data, */ if (qbuf->ops_id == EXYNOS_DRM_OPS_DST) { /* get event for destination buffer */ - ret = ipp_get_event(drm_dev, file, c_node, qbuf); + ret = ipp_get_event(drm_dev, c_node, qbuf); if (ret) { DRM_ERROR("failed to get event.\n"); goto err_clean_node; @@ -1007,7 +1007,7 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data, c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock, cmd_ctrl->prop_id); - if (!c_node) { + if (!c_node || c_node->filp != file) { DRM_ERROR("invalid command node list.\n"); return -ENODEV; } @@ -1257,80 +1257,39 @@ static int ipp_stop_property(struct drm_device *drm_dev, struct exynos_drm_ippdrv *ippdrv, struct drm_exynos_ipp_cmd_node *c_node) { - struct drm_exynos_ipp_mem_node *m_node, *tm_node; struct drm_exynos_ipp_property *property = &c_node->property; - struct list_head *head; - int ret = 0, i; + int i; DRM_DEBUG_KMS("prop_id[%d]\n", property->prop_id); - /* put event */ - ipp_put_event(c_node, NULL); - - mutex_lock(&c_node->mem_lock); + /* stop operations */ + if (ippdrv->stop) + ippdrv->stop(ippdrv->dev, property->cmd); /* check command */ switch (property->cmd) { case IPP_CMD_M2M: - for_each_ipp_ops(i) { - /* source/destination memory list */ - head = &c_node->mem_list[i]; - - list_for_each_entry_safe(m_node, tm_node, - head, list) { - ret = ipp_put_mem_node(drm_dev, c_node, - m_node); - if (ret) { - DRM_ERROR("failed to put m_node.\n"); - goto err_clear; - } - } - } + for_each_ipp_ops(i) + ipp_clean_mem_nodes(drm_dev, c_node, i); break; case IPP_CMD_WB: - /* destination memory list */ - head = &c_node->mem_list[EXYNOS_DRM_OPS_DST]; - - list_for_each_entry_safe(m_node, tm_node, head, list) { - ret = ipp_put_mem_node(drm_dev, c_node, m_node); - if (ret) { - DRM_ERROR("failed to put m_node.\n"); - goto err_clear; - } - } + ipp_clean_mem_nodes(drm_dev, c_node, EXYNOS_DRM_OPS_DST); break; case IPP_CMD_OUTPUT: - /* source memory list */ - head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC]; - - list_for_each_entry_safe(m_node, tm_node, head, list) { - ret = ipp_put_mem_node(drm_dev, c_node, m_node); - if (ret) { - DRM_ERROR("failed to put m_node.\n"); - goto err_clear; - } - } + ipp_clean_mem_nodes(drm_dev, c_node, EXYNOS_DRM_OPS_SRC); break; default: DRM_ERROR("invalid operations.\n"); - ret = -EINVAL; - goto err_clear; + return -EINVAL; } -err_clear: - mutex_unlock(&c_node->mem_lock); - - /* stop operations */ - if (ippdrv->stop) - ippdrv->stop(ippdrv->dev, property->cmd); - - return ret; + return 0; } void ipp_sched_cmd(struct work_struct *work) { struct drm_exynos_ipp_cmd_work *cmd_work = - (struct drm_exynos_ipp_cmd_work *)work; + container_of(work, struct drm_exynos_ipp_cmd_work, work); struct exynos_drm_ippdrv *ippdrv; struct drm_exynos_ipp_cmd_node *c_node; struct drm_exynos_ipp_property *property; @@ -1543,7 +1502,7 @@ err_event_unlock: void ipp_sched_event(struct work_struct *work) { struct drm_exynos_ipp_event_work *event_work = - (struct drm_exynos_ipp_event_work *)work; + container_of(work, struct drm_exynos_ipp_event_work, work); struct exynos_drm_ippdrv *ippdrv; struct drm_exynos_ipp_cmd_node *c_node; int ret; @@ -1646,11 +1605,11 @@ err: static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev) { - struct exynos_drm_ippdrv *ippdrv; + struct exynos_drm_ippdrv *ippdrv, *t; struct ipp_context *ctx = get_ipp_context(dev); /* get ipp driver entry */ - list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { + list_for_each_entry_safe(ippdrv, t, &exynos_drm_ippdrv_list, drv_list) { if (is_drm_iommu_supported(drm_dev)) drm_iommu_detach_device(drm_dev, ippdrv->dev); @@ -1677,14 +1636,11 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev, static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev, struct drm_file *file) { - struct drm_exynos_file_private *file_priv = file->driver_priv; struct exynos_drm_ippdrv *ippdrv = NULL; struct ipp_context *ctx = get_ipp_context(dev); struct drm_exynos_ipp_cmd_node *c_node, *tc_node; int count = 0; - DRM_DEBUG_KMS("for priv[0x%x]\n", (int)file_priv->ipp_dev); - list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { mutex_lock(&ippdrv->cmd_lock); list_for_each_entry_safe(c_node, tc_node, @@ -1692,7 +1648,7 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev, DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n", count++, (int)ippdrv); - if (c_node->dev == file_priv->ipp_dev) { + if (c_node->filp == file) { /* * userland goto unnormal state. process killed. * and close the file. @@ -1808,63 +1764,12 @@ static int ipp_remove(struct platform_device *pdev) return 0; } -static int ipp_power_ctrl(struct ipp_context *ctx, bool enable) -{ - DRM_DEBUG_KMS("enable[%d]\n", enable); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int ipp_suspend(struct device *dev) -{ - struct ipp_context *ctx = get_ipp_context(dev); - - if (pm_runtime_suspended(dev)) - return 0; - - return ipp_power_ctrl(ctx, false); -} - -static int ipp_resume(struct device *dev) -{ - struct ipp_context *ctx = get_ipp_context(dev); - - if (!pm_runtime_suspended(dev)) - return ipp_power_ctrl(ctx, true); - - return 0; -} -#endif - -#ifdef CONFIG_PM_RUNTIME -static int ipp_runtime_suspend(struct device *dev) -{ - struct ipp_context *ctx = get_ipp_context(dev); - - return ipp_power_ctrl(ctx, false); -} - -static int ipp_runtime_resume(struct device *dev) -{ - struct ipp_context *ctx = get_ipp_context(dev); - - return ipp_power_ctrl(ctx, true); -} -#endif - -static const struct dev_pm_ops ipp_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(ipp_suspend, ipp_resume) - SET_RUNTIME_PM_OPS(ipp_runtime_suspend, ipp_runtime_resume, NULL) -}; - struct platform_driver ipp_driver = { .probe = ipp_probe, .remove = ipp_remove, .driver = { .name = "exynos-drm-ipp", .owner = THIS_MODULE, - .pm = &ipp_pm_ops, }, }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h index 6f48d62aeb30..2a61547a39d0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.h +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.h @@ -48,7 +48,6 @@ struct drm_exynos_ipp_cmd_work { /* * A structure of command node. * - * @dev: IPP device. * @list: list head to command queue information. * @event_list: list head of event. * @mem_list: list head to source,destination memory queue information. @@ -62,9 +61,9 @@ struct drm_exynos_ipp_cmd_work { * @stop_work: stop command work structure. * @event_work: event work structure. * @state: state of command node. + * @filp: associated file pointer. */ struct drm_exynos_ipp_cmd_node { - struct device *dev; struct list_head list; struct list_head event_list; struct list_head mem_list[EXYNOS_DRM_OPS_MAX]; @@ -78,6 +77,7 @@ struct drm_exynos_ipp_cmd_node { struct drm_exynos_ipp_cmd_work *stop_work; struct drm_exynos_ipp_event_work *event_work; enum drm_exynos_ipp_state state; + struct drm_file *filp; }; /* diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 8371cbd7631d..c7045a663763 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -139,6 +139,8 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, overlay->crtc_x, overlay->crtc_y, overlay->crtc_width, overlay->crtc_height); + plane->crtc = crtc; + exynos_drm_crtc_plane_mode_set(crtc, overlay); return 0; @@ -187,8 +189,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (ret < 0) return ret; - plane->crtc = crtc; - exynos_plane_commit(plane); exynos_plane_dpms(plane, DRM_MODE_DPMS_ON); @@ -254,25 +254,26 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane) } struct drm_plane *exynos_plane_init(struct drm_device *dev, - unsigned long possible_crtcs, bool priv) + unsigned long possible_crtcs, + enum drm_plane_type type) { struct exynos_plane *exynos_plane; int err; exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); if (!exynos_plane) - return NULL; + return ERR_PTR(-ENOMEM); - err = drm_plane_init(dev, &exynos_plane->base, possible_crtcs, - &exynos_plane_funcs, formats, ARRAY_SIZE(formats), - priv); + err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs, + &exynos_plane_funcs, formats, + ARRAY_SIZE(formats), type); if (err) { DRM_ERROR("failed to initialize plane\n"); kfree(exynos_plane); - return NULL; + return ERR_PTR(err); } - if (priv) + if (type == DRM_PLANE_TYPE_PRIMARY) exynos_plane->overlay.zpos = DEFAULT_ZPOS; else exynos_plane_attach_zpos_property(&exynos_plane->base); diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h index 84d464c90d3d..0d1986b115f8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h @@ -17,4 +17,5 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, void exynos_plane_commit(struct drm_plane *plane); void exynos_plane_dpms(struct drm_plane *plane, int mode); struct drm_plane *exynos_plane_init(struct drm_device *dev, - unsigned long possible_crtcs, bool priv); + unsigned long possible_crtcs, + enum drm_plane_type type); diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index 55af6b41c1df..b6a37d4f5b13 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c @@ -156,8 +156,7 @@ static irqreturn_t rotator_irq_handler(int irq, void *arg) event_work->ippdrv = ippdrv; event_work->buf_id[EXYNOS_DRM_OPS_DST] = rot->cur_buf_id[EXYNOS_DRM_OPS_DST]; - queue_work(ippdrv->event_workq, - (struct work_struct *)event_work); + queue_work(ippdrv->event_workq, &event_work->work); } else { DRM_ERROR("the SFR is set illegally\n"); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 9528d81d8004..d565207040a2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -303,23 +303,6 @@ static int vidi_mgr_initialize(struct exynos_drm_manager *mgr, mgr->drm_dev = ctx->drm_dev = drm_dev; mgr->pipe = ctx->pipe = priv->pipe++; - /* - * enable drm irq mode. - * - with irq_enabled = 1, we can use the vblank feature. - * - * P.S. note that we wouldn't use drm irq handler but - * just specific driver own one instead because - * drm framework supports only one irq handler. - */ - drm_dev->irq_enabled = 1; - - /* - * with vblank_disable_allowed = 1, vblank interrupt will be disabled - * by drm timer once a current process gives up ownership of - * vblank event.(after drm_vblank_put function is called) - */ - drm_dev->vblank_disable_allowed = 1; - return 0; } @@ -648,7 +631,6 @@ static int vidi_remove(struct platform_device *pdev) struct exynos_drm_manager *mgr = platform_get_drvdata(pdev); struct vidi_context *ctx = mgr->ctx; struct drm_encoder *encoder = ctx->encoder; - struct drm_crtc *crtc = mgr->crtc; if (ctx->raw_edid != (struct edid *)fake_edid_info) { kfree(ctx->raw_edid); @@ -657,7 +639,6 @@ static int vidi_remove(struct platform_device *pdev) return -EINVAL; } - crtc->funcs->destroy(crtc); encoder->funcs->destroy(encoder); drm_connector_cleanup(&ctx->connector); diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 562966db2aa1..7910fb37d9bb 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1040,6 +1040,8 @@ static enum drm_connector_status hdmi_detect(struct drm_connector *connector, static void hdmi_connector_destroy(struct drm_connector *connector) { + drm_connector_unregister(connector); + drm_connector_cleanup(connector); } static struct drm_connector_funcs hdmi_connector_funcs = { @@ -2314,8 +2316,8 @@ static void hdmi_unbind(struct device *dev, struct device *master, void *data) struct drm_encoder *encoder = display->encoder; struct hdmi_context *hdata = display->ctx; + hdmi_connector_destroy(&hdata->connector); encoder->funcs->destroy(encoder); - drm_connector_cleanup(&hdata->connector); } static const struct component_ops hdmi_component_ops = { diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index e8b4ec84b312..a41c84ee3a2d 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1302,15 +1302,12 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) static void mixer_unbind(struct device *dev, struct device *master, void *data) { struct exynos_drm_manager *mgr = dev_get_drvdata(dev); - struct drm_crtc *crtc = mgr->crtc; dev_info(dev, "remove successful\n"); mixer_mgr_remove(mgr); pm_runtime_disable(dev); - - crtc->funcs->destroy(crtc); } static const struct component_ops mixer_component_ops = { diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index d0dd3bea8aa5..ddd90ddbc200 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -540,7 +540,8 @@ static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red, static int psbfb_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { - struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper; + struct psb_fbdev *psb_fbdev = + container_of(helper, struct psb_fbdev, psb_fb_helper); struct drm_device *dev = psb_fbdev->psb_fb_helper.dev; struct drm_psb_private *dev_priv = dev->dev_private; int bytespp; diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h index f5860a739bd8..cdbb350c9d5d 100644 --- a/drivers/gpu/drm/gma500/gtt.h +++ b/drivers/gpu/drm/gma500/gtt.h @@ -21,6 +21,7 @@ #define _PSB_GTT_H_ #include <drm/drmP.h> +#include <drm/drm_gem.h> /* This wants cleaning up with respect to the psb_dev and un-needed stuff */ struct psb_gtt { diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index 6cb08a1c6b62..44f4a131c8dd 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -47,7 +47,7 @@ static const struct file_operations i810_driver_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, - .mmap = drm_mmap, + .mmap = drm_legacy_mmap, .poll = drm_poll, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 32180ac92770..16a6f6d187a1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -43,6 +43,7 @@ #include <linux/i2c-algo-bit.h> #include <drm/intel-gtt.h> #include <drm/drm_legacy.h> /* for struct drm_dma_handle */ +#include <drm/drm_gem.h> #include <linux/backlight.h> #include <linux/hashtable.h> #include <linux/intel-iommu.h> diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index cb5c71f4b28e..5e2f131a6a72 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c @@ -48,7 +48,7 @@ static const struct file_operations mga_driver_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, - .mmap = drm_mmap, + .mmap = drm_legacy_mmap, .poll = drm_poll, #ifdef CONFIG_COMPAT .compat_ioctl = mga_compat_ioctl, diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index c03e347f3ffd..e9eea1d4e7c3 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -22,6 +22,8 @@ #include <drm/ttm/ttm_memory.h> #include <drm/ttm/ttm_module.h> +#include <drm/drm_gem.h> + #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index 5451dc58eff1..4415af3666ab 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -158,7 +158,8 @@ static int mgag200fb_create_object(struct mga_fbdev *afbdev, static int mgag200fb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { - struct mga_fbdev *mfbdev = (struct mga_fbdev *)helper; + struct mga_fbdev *mfbdev = + container_of(helper, struct mga_fbdev, helper); struct drm_device *dev = mfbdev->helper.dev; struct drm_mode_fb_cmd2 mode_cmd; struct mga_device *mdev = dev->dev_private; diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c index be883ef5a1d3..d16964ea0ed4 100644 --- a/drivers/gpu/drm/mgag200/mgag200_ttm.c +++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c @@ -339,7 +339,7 @@ int mgag200_bo_create(struct drm_device *dev, int size, int align, ret = ttm_bo_init(&mdev->ttm.bdev, &mgabo->bo, size, ttm_bo_type_device, &mgabo->placement, align >> PAGE_SHIFT, false, NULL, acc_size, - NULL, mgag200_bo_ttm_destroy); + NULL, NULL, mgag200_bo_ttm_destroy); if (ret) return ret; @@ -428,7 +428,7 @@ int mgag200_mmap(struct file *filp, struct vm_area_struct *vma) struct mga_device *mdev; if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) - return drm_mmap(filp, vma); + return -EINVAL; file_priv = filp->private_data; mdev = file_priv->minor->dev->dev_private; diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 8a2c5fd0893e..67f9d0a2332c 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -51,6 +51,7 @@ static inline struct device *msm_iommu_get_ctx(const char *ctx_name) #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> #include <drm/msm_drm.h> +#include <drm/drm_gem.h> struct msm_kms; struct msm_gpu; @@ -170,7 +171,7 @@ struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj); void *msm_gem_prime_vmap(struct drm_gem_object *obj); void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, - size_t size, struct sg_table *sg); + struct dma_buf_attachment *attach, struct sg_table *sg); int msm_gem_prime_pin(struct drm_gem_object *obj); void msm_gem_prime_unpin(struct drm_gem_object *obj); void *msm_gem_vaddr_locked(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c index d48f9fc5129b..ad772fe36115 100644 --- a/drivers/gpu/drm/msm/msm_gem_prime.c +++ b/drivers/gpu/drm/msm/msm_gem_prime.c @@ -18,6 +18,7 @@ #include "msm_drv.h" #include "msm_gem.h" +#include <linux/dma-buf.h> struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj) { @@ -37,9 +38,9 @@ void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) } struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, - size_t size, struct sg_table *sg) + struct dma_buf_attachment *attach, struct sg_table *sg) { - return msm_gem_import(dev, size, sg); + return msm_gem_import(dev, attach->dmabuf->size, sg); } int msm_gem_prime_pin(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index b90aa5c1f90a..fca6a1f9c20c 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1127,7 +1127,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, - 0, 0x0000, NULL, &nv_crtc->cursor.nvbo); + 0, 0x0000, NULL, NULL, &nv_crtc->cursor.nvbo); if (!ret) { ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); if (!ret) { diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c index b36afcbbc83f..1e9056a8df94 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c @@ -97,7 +97,8 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_w, uint32_t src_h) { struct nvif_device *dev = &nouveau_drm(plane->dev)->device; - struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; + struct nouveau_plane *nv_plane = + container_of(plane, struct nouveau_plane, base); struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_bo *cur = nv_plane->cur; @@ -173,7 +174,8 @@ static int nv10_disable_plane(struct drm_plane *plane) { struct nvif_device *dev = &nouveau_drm(plane->dev)->device; - struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; + struct nouveau_plane *nv_plane = + container_of(plane, struct nouveau_plane, base); nvif_wr32(dev, NV_PVIDEO_STOP, 1); if (nv_plane->cur) { @@ -224,7 +226,8 @@ nv_set_property(struct drm_plane *plane, struct drm_property *property, uint64_t value) { - struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; + struct nouveau_plane *nv_plane = + container_of(plane, struct nouveau_plane, base); if (property == nv_plane->props.colorkey) nv_plane->colorkey = value; @@ -344,7 +347,8 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_w, uint32_t src_h) { struct nvif_device *dev = &nouveau_drm(plane->dev)->device; - struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; + struct nouveau_plane *nv_plane = + container_of(plane, struct nouveau_plane, base); struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); struct nouveau_bo *cur = nv_plane->cur; uint32_t overlay = 1; @@ -423,7 +427,8 @@ static int nv04_disable_plane(struct drm_plane *plane) { struct nvif_device *dev = &nouveau_drm(plane->dev)->device; - struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; + struct nouveau_plane *nv_plane = + container_of(plane, struct nouveau_plane, base); nvif_mask(dev, NV_PVIDEO_OVERLAY, 1, 0); nvif_wr32(dev, NV_PVIDEO_OE_STATE, 0); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index eea74b127b03..3d474ac03f88 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -181,7 +181,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, int nouveau_bo_new(struct drm_device *dev, int size, int align, uint32_t flags, uint32_t tile_mode, uint32_t tile_flags, - struct sg_table *sg, + struct sg_table *sg, struct reservation_object *robj, struct nouveau_bo **pnvbo) { struct nouveau_drm *drm = nouveau_drm(dev); @@ -230,7 +230,7 @@ nouveau_bo_new(struct drm_device *dev, int size, int align, ret = ttm_bo_init(&drm->ttm.bdev, &nvbo->bo, size, type, &nvbo->placement, align >> PAGE_SHIFT, false, NULL, acc_size, sg, - nouveau_bo_del_ttm); + robj, nouveau_bo_del_ttm); if (ret) { /* ttm will call nouveau_bo_del_ttm if it fails.. */ return ret; @@ -970,7 +970,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, } mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING); - ret = nouveau_fence_sync(nouveau_bo(bo), chan, true); + ret = nouveau_fence_sync(nouveau_bo(bo), chan, true, intr); if (ret == 0) { ret = drm->ttm.move(chan, bo, &bo->mem, new_mem); if (ret == 0) { diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index ae95b2d43b36..22d2c764d80b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -1,6 +1,8 @@ #ifndef __NOUVEAU_BO_H__ #define __NOUVEAU_BO_H__ +#include <drm/drm_gem.h> + struct nouveau_channel; struct nouveau_fence; struct nouveau_vma; @@ -68,6 +70,7 @@ extern struct ttm_bo_driver nouveau_bo_driver; void nouveau_bo_move_init(struct nouveau_drm *); int nouveau_bo_new(struct drm_device *, int size, int align, u32 flags, u32 tile_mode, u32 tile_flags, struct sg_table *sg, + struct reservation_object *robj, struct nouveau_bo **); int nouveau_bo_pin(struct nouveau_bo *, u32 flags); int nouveau_bo_unpin(struct nouveau_bo *); diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 9a362ddd8225..977fb8f15d97 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -106,7 +106,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, if (nouveau_vram_pushbuf) target = TTM_PL_FLAG_VRAM; - ret = nouveau_bo_new(drm->dev, size, 0, target, 0, 0, NULL, + ret = nouveau_bo_new(drm->dev, size, 0, target, 0, 0, NULL, NULL, &chan->push.buffer); if (ret == 0) { ret = nouveau_bo_pin(chan->push.buffer, target); diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 6d0a3cdc752b..334db3c6e40c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -658,7 +658,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, spin_unlock_irqrestore(&dev->event_lock, flags); /* Synchronize with the old framebuffer */ - ret = nouveau_fence_sync(old_bo, chan, false); + ret = nouveau_fence_sync(old_bo, chan, false, false); if (ret) goto fail; @@ -722,7 +722,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, goto fail_unpin; /* synchronise rendering channel with the kernel's channel */ - ret = nouveau_fence_sync(new_bo, chan, false); + ret = nouveau_fence_sync(new_bo, chan, false, true); if (ret) { ttm_bo_unreserve(&new_bo->bo); goto fail_unpin; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index b02b02452c85..8ae36f265fb8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -10,7 +10,7 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 2 -#define DRIVER_PATCHLEVEL 0 +#define DRIVER_PATCHLEVEL 1 /* * 1.1.1: @@ -26,6 +26,8 @@ * 1.2.0: * - object api exposed to userspace * - fermi,kepler,maxwell zbc + * 1.2.1: + * - allow concurrent access to bo's mapped read/write. */ #include <nvif/client.h> diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index f0ae10ca3ba9..dc1753c368e3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -308,7 +308,8 @@ static int nouveau_fbcon_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { - struct nouveau_fbdev *fbcon = (struct nouveau_fbdev *)helper; + struct nouveau_fbdev *fbcon = + container_of(helper, struct nouveau_fbdev, helper); struct drm_device *dev = fbcon->dev; struct nouveau_drm *drm = nouveau_drm(dev); struct nvif_device *device = &drm->device; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index decfe6c4ac07..515cd9aebb99 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -101,6 +101,18 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx) } static void +nouveau_fence_context_put(struct kref *fence_ref) +{ + kfree(container_of(fence_ref, struct nouveau_fence_chan, fence_ref)); +} + +void +nouveau_fence_context_free(struct nouveau_fence_chan *fctx) +{ + kref_put(&fctx->fence_ref, nouveau_fence_context_put); +} + +static void nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx) { struct nouveau_fence *fence; @@ -141,6 +153,7 @@ void nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx) { struct nouveau_fence_priv *priv = (void*)chan->drm->fence; + struct nouveau_cli *cli = (void *)nvif_client(chan->object); int ret; INIT_LIST_HEAD(&fctx->flip); @@ -148,6 +161,14 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha spin_lock_init(&fctx->lock); fctx->context = priv->context_base + chan->chid; + if (chan == chan->drm->cechan) + strcpy(fctx->name, "copy engine channel"); + else if (chan == chan->drm->channel) + strcpy(fctx->name, "generic kernel channel"); + else + strcpy(fctx->name, nvkm_client(&cli->base)->name); + + kref_init(&fctx->fence_ref); if (!priv->uevent) return; @@ -195,8 +216,12 @@ nouveau_fence_work(struct fence *fence, work = kmalloc(sizeof(*work), GFP_KERNEL); if (!work) { + /* + * this might not be a nouveau fence any more, + * so force a lazy wait here + */ WARN_ON(nouveau_fence_wait((struct nouveau_fence *)fence, - false, false)); + true, false)); goto err; } @@ -226,12 +251,11 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) if (priv->uevent) fence_init(&fence->base, &nouveau_fence_ops_uevent, - &fctx->lock, - priv->context_base + chan->chid, ++fctx->sequence); + &fctx->lock, fctx->context, ++fctx->sequence); else fence_init(&fence->base, &nouveau_fence_ops_legacy, - &fctx->lock, - priv->context_base + chan->chid, ++fctx->sequence); + &fctx->lock, fctx->context, ++fctx->sequence); + kref_get(&fctx->fence_ref); trace_fence_emit(&fence->base); ret = fctx->emit(fence); @@ -342,7 +366,7 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) } int -nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool exclusive) +nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool exclusive, bool intr) { struct nouveau_fence_chan *fctx = chan->fence; struct fence *fence; @@ -369,7 +393,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e prev = f->channel; if (!prev || (prev != chan && (ret = fctx->sync(f, prev, chan)))) - ret = fence_wait(fence, true); + ret = fence_wait(fence, intr); return ret; } @@ -387,8 +411,8 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e if (f) prev = f->channel; - if (!prev || (ret = fctx->sync(f, prev, chan))) - ret = fence_wait(fence, true); + if (!prev || (prev != chan && (ret = fctx->sync(f, prev, chan)))) + ret = fence_wait(fence, intr); if (ret) break; @@ -482,13 +506,22 @@ static bool nouveau_fence_no_signaling(struct fence *f) return true; } +static void nouveau_fence_release(struct fence *f) +{ + struct nouveau_fence *fence = from_fence(f); + struct nouveau_fence_chan *fctx = nouveau_fctx(fence); + + kref_put(&fctx->fence_ref, nouveau_fence_context_put); + fence_free(&fence->base); +} + static const struct fence_ops nouveau_fence_ops_legacy = { .get_driver_name = nouveau_fence_get_get_driver_name, .get_timeline_name = nouveau_fence_get_timeline_name, .enable_signaling = nouveau_fence_no_signaling, .signaled = nouveau_fence_is_signaled, .wait = nouveau_fence_wait_legacy, - .release = NULL + .release = nouveau_fence_release }; static bool nouveau_fence_enable_signaling(struct fence *f) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 986c8135e564..943b0b17b1fc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -26,10 +26,12 @@ int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); bool nouveau_fence_done(struct nouveau_fence *); void nouveau_fence_work(struct fence *, void (*)(void *), void *); int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); -int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive); +int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr); struct nouveau_fence_chan { spinlock_t lock; + struct kref fence_ref; + struct list_head pending; struct list_head flip; @@ -42,7 +44,7 @@ struct nouveau_fence_chan { u32 sequence; u32 context; - char name[24]; + char name[32]; struct nvif_notify notify; int notify_ref; @@ -63,6 +65,7 @@ struct nouveau_fence_priv { void nouveau_fence_context_new(struct nouveau_channel *, struct nouveau_fence_chan *); void nouveau_fence_context_del(struct nouveau_fence_chan *); +void nouveau_fence_context_free(struct nouveau_fence_chan *); int nv04_fence_create(struct nouveau_drm *); int nv04_fence_mthd(struct nouveau_channel *, u32, u32, u32); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index b7dbd16904e0..36951ee4b157 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -165,7 +165,7 @@ nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain, flags |= TTM_PL_FLAG_SYSTEM; ret = nouveau_bo_new(dev, size, align, flags, tile_mode, - tile_flags, NULL, pnvbo); + tile_flags, NULL, NULL, pnvbo); if (ret) return ret; nvbo = *pnvbo; @@ -459,7 +459,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, return ret; } - ret = nouveau_fence_sync(nvbo, chan, !!b->write_domains); + ret = nouveau_fence_sync(nvbo, chan, !!b->write_domains, true); if (unlikely(ret)) { if (ret != -ERESTARTSYS) NV_PRINTK(error, cli, "fail post-validate sync\n"); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.h b/drivers/gpu/drm/nouveau/nouveau_gem.h index ddab762d81fe..e4049faca780 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.h +++ b/drivers/gpu/drm/nouveau/nouveau_gem.h @@ -39,7 +39,7 @@ struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *); extern void nouveau_gem_prime_unpin(struct drm_gem_object *); extern struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *); extern struct drm_gem_object *nouveau_gem_prime_import_sg_table( - struct drm_device *, size_t size, struct sg_table *); + struct drm_device *, struct dma_buf_attachment *, struct sg_table *); extern void *nouveau_gem_prime_vmap(struct drm_gem_object *); extern void nouveau_gem_prime_vunmap(struct drm_gem_object *, void *); diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index 1f51008e4d26..228226ab27fc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -23,6 +23,7 @@ */ #include <drm/drmP.h> +#include <linux/dma-buf.h> #include "nouveau_drm.h" #include "nouveau_gem.h" @@ -56,17 +57,20 @@ void nouveau_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) } struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, - size_t size, + struct dma_buf_attachment *attach, struct sg_table *sg) { struct nouveau_bo *nvbo; + struct reservation_object *robj = attach->dmabuf->resv; u32 flags = 0; int ret; flags = TTM_PL_FLAG_TT; - ret = nouveau_bo_new(dev, size, 0, flags, 0, 0, - sg, &nvbo); + ww_mutex_lock(&robj->lock, NULL); + ret = nouveau_bo_new(dev, attach->dmabuf->size, 0, flags, 0, 0, + sg, robj, &nvbo); + ww_mutex_unlock(&robj->lock); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index e81d086577ce..753a6def61e7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -281,7 +281,7 @@ nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) struct nouveau_drm *drm = nouveau_drm(file_priv->minor->dev); if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) - return drm_mmap(filp, vma); + return -EINVAL; return ttm_bo_mmap(filp, vma, &drm->ttm.bdev); } diff --git a/drivers/gpu/drm/nouveau/nv04_fence.c b/drivers/gpu/drm/nouveau/nv04_fence.c index 4484131d826a..f9859deb108a 100644 --- a/drivers/gpu/drm/nouveau/nv04_fence.c +++ b/drivers/gpu/drm/nouveau/nv04_fence.c @@ -67,7 +67,7 @@ nv04_fence_context_del(struct nouveau_channel *chan) struct nv04_fence_chan *fctx = chan->fence; nouveau_fence_context_del(&fctx->base); chan->fence = NULL; - kfree(fctx); + nouveau_fence_context_free(&fctx->base); } static int diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c index 737d066ffc60..5e1ea1cdce75 100644 --- a/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/drivers/gpu/drm/nouveau/nv10_fence.c @@ -63,7 +63,7 @@ nv10_fence_context_del(struct nouveau_channel *chan) nvif_object_fini(&fctx->head[i]); nvif_object_fini(&fctx->sema); chan->fence = NULL; - kfree(fctx); + nouveau_fence_context_free(&fctx->base); } int diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c index 6f9a1f8e2d0f..40b461c7d5c5 100644 --- a/drivers/gpu/drm/nouveau/nv17_fence.c +++ b/drivers/gpu/drm/nouveau/nv17_fence.c @@ -129,7 +129,7 @@ nv17_fence_create(struct nouveau_drm *drm) spin_lock_init(&priv->lock); ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, - 0, 0x0000, NULL, &priv->bo); + 0, 0x0000, NULL, NULL, &priv->bo); if (!ret) { ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); if (!ret) { diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index fdb3e1adea1e..ae873d1a8d46 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1383,7 +1383,7 @@ nv50_crtc_create(struct drm_device *dev, int index) drm_mode_crtc_set_gamma_size(crtc, 256); ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM, - 0, 0x0000, NULL, &head->base.lut.nvbo); + 0, 0x0000, NULL, NULL, &head->base.lut.nvbo); if (!ret) { ret = nouveau_bo_pin(head->base.lut.nvbo, TTM_PL_FLAG_VRAM); if (!ret) { @@ -1406,7 +1406,7 @@ nv50_crtc_create(struct drm_device *dev, int index) goto out; ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM, - 0, 0x0000, NULL, &head->base.cursor.nvbo); + 0, 0x0000, NULL, NULL, &head->base.cursor.nvbo); if (!ret) { ret = nouveau_bo_pin(head->base.cursor.nvbo, TTM_PL_FLAG_VRAM); if (!ret) { @@ -2468,7 +2468,7 @@ nv50_display_create(struct drm_device *dev) /* small shared memory area we use for notifiers and semaphores */ ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, - 0, 0x0000, NULL, &disp->sync); + 0, 0x0000, NULL, NULL, &disp->sync); if (!ret) { ret = nouveau_bo_pin(disp->sync, TTM_PL_FLAG_VRAM); if (!ret) { diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index 08fad3668a1c..22d242b37962 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c @@ -100,7 +100,7 @@ nv50_fence_create(struct nouveau_drm *drm) spin_lock_init(&priv->lock); ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, - 0, 0x0000, NULL, &priv->bo); + 0, 0x0000, NULL, NULL, &priv->bo); if (!ret) { ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); if (!ret) { diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index a2f28082c272..d6c6c87c3f07 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -120,11 +120,12 @@ nv84_fence_context_del(struct nouveau_channel *chan) nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); } + nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence); nouveau_bo_vma_del(priv->bo, &fctx->vma_gart); nouveau_bo_vma_del(priv->bo, &fctx->vma); nouveau_fence_context_del(&fctx->base); chan->fence = NULL; - kfree(fctx); + nouveau_fence_context_free(&fctx->base); } int @@ -159,8 +160,6 @@ nv84_fence_context_new(struct nouveau_channel *chan) ret = nouveau_bo_vma_add(bo, cli->vm, &fctx->dispc_vma[i]); } - nouveau_bo_wr32(priv->bo, chan->chid * 16/4, 0x00000000); - if (ret) nv84_fence_context_del(chan); return ret; @@ -233,7 +232,7 @@ nv84_fence_create(struct nouveau_drm *drm) priv->base.uevent = true; ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0, - TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo); + TTM_PL_FLAG_VRAM, 0, 0, NULL, NULL, &priv->bo); if (ret == 0) { ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); if (ret == 0) { @@ -247,7 +246,7 @@ nv84_fence_create(struct nouveau_drm *drm) if (ret == 0) ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0, - TTM_PL_FLAG_TT, 0, 0, NULL, + TTM_PL_FLAG_TT, 0, 0, NULL, NULL, &priv->bo_gart); if (ret == 0) { ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 84d73a61b34b..60e47b33c801 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -26,6 +26,7 @@ #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> #include <drm/omap_drm.h> +#include <drm/drm_gem.h> #include <linux/platform_data/omap_drm.h> diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index d75c0a9f674f..7c6cafe21f5f 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -43,6 +43,8 @@ #include <ttm/ttm_placement.h> #include <ttm/ttm_module.h> +#include <drm/drm_gem.h> + /* just for ttm_validate_buffer */ #include <ttm/ttm_execbuf_util.h> @@ -535,7 +537,7 @@ int qxl_gem_prime_pin(struct drm_gem_object *obj); void qxl_gem_prime_unpin(struct drm_gem_object *obj); struct sg_table *qxl_gem_prime_get_sg_table(struct drm_gem_object *obj); struct drm_gem_object *qxl_gem_prime_import_sg_table( - struct drm_device *dev, size_t size, + struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt); void *qxl_gem_prime_vmap(struct drm_gem_object *obj); void qxl_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c index df567888bb1e..3d7c1d00a424 100644 --- a/drivers/gpu/drm/qxl/qxl_fb.c +++ b/drivers/gpu/drm/qxl/qxl_fb.c @@ -625,7 +625,8 @@ static int qxl_fb_find_or_create_single( struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { - struct qxl_fbdev *qfbdev = (struct qxl_fbdev *)helper; + struct qxl_fbdev *qfbdev = + container_of(helper, struct qxl_fbdev, helper); int new_fb = 0; int ret; diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index 69c104c3240f..cdeaf08fdc74 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -110,7 +110,7 @@ int qxl_bo_create(struct qxl_device *qdev, r = ttm_bo_init(&qdev->mman.bdev, &bo->tbo, size, type, &bo->placement, 0, !kernel, NULL, size, - NULL, &qxl_ttm_bo_destroy); + NULL, NULL, &qxl_ttm_bo_destroy); if (unlikely(r != 0)) { if (r != -ERESTARTSYS) dev_err(qdev->dev, diff --git a/drivers/gpu/drm/qxl/qxl_prime.c b/drivers/gpu/drm/qxl/qxl_prime.c index ba0689c728e8..3d031b50a8fd 100644 --- a/drivers/gpu/drm/qxl/qxl_prime.c +++ b/drivers/gpu/drm/qxl/qxl_prime.c @@ -46,7 +46,7 @@ struct sg_table *qxl_gem_prime_get_sg_table(struct drm_gem_object *obj) } struct drm_gem_object *qxl_gem_prime_import_sg_table( - struct drm_device *dev, size_t size, + struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *table) { WARN_ONCE(1, "not implemented"); diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index abe945a04fd4..0cbc4c987164 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -127,7 +127,7 @@ int qxl_mmap(struct file *filp, struct vm_area_struct *vma) if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) { pr_info("%s: vma->vm_pgoff (%ld) < DRM_FILE_PAGE_OFFSET\n", __func__, vma->vm_pgoff); - return drm_mmap(filp, vma); + return -EINVAL; } file_priv = filp->private_data; diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 4a59370eb580..c57b4de63caf 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -46,7 +46,7 @@ static const struct file_operations r128_driver_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, - .mmap = drm_mmap, + .mmap = drm_legacy_mmap, .poll = drm_poll, #ifdef CONFIG_COMPAT .compat_ioctl = r128_compat_ioctl, diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index 7d7aed5357f0..d01b87991422 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -72,7 +72,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ r200.o radeon_legacy_tv.o r600_cs.o r600_blit_shaders.o \ - radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o dce3_1_afmt.o \ + radeon_pm.o atombios_dp.o r600_hdmi.o dce3_1_afmt.o \ evergreen.o evergreen_cs.o evergreen_blit_shaders.o \ evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \ atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \ diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index a7f2ddf09a9d..b8cd7975f797 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -291,29 +291,6 @@ static void radeon_atom_backlight_exit(struct radeon_encoder *encoder) bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, struct drm_display_mode *mode); - -static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) -{ - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_LVDS: - case ENCODER_OBJECT_ID_INTERNAL_TMDS1: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: - case ENCODER_OBJECT_ID_INTERNAL_DVO1: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: - case ENCODER_OBJECT_ID_INTERNAL_DDI: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: - return true; - default: - return false; - } -} - static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c index f81d7ca134db..300d971187c4 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.c +++ b/drivers/gpu/drm/radeon/btc_dpm.c @@ -1170,23 +1170,6 @@ static const struct radeon_blacklist_clocks btc_blacklist_clocks[] = { 25000, 30000, RADEON_SCLK_UP } }; -void btc_get_max_clock_from_voltage_dependency_table(struct radeon_clock_voltage_dependency_table *table, - u32 *max_clock) -{ - u32 i, clock = 0; - - if ((table == NULL) || (table->count == 0)) { - *max_clock = clock; - return; - } - - for (i = 0; i < table->count; i++) { - if (clock < table->entries[i].clk) - clock = table->entries[i].clk; - } - *max_clock = clock; -} - void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table, u32 clock, u16 max_voltage, u16 *voltage) { @@ -2099,7 +2082,6 @@ static void btc_apply_state_adjust_rules(struct radeon_device *rdev, bool disable_mclk_switching; u32 mclk, sclk; u16 vddc, vddci; - u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; if ((rdev->pm.dpm.new_active_crtc_count > 1) || btc_dpm_vblank_too_short(rdev)) @@ -2141,39 +2123,6 @@ static void btc_apply_state_adjust_rules(struct radeon_device *rdev, ps->low.vddci = max_limits->vddci; } - /* limit clocks to max supported clocks based on voltage dependency tables */ - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk, - &max_sclk_vddc); - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk, - &max_mclk_vddci); - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk, - &max_mclk_vddc); - - if (max_sclk_vddc) { - if (ps->low.sclk > max_sclk_vddc) - ps->low.sclk = max_sclk_vddc; - if (ps->medium.sclk > max_sclk_vddc) - ps->medium.sclk = max_sclk_vddc; - if (ps->high.sclk > max_sclk_vddc) - ps->high.sclk = max_sclk_vddc; - } - if (max_mclk_vddci) { - if (ps->low.mclk > max_mclk_vddci) - ps->low.mclk = max_mclk_vddci; - if (ps->medium.mclk > max_mclk_vddci) - ps->medium.mclk = max_mclk_vddci; - if (ps->high.mclk > max_mclk_vddci) - ps->high.mclk = max_mclk_vddci; - } - if (max_mclk_vddc) { - if (ps->low.mclk > max_mclk_vddc) - ps->low.mclk = max_mclk_vddc; - if (ps->medium.mclk > max_mclk_vddc) - ps->medium.mclk = max_mclk_vddc; - if (ps->high.mclk > max_mclk_vddc) - ps->high.mclk = max_mclk_vddc; - } - /* XXX validate the min clocks required for display */ if (disable_mclk_switching) { diff --git a/drivers/gpu/drm/radeon/btc_dpm.h b/drivers/gpu/drm/radeon/btc_dpm.h index 3b6f12b7760b..1a15e0e41950 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.h +++ b/drivers/gpu/drm/radeon/btc_dpm.h @@ -46,8 +46,6 @@ void btc_adjust_clock_combinations(struct radeon_device *rdev, struct rv7xx_pl *pl); void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table, u32 clock, u16 max_voltage, u16 *voltage); -void btc_get_max_clock_from_voltage_dependency_table(struct radeon_clock_voltage_dependency_table *table, - u32 *max_clock); void btc_apply_voltage_delta_rules(struct radeon_device *rdev, u16 max_vddc, u16 max_vddci, u16 *vddc, u16 *vddci); diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index d416bb2ff48d..f5c8c0445a94 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -162,8 +162,6 @@ static const struct ci_pt_config_reg didt_config_ci[] = }; extern u8 rv770_get_memory_module_index(struct radeon_device *rdev); -extern void btc_get_max_clock_from_voltage_dependency_table(struct radeon_clock_voltage_dependency_table *table, - u32 *max_clock); extern int ni_copy_and_switch_arb_sets(struct radeon_device *rdev, u32 arb_freq_src, u32 arb_freq_dest); extern u8 si_get_ddr3_mclk_frequency_ratio(u32 memory_clock); @@ -748,7 +746,6 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev, struct radeon_clock_and_voltage_limits *max_limits; bool disable_mclk_switching; u32 sclk, mclk; - u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; int i; if (rps->vce_active) { @@ -784,29 +781,6 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev, } } - /* limit clocks to max supported clocks based on voltage dependency tables */ - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk, - &max_sclk_vddc); - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk, - &max_mclk_vddci); - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk, - &max_mclk_vddc); - - for (i = 0; i < ps->performance_level_count; i++) { - if (max_sclk_vddc) { - if (ps->performance_levels[i].sclk > max_sclk_vddc) - ps->performance_levels[i].sclk = max_sclk_vddc; - } - if (max_mclk_vddci) { - if (ps->performance_levels[i].mclk > max_mclk_vddci) - ps->performance_levels[i].mclk = max_mclk_vddci; - } - if (max_mclk_vddc) { - if (ps->performance_levels[i].mclk > max_mclk_vddc) - ps->performance_levels[i].mclk = max_mclk_vddc; - } - } - /* XXX validate the min clocks required for display */ if (disable_mclk_switching) { @@ -5293,9 +5267,13 @@ int ci_dpm_init(struct radeon_device *rdev) void ci_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, struct seq_file *m) { + struct ci_power_info *pi = ci_get_pi(rdev); + struct radeon_ps *rps = &pi->current_rps; u32 sclk = ci_get_average_sclk_freq(rdev); u32 mclk = ci_get_average_mclk_freq(rdev); + seq_printf(m, "uvd %sabled\n", pi->uvd_enabled ? "en" : "dis"); + seq_printf(m, "vce %sabled\n", rps->vce_active ? "en" : "dis"); seq_printf(m, "power level avg sclk: %u mclk: %u\n", sclk, mclk); } diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 0d761f73a7fa..d48a539b038a 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -3993,7 +3993,7 @@ struct radeon_fence *cik_copy_cpdma(struct radeon_device *rdev, return ERR_PTR(r); } - radeon_semaphore_sync_resv(sem, resv, false); + radeon_semaphore_sync_resv(rdev, sem, resv, false); radeon_semaphore_sync_rings(rdev, sem, ring->idx); for (i = 0; i < num_loops; i++) { @@ -4235,7 +4235,7 @@ static int cik_cp_gfx_load_microcode(struct radeon_device *rdev) WREG32(CP_PFP_UCODE_ADDR, 0); for (i = 0; i < fw_size; i++) WREG32(CP_PFP_UCODE_DATA, le32_to_cpup(fw_data++)); - WREG32(CP_PFP_UCODE_ADDR, 0); + WREG32(CP_PFP_UCODE_ADDR, le32_to_cpu(pfp_hdr->header.ucode_version)); /* CE */ fw_data = (const __le32 *) @@ -4244,7 +4244,7 @@ static int cik_cp_gfx_load_microcode(struct radeon_device *rdev) WREG32(CP_CE_UCODE_ADDR, 0); for (i = 0; i < fw_size; i++) WREG32(CP_CE_UCODE_DATA, le32_to_cpup(fw_data++)); - WREG32(CP_CE_UCODE_ADDR, 0); + WREG32(CP_CE_UCODE_ADDR, le32_to_cpu(ce_hdr->header.ucode_version)); /* ME */ fw_data = (const __be32 *) @@ -4253,7 +4253,8 @@ static int cik_cp_gfx_load_microcode(struct radeon_device *rdev) WREG32(CP_ME_RAM_WADDR, 0); for (i = 0; i < fw_size; i++) WREG32(CP_ME_RAM_DATA, le32_to_cpup(fw_data++)); - WREG32(CP_ME_RAM_WADDR, 0); + WREG32(CP_ME_RAM_WADDR, le32_to_cpu(me_hdr->header.ucode_version)); + WREG32(CP_ME_RAM_RADDR, le32_to_cpu(me_hdr->header.ucode_version)); } else { const __be32 *fw_data; @@ -4279,10 +4280,6 @@ static int cik_cp_gfx_load_microcode(struct radeon_device *rdev) WREG32(CP_ME_RAM_WADDR, 0); } - WREG32(CP_PFP_UCODE_ADDR, 0); - WREG32(CP_CE_UCODE_ADDR, 0); - WREG32(CP_ME_RAM_WADDR, 0); - WREG32(CP_ME_RAM_RADDR, 0); return 0; } @@ -4564,7 +4561,7 @@ static int cik_cp_compute_load_microcode(struct radeon_device *rdev) WREG32(CP_MEC_ME1_UCODE_ADDR, 0); for (i = 0; i < fw_size; i++) WREG32(CP_MEC_ME1_UCODE_DATA, le32_to_cpup(fw_data++)); - WREG32(CP_MEC_ME1_UCODE_ADDR, 0); + WREG32(CP_MEC_ME1_UCODE_ADDR, le32_to_cpu(mec_hdr->header.ucode_version)); /* MEC2 */ if (rdev->family == CHIP_KAVERI) { @@ -4578,7 +4575,7 @@ static int cik_cp_compute_load_microcode(struct radeon_device *rdev) WREG32(CP_MEC_ME2_UCODE_ADDR, 0); for (i = 0; i < fw_size; i++) WREG32(CP_MEC_ME2_UCODE_DATA, le32_to_cpup(fw_data++)); - WREG32(CP_MEC_ME2_UCODE_ADDR, 0); + WREG32(CP_MEC_ME2_UCODE_ADDR, le32_to_cpu(mec2_hdr->header.ucode_version)); } } else { const __be32 *fw_data; @@ -4690,7 +4687,7 @@ static int cik_mec_init(struct radeon_device *rdev) r = radeon_bo_create(rdev, rdev->mec.num_mec *rdev->mec.num_pipe * MEC_HPD_SIZE * 2, PAGE_SIZE, true, - RADEON_GEM_DOMAIN_GTT, 0, NULL, + RADEON_GEM_DOMAIN_GTT, 0, NULL, NULL, &rdev->mec.hpd_eop_obj); if (r) { dev_warn(rdev->dev, "(%d) create HDP EOP bo failed\n", r); @@ -4861,7 +4858,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev) sizeof(struct bonaire_mqd), PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT, 0, NULL, - &rdev->ring[idx].mqd_obj); + NULL, &rdev->ring[idx].mqd_obj); if (r) { dev_warn(rdev->dev, "(%d) create MQD bo failed\n", r); return r; @@ -6227,7 +6224,7 @@ static int cik_rlc_resume(struct radeon_device *rdev) WREG32(RLC_GPM_UCODE_ADDR, 0); for (i = 0; i < size; i++) WREG32(RLC_GPM_UCODE_DATA, le32_to_cpup(fw_data++)); - WREG32(RLC_GPM_UCODE_ADDR, 0); + WREG32(RLC_GPM_UCODE_ADDR, le32_to_cpu(hdr->header.ucode_version)); } else { const __be32 *fw_data; diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index c01a6100c318..c473c9125295 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -571,7 +571,7 @@ struct radeon_fence *cik_copy_dma(struct radeon_device *rdev, return ERR_PTR(r); } - radeon_semaphore_sync_resv(sem, resv, false); + radeon_semaphore_sync_resv(rdev, sem, resv, false); radeon_semaphore_sync_rings(rdev, sem, ring->idx); for (i = 0; i < num_loops; i++) { diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c index 51800e340a57..950af153f30e 100644 --- a/drivers/gpu/drm/radeon/dce3_1_afmt.c +++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c @@ -165,7 +165,7 @@ void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *m /* disable audio prior to setting up hw */ dig->afmt->pin = r600_audio_get_pin(rdev); - r600_audio_enable(rdev, dig->afmt->pin, false); + r600_audio_enable(rdev, dig->afmt->pin, 0); r600_audio_set_dto(encoder, mode->clock); @@ -240,5 +240,5 @@ void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *m r600_hdmi_audio_workaround(encoder); /* enable audio after to setting up hw */ - r600_audio_enable(rdev, dig->afmt->pin, true); + r600_audio_enable(rdev, dig->afmt->pin, 0xf); } diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index ab29f953a767..c0bbf68dbc27 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -284,13 +284,13 @@ static int dce6_audio_chipset_supported(struct radeon_device *rdev) void dce6_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin, - bool enable) + u8 enable_mask) { if (!pin) return; - WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL, - enable ? AUDIO_ENABLED : 0); + WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, + enable_mask ? AUDIO_ENABLED : 0); } static const u32 pin_offsets[7] = diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index dbca60c7d097..8fe9f870fb5a 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -22,7 +22,6 @@ * Authors: Alex Deucher */ #include <linux/firmware.h> -#include <linux/platform_device.h> #include <linux/slab.h> #include <drm/drmP.h> #include "radeon.h" @@ -4023,7 +4022,7 @@ int sumo_rlc_init(struct radeon_device *rdev) if (rdev->rlc.save_restore_obj == NULL) { r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, 0, NULL, - &rdev->rlc.save_restore_obj); + NULL, &rdev->rlc.save_restore_obj); if (r) { dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r); return r; @@ -4102,7 +4101,7 @@ int sumo_rlc_init(struct radeon_device *rdev) if (rdev->rlc.clear_state_obj == NULL) { r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, 0, NULL, - &rdev->rlc.clear_state_obj); + NULL, &rdev->rlc.clear_state_obj); if (r) { dev_warn(rdev->dev, "(%d) create RLC c bo failed\n", r); sumo_rlc_fini(rdev); @@ -4179,7 +4178,7 @@ int sumo_rlc_init(struct radeon_device *rdev) r = radeon_bo_create(rdev, rdev->rlc.cp_table_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, 0, NULL, - &rdev->rlc.cp_table_obj); + NULL, &rdev->rlc.cp_table_obj); if (r) { dev_warn(rdev->dev, "(%d) create RLC cp table bo failed\n", r); sumo_rlc_fini(rdev); diff --git a/drivers/gpu/drm/radeon/evergreen_dma.c b/drivers/gpu/drm/radeon/evergreen_dma.c index 946f37d0b469..66bcfadeedd1 100644 --- a/drivers/gpu/drm/radeon/evergreen_dma.c +++ b/drivers/gpu/drm/radeon/evergreen_dma.c @@ -133,7 +133,7 @@ struct radeon_fence *evergreen_copy_dma(struct radeon_device *rdev, return ERR_PTR(r); } - radeon_semaphore_sync_resv(sem, resv, false); + radeon_semaphore_sync_resv(rdev, sem, resv, false); radeon_semaphore_sync_rings(rdev, sem, ring->idx); for (i = 0; i < num_loops; i++) { diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 278c7a139d74..2514d659b1ba 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -38,6 +38,37 @@ extern void dce6_afmt_select_pin(struct drm_encoder *encoder); extern void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, struct drm_display_mode *mode); +/* enable the audio stream */ +static void dce4_audio_enable(struct radeon_device *rdev, + struct r600_audio_pin *pin, + u8 enable_mask) +{ + u32 tmp = RREG32(AZ_HOT_PLUG_CONTROL); + + if (!pin) + return; + + if (enable_mask) { + tmp |= AUDIO_ENABLED; + if (enable_mask & 1) + tmp |= PIN0_AUDIO_ENABLED; + if (enable_mask & 2) + tmp |= PIN1_AUDIO_ENABLED; + if (enable_mask & 4) + tmp |= PIN2_AUDIO_ENABLED; + if (enable_mask & 8) + tmp |= PIN3_AUDIO_ENABLED; + } else { + tmp &= ~(AUDIO_ENABLED | + PIN0_AUDIO_ENABLED | + PIN1_AUDIO_ENABLED | + PIN2_AUDIO_ENABLED | + PIN3_AUDIO_ENABLED); + } + + WREG32(AZ_HOT_PLUG_CONTROL, tmp); +} + /* * update the N and CTS parameters for a given pixel clock rate */ @@ -318,10 +349,10 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode /* disable audio prior to setting up hw */ if (ASIC_IS_DCE6(rdev)) { dig->afmt->pin = dce6_audio_get_pin(rdev); - dce6_audio_enable(rdev, dig->afmt->pin, false); + dce6_audio_enable(rdev, dig->afmt->pin, 0); } else { dig->afmt->pin = r600_audio_get_pin(rdev); - r600_audio_enable(rdev, dig->afmt->pin, false); + dce4_audio_enable(rdev, dig->afmt->pin, 0); } evergreen_audio_set_dto(encoder, mode->clock); @@ -463,13 +494,15 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode /* enable audio after to setting up hw */ if (ASIC_IS_DCE6(rdev)) - dce6_audio_enable(rdev, dig->afmt->pin, true); + dce6_audio_enable(rdev, dig->afmt->pin, 1); else - r600_audio_enable(rdev, dig->afmt->pin, true); + dce4_audio_enable(rdev, dig->afmt->pin, 0xf); } void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) { + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; @@ -482,6 +515,14 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) if (!enable && !dig->afmt->enabled) return; + if (!enable && dig->afmt->pin) { + if (ASIC_IS_DCE6(rdev)) + dce6_audio_enable(rdev, dig->afmt->pin, 0); + else + dce4_audio_enable(rdev, dig->afmt->pin, 0); + dig->afmt->pin = NULL; + } + dig->afmt->enabled = enable; DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n", diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index 8b58e11b64fa..7b129d2b44be 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -2773,6 +2773,8 @@ void kv_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, tmp = (RREG32_SMC(SMU_VOLTAGE_STATUS) & SMU_VOLTAGE_CURRENT_LEVEL_MASK) >> SMU_VOLTAGE_CURRENT_LEVEL_SHIFT; vddc = kv_convert_8bit_index_to_voltage(rdev, (u16)tmp); + seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en"); + seq_printf(m, "vce %sabled\n", pi->vce_power_gated ? "dis" : "en"); seq_printf(m, "power level %d sclk: %u vddc: %u\n", current_index, sclk, vddc); } diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index 01fc4888e6fe..715b181c6243 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -789,7 +789,6 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev, bool disable_mclk_switching; u32 mclk; u16 vddci; - u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; int i; if ((rdev->pm.dpm.new_active_crtc_count > 1) || @@ -816,29 +815,6 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev, } } - /* limit clocks to max supported clocks based on voltage dependency tables */ - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk, - &max_sclk_vddc); - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk, - &max_mclk_vddci); - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk, - &max_mclk_vddc); - - for (i = 0; i < ps->performance_level_count; i++) { - if (max_sclk_vddc) { - if (ps->performance_levels[i].sclk > max_sclk_vddc) - ps->performance_levels[i].sclk = max_sclk_vddc; - } - if (max_mclk_vddci) { - if (ps->performance_levels[i].mclk > max_mclk_vddci) - ps->performance_levels[i].mclk = max_mclk_vddci; - } - if (max_mclk_vddc) { - if (ps->performance_levels[i].mclk > max_mclk_vddc) - ps->performance_levels[i].mclk = max_mclk_vddc; - } - } - /* XXX validate the min clocks required for display */ /* adjust low state */ diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 25f367ac4637..85414283fccc 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1430,7 +1430,7 @@ int r600_vram_scratch_init(struct radeon_device *rdev) if (rdev->vram_scratch.robj == NULL) { r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, - 0, NULL, &rdev->vram_scratch.robj); + 0, NULL, NULL, &rdev->vram_scratch.robj); if (r) { return r; } @@ -2912,7 +2912,7 @@ struct radeon_fence *r600_copy_cpdma(struct radeon_device *rdev, return ERR_PTR(r); } - radeon_semaphore_sync_resv(sem, resv, false); + radeon_semaphore_sync_resv(rdev, sem, resv, false); radeon_semaphore_sync_rings(rdev, sem, ring->idx); radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); @@ -3368,7 +3368,7 @@ int r600_ih_ring_alloc(struct radeon_device *rdev) r = radeon_bo_create(rdev, rdev->ih.ring_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT, 0, - NULL, &rdev->ih.ring_obj); + NULL, NULL, &rdev->ih.ring_obj); if (r) { DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r); return r; diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c deleted file mode 100644 index bffac10c4296..000000000000 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2008 Advanced Micro Devices, Inc. - * Copyright 2008 Red Hat Inc. - * Copyright 2009 Christian König. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Christian König - */ -#include <drm/drmP.h> -#include "radeon.h" -#include "radeon_reg.h" -#include "radeon_asic.h" -#include "atom.h" - -/* - * check if enc_priv stores radeon_encoder_atom_dig - */ -static bool radeon_dig_encoder(struct drm_encoder *encoder) -{ - struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_LVDS: - case ENCODER_OBJECT_ID_INTERNAL_TMDS1: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: - case ENCODER_OBJECT_ID_INTERNAL_DVO1: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: - case ENCODER_OBJECT_ID_INTERNAL_DDI: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - return true; - } - return false; -} - -/* - * check if the chipset is supported - */ -static int r600_audio_chipset_supported(struct radeon_device *rdev) -{ - return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev); -} - -struct r600_audio_pin r600_audio_status(struct radeon_device *rdev) -{ - struct r600_audio_pin status; - uint32_t value; - - value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); - - /* number of channels */ - status.channels = (value & 0x7) + 1; - - /* bits per sample */ - switch ((value & 0xF0) >> 4) { - case 0x0: - status.bits_per_sample = 8; - break; - case 0x1: - status.bits_per_sample = 16; - break; - case 0x2: - status.bits_per_sample = 20; - break; - case 0x3: - status.bits_per_sample = 24; - break; - case 0x4: - status.bits_per_sample = 32; - break; - default: - dev_err(rdev->dev, "Unknown bits per sample 0x%x, using 16\n", - (int)value); - status.bits_per_sample = 16; - } - - /* current sampling rate in HZ */ - if (value & 0x4000) - status.rate = 44100; - else - status.rate = 48000; - status.rate *= ((value >> 11) & 0x7) + 1; - status.rate /= ((value >> 8) & 0x7) + 1; - - value = RREG32(R600_AUDIO_STATUS_BITS); - - /* iec 60958 status bits */ - status.status_bits = value & 0xff; - - /* iec 60958 category code */ - status.category_code = (value >> 8) & 0xff; - - return status; -} - -/* - * update all hdmi interfaces with current audio parameters - */ -void r600_audio_update_hdmi(struct work_struct *work) -{ - struct radeon_device *rdev = container_of(work, struct radeon_device, - audio_work); - struct drm_device *dev = rdev->ddev; - struct r600_audio_pin audio_status = r600_audio_status(rdev); - struct drm_encoder *encoder; - bool changed = false; - - if (rdev->audio.pin[0].channels != audio_status.channels || - rdev->audio.pin[0].rate != audio_status.rate || - rdev->audio.pin[0].bits_per_sample != audio_status.bits_per_sample || - rdev->audio.pin[0].status_bits != audio_status.status_bits || - rdev->audio.pin[0].category_code != audio_status.category_code) { - rdev->audio.pin[0] = audio_status; - changed = true; - } - - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - if (!radeon_dig_encoder(encoder)) - continue; - if (changed || r600_hdmi_buffer_status_changed(encoder)) - r600_hdmi_update_audio_settings(encoder); - } -} - -/* enable the audio stream */ -void r600_audio_enable(struct radeon_device *rdev, - struct r600_audio_pin *pin, - bool enable) -{ - u32 value = 0; - - if (!pin) - return; - - if (ASIC_IS_DCE4(rdev)) { - if (enable) { - value |= 0x81000000; /* Required to enable audio */ - value |= 0x0e1000f0; /* fglrx sets that too */ - } - WREG32(EVERGREEN_AUDIO_ENABLE, value); - } else { - WREG32_P(R600_AUDIO_ENABLE, - enable ? 0x81000000 : 0x0, ~0x81000000); - } -} - -/* - * initialize the audio vars - */ -int r600_audio_init(struct radeon_device *rdev) -{ - if (!radeon_audio || !r600_audio_chipset_supported(rdev)) - return 0; - - rdev->audio.enabled = true; - - rdev->audio.num_pins = 1; - rdev->audio.pin[0].channels = -1; - rdev->audio.pin[0].rate = -1; - rdev->audio.pin[0].bits_per_sample = -1; - rdev->audio.pin[0].status_bits = 0; - rdev->audio.pin[0].category_code = 0; - rdev->audio.pin[0].id = 0; - /* disable audio. it will be set up later */ - r600_audio_enable(rdev, &rdev->audio.pin[0], false); - - return 0; -} - -/* - * release the audio timer - * TODO: How to do this correctly on SMP systems? - */ -void r600_audio_fini(struct radeon_device *rdev) -{ - if (!rdev->audio.enabled) - return; - - r600_audio_enable(rdev, &rdev->audio.pin[0], false); - - rdev->audio.enabled = false; -} - -struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev) -{ - /* only one pin on 6xx-NI */ - return &rdev->audio.pin[0]; -} diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c index fc54224ce87b..a49db830a47f 100644 --- a/drivers/gpu/drm/radeon/r600_dma.c +++ b/drivers/gpu/drm/radeon/r600_dma.c @@ -470,7 +470,7 @@ struct radeon_fence *r600_copy_dma(struct radeon_device *rdev, return ERR_PTR(r); } - radeon_semaphore_sync_resv(sem, resv, false); + radeon_semaphore_sync_resv(rdev, sem, resv, false); radeon_semaphore_sync_rings(rdev, sem, ring->idx); for (i = 0; i < num_loops; i++) { diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 26ef8ced6f89..b90dc0eb08e6 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -72,6 +72,169 @@ static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { /* + * check if the chipset is supported + */ +static int r600_audio_chipset_supported(struct radeon_device *rdev) +{ + return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev); +} + +static struct r600_audio_pin r600_audio_status(struct radeon_device *rdev) +{ + struct r600_audio_pin status; + uint32_t value; + + value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL); + + /* number of channels */ + status.channels = (value & 0x7) + 1; + + /* bits per sample */ + switch ((value & 0xF0) >> 4) { + case 0x0: + status.bits_per_sample = 8; + break; + case 0x1: + status.bits_per_sample = 16; + break; + case 0x2: + status.bits_per_sample = 20; + break; + case 0x3: + status.bits_per_sample = 24; + break; + case 0x4: + status.bits_per_sample = 32; + break; + default: + dev_err(rdev->dev, "Unknown bits per sample 0x%x, using 16\n", + (int)value); + status.bits_per_sample = 16; + } + + /* current sampling rate in HZ */ + if (value & 0x4000) + status.rate = 44100; + else + status.rate = 48000; + status.rate *= ((value >> 11) & 0x7) + 1; + status.rate /= ((value >> 8) & 0x7) + 1; + + value = RREG32(R600_AUDIO_STATUS_BITS); + + /* iec 60958 status bits */ + status.status_bits = value & 0xff; + + /* iec 60958 category code */ + status.category_code = (value >> 8) & 0xff; + + return status; +} + +/* + * update all hdmi interfaces with current audio parameters + */ +void r600_audio_update_hdmi(struct work_struct *work) +{ + struct radeon_device *rdev = container_of(work, struct radeon_device, + audio_work); + struct drm_device *dev = rdev->ddev; + struct r600_audio_pin audio_status = r600_audio_status(rdev); + struct drm_encoder *encoder; + bool changed = false; + + if (rdev->audio.pin[0].channels != audio_status.channels || + rdev->audio.pin[0].rate != audio_status.rate || + rdev->audio.pin[0].bits_per_sample != audio_status.bits_per_sample || + rdev->audio.pin[0].status_bits != audio_status.status_bits || + rdev->audio.pin[0].category_code != audio_status.category_code) { + rdev->audio.pin[0] = audio_status; + changed = true; + } + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (!radeon_encoder_is_digital(encoder)) + continue; + if (changed || r600_hdmi_buffer_status_changed(encoder)) + r600_hdmi_update_audio_settings(encoder); + } +} + +/* enable the audio stream */ +void r600_audio_enable(struct radeon_device *rdev, + struct r600_audio_pin *pin, + u8 enable_mask) +{ + u32 tmp = RREG32(AZ_HOT_PLUG_CONTROL); + + if (!pin) + return; + + if (enable_mask) { + tmp |= AUDIO_ENABLED; + if (enable_mask & 1) + tmp |= PIN0_AUDIO_ENABLED; + if (enable_mask & 2) + tmp |= PIN1_AUDIO_ENABLED; + if (enable_mask & 4) + tmp |= PIN2_AUDIO_ENABLED; + if (enable_mask & 8) + tmp |= PIN3_AUDIO_ENABLED; + } else { + tmp &= ~(AUDIO_ENABLED | + PIN0_AUDIO_ENABLED | + PIN1_AUDIO_ENABLED | + PIN2_AUDIO_ENABLED | + PIN3_AUDIO_ENABLED); + } + + WREG32(AZ_HOT_PLUG_CONTROL, tmp); +} + +/* + * initialize the audio vars + */ +int r600_audio_init(struct radeon_device *rdev) +{ + if (!radeon_audio || !r600_audio_chipset_supported(rdev)) + return 0; + + rdev->audio.enabled = true; + + rdev->audio.num_pins = 1; + rdev->audio.pin[0].channels = -1; + rdev->audio.pin[0].rate = -1; + rdev->audio.pin[0].bits_per_sample = -1; + rdev->audio.pin[0].status_bits = 0; + rdev->audio.pin[0].category_code = 0; + rdev->audio.pin[0].id = 0; + /* disable audio. it will be set up later */ + r600_audio_enable(rdev, &rdev->audio.pin[0], 0); + + return 0; +} + +/* + * release the audio timer + * TODO: How to do this correctly on SMP systems? + */ +void r600_audio_fini(struct radeon_device *rdev) +{ + if (!rdev->audio.enabled) + return; + + r600_audio_enable(rdev, &rdev->audio.pin[0], 0); + + rdev->audio.enabled = false; +} + +struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev) +{ + /* only one pin on 6xx-NI */ + return &rdev->audio.pin[0]; +} + +/* * calculate CTS and N values if they are not found in the table */ static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq) @@ -357,7 +520,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod /* disable audio prior to setting up hw */ dig->afmt->pin = r600_audio_get_pin(rdev); - r600_audio_enable(rdev, dig->afmt->pin, false); + r600_audio_enable(rdev, dig->afmt->pin, 0xf); r600_audio_set_dto(encoder, mode->clock); @@ -443,7 +606,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001); /* enable audio after to setting up hw */ - r600_audio_enable(rdev, dig->afmt->pin, true); + r600_audio_enable(rdev, dig->afmt->pin, 0xf); } /** @@ -528,6 +691,11 @@ void r600_hdmi_enable(struct drm_encoder *encoder, bool enable) if (!enable && !dig->afmt->enabled) return; + if (!enable && dig->afmt->pin) { + r600_audio_enable(rdev, dig->afmt->pin, 0); + dig->afmt->pin = NULL; + } + /* Older chipsets require setting HDMI and routing manually */ if (!ASIC_IS_DCE3(rdev)) { if (enable) diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 671b48032a3d..ebf68fa6d1f1 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -934,6 +934,23 @@ # define TARGET_LINK_SPEED_MASK (0xf << 0) # define SELECTABLE_DEEMPHASIS (1 << 6) +/* Audio */ +#define AZ_HOT_PLUG_CONTROL 0x7300 +# define AZ_FORCE_CODEC_WAKE (1 << 0) +# define JACK_DETECTION_ENABLE (1 << 4) +# define UNSOLICITED_RESPONSE_ENABLE (1 << 8) +# define CODEC_HOT_PLUG_ENABLE (1 << 12) +# define AUDIO_ENABLED (1 << 31) +/* DCE3 adds */ +# define PIN0_JACK_DETECTION_ENABLE (1 << 4) +# define PIN1_JACK_DETECTION_ENABLE (1 << 5) +# define PIN2_JACK_DETECTION_ENABLE (1 << 6) +# define PIN3_JACK_DETECTION_ENABLE (1 << 7) +# define PIN0_AUDIO_ENABLED (1 << 24) +# define PIN1_AUDIO_ENABLED (1 << 25) +# define PIN2_AUDIO_ENABLED (1 << 26) +# define PIN3_AUDIO_ENABLED (1 << 27) + /* Audio clocks DCE 2.0/3.0 */ #define AUDIO_DTO 0x7340 # define AUDIO_DTO_PHASE(x) (((x) & 0xffff) << 0) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 82b0e11ade89..e01424fe2848 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -74,6 +74,8 @@ #include <ttm/ttm_module.h> #include <ttm/ttm_execbuf_util.h> +#include <drm/drm_gem.h> + #include "radeon_family.h" #include "radeon_mode.h" #include "radeon_reg.h" @@ -587,9 +589,10 @@ bool radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, struct radeon_semaphore *semaphore); void radeon_semaphore_sync_fence(struct radeon_semaphore *semaphore, struct radeon_fence *fence); -void radeon_semaphore_sync_resv(struct radeon_semaphore *semaphore, - struct reservation_object *resv, - bool shared); +int radeon_semaphore_sync_resv(struct radeon_device *rdev, + struct radeon_semaphore *semaphore, + struct reservation_object *resv, + bool shared); int radeon_semaphore_sync_rings(struct radeon_device *rdev, struct radeon_semaphore *semaphore, int waiting_ring); @@ -710,7 +713,7 @@ struct radeon_flip_work { uint64_t base; struct drm_pending_vblank_event *event; struct radeon_bo *old_rbo; - struct radeon_fence *fence; + struct fence *fence; }; struct r500_irq_stat_regs { @@ -2975,10 +2978,10 @@ struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev); struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev); void r600_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin, - bool enable); + u8 enable_mask); void dce6_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin, - bool enable); + u8 enable_mask); /* * R600 vram scratch functions diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index ca01bb8ea217..c41363f4fc1a 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -392,7 +392,6 @@ void r600_disable_interrupts(struct radeon_device *rdev); void r600_rlc_stop(struct radeon_device *rdev); /* r600 audio */ int r600_audio_init(struct radeon_device *rdev); -struct r600_audio_pin r600_audio_status(struct radeon_device *rdev); void r600_audio_fini(struct radeon_device *rdev); void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock); void r600_hdmi_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index e74c7e387dde..df69b92ba164 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -458,7 +458,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, return true; } -const int supported_devices_connector_convert[] = { +static const int supported_devices_connector_convert[] = { DRM_MODE_CONNECTOR_Unknown, DRM_MODE_CONNECTOR_VGA, DRM_MODE_CONNECTOR_DVII, @@ -477,7 +477,7 @@ const int supported_devices_connector_convert[] = { DRM_MODE_CONNECTOR_DisplayPort }; -const uint16_t supported_devices_connector_object_id_convert[] = { +static const uint16_t supported_devices_connector_object_id_convert[] = { CONNECTOR_OBJECT_ID_NONE, CONNECTOR_OBJECT_ID_VGA, CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, /* not all boards support DL */ @@ -494,7 +494,7 @@ const uint16_t supported_devices_connector_object_id_convert[] = { CONNECTOR_OBJECT_ID_SVIDEO }; -const int object_connector_convert[] = { +static const int object_connector_convert[] = { DRM_MODE_CONNECTOR_Unknown, DRM_MODE_CONNECTOR_DVII, DRM_MODE_CONNECTOR_DVII, diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index 1e8855060fc7..9e7f23dd14bd 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c @@ -93,7 +93,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, int time; n = RADEON_BENCHMARK_ITERATIONS; - r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, 0, NULL, &sobj); + r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, 0, NULL, NULL, &sobj); if (r) { goto out_cleanup; } @@ -105,7 +105,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, if (r) { goto out_cleanup; } - r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, 0, NULL, &dobj); + r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, 0, NULL, NULL, &dobj); if (r) { goto out_cleanup; } diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 6651177110f0..3e5f6b71f3ad 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -116,7 +116,7 @@ enum radeon_combios_connector { CONNECTOR_UNSUPPORTED_LEGACY }; -const int legacy_connector_convert[] = { +static const int legacy_connector_convert[] = { DRM_MODE_CONNECTOR_Unknown, DRM_MODE_CONNECTOR_DVID, DRM_MODE_CONNECTOR_VGA, diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index f662de41ba49..1c893447d7cd 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -249,9 +249,9 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority return 0; } -static void radeon_cs_sync_rings(struct radeon_cs_parser *p) +static int radeon_cs_sync_rings(struct radeon_cs_parser *p) { - int i; + int i, r = 0; for (i = 0; i < p->nrelocs; i++) { struct reservation_object *resv; @@ -260,9 +260,13 @@ static void radeon_cs_sync_rings(struct radeon_cs_parser *p) continue; resv = p->relocs[i].robj->tbo.resv; - radeon_semaphore_sync_resv(p->ib.semaphore, resv, - p->relocs[i].tv.shared); + r = radeon_semaphore_sync_resv(p->rdev, p->ib.semaphore, resv, + p->relocs[i].tv.shared); + + if (r) + break; } + return r; } /* XXX: note that this is called from the legacy UMS CS ioctl as well */ @@ -472,13 +476,19 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev, return r; } + r = radeon_cs_sync_rings(parser); + if (r) { + if (r != -ERESTARTSYS) + DRM_ERROR("Failed to sync rings: %i\n", r); + return r; + } + if (parser->ring == R600_RING_TYPE_UVD_INDEX) radeon_uvd_note_usage(rdev); else if ((parser->ring == TN_RING_TYPE_VCE1_INDEX) || (parser->ring == TN_RING_TYPE_VCE2_INDEX)) radeon_vce_note_usage(rdev); - radeon_cs_sync_rings(parser); r = radeon_ib_schedule(rdev, &parser->ib, NULL, true); if (r) { DRM_ERROR("Failed to schedule IB !\n"); @@ -565,7 +575,13 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, if (r) { goto out; } - radeon_cs_sync_rings(parser); + + r = radeon_cs_sync_rings(parser); + if (r) { + if (r != -ERESTARTSYS) + DRM_ERROR("Failed to sync rings: %i\n", r); + goto out; + } radeon_semaphore_sync_fence(parser->ib.semaphore, vm->fence); if ((rdev->family >= CHIP_TAHITI) && diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index e84a76e6656a..6fbab1582112 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -430,7 +430,7 @@ int radeon_wb_init(struct radeon_device *rdev) if (rdev->wb.wb_obj == NULL) { r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, - RADEON_GEM_DOMAIN_GTT, 0, NULL, + RADEON_GEM_DOMAIN_GTT, 0, NULL, NULL, &rdev->wb.wb_obj); if (r) { dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 4eb37976f879..00ead8c2758a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -402,14 +402,21 @@ static void radeon_flip_work_func(struct work_struct *__work) down_read(&rdev->exclusive_lock); if (work->fence) { - r = radeon_fence_wait(work->fence, false); - if (r == -EDEADLK) { - up_read(&rdev->exclusive_lock); - do { - r = radeon_gpu_reset(rdev); - } while (r == -EAGAIN); - down_read(&rdev->exclusive_lock); - } + struct radeon_fence *fence; + + fence = to_radeon_fence(work->fence); + if (fence && fence->rdev == rdev) { + r = radeon_fence_wait(fence, false); + if (r == -EDEADLK) { + up_read(&rdev->exclusive_lock); + do { + r = radeon_gpu_reset(rdev); + } while (r == -EAGAIN); + down_read(&rdev->exclusive_lock); + } + } else + r = fence_wait(work->fence, false); + if (r) DRM_ERROR("failed to wait on page flip fence (%d)!\n", r); @@ -418,7 +425,8 @@ static void radeon_flip_work_func(struct work_struct *__work) * confused about which BO the CRTC is scanning out */ - radeon_fence_unref(&work->fence); + fence_put(work->fence); + work->fence = NULL; } /* We borrow the event spin lock for protecting flip_status */ @@ -494,7 +502,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, DRM_ERROR("failed to pin new rbo buffer before flip\n"); goto cleanup; } - work->fence = (struct radeon_fence *)fence_get(reservation_object_get_excl(new_rbo->tbo.resv)); + work->fence = fence_get(reservation_object_get_excl(new_rbo->tbo.resv)); radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL); radeon_bo_unreserve(new_rbo); @@ -576,7 +584,7 @@ pflip_cleanup: cleanup: drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); - radeon_fence_unref(&work->fence); + fence_put(work->fence); kfree(work); return r; } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index ec7e963d9bf7..69c6a835bcd5 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -38,6 +38,8 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/vga_switcheroo.h> +#include <drm/drm_gem.h> + #include "drm_crtc_helper.h" /* * KMS wrapper. @@ -133,7 +135,7 @@ int radeon_mode_dumb_create(struct drm_file *file_priv, struct drm_mode_create_dumb *args); struct sg_table *radeon_gem_prime_get_sg_table(struct drm_gem_object *obj); struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev, - size_t size, + struct dma_buf_attachment *, struct sg_table *sg); int radeon_gem_prime_pin(struct drm_gem_object *obj); void radeon_gem_prime_unpin(struct drm_gem_object *obj); @@ -308,7 +310,7 @@ static const struct file_operations radeon_driver_old_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, - .mmap = drm_mmap, + .mmap = drm_legacy_mmap, .poll = drm_poll, .read = drm_read, #ifdef CONFIG_COMPAT diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 3c2094c25b53..109843dab5e5 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -382,3 +382,24 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder, } } +bool radeon_encoder_is_digital(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: + return true; + default: + return false; + } +} diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 94b0f2aa3d7c..0ea1db83d573 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -189,7 +189,8 @@ out_unref: static int radeonfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { - struct radeon_fbdev *rfbdev = (struct radeon_fbdev *)helper; + struct radeon_fbdev *rfbdev = + container_of(helper, struct radeon_fbdev, helper); struct radeon_device *rdev = rfbdev->rdev; struct fb_info *info; struct drm_framebuffer *fb = NULL; diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index af9f2d6bd7d0..995167025282 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -541,6 +541,15 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr) uint64_t seq[RADEON_NUM_RINGS] = {}; long r; + /* + * This function should not be called on !radeon fences. + * If this is the case, it would mean this function can + * also be called on radeon fences belonging to another card. + * exclusive_lock is not held in that case. + */ + if (WARN_ON_ONCE(!to_radeon_fence(&fence->base))) + return fence_wait(&fence->base, intr); + seq[fence->ring] = fence->seq; r = radeon_fence_wait_seq_timeout(fence->rdev, seq, intr, MAX_SCHEDULE_TIMEOUT); if (r < 0) { diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index a053a0779aac..84146d5901aa 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -128,7 +128,7 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev) if (rdev->gart.robj == NULL) { r = radeon_bo_create(rdev, rdev->gart.table_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, - 0, NULL, &rdev->gart.robj); + 0, NULL, NULL, &rdev->gart.robj); if (r) { return r; } diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 4b7c8ec36c2f..c194497aa586 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -67,7 +67,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, unsigned long size, retry: r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, - flags, NULL, &robj); + flags, NULL, NULL, &robj); if (r) { if (r != -ERESTARTSYS) { if (initial_domain == RADEON_GEM_DOMAIN_VRAM) { diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index e27608c29c11..04db2fdd8692 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -777,6 +777,7 @@ extern void atombios_digital_setup(struct drm_encoder *encoder, int action); extern int atombios_get_encoder_mode(struct drm_encoder *encoder); extern bool atombios_set_edp_panel_power(struct drm_connector *connector, int action); extern void radeon_encoder_set_active_device(struct drm_encoder *encoder); +extern bool radeon_encoder_is_digital(struct drm_encoder *encoder); extern void radeon_crtc_load_lut(struct drm_crtc *crtc); extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 8abee5fa93bd..99a960a4f302 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -167,8 +167,10 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) } int radeon_bo_create(struct radeon_device *rdev, - unsigned long size, int byte_align, bool kernel, u32 domain, - u32 flags, struct sg_table *sg, struct radeon_bo **bo_ptr) + unsigned long size, int byte_align, bool kernel, + u32 domain, u32 flags, struct sg_table *sg, + struct reservation_object *resv, + struct radeon_bo **bo_ptr) { struct radeon_bo *bo; enum ttm_bo_type type; @@ -216,7 +218,7 @@ int radeon_bo_create(struct radeon_device *rdev, down_read(&rdev->pm.mclk_lock); r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type, &bo->placement, page_align, !kernel, NULL, - acc_size, sg, &radeon_ttm_bo_destroy); + acc_size, sg, resv, &radeon_ttm_bo_destroy); up_read(&rdev->pm.mclk_lock); if (unlikely(r != 0)) { return r; diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 98a47fdf3625..1b8ec7917154 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -126,6 +126,7 @@ extern int radeon_bo_create(struct radeon_device *rdev, unsigned long size, int byte_align, bool kernel, u32 domain, u32 flags, struct sg_table *sg, + struct reservation_object *resv, struct radeon_bo **bo_ptr); extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr); extern void radeon_bo_kunmap(struct radeon_bo *bo); diff --git a/drivers/gpu/drm/radeon/radeon_prime.c b/drivers/gpu/drm/radeon/radeon_prime.c index d5414d42e44b..f3609c97496b 100644 --- a/drivers/gpu/drm/radeon/radeon_prime.c +++ b/drivers/gpu/drm/radeon/radeon_prime.c @@ -27,6 +27,7 @@ #include "radeon.h" #include <drm/radeon_drm.h> +#include <linux/dma-buf.h> struct sg_table *radeon_gem_prime_get_sg_table(struct drm_gem_object *obj) { @@ -57,15 +58,18 @@ void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) } struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev, - size_t size, + struct dma_buf_attachment *attach, struct sg_table *sg) { + struct reservation_object *resv = attach->dmabuf->resv; struct radeon_device *rdev = dev->dev_private; struct radeon_bo *bo; int ret; - ret = radeon_bo_create(rdev, size, PAGE_SIZE, false, - RADEON_GEM_DOMAIN_GTT, 0, sg, &bo); + ww_mutex_lock(&resv->lock, NULL); + ret = radeon_bo_create(rdev, attach->dmabuf->size, PAGE_SIZE, false, + RADEON_GEM_DOMAIN_GTT, 0, sg, resv, &bo); + ww_mutex_unlock(&resv->lock); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 6f2a9bd6bb54..3d17af34afa7 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -383,7 +383,7 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig /* Allocate ring buffer */ if (ring->ring_obj == NULL) { r = radeon_bo_create(rdev, ring->ring_size, PAGE_SIZE, true, - RADEON_GEM_DOMAIN_GTT, 0, + RADEON_GEM_DOMAIN_GTT, 0, NULL, NULL, &ring->ring_obj); if (r) { dev_err(rdev->dev, "(%d) ring create failed\n", r); diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c index b84f97c8718c..c507896aca45 100644 --- a/drivers/gpu/drm/radeon/radeon_sa.c +++ b/drivers/gpu/drm/radeon/radeon_sa.c @@ -65,7 +65,7 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev, } r = radeon_bo_create(rdev, size, align, true, - domain, flags, NULL, &sa_manager->bo); + domain, flags, NULL, NULL, &sa_manager->bo); if (r) { dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r); return r; diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 4d4b0773638a..6deb08f045b7 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c @@ -124,27 +124,42 @@ void radeon_semaphore_sync_fence(struct radeon_semaphore *semaphore, * * Sync to the fence using this semaphore object */ -void radeon_semaphore_sync_resv(struct radeon_semaphore *sema, - struct reservation_object *resv, - bool shared) +int radeon_semaphore_sync_resv(struct radeon_device *rdev, + struct radeon_semaphore *sema, + struct reservation_object *resv, + bool shared) { struct reservation_object_list *flist; struct fence *f; + struct radeon_fence *fence; unsigned i; + int r = 0; /* always sync to the exclusive fence */ f = reservation_object_get_excl(resv); - radeon_semaphore_sync_fence(sema, (struct radeon_fence*)f); + fence = f ? to_radeon_fence(f) : NULL; + if (fence && fence->rdev == rdev) + radeon_semaphore_sync_fence(sema, fence); + else if (f) + r = fence_wait(f, true); flist = reservation_object_get_list(resv); - if (shared || !flist) - return; + if (shared || !flist || r) + return r; for (i = 0; i < flist->shared_count; ++i) { f = rcu_dereference_protected(flist->shared[i], reservation_object_held(resv)); - radeon_semaphore_sync_fence(sema, (struct radeon_fence*)f); + fence = to_radeon_fence(f); + if (fence && fence->rdev == rdev) + radeon_semaphore_sync_fence(sema, fence); + else + r = fence_wait(f, true); + + if (r) + break; } + return r; } /** diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index ce943e1a5e51..07b506b41008 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -67,7 +67,7 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag) } r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, - 0, NULL, &vram_obj); + 0, NULL, NULL, &vram_obj); if (r) { DRM_ERROR("Failed to create VRAM object\n"); goto out_cleanup; @@ -87,7 +87,8 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag) struct radeon_fence *fence = NULL; r = radeon_bo_create(rdev, size, PAGE_SIZE, true, - RADEON_GEM_DOMAIN_GTT, 0, NULL, gtt_obj + i); + RADEON_GEM_DOMAIN_GTT, 0, NULL, NULL, + gtt_obj + i); if (r) { DRM_ERROR("Failed to create GTT object %d\n", i); goto out_lclean; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index eca2ce60d440..8624979afb65 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -675,10 +675,17 @@ static struct ttm_tt *radeon_ttm_tt_create(struct ttm_bo_device *bdev, return >t->ttm.ttm; } +static struct radeon_ttm_tt *radeon_ttm_tt_to_gtt(struct ttm_tt *ttm) +{ + if (!ttm || ttm->func != &radeon_backend_func) + return NULL; + return (struct radeon_ttm_tt *)ttm; +} + static int radeon_ttm_tt_populate(struct ttm_tt *ttm) { + struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); struct radeon_device *rdev; - struct radeon_ttm_tt *gtt = (void *)ttm; unsigned i; int r; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); @@ -686,7 +693,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm) if (ttm->state != tt_unpopulated) return 0; - if (gtt->userptr) { + if (gtt && gtt->userptr) { ttm->sg = kcalloc(1, sizeof(struct sg_table), GFP_KERNEL); if (!ttm->sg) return -ENOMEM; @@ -741,11 +748,11 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm) static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm) { struct radeon_device *rdev; - struct radeon_ttm_tt *gtt = (void *)ttm; + struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); unsigned i; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); - if (gtt->userptr) { + if (gtt && gtt->userptr) { kfree(ttm->sg); ttm->page_flags &= ~TTM_PAGE_FLAG_SG; return; @@ -782,7 +789,7 @@ static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm) int radeon_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, uint32_t flags) { - struct radeon_ttm_tt *gtt = (void *)ttm; + struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); if (gtt == NULL) return -EINVAL; @@ -795,7 +802,7 @@ int radeon_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, bool radeon_ttm_tt_has_userptr(struct ttm_tt *ttm) { - struct radeon_ttm_tt *gtt = (void *)ttm; + struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); if (gtt == NULL) return false; @@ -805,7 +812,7 @@ bool radeon_ttm_tt_has_userptr(struct ttm_tt *ttm) bool radeon_ttm_tt_is_readonly(struct ttm_tt *ttm) { - struct radeon_ttm_tt *gtt = (void *)ttm; + struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); if (gtt == NULL) return false; @@ -858,7 +865,7 @@ int radeon_ttm_init(struct radeon_device *rdev) radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); r = radeon_bo_create(rdev, 256 * 1024, PAGE_SIZE, true, - RADEON_GEM_DOMAIN_VRAM, 0, + RADEON_GEM_DOMAIN_VRAM, 0, NULL, NULL, &rdev->stollen_vga_memory); if (r) { return r; @@ -956,7 +963,7 @@ int radeon_mmap(struct file *filp, struct vm_area_struct *vma) int r; if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) { - return drm_mmap(filp, vma); + return -EINVAL; } file_priv = filp->private_data; diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index ba4f38916026..11b662469253 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -141,7 +141,8 @@ int radeon_uvd_init(struct radeon_device *rdev) RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE + RADEON_GPU_PAGE_SIZE; r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true, - RADEON_GEM_DOMAIN_VRAM, 0, NULL, &rdev->uvd.vcpu_bo); + RADEON_GEM_DOMAIN_VRAM, 0, NULL, + NULL, &rdev->uvd.vcpu_bo); if (r) { dev_err(rdev->dev, "(%d) failed to allocate UVD bo\n", r); return r; diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index c7190aadbd89..9e85757d5599 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c @@ -126,7 +126,8 @@ int radeon_vce_init(struct radeon_device *rdev) size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) + RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE; r = radeon_bo_create(rdev, size, PAGE_SIZE, true, - RADEON_GEM_DOMAIN_VRAM, 0, NULL, &rdev->vce.vcpu_bo); + RADEON_GEM_DOMAIN_VRAM, 0, NULL, NULL, + &rdev->vce.vcpu_bo); if (r) { dev_err(rdev->dev, "(%d) failed to allocate VCE bo\n", r); return r; diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index ce870959dff8..4532cc76a0a6 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -548,7 +548,8 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, r = radeon_bo_create(rdev, RADEON_VM_PTE_COUNT * 8, RADEON_GPU_PAGE_SIZE, true, - RADEON_GEM_DOMAIN_VRAM, 0, NULL, &pt); + RADEON_GEM_DOMAIN_VRAM, 0, + NULL, NULL, &pt); if (r) return r; @@ -698,7 +699,7 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev, if (ib.length_dw != 0) { radeon_asic_vm_pad_ib(rdev, &ib); - radeon_semaphore_sync_resv(ib.semaphore, pd->tbo.resv, false); + radeon_semaphore_sync_resv(rdev, ib.semaphore, pd->tbo.resv, false); radeon_semaphore_sync_fence(ib.semaphore, vm->last_id_use); WARN_ON(ib.length_dw > ndw); r = radeon_ib_schedule(rdev, &ib, NULL, false); @@ -825,7 +826,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev, unsigned nptes; uint64_t pte; - radeon_semaphore_sync_resv(ib->semaphore, pt->tbo.resv, false); + radeon_semaphore_sync_resv(rdev, ib->semaphore, pt->tbo.resv, false); if ((addr & ~mask) == (end & ~mask)) nptes = end - addr; @@ -1127,7 +1128,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) r = radeon_bo_create(rdev, pd_size, align, true, RADEON_GEM_DOMAIN_VRAM, 0, NULL, - &vm->page_directory); + NULL, &vm->page_directory); if (r) return r; diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index d9f5ce715c9b..372016e266d0 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -26,7 +26,6 @@ * Jerome Glisse */ #include <linux/firmware.h> -#include <linux/platform_device.h> #include <linux/slab.h> #include <drm/drmP.h> #include "radeon.h" diff --git a/drivers/gpu/drm/radeon/rv770_dma.c b/drivers/gpu/drm/radeon/rv770_dma.c index c112764adfdf..7f34bad2e724 100644 --- a/drivers/gpu/drm/radeon/rv770_dma.c +++ b/drivers/gpu/drm/radeon/rv770_dma.c @@ -67,7 +67,7 @@ struct radeon_fence *rv770_copy_dma(struct radeon_device *rdev, return ERR_PTR(r); } - radeon_semaphore_sync_resv(sem, resv, false); + radeon_semaphore_sync_resv(rdev, sem, resv, false); radeon_semaphore_sync_rings(rdev, sem, ring->idx); for (i = 0; i < num_loops; i++) { diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 6bce40847753..423a8cd052aa 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -4684,7 +4684,7 @@ static int si_vm_packet3_compute_check(struct radeon_device *rdev, int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) { int ret = 0; - u32 idx = 0; + u32 idx = 0, i; struct radeon_cs_packet pkt; do { @@ -4695,6 +4695,12 @@ int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) switch (pkt.type) { case RADEON_PACKET_TYPE0: dev_err(rdev->dev, "Packet0 not allowed!\n"); + for (i = 0; i < ib->length_dw; i++) { + if (i == idx) + printk("\t0x%08x <---\n", ib->ptr[i]); + else + printk("\t0x%08x\n", ib->ptr[i]); + } ret = -EINVAL; break; case RADEON_PACKET_TYPE2: diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c index 9b0dfbc913f3..b58f12b762d7 100644 --- a/drivers/gpu/drm/radeon/si_dma.c +++ b/drivers/gpu/drm/radeon/si_dma.c @@ -252,7 +252,7 @@ struct radeon_fence *si_copy_dma(struct radeon_device *rdev, return ERR_PTR(r); } - radeon_semaphore_sync_resv(sem, resv, false); + radeon_semaphore_sync_resv(rdev, sem, resv, false); radeon_semaphore_sync_rings(rdev, sem, ring->idx); for (i = 0; i < num_loops; i++) { diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 70e61ffeace2..9e4d5d7d348f 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2916,7 +2916,6 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, bool disable_sclk_switching = false; u32 mclk, sclk; u16 vddc, vddci; - u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; int i; if ((rdev->pm.dpm.new_active_crtc_count > 1) || @@ -2950,29 +2949,6 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, } } - /* limit clocks to max supported clocks based on voltage dependency tables */ - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk, - &max_sclk_vddc); - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk, - &max_mclk_vddci); - btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk, - &max_mclk_vddc); - - for (i = 0; i < ps->performance_level_count; i++) { - if (max_sclk_vddc) { - if (ps->performance_levels[i].sclk > max_sclk_vddc) - ps->performance_levels[i].sclk = max_sclk_vddc; - } - if (max_mclk_vddci) { - if (ps->performance_levels[i].mclk > max_mclk_vddci) - ps->performance_levels[i].mclk = max_mclk_vddci; - } - if (max_mclk_vddc) { - if (ps->performance_levels[i].mclk > max_mclk_vddc) - ps->performance_levels[i].mclk = max_mclk_vddc; - } - } - /* XXX validate the min clocks required for display */ if (disable_mclk_switching) { diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index fd414d34d885..6635da9ec986 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -736,7 +736,7 @@ # define DESCRIPTION16(x) (((x) & 0xff) << 0) # define DESCRIPTION17(x) (((x) & 0xff) << 8) -#define AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL 0x54 +#define AZ_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL 0x54 # define AUDIO_ENABLED (1 << 31) #define AZ_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 0x56 diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index 1b09d2182037..21aed1febeb4 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -40,7 +40,7 @@ static const struct file_operations savage_driver_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, - .mmap = drm_mmap, + .mmap = drm_legacy_mmap, .poll = drm_poll, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 54858e6fedaf..79bce76cb8f7 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -70,7 +70,7 @@ static const struct file_operations sis_driver_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, - .mmap = drm_mmap, + .mmap = drm_legacy_mmap, .poll = drm_poll, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index df533ff999a4..fab5ebcb0fef 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -36,6 +36,7 @@ #include "tdfx_drv.h" #include <drm/drm_pciids.h> +#include <drm/drm_legacy.h> static struct pci_device_id pciidlist[] = { tdfx_PCI_IDS @@ -46,7 +47,7 @@ static const struct file_operations tdfx_driver_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, - .mmap = drm_mmap, + .mmap = drm_legacy_mmap, .poll = drm_poll, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h index 43a25c853357..6538b56780c2 100644 --- a/drivers/gpu/drm/tegra/gem.h +++ b/drivers/gpu/drm/tegra/gem.h @@ -15,6 +15,7 @@ #include <drm/drm.h> #include <drm/drmP.h> +#include <drm/drm_gem.h> #define TEGRA_BO_BOTTOM_UP (1 << 0) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index a11969acfea5..8f5cec67c47d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1068,6 +1068,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev, struct file *persistent_swap_storage, size_t acc_size, struct sg_table *sg, + struct reservation_object *resv, void (*destroy) (struct ttm_buffer_object *)) { int ret = 0; @@ -1121,8 +1122,13 @@ int ttm_bo_init(struct ttm_bo_device *bdev, bo->persistent_swap_storage = persistent_swap_storage; bo->acc_size = acc_size; bo->sg = sg; - bo->resv = &bo->ttm_resv; - reservation_object_init(bo->resv); + if (resv) { + bo->resv = resv; + lockdep_assert_held(&bo->resv->lock.base); + } else { + bo->resv = &bo->ttm_resv; + reservation_object_init(&bo->ttm_resv); + } atomic_inc(&bo->glob->bo_count); drm_vma_node_reset(&bo->vma_node); @@ -1135,13 +1141,19 @@ int ttm_bo_init(struct ttm_bo_device *bdev, ret = drm_vma_offset_add(&bdev->vma_manager, &bo->vma_node, bo->mem.num_pages); - locked = ww_mutex_trylock(&bo->resv->lock); - WARN_ON(!locked); + /* passed reservation objects should already be locked, + * since otherwise lockdep will be angered in radeon. + */ + if (!resv) { + locked = ww_mutex_trylock(&bo->resv->lock); + WARN_ON(!locked); + } if (likely(!ret)) ret = ttm_bo_validate(bo, placement, interruptible, false); - ttm_bo_unreserve(bo); + if (!resv) + ttm_bo_unreserve(bo); if (unlikely(ret)) ttm_bo_unref(&bo); @@ -1199,7 +1211,7 @@ int ttm_bo_create(struct ttm_bo_device *bdev, acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object)); ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment, interruptible, persistent_swap_storage, acc_size, - NULL, NULL); + NULL, NULL, NULL); if (likely(ret == 0)) *p_bo = bo; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 824af90cbe31..882cccdad272 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -480,28 +480,24 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp) { + /* Cached mappings need no adjustment */ + if (caching_flags & TTM_PL_FLAG_CACHED) + return tmp; + #if defined(__i386__) || defined(__x86_64__) if (caching_flags & TTM_PL_FLAG_WC) tmp = pgprot_writecombine(tmp); else if (boot_cpu_data.x86 > 3) tmp = pgprot_noncached(tmp); - -#elif defined(__powerpc__) - if (!(caching_flags & TTM_PL_FLAG_CACHED)) { - pgprot_val(tmp) |= _PAGE_NO_CACHE; - if (caching_flags & TTM_PL_FLAG_UNCACHED) - pgprot_val(tmp) |= _PAGE_GUARDED; - } #endif -#if defined(__ia64__) || defined(__arm__) +#if defined(__ia64__) || defined(__arm__) || defined(__powerpc__) if (caching_flags & TTM_PL_FLAG_WC) tmp = pgprot_writecombine(tmp); else tmp = pgprot_noncached(tmp); #endif #if defined(__sparc__) || defined(__mips__) - if (!(caching_flags & TTM_PL_FLAG_CACHED)) - tmp = pgprot_noncached(tmp); + tmp = pgprot_noncached(tmp); #endif return tmp; } @@ -560,9 +556,7 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, * We need to use vmap to get the desired page protection * or to make the buffer object look contiguous. */ - prot = (mem->placement & TTM_PL_FLAG_CACHED) ? - PAGE_KERNEL : - ttm_io_prot(mem->placement, PAGE_KERNEL); + prot = ttm_io_prot(mem->placement, PAGE_KERNEL); map->bo_kmap_type = ttm_bo_map_vmap; map->virtual = vmap(ttm->pages + start_page, num_pages, 0, prot); diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index d05437f219e9..8fb7213277cc 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -197,9 +197,8 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) cvma.vm_page_prot); } else { ttm = bo->ttm; - if (!(bo->mem.placement & TTM_PL_FLAG_CACHED)) - cvma.vm_page_prot = ttm_io_prot(bo->mem.placement, - cvma.vm_page_prot); + cvma.vm_page_prot = ttm_io_prot(bo->mem.placement, + cvma.vm_page_prot); /* Allocate all page at once, most common usage */ if (ttm->bdev->driver->ttm_tt_populate(ttm)) { diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 51e10ee77f39..c7490a2489a7 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -15,6 +15,7 @@ #define UDL_DRV_H #include <linux/usb.h> +#include <drm/drm_gem.h> #define DRIVER_NAME "udl" #define DRIVER_DESC "DisplayLink" diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index d1da339843ca..8cbcb4589bd3 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -472,7 +472,8 @@ udl_framebuffer_init(struct drm_device *dev, static int udlfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { - struct udl_fbdev *ufbdev = (struct udl_fbdev *)helper; + struct udl_fbdev *ufbdev = + container_of(helper, struct udl_fbdev, helper); struct drm_device *dev = ufbdev->helper.dev; struct fb_info *info; struct device *device = dev->dev; diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index c16ffa63ded6..ed8aa8ff861a 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -62,7 +62,7 @@ static const struct file_operations via_driver_fops = { .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, - .mmap = drm_mmap, + .mmap = drm_legacy_mmap, .poll = drm_poll, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 26584316cb78..026de7cea0f6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -430,7 +430,7 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv, ret = ttm_bo_init(bdev, &vmw_bo->base, size, ttm_bo_type_device, placement, 0, interruptible, - NULL, acc_size, NULL, bo_free); + NULL, acc_size, NULL, NULL, bo_free); return ret; } |