Skip to content

Commit

Permalink
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/daeinki/drm-exynos into drm-next

Inki writes:
"- add dmabuf attach/detach feature
  . This patch would resolve performance deterioration issue
    when v4l2-based driver is using the buffer imported from gem.
- drm/exynos: use DMA_ATTR_NO_KERNEL_MAPPING attribute
  . With gem allocation, kernel space mapping isn't allocated and
    also physical pages aren't mapped with the kernel space.
    The physical pages are mapped with kernel space though vmap
    function only for console framebuffer.
- add the below two patches I missed.
  drm: exynos: moved exynos drm device registration to drm driver
  drm: exynos: moved exynos drm hdmi device registration to drm driver
- add IPP subsystem framework and its-based device drivers.
  . This patch set includes fimc, rotator and gsc drivers to perform
    image scaling, rotation and color space conversion.
- add runtime pm support to hdmi driver.
- And fixups and cleanups."

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (30 commits)
  drm/exynos: add gsc ipp driver
  drm/exynos: add rotator ipp driver
  drm/exynos: add fimc ipp driver
  drm/exynos: add iommu support for ipp
  drm/exynos: add ipp subsystem
  drm/exynos: support device tree for fimd
  drm/exynos: support extended screen coordinate of fimd
  drm/exynos: fix x, y coordinates for right bottom pixel
  drm/exynos: fix fb offset calculation for plane
  drm/exynos: hdmi: Fix potential NULL pointer dereference error
  drm/exynos: hdmi: Add CONFIG_OF and use of_match_ptr() macro
  drm/exynos: add support for hdmiphy power control for exynos5
  drm/exynos: add runtime pm support for mixer
  drm/exynos: added runtime pm support for hdmi
  drm/exynos: fix allocation and cache mapping type
  drm/exynos: reorder framebuffer init sequence
  drm/exynos/iommu: fix return value check in drm_create_iommu_mapping()
  drm/exynos: remove unused vaddr member
  drm/exynos: use DMA_ATTR_NO_KERNEL_MAPPING attribute
  drm/exynos: add exception codes to exynos_drm_fbdev_create()
  ...
  • Loading branch information
airlied committed Dec 16, 2012
2 parents 652a187 + f264638 commit 2f3f240
Show file tree
Hide file tree
Showing 35 changed files with 9,158 additions and 264 deletions.
24 changes: 24 additions & 0 deletions drivers/gpu/drm/exynos/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,27 @@ config DRM_EXYNOS_G2D
depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D
help
Choose this option if you want to use Exynos G2D for DRM.

config DRM_EXYNOS_IPP
bool "Exynos DRM IPP"
depends on DRM_EXYNOS
help
Choose this option if you want to use IPP feature for DRM.

config DRM_EXYNOS_FIMC
bool "Exynos DRM FIMC"
depends on DRM_EXYNOS_IPP
help
Choose this option if you want to use Exynos FIMC for DRM.

config DRM_EXYNOS_ROTATOR
bool "Exynos DRM Rotator"
depends on DRM_EXYNOS_IPP
help
Choose this option if you want to use Exynos Rotator for DRM.

config DRM_EXYNOS_GSC
bool "Exynos DRM GSC"
depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5
help
Choose this option if you want to use Exynos GSC for DRM.
4 changes: 4 additions & 0 deletions drivers/gpu/drm/exynos/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,9 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o \
exynos_drm_hdmi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o
exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o
exynosdrm-$(CONFIG_DRM_EXYNOS_FIMC) += exynos_drm_fimc.o
exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR) += exynos_drm_rotator.o
exynosdrm-$(CONFIG_DRM_EXYNOS_GSC) += exynos_drm_gsc.o

obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o
4 changes: 3 additions & 1 deletion drivers/gpu/drm/exynos/exynos_ddc.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,21 @@ static struct i2c_device_id ddc_idtable[] = {
{ },
};

#ifdef CONFIG_OF
static struct of_device_id hdmiddc_match_types[] = {
{
.compatible = "samsung,exynos5-hdmiddc",
}, {
/* end node */
}
};
#endif

