mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 03:27:30 -04:00
Merge tag 'exynos-drm-next-for-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
New feature and cleanup for Exynos fbdev - Move fbdev emulation to DRM client buffers . Reuses standard ADDFB2/GEM paths and simplifies cleanup. - Use DRM format helpers for geometry and size . Applies 4CC-based format/pitch/size calculation with stronger checks and PAGE_SIZE alignment. . Sets screen_size and fix.smem_len from actual allocated size. Exynos DRM internal cleanup - Adopt DRM core DMA tracking and drop redundant code . Removes private DMA tracking, exynos_drm_gem_prime_import(), and obsolete iommu_dma_init_domain() stub. - Reduce duplication and tighten local scope . Replaces MAX_FB_BUFFER with DRM_FORMAT_MAX_PLANES. . Drops redundant exynos_drm_gem.size and internalizes local-only helpers. Bug fix for Exynos fbdev behavior - Fix screen_buffer offset handling . Keeps screen_buffer at framebuffer base and avoids applying scanout offset. . Includes Fixes and stable Cc for backporting. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Inki Dae <inki.dae@samsung.com> Link: https://patch.msgid.link/20260521143624.56906-1-inki.dae@samsung.com
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/exynos_drm.h>
|
||||
|
||||
@@ -23,10 +24,6 @@
|
||||
#define to_dma_iommu_mapping(dev) NULL
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_IOMMU_DMA)
|
||||
#define iommu_dma_init_domain(...) ({ -EINVAL; })
|
||||
#endif
|
||||
|
||||
#define EXYNOS_DEV_ADDR_START 0x20000000
|
||||
#define EXYNOS_DEV_ADDR_SIZE 0x40000000
|
||||
|
||||
@@ -45,7 +42,7 @@ static int drm_iommu_attach_device(struct drm_device *drm_dev,
|
||||
struct exynos_drm_private *priv = drm_dev->dev_private;
|
||||
int ret = 0;
|
||||
|
||||
if (get_dma_ops(priv->dma_dev) != get_dma_ops(subdrv_dev)) {
|
||||
if (get_dma_ops(drm_dev_dma_dev(drm_dev)) != get_dma_ops(subdrv_dev)) {
|
||||
DRM_DEV_ERROR(subdrv_dev, "Device %s lacks support for IOMMU\n",
|
||||
dev_name(subdrv_dev));
|
||||
return -EINVAL;
|
||||
@@ -97,8 +94,8 @@ int exynos_drm_register_dma(struct drm_device *drm, struct device *dev,
|
||||
{
|
||||
struct exynos_drm_private *priv = drm->dev_private;
|
||||
|
||||
if (!priv->dma_dev) {
|
||||
priv->dma_dev = dev;
|
||||
if (drm_dev_dma_dev(drm) == drm->dev) {
|
||||
drm_dev_set_dma_dev(drm, dev);
|
||||
DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n",
|
||||
dev_name(dev));
|
||||
}
|
||||
@@ -113,7 +110,7 @@ int exynos_drm_register_dma(struct drm_device *drm, struct device *dev,
|
||||
mapping = arm_iommu_create_mapping(dev,
|
||||
EXYNOS_DEV_ADDR_START, EXYNOS_DEV_ADDR_SIZE);
|
||||
else if (IS_ENABLED(CONFIG_IOMMU_DMA))
|
||||
mapping = iommu_get_domain_for_dev(priv->dma_dev);
|
||||
mapping = iommu_get_domain_for_dev(dev);
|
||||
|
||||
if (!mapping)
|
||||
return -ENODEV;
|
||||
@@ -139,5 +136,5 @@ void exynos_drm_cleanup_dma(struct drm_device *drm)
|
||||
|
||||
arm_iommu_release_mapping(priv->mapping);
|
||||
priv->mapping = NULL;
|
||||
priv->dma_dev = NULL;
|
||||
drm_dev_set_dma_dev(drm, NULL);
|
||||
}
|
||||
|
||||
@@ -109,7 +109,6 @@ static const struct drm_driver exynos_drm_driver = {
|
||||
.open = exynos_drm_open,
|
||||
.postclose = exynos_drm_postclose,
|
||||
.dumb_create = exynos_drm_gem_dumb_create,
|
||||
.gem_prime_import = exynos_drm_gem_prime_import,
|
||||
.gem_prime_import_sg_table = exynos_drm_gem_prime_import_sg_table,
|
||||
EXYNOS_DRM_FBDEV_DRIVER_OPS,
|
||||
.ioctls = exynos_ioctls,
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#define MAX_CRTC 3
|
||||
#define MAX_PLANE 5
|
||||
#define MAX_FB_BUFFER 4
|
||||
|
||||
#define DEFAULT_WIN 0
|
||||
|
||||
@@ -198,7 +197,6 @@ struct drm_exynos_file_private {
|
||||
*/
|
||||
struct exynos_drm_private {
|
||||
struct device *g2d_dev;
|
||||
struct device *dma_dev;
|
||||
struct device *vidi_dev;
|
||||
void *mapping;
|
||||
|
||||
@@ -208,13 +206,6 @@ struct exynos_drm_private {
|
||||
wait_queue_head_t wait;
|
||||
};
|
||||
|
||||
static inline struct device *to_dma_dev(struct drm_device *dev)
|
||||
{
|
||||
struct exynos_drm_private *priv = dev->dev_private;
|
||||
|
||||
return priv->dma_dev;
|
||||
}
|
||||
|
||||
static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
|
||||
{
|
||||
struct exynos_drm_private *priv = drm_dev->dev_private;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "exynos_drm_drv.h"
|
||||
#include "exynos_drm_fb.h"
|
||||
#include "exynos_drm_fbdev.h"
|
||||
#include "exynos_drm_gem.h"
|
||||
|
||||
static int check_fb_gem_memory_type(struct drm_device *drm_dev,
|
||||
struct exynos_drm_gem *exynos_gem)
|
||||
@@ -55,7 +56,7 @@ static const struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
|
||||
.create_handle = drm_gem_fb_create_handle,
|
||||
};
|
||||
|
||||
struct drm_framebuffer *
|
||||
static struct drm_framebuffer *
|
||||
exynos_drm_framebuffer_init(struct drm_device *dev,
|
||||
const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
@@ -99,7 +100,7 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
|
||||
const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
|
||||
struct exynos_drm_gem *exynos_gem[DRM_FORMAT_MAX_PLANES];
|
||||
struct drm_framebuffer *fb;
|
||||
int i;
|
||||
int ret;
|
||||
@@ -119,7 +120,7 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (size > exynos_gem[i]->size) {
|
||||
if (size > exynos_gem[i]->base.size) {
|
||||
i++;
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
@@ -145,7 +146,7 @@ dma_addr_t exynos_drm_fb_dma_addr(struct drm_framebuffer *fb, int index)
|
||||
{
|
||||
struct exynos_drm_gem *exynos_gem;
|
||||
|
||||
if (WARN_ON_ONCE(index >= MAX_FB_BUFFER))
|
||||
if (WARN_ON_ONCE(index >= DRM_FORMAT_MAX_PLANES))
|
||||
return 0;
|
||||
|
||||
exynos_gem = to_exynos_gem(fb->obj[index]);
|
||||
|
||||
@@ -10,14 +10,10 @@
|
||||
#ifndef _EXYNOS_DRM_FB_H_
|
||||
#define _EXYNOS_DRM_FB_H_
|
||||
|
||||
#include "exynos_drm_gem.h"
|
||||
#include <linux/types.h>
|
||||
|
||||
struct drm_framebuffer *
|
||||
exynos_drm_framebuffer_init(struct drm_device *dev,
|
||||
const struct drm_format_info *info,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct exynos_drm_gem **exynos_gem,
|
||||
int count);
|
||||
struct drm_device;
|
||||
struct drm_framebuffer;
|
||||
|
||||
dma_addr_t exynos_drm_fb_dma_addr(struct drm_framebuffer *fb, int index);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "exynos_drm_drv.h"
|
||||
#include "exynos_drm_fb.h"
|
||||
#include "exynos_drm_fbdev.h"
|
||||
#include "exynos_drm_gem.h"
|
||||
|
||||
#define MAX_CONNECTOR 4
|
||||
|
||||
@@ -36,12 +37,10 @@ static int exynos_drm_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||
static void exynos_drm_fb_destroy(struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
|
||||
drm_fb_helper_fini(fb_helper);
|
||||
|
||||
drm_framebuffer_remove(fb);
|
||||
|
||||
drm_client_buffer_delete(fb_helper->buffer);
|
||||
drm_client_release(&fb_helper->client);
|
||||
}
|
||||
|
||||
@@ -54,40 +53,23 @@ static const struct fb_ops exynos_drm_fb_ops = {
|
||||
.fb_destroy = exynos_drm_fb_destroy,
|
||||
};
|
||||
|
||||
static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes,
|
||||
struct exynos_drm_gem *exynos_gem)
|
||||
{
|
||||
struct fb_info *fbi = helper->info;
|
||||
struct drm_framebuffer *fb = helper->fb;
|
||||
unsigned int size = fb->width * fb->height * fb->format->cpp[0];
|
||||
unsigned long offset;
|
||||
|
||||
fbi->fbops = &exynos_drm_fb_ops;
|
||||
|
||||
drm_fb_helper_fill_info(fbi, helper, sizes);
|
||||
|
||||
offset = fbi->var.xoffset * fb->format->cpp[0];
|
||||
offset += fbi->var.yoffset * fb->pitches[0];
|
||||
|
||||
fbi->flags |= FBINFO_VIRTFB;
|
||||
fbi->screen_buffer = exynos_gem->kvaddr + offset;
|
||||
fbi->screen_size = size;
|
||||
fbi->fix.smem_len = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_fb_helper_funcs exynos_drm_fbdev_helper_funcs = {
|
||||
};
|
||||
|
||||
int exynos_drm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct drm_client_dev *client = &helper->client;
|
||||
struct drm_device *dev = client->dev;
|
||||
struct drm_file *file = client->file;
|
||||
struct fb_info *info = helper->info;
|
||||
u32 fourcc, pitch;
|
||||
u64 size;
|
||||
const struct drm_format_info *format;
|
||||
struct exynos_drm_gem *exynos_gem;
|
||||
struct drm_device *dev = helper->dev;
|
||||
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
|
||||
unsigned long size;
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_client_buffer *buffer;
|
||||
u32 handle;
|
||||
int ret;
|
||||
|
||||
DRM_DEV_DEBUG_KMS(dev->dev,
|
||||
@@ -95,40 +77,61 @@ int exynos_drm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
||||
sizes->surface_width, sizes->surface_height,
|
||||
sizes->surface_bpp);
|
||||
|
||||
mode_cmd.width = sizes->surface_width;
|
||||
mode_cmd.height = sizes->surface_height;
|
||||
mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3);
|
||||
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
|
||||
sizes->surface_depth);
|
||||
|
||||
size = mode_cmd.pitches[0] * mode_cmd.height;
|
||||
fourcc = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
|
||||
if (fourcc == DRM_FORMAT_INVALID)
|
||||
return -EINVAL;
|
||||
format = drm_get_format_info(dev, fourcc, DRM_FORMAT_MOD_LINEAR);
|
||||
if (!format)
|
||||
return -EINVAL;
|
||||
pitch = drm_format_info_min_pitch(format, 0, sizes->surface_width);
|
||||
if (!pitch)
|
||||
return -EINVAL;
|
||||
if (check_mul_overflow(pitch, sizes->surface_height, &size))
|
||||
return -EINVAL;
|
||||
size = ALIGN(size, PAGE_SIZE);
|
||||
if (size < PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
exynos_gem = exynos_drm_gem_create(dev, EXYNOS_BO_WC, size, true);
|
||||
if (IS_ERR(exynos_gem))
|
||||
return PTR_ERR(exynos_gem);
|
||||
obj = &exynos_gem->base;
|
||||
|
||||
helper->fb =
|
||||
exynos_drm_framebuffer_init(dev,
|
||||
drm_get_format_info(dev, mode_cmd.pixel_format,
|
||||
mode_cmd.modifier[0]),
|
||||
&mode_cmd, &exynos_gem, 1);
|
||||
if (IS_ERR(helper->fb)) {
|
||||
DRM_DEV_ERROR(dev->dev, "failed to create drm framebuffer.\n");
|
||||
ret = PTR_ERR(helper->fb);
|
||||
goto err_destroy_gem;
|
||||
ret = drm_gem_handle_create(file, obj, &handle);
|
||||
if (ret)
|
||||
goto err_drm_gem_object_put;
|
||||
|
||||
buffer = drm_client_buffer_create(client, sizes->surface_width, sizes->surface_height,
|
||||
fourcc, handle, pitch);
|
||||
if (IS_ERR(buffer)) {
|
||||
ret = PTR_ERR(buffer);
|
||||
goto err_drm_gem_handle_delete;
|
||||
}
|
||||
helper->funcs = &exynos_drm_fbdev_helper_funcs;
|
||||
|
||||
ret = exynos_drm_fbdev_update(helper, sizes, exynos_gem);
|
||||
if (ret < 0)
|
||||
goto err_destroy_framebuffer;
|
||||
helper->funcs = &exynos_drm_fbdev_helper_funcs;
|
||||
helper->buffer = buffer;
|
||||
helper->fb = buffer->fb;
|
||||
|
||||
info->fbops = &exynos_drm_fb_ops;
|
||||
|
||||
drm_fb_helper_fill_info(info, helper, sizes);
|
||||
|
||||
info->flags |= FBINFO_VIRTFB;
|
||||
info->screen_buffer = exynos_gem->kvaddr;
|
||||
info->screen_size = obj->size;
|
||||
info->fix.smem_len = obj->size;
|
||||
|
||||
/* The handle is only needed for creating the framebuffer. */
|
||||
drm_gem_handle_delete(file, handle);
|
||||
|
||||
/* The framebuffer still holds a reference on the GEM object. */
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_framebuffer:
|
||||
drm_framebuffer_cleanup(helper->fb);
|
||||
helper->fb = NULL;
|
||||
err_destroy_gem:
|
||||
exynos_drm_gem_destroy(exynos_gem);
|
||||
err_drm_gem_handle_delete:
|
||||
drm_gem_handle_delete(file, handle);
|
||||
err_drm_gem_object_put:
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/exynos_drm.h>
|
||||
@@ -278,7 +279,7 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
|
||||
|
||||
g2d->cmdlist_dma_attrs = DMA_ATTR_WRITE_COMBINE;
|
||||
|
||||
g2d->cmdlist_pool_virt = dma_alloc_attrs(to_dma_dev(g2d->drm_dev),
|
||||
g2d->cmdlist_pool_virt = dma_alloc_attrs(drm_dev_dma_dev(g2d->drm_dev),
|
||||
G2D_CMDLIST_POOL_SIZE,
|
||||
&g2d->cmdlist_pool, GFP_KERNEL,
|
||||
g2d->cmdlist_dma_attrs);
|
||||
@@ -311,7 +312,7 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dma_free_attrs(to_dma_dev(g2d->drm_dev), G2D_CMDLIST_POOL_SIZE,
|
||||
dma_free_attrs(drm_dev_dma_dev(g2d->drm_dev), G2D_CMDLIST_POOL_SIZE,
|
||||
g2d->cmdlist_pool_virt,
|
||||
g2d->cmdlist_pool, g2d->cmdlist_dma_attrs);
|
||||
return ret;
|
||||
@@ -322,7 +323,7 @@ static void g2d_fini_cmdlist(struct g2d_data *g2d)
|
||||
kfree(g2d->cmdlist_node);
|
||||
|
||||
if (g2d->cmdlist_pool_virt && g2d->cmdlist_pool) {
|
||||
dma_free_attrs(to_dma_dev(g2d->drm_dev),
|
||||
dma_free_attrs(drm_dev_dma_dev(g2d->drm_dev),
|
||||
G2D_CMDLIST_POOL_SIZE,
|
||||
g2d->cmdlist_pool_virt,
|
||||
g2d->cmdlist_pool, g2d->cmdlist_dma_attrs);
|
||||
@@ -397,7 +398,7 @@ static void g2d_userptr_put_dma_addr(struct g2d_data *g2d,
|
||||
return;
|
||||
|
||||
out:
|
||||
dma_unmap_sgtable(to_dma_dev(g2d->drm_dev), g2d_userptr->sgt,
|
||||
dma_unmap_sgtable(drm_dev_dma_dev(g2d->drm_dev), g2d_userptr->sgt,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
|
||||
unpin_user_pages_dirty_lock(g2d_userptr->pages, g2d_userptr->npages,
|
||||
@@ -506,7 +507,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct g2d_data *g2d,
|
||||
|
||||
g2d_userptr->sgt = sgt;
|
||||
|
||||
ret = dma_map_sgtable(to_dma_dev(g2d->drm_dev), sgt,
|
||||
ret = dma_map_sgtable(drm_dev_dma_dev(g2d->drm_dev), sgt,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(g2d->dev, "failed to map sgt with dma region.\n");
|
||||
@@ -719,7 +720,7 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
|
||||
}
|
||||
|
||||
if (!g2d_check_buf_desc_is_valid(g2d, buf_desc,
|
||||
reg_type, exynos_gem->size)) {
|
||||
reg_type, exynos_gem->base.size)) {
|
||||
exynos_drm_gem_put(exynos_gem);
|
||||
ret = -EFAULT;
|
||||
goto err;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/shmem_fs.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_dumb_buffers.h>
|
||||
#include <drm/drm_prime.h>
|
||||
#include <drm/drm_print.h>
|
||||
@@ -29,7 +30,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem, bool kvmap)
|
||||
unsigned long attr = 0;
|
||||
|
||||
if (exynos_gem->dma_addr) {
|
||||
DRM_DEV_DEBUG_KMS(to_dma_dev(dev), "already allocated.\n");
|
||||
DRM_DEV_DEBUG_KMS(drm_dev_dma_dev(dev), "already allocated.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -54,19 +55,19 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem, bool kvmap)
|
||||
attr |= DMA_ATTR_NO_KERNEL_MAPPING;
|
||||
|
||||
exynos_gem->dma_attrs = attr;
|
||||
exynos_gem->cookie = dma_alloc_attrs(to_dma_dev(dev), exynos_gem->size,
|
||||
exynos_gem->cookie = dma_alloc_attrs(drm_dev_dma_dev(dev), exynos_gem->base.size,
|
||||
&exynos_gem->dma_addr, GFP_KERNEL,
|
||||
exynos_gem->dma_attrs);
|
||||
if (!exynos_gem->cookie) {
|
||||
DRM_DEV_ERROR(to_dma_dev(dev), "failed to allocate buffer.\n");
|
||||
DRM_DEV_ERROR(drm_dev_dma_dev(dev), "failed to allocate buffer.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (kvmap)
|
||||
exynos_gem->kvaddr = exynos_gem->cookie;
|
||||
|
||||
DRM_DEV_DEBUG_KMS(to_dma_dev(dev), "dma_addr(0x%lx), size(0x%lx)\n",
|
||||
(unsigned long)exynos_gem->dma_addr, exynos_gem->size);
|
||||
DRM_DEV_DEBUG_KMS(drm_dev_dma_dev(dev), "dma_addr(0x%lx), size(0x%lx)\n",
|
||||
(unsigned long)exynos_gem->dma_addr, exynos_gem->base.size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -80,9 +81,9 @@ static void exynos_drm_free_buf(struct exynos_drm_gem *exynos_gem)
|
||||
}
|
||||
|
||||
DRM_DEV_DEBUG_KMS(dev->dev, "dma_addr(0x%lx), size(0x%lx)\n",
|
||||
(unsigned long)exynos_gem->dma_addr, exynos_gem->size);
|
||||
(unsigned long)exynos_gem->dma_addr, exynos_gem->base.size);
|
||||
|
||||
dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie,
|
||||
dma_free_attrs(drm_dev_dma_dev(dev), exynos_gem->base.size, exynos_gem->cookie,
|
||||
(dma_addr_t)exynos_gem->dma_addr,
|
||||
exynos_gem->dma_attrs);
|
||||
}
|
||||
@@ -101,7 +102,7 @@ static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
DRM_DEV_DEBUG_KMS(to_dma_dev(obj->dev), "gem handle = 0x%x\n", *handle);
|
||||
DRM_DEV_DEBUG_KMS(drm_dev_dma_dev(obj->dev), "gem handle = 0x%x\n", *handle);
|
||||
|
||||
/* drop reference from allocate - handle holds it now. */
|
||||
drm_gem_object_put(obj);
|
||||
@@ -113,7 +114,7 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem *exynos_gem)
|
||||
{
|
||||
struct drm_gem_object *obj = &exynos_gem->base;
|
||||
|
||||
DRM_DEV_DEBUG_KMS(to_dma_dev(obj->dev), "handle count = %d\n",
|
||||
DRM_DEV_DEBUG_KMS(drm_dev_dma_dev(obj->dev), "handle count = %d\n",
|
||||
obj->handle_count);
|
||||
|
||||
/*
|
||||
@@ -133,6 +134,11 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem *exynos_gem)
|
||||
kfree(exynos_gem);
|
||||
}
|
||||
|
||||
static void exynos_drm_gem_free_object(struct drm_gem_object *obj)
|
||||
{
|
||||
exynos_drm_gem_destroy(to_exynos_gem(obj));
|
||||
}
|
||||
|
||||
static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
|
||||
.open = drm_gem_vm_open,
|
||||
.close = drm_gem_vm_close,
|
||||
@@ -156,7 +162,6 @@ static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
|
||||
if (!exynos_gem)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
exynos_gem->size = size;
|
||||
obj = &exynos_gem->base;
|
||||
|
||||
obj->funcs = &exynos_drm_gem_object_funcs;
|
||||
@@ -281,11 +286,11 @@ static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
|
||||
vm_size = vma->vm_end - vma->vm_start;
|
||||
|
||||
/* check if user-requested size is valid. */
|
||||
if (vm_size > exynos_gem->size)
|
||||
if (vm_size > exynos_gem->base.size)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dma_mmap_attrs(to_dma_dev(drm_dev), vma, exynos_gem->cookie,
|
||||
exynos_gem->dma_addr, exynos_gem->size,
|
||||
ret = dma_mmap_attrs(drm_dev_dma_dev(drm_dev), vma, exynos_gem->cookie,
|
||||
exynos_gem->dma_addr, exynos_gem->base.size,
|
||||
exynos_gem->dma_attrs);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to mmap.\n");
|
||||
@@ -311,18 +316,13 @@ int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
|
||||
exynos_gem = to_exynos_gem(obj);
|
||||
|
||||
args->flags = exynos_gem->flags;
|
||||
args->size = exynos_gem->size;
|
||||
args->size = obj->size;
|
||||
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void exynos_drm_gem_free_object(struct drm_gem_object *obj)
|
||||
{
|
||||
exynos_drm_gem_destroy(to_exynos_gem(obj));
|
||||
}
|
||||
|
||||
int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
|
||||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
@@ -372,7 +372,7 @@ static int exynos_drm_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct
|
||||
|
||||
vm_flags_set(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP);
|
||||
|
||||
DRM_DEV_DEBUG_KMS(to_dma_dev(obj->dev), "flags = 0x%x\n",
|
||||
DRM_DEV_DEBUG_KMS(drm_dev_dma_dev(obj->dev), "flags = 0x%x\n",
|
||||
exynos_gem->flags);
|
||||
|
||||
/* non-cachable as default. */
|
||||
@@ -398,12 +398,6 @@ static int exynos_drm_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct
|
||||
}
|
||||
|
||||
/* low-level interface prime helpers */
|
||||
struct drm_gem_object *exynos_drm_gem_prime_import(struct drm_device *dev,
|
||||
struct dma_buf *dma_buf)
|
||||
{
|
||||
return drm_gem_prime_import_dev(dev, dma_buf, to_dma_dev(dev));
|
||||
}
|
||||
|
||||
struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj)
|
||||
{
|
||||
struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
|
||||
@@ -415,8 +409,8 @@ struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj)
|
||||
if (!sgt)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = dma_get_sgtable_attrs(to_dma_dev(drm_dev), sgt, exynos_gem->cookie,
|
||||
exynos_gem->dma_addr, exynos_gem->size,
|
||||
ret = dma_get_sgtable_attrs(drm_dev_dma_dev(drm_dev), sgt, exynos_gem->cookie,
|
||||
exynos_gem->dma_addr, obj->size,
|
||||
exynos_gem->dma_attrs);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to get sgtable, %d\n", ret);
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
* - a new handle to this gem object would be created
|
||||
* by drm_gem_handle_create().
|
||||
* @flags: indicate memory type to allocated buffer and cache attruibute.
|
||||
* @size: size requested from user, in bytes and this size is aligned
|
||||
* in page unit.
|
||||
* @cookie: cookie returned by dma_alloc_attrs
|
||||
* @kvaddr: kernel virtual address to allocated memory region (for fbdev)
|
||||
* @dma_addr: bus address(accessed by dma) to allocated memory region.
|
||||
@@ -38,7 +36,6 @@
|
||||
struct exynos_drm_gem {
|
||||
struct drm_gem_object base;
|
||||
unsigned int flags;
|
||||
unsigned long size;
|
||||
void *cookie;
|
||||
void *kvaddr;
|
||||
dma_addr_t dma_addr;
|
||||
@@ -88,17 +85,12 @@ static inline void exynos_drm_gem_put(struct exynos_drm_gem *exynos_gem)
|
||||
int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
/* free gem object. */
|
||||
void exynos_drm_gem_free_object(struct drm_gem_object *obj);
|
||||
|
||||
/* create memory region for drm framebuffer. */
|
||||
int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
|
||||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args);
|
||||
|
||||
/* low-level interface prime helpers */
|
||||
struct drm_gem_object *exynos_drm_gem_prime_import(struct drm_device *dev,
|
||||
struct dma_buf *dma_buf);
|
||||
struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj);
|
||||
struct drm_gem_object *
|
||||
exynos_drm_gem_prime_import_sg_table(struct drm_device *dev,
|
||||
|
||||
@@ -364,7 +364,7 @@ static int exynos_drm_ipp_task_setup_buffer(struct exynos_drm_ipp_buffer *buf,
|
||||
}
|
||||
buf->exynos_gem[i] = gem;
|
||||
|
||||
if (size + buf->buf.offset[i] > buf->exynos_gem[i]->size) {
|
||||
if (size + buf->buf.offset[i] > buf->exynos_gem[i]->base.size) {
|
||||
i++;
|
||||
ret = -EINVAL;
|
||||
goto gem_free;
|
||||
|
||||
@@ -70,9 +70,9 @@ struct exynos_drm_ipp_buffer {
|
||||
struct drm_exynos_ipp_task_buffer buf;
|
||||
struct drm_exynos_ipp_task_rect rect;
|
||||
|
||||
struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
|
||||
struct exynos_drm_gem *exynos_gem[DRM_FORMAT_MAX_PLANES];
|
||||
const struct drm_format_info *format;
|
||||
dma_addr_t dma_addr[MAX_FB_BUFFER];
|
||||
dma_addr_t dma_addr[DRM_FORMAT_MAX_PLANES];
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user