struct i2c_driver ddc_driver = {
.driver = {
.name = "exynos-hdmiddc",
.owner = THIS_MODULE,
.of_match_table = hdmiddc_match_types,
.of_match_table = of_match_ptr(hdmiddc_match_types),
},
.id_table = ddc_idtable,
.probe = s5p_ddc_probe,
Expand Down
49 changes: 27 additions & 22 deletions drivers/gpu/drm/exynos/exynos_drm_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
unsigned int flags, struct exynos_drm_gem_buf *buf)
{
int ret = 0;
enum dma_attr attr = DMA_ATTR_FORCE_CONTIGUOUS;
enum dma_attr attr;
unsigned int nr_pages;

DRM_DEBUG_KMS("%s\n", __FILE__);

Expand All @@ -45,44 +46,49 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,

init_dma_attrs(&buf->dma_attrs);

if (flags & EXYNOS_BO_NONCONTIG)
/*
* if EXYNOS_BO_CONTIG, fully physically contiguous memory
* region will be allocated else physically contiguous
* as possible.
*/
if (flags & EXYNOS_BO_CONTIG)
dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &buf->dma_attrs);

/*
* if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping
* else cachable mapping.
*/
if (flags & EXYNOS_BO_WC || !(flags & EXYNOS_BO_CACHABLE))
attr = DMA_ATTR_WRITE_COMBINE;
else
attr = DMA_ATTR_NON_CONSISTENT;

dma_set_attr(attr, &buf->dma_attrs);
dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);

buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size,
buf->pages = dma_alloc_attrs(dev->dev, buf->size,
&buf->dma_addr, GFP_KERNEL, &buf->dma_attrs);
if (!buf->kvaddr) {
if (!buf->pages) {
DRM_ERROR("failed to allocate buffer.\n");
return -ENOMEM;
}

buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
nr_pages = buf->size >> PAGE_SHIFT;
buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages);
if (!buf->sgt) {
DRM_ERROR("failed to allocate sg table.\n");
DRM_ERROR("failed to get sg table.\n");
ret = -ENOMEM;
goto err_free_attrs;
}

ret = dma_get_sgtable(dev->dev, buf->sgt, buf->kvaddr, buf->dma_addr,
buf->size);
if (ret < 0) {
DRM_ERROR("failed to get sgtable.\n");
goto err_free_sgt;
}

DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
(unsigned long)buf->kvaddr,
DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
(unsigned long)buf->dma_addr,
buf->size);

return ret;

err_free_sgt:
kfree(buf->sgt);
buf->sgt = NULL;
err_free_attrs:
dma_free_attrs(dev->dev, buf->size, buf->kvaddr,
dma_free_attrs(dev->dev, buf->size, buf->pages,
(dma_addr_t)buf->dma_addr, &buf->dma_attrs);
buf->dma_addr = (dma_addr_t)NULL;

Expand All @@ -99,8 +105,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
return;
}

DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
(unsigned long)buf->kvaddr,
DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
(unsigned long)buf->dma_addr,
buf->size);

Expand All @@ -109,7 +114,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
kfree(buf->sgt);
buf->sgt = NULL;

dma_free_attrs(dev->dev, buf->size, buf->kvaddr,
dma_free_attrs(dev->dev, buf->size, buf->pages,
(dma_addr_t)buf->dma_addr, &buf->dma_attrs);
buf->dma_addr = (dma_addr_t)NULL;
}
Expand Down
104 changes: 73 additions & 31 deletions drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,63 +30,107 @@

#include <linux/dma-buf.h>

static struct sg_table *exynos_get_sgt(struct drm_device *drm_dev,
struct exynos_drm_gem_buf *buf)
struct exynos_drm_dmabuf_attachment {
struct sg_table sgt;
enum dma_data_direction dir;
};

static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf,
struct device *dev,
struct dma_buf_attachment *attach)
{
struct sg_table *sgt = NULL;
int ret;
struct exynos_drm_dmabuf_attachment *exynos_attach;

sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
if (!sgt)
goto out;
exynos_attach = kzalloc(sizeof(*exynos_attach), GFP_KERNEL);
if (!exynos_attach)
return -ENOMEM;

ret = dma_get_sgtable(drm_dev->dev, sgt, buf->kvaddr,
buf->dma_addr, buf->size);
if (ret < 0) {
DRM_ERROR("failed to get sgtable.\n");
goto err_free_sgt;
}
exynos_attach->dir = DMA_NONE;
attach->priv = exynos_attach;

return sgt;
return 0;
}

err_free_sgt:
kfree(sgt);
sgt = NULL;
out:
return NULL;
static void exynos_gem_detach_dma_buf(struct dma_buf *dmabuf,
struct dma_buf_attachment *attach)
{
struct exynos_drm_dmabuf_attachment *exynos_attach = attach->priv;
struct sg_table *sgt;

if (!exynos_attach)
return;

sgt = &exynos_attach->sgt;

if (exynos_attach->dir != DMA_NONE)
dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents,
exynos_attach->dir);

sg_free_table(sgt);
kfree(exynos_attach);
attach->priv = NULL;
}

static struct sg_table *
exynos_gem_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
{
struct exynos_drm_dmabuf_attachment *exynos_attach = attach->priv;
struct exynos_drm_gem_obj *gem_obj = attach->dmabuf->priv;
struct drm_device *dev = gem_obj->base.dev;
struct exynos_drm_gem_buf *buf;
struct scatterlist *rd, *wr;
struct sg_table *sgt = NULL;
int nents;
unsigned int i;
int nents, ret;

DRM_DEBUG_PRIME("%s\n", __FILE__);

if (WARN_ON(dir == DMA_NONE))
return ERR_PTR(-EINVAL);

/* just return current sgt if already requested. */
if (exynos_attach->dir == dir)
return &exynos_attach->sgt;

/* reattaching is not allowed. */
if (WARN_ON(exynos_attach->dir != DMA_NONE))
return ERR_PTR(-EBUSY);

buf = gem_obj->buffer;
if (!buf) {
DRM_ERROR("buffer is null.\n");
return sgt;
return ERR_PTR(-ENOMEM);
}

sgt = &exynos_attach->sgt;

ret = sg_alloc_table(sgt, buf->sgt->orig_nents, GFP_KERNEL);
if (ret) {
DRM_ERROR("failed to alloc sgt.\n");
return ERR_PTR(-ENOMEM);
}

mutex_lock(&dev->struct_mutex);

sgt = exynos_get_sgt(dev, buf);
if (!sgt)
goto err_unlock;
rd = buf->sgt->sgl;
wr = sgt->sgl;
for (i = 0; i < sgt->orig_nents; ++i) {
sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
rd = sg_next(rd);
wr = sg_next(wr);
}

nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir);
nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
if (!nents) {
DRM_ERROR("failed to map sgl with iommu.\n");
sgt = NULL;
sgt = ERR_PTR(-EIO);
goto err_unlock;
}

exynos_attach->dir = dir;
attach->priv = exynos_attach;

DRM_DEBUG_PRIME("buffer size = 0x%lx\n", buf->size);

err_unlock:
Expand All @@ -98,11 +142,7 @@ static void exynos_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
struct sg_table *sgt,
enum dma_data_direction dir)
{
dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);

sg_free_table(sgt);
kfree(sgt);
sgt = NULL;
/* Nothing to do. */
}

static void exynos_dmabuf_release(struct dma_buf *dmabuf)
Expand Down Expand Up @@ -164,6 +204,8 @@ static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf,
}

static struct dma_buf_ops exynos_dmabuf_ops = {
.attach = exynos_gem_attach_dma_buf,
.detach = exynos_gem_detach_dma_buf,
.map_dma_buf = exynos_gem_map_dma_buf,
.unmap_dma_buf = exynos_gem_unmap_dma_buf,
.kmap = exynos_gem_dmabuf_kmap,
Expand Down
Loading

0 comments on commit 2f3f240

Please sign in to comment.