mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
ge2d: add ge2d dma_buf support [1/2]
PD#SWPL-4036 Problem: don't support dma_buf Solution: add ge2d dma_buf support Verify: test pass on w400 Change-Id: I1277d04fb30753e579d5edc5f46f2406dc27217a Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com> Signed-off-by: Luan Yuan <luan.yuan@amlogic.com>
This commit is contained in:
committed by
Luan Yuan
parent
5cc4b46815
commit
b4f3eddec7
@@ -14741,6 +14741,11 @@ F: drivers/amlogic/media/common/canvas/canvas_mgr.c
|
||||
F: drivers/amlogic/media/common/vfm/vfm.c
|
||||
F: include/linux/amlogic/media/camera/*
|
||||
|
||||
AMLOGIC multimedia
|
||||
M: Pengcheng Chen <pengcheng.chen@amlogic.com>
|
||||
F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c
|
||||
F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h
|
||||
|
||||
AMLOGIC VIDEOSYNC
|
||||
M: Jintao Xu <jintao.xu@amlogic.com>
|
||||
F: drivers/amlogic/media/video_processor/videosync/Kconfig
|
||||
|
||||
@@ -5,7 +5,8 @@ ge2d-objs = bitblt.o \
|
||||
ge2d_wq.o \
|
||||
stretchblt.o \
|
||||
ge2d_main.o \
|
||||
blend.o
|
||||
blend.o \
|
||||
ge2d_dmabuf.o
|
||||
|
||||
obj-$(CONFIG_AMLOGIC_MEDIA_GE2D) += ge2d.o
|
||||
ccflags-y += -Iinclude/linux/media/ge2d/
|
||||
|
||||
634
drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c
Normal file
634
drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c
Normal file
@@ -0,0 +1,634 @@
|
||||
/*
|
||||
* drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include "ge2d_log.h"
|
||||
#include "ge2d_dmabuf.h"
|
||||
|
||||
/* dma free*/
|
||||
static void aml_dma_put(void *buf_priv)
|
||||
{
|
||||
struct aml_dma_buf *buf = buf_priv;
|
||||
|
||||
if (!atomic_dec_and_test(&buf->refcount)) {
|
||||
ge2d_log_dbg("aml_dma_put, refcont=%d\n",
|
||||
atomic_read(&buf->refcount));
|
||||
return;
|
||||
}
|
||||
if (buf->sgt_base) {
|
||||
sg_free_table(buf->sgt_base);
|
||||
kfree(buf->sgt_base);
|
||||
}
|
||||
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
|
||||
buf->attrs);
|
||||
put_device(buf->dev);
|
||||
kfree(buf);
|
||||
ge2d_log_dbg("aml_dma_put free!\n");
|
||||
}
|
||||
|
||||
static void *aml_dma_alloc(struct device *dev, unsigned long attrs,
|
||||
unsigned long size, enum dma_data_direction dma_dir,
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
struct aml_dma_buf *buf;
|
||||
|
||||
if (WARN_ON(!dev))
|
||||
return (void *)(-EINVAL);
|
||||
|
||||
buf = kzalloc(sizeof(struct aml_dma_buf), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
if (attrs)
|
||||
buf->attrs = attrs;
|
||||
buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr,
|
||||
gfp_flags, buf->attrs);
|
||||
if (!buf->cookie) {
|
||||
dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
|
||||
kfree(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0)
|
||||
buf->vaddr = buf->cookie;
|
||||
|
||||
/* Prevent the device from being released while the buffer is used */
|
||||
buf->dev = get_device(dev);
|
||||
buf->size = size;
|
||||
buf->dma_dir = dma_dir;
|
||||
|
||||
atomic_inc(&buf->refcount);
|
||||
ge2d_log_dbg("aml_dma_alloc, refcont=%d\n",
|
||||
atomic_read(&buf->refcount));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma)
|
||||
{
|
||||
struct aml_dma_buf *buf = buf_priv;
|
||||
int ret;
|
||||
|
||||
if (!buf) {
|
||||
pr_err("No buffer to map\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to
|
||||
* map whole buffer
|
||||
*/
|
||||
vma->vm_pgoff = 0;
|
||||
|
||||
ret = dma_mmap_attrs(buf->dev, vma, buf->cookie,
|
||||
buf->dma_addr, buf->size, buf->attrs);
|
||||
|
||||
if (ret) {
|
||||
pr_err("Remapping memory failed, error: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ge2d_log_dbg("mapped dma addr 0x%08lx at 0x%08lx, size %d\n",
|
||||
(unsigned long)buf->dma_addr, vma->vm_start,
|
||||
buf->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* DMABUF ops for exporters */
|
||||
/*********************************************/
|
||||
struct aml_attachment {
|
||||
struct sg_table sgt;
|
||||
enum dma_data_direction dma_dir;
|
||||
};
|
||||
|
||||
static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
|
||||
struct dma_buf_attachment *dbuf_attach)
|
||||
{
|
||||
struct aml_attachment *attach;
|
||||
unsigned int i;
|
||||
struct scatterlist *rd, *wr;
|
||||
struct sg_table *sgt;
|
||||
struct aml_dma_buf *buf = dbuf->priv;
|
||||
int ret;
|
||||
|
||||
attach = kzalloc(sizeof(*attach), GFP_KERNEL);
|
||||
if (!attach)
|
||||
return -ENOMEM;
|
||||
|
||||
sgt = &attach->sgt;
|
||||
/* Copy the buf->base_sgt scatter list to the attachment, as we can't
|
||||
* map the same scatter list to multiple attachments at the same time.
|
||||
*/
|
||||
ret = sg_alloc_table(sgt, buf->sgt_base->orig_nents, GFP_KERNEL);
|
||||
if (ret) {
|
||||
kfree(attach);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rd = buf->sgt_base->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);
|
||||
}
|
||||
|
||||
attach->dma_dir = DMA_NONE;
|
||||
dbuf_attach->priv = attach;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aml_dmabuf_ops_detach(struct dma_buf *dbuf,
|
||||
struct dma_buf_attachment *db_attach)
|
||||
{
|
||||
struct aml_attachment *attach = db_attach->priv;
|
||||
struct sg_table *sgt;
|
||||
|
||||
if (!attach)
|
||||
return;
|
||||
|
||||
sgt = &attach->sgt;
|
||||
|
||||
/* release the scatterlist cache */
|
||||
if (attach->dma_dir != DMA_NONE)
|
||||
dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
|
||||
attach->dma_dir);
|
||||
sg_free_table(sgt);
|
||||
kfree(attach);
|
||||
db_attach->priv = NULL;
|
||||
|
||||
}
|
||||
|
||||
static struct sg_table *aml_dmabuf_ops_map(
|
||||
struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
|
||||
{
|
||||
struct aml_attachment *attach = db_attach->priv;
|
||||
/* stealing dmabuf mutex to serialize map/unmap operations */
|
||||
struct mutex *lock = &db_attach->dmabuf->lock;
|
||||
struct sg_table *sgt;
|
||||
|
||||
mutex_lock(lock);
|
||||
|
||||
sgt = &attach->sgt;
|
||||
/* return previously mapped sg table */
|
||||
if (attach->dma_dir == dma_dir) {
|
||||
mutex_unlock(lock);
|
||||
return sgt;
|
||||
}
|
||||
|
||||
/* release any previous cache */
|
||||
if (attach->dma_dir != DMA_NONE) {
|
||||
dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
|
||||
attach->dma_dir);
|
||||
attach->dma_dir = DMA_NONE;
|
||||
}
|
||||
|
||||
/* mapping to the client with new direction */
|
||||
sgt->nents = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
|
||||
dma_dir);
|
||||
if (!sgt->nents) {
|
||||
pr_err("failed to map scatterlist\n");
|
||||
mutex_unlock(lock);
|
||||
return (void *)(-EIO);
|
||||
}
|
||||
|
||||
attach->dma_dir = dma_dir;
|
||||
|
||||
mutex_unlock(lock);
|
||||
return sgt;
|
||||
}
|
||||
|
||||
static void aml_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
|
||||
struct sg_table *sgt, enum dma_data_direction dma_dir)
|
||||
{
|
||||
/* nothing to be done here */
|
||||
}
|
||||
|
||||
static void aml_dmabuf_ops_release(struct dma_buf *dbuf)
|
||||
{
|
||||
/* drop reference obtained in vb2_dc_get_dmabuf */
|
||||
aml_dma_put(dbuf->priv);
|
||||
}
|
||||
|
||||
static void *aml_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
|
||||
{
|
||||
struct aml_dma_buf *buf = dbuf->priv;
|
||||
|
||||
return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL;
|
||||
}
|
||||
|
||||
static void *aml_dmabuf_ops_vmap(struct dma_buf *dbuf)
|
||||
{
|
||||
struct aml_dma_buf *buf = dbuf->priv;
|
||||
|
||||
return buf->vaddr;
|
||||
}
|
||||
|
||||
static int aml_dmabuf_ops_mmap(struct dma_buf *dbuf,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
return aml_dma_mmap(dbuf->priv, vma);
|
||||
}
|
||||
|
||||
static struct dma_buf_ops ge2d_dmabuf_ops = {
|
||||
.attach = aml_dmabuf_ops_attach,
|
||||
.detach = aml_dmabuf_ops_detach,
|
||||
.map_dma_buf = aml_dmabuf_ops_map,
|
||||
.unmap_dma_buf = aml_dmabuf_ops_unmap,
|
||||
.kmap = aml_dmabuf_ops_kmap,
|
||||
.kmap_atomic = aml_dmabuf_ops_kmap,
|
||||
.vmap = aml_dmabuf_ops_vmap,
|
||||
.mmap = aml_dmabuf_ops_mmap,
|
||||
.release = aml_dmabuf_ops_release,
|
||||
};
|
||||
|
||||
static struct sg_table *get_base_sgt(struct aml_dma_buf *buf)
|
||||
{
|
||||
int ret;
|
||||
struct sg_table *sgt;
|
||||
|
||||
sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
|
||||
if (!sgt)
|
||||
return NULL;
|
||||
|
||||
ret = dma_get_sgtable(buf->dev, sgt, buf->cookie,
|
||||
buf->dma_addr, buf->size);
|
||||
if (ret < 0) {
|
||||
dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
|
||||
kfree(sgt);
|
||||
return NULL;
|
||||
}
|
||||
return sgt;
|
||||
}
|
||||
|
||||
static struct dma_buf *get_dmabuf(void *buf_priv, unsigned long flags)
|
||||
{
|
||||
struct aml_dma_buf *buf = buf_priv;
|
||||
struct dma_buf *dbuf;
|
||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||
|
||||
exp_info.ops = &ge2d_dmabuf_ops;
|
||||
exp_info.size = buf->size;
|
||||
exp_info.flags = flags;
|
||||
exp_info.priv = buf;
|
||||
|
||||
if (!buf->sgt_base)
|
||||
buf->sgt_base = get_base_sgt(buf);
|
||||
|
||||
if (WARN_ON(!buf->sgt_base))
|
||||
return NULL;
|
||||
|
||||
dbuf = dma_buf_export(&exp_info);
|
||||
if (IS_ERR(dbuf))
|
||||
return NULL;
|
||||
|
||||
/* dmabuf keeps reference to vb2 buffer */
|
||||
atomic_inc(&buf->refcount);
|
||||
ge2d_log_dbg("get_dmabuf, refcount=%d\n",
|
||||
atomic_read(&buf->refcount));
|
||||
return dbuf;
|
||||
}
|
||||
|
||||
/* ge2d dma-buf api.h*/
|
||||
static int find_empty_dma_buffer(struct aml_dma_buffer *buffer)
|
||||
{
|
||||
int i;
|
||||
int found = 0;
|
||||
|
||||
for (i = 0; i < AML_MAX_DMABUF; i++) {
|
||||
if (buffer->gd_buffer[i].alloc)
|
||||
continue;
|
||||
else {
|
||||
ge2d_log_dbg("find_empty_dma_buffer i=%d\n", i);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
return i;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *ge2d_dma_buffer_create(void)
|
||||
{
|
||||
int i;
|
||||
struct aml_dma_buffer *buffer;
|
||||
|
||||
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
mutex_init(&buffer->lock);
|
||||
for (i = 0; i < AML_MAX_DMABUF; i++) {
|
||||
buffer->gd_buffer[i].mem_priv = NULL;
|
||||
buffer->gd_buffer[i].index = 0;
|
||||
buffer->gd_buffer[i].alloc = 0;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void ge2d_dma_buffer_destroy(struct aml_dma_buffer *buffer)
|
||||
{
|
||||
kfree(buffer);
|
||||
}
|
||||
|
||||
int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer,
|
||||
struct device *dev,
|
||||
struct ge2d_dmabuf_req_s *ge2d_req_buf)
|
||||
{
|
||||
void *buf;
|
||||
unsigned int size;
|
||||
int index;
|
||||
|
||||
if (WARN_ON(!dev))
|
||||
return (-EINVAL);
|
||||
if (!ge2d_req_buf)
|
||||
return (-EINVAL);
|
||||
if (!buffer)
|
||||
return (-EINVAL);
|
||||
|
||||
size = PAGE_ALIGN(ge2d_req_buf->len);
|
||||
if (size == 0)
|
||||
return (-EINVAL);
|
||||
|
||||
index = find_empty_dma_buffer(buffer);
|
||||
if ((index < 0) || (index >= AML_MAX_DMABUF)) {
|
||||
pr_err("no empty buffer found\n");
|
||||
return (-ENOMEM);
|
||||
}
|
||||
|
||||
buf = aml_dma_alloc(dev, 0, size, ge2d_req_buf->dma_dir,
|
||||
GFP_HIGHUSER | __GFP_ZERO);
|
||||
if (!buf)
|
||||
return (-ENOMEM);
|
||||
|
||||
mutex_lock(&(buffer->lock));
|
||||
buffer->gd_buffer[index].mem_priv = buf;
|
||||
buffer->gd_buffer[index].index = index;
|
||||
buffer->gd_buffer[index].alloc = 1;
|
||||
mutex_unlock(&(buffer->lock));
|
||||
ge2d_req_buf->index = index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ge2d_dma_buffer_free(struct aml_dma_buffer *buffer, int index)
|
||||
{
|
||||
struct aml_dma_buf *buf;
|
||||
|
||||
if (!buffer)
|
||||
return (-EINVAL);
|
||||
if ((index < 0) || (index >= AML_MAX_DMABUF))
|
||||
return (-EINVAL);
|
||||
|
||||
buf = buffer->gd_buffer[index].mem_priv;
|
||||
if (!buf) {
|
||||
pr_err("aml_dma_buf is null\n");
|
||||
return (-EINVAL);
|
||||
}
|
||||
aml_dma_put(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ge2d_dma_buffer_export(struct aml_dma_buffer *buffer,
|
||||
struct ge2d_dmabuf_exp_s *ge2d_exp_buf)
|
||||
{
|
||||
struct aml_dma_buf *buf;
|
||||
struct dma_buf *dbuf;
|
||||
int ret, index;
|
||||
unsigned int flags;
|
||||
|
||||
if (!ge2d_exp_buf)
|
||||
return (-EINVAL);
|
||||
if (!buffer)
|
||||
return (-EINVAL);
|
||||
|
||||
index = ge2d_exp_buf->index;
|
||||
if ((index < 0) || (index >= AML_MAX_DMABUF))
|
||||
return (-EINVAL);
|
||||
|
||||
flags = ge2d_exp_buf->flags;
|
||||
buf = buffer->gd_buffer[index].mem_priv;
|
||||
if (!buf) {
|
||||
pr_err("aml_dma_buf is null\n");
|
||||
return (-EINVAL);
|
||||
}
|
||||
|
||||
dbuf = get_dmabuf(buf, flags & O_ACCMODE);
|
||||
if (IS_ERR_OR_NULL(dbuf)) {
|
||||
pr_err("failed to export buffer %d\n", index);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
|
||||
if (ret < 0) {
|
||||
pr_err("buffer %d, failed to export (%d)\n",
|
||||
index, ret);
|
||||
dma_buf_put(dbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ge2d_log_dbg("buffer %d,exported as %d descriptor\n",
|
||||
index, ret);
|
||||
ge2d_exp_buf->fd = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg)
|
||||
{
|
||||
long ret = -1;
|
||||
int fd = -1;
|
||||
struct dma_buf *dbuf = NULL;
|
||||
struct dma_buf_attachment *d_att = NULL;
|
||||
struct sg_table *sg = NULL;
|
||||
void *vaddr = NULL;
|
||||
struct device *dev = NULL;
|
||||
enum dma_data_direction dir;
|
||||
|
||||
if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL) {
|
||||
pr_err("error input param");
|
||||
return -EINVAL;
|
||||
}
|
||||
fd = cfg->fd;
|
||||
dev = cfg->dev;
|
||||
dir = cfg->dir;
|
||||
|
||||
dbuf = dma_buf_get(fd);
|
||||
if (dbuf == NULL) {
|
||||
pr_err("failed to get dma buffer");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
d_att = dma_buf_attach(dbuf, dev);
|
||||
if (d_att == NULL) {
|
||||
pr_err("failed to set dma attach");
|
||||
goto attach_err;
|
||||
}
|
||||
|
||||
sg = dma_buf_map_attachment(d_att, dir);
|
||||
if (sg == NULL) {
|
||||
pr_err("failed to get dma sg");
|
||||
goto map_attach_err;
|
||||
}
|
||||
|
||||
ret = dma_buf_begin_cpu_access(dbuf, dir);
|
||||
if (ret != 0) {
|
||||
pr_err("failed to access dma buff");
|
||||
goto access_err;
|
||||
}
|
||||
|
||||
vaddr = dma_buf_vmap(dbuf);
|
||||
if (vaddr == NULL) {
|
||||
pr_err("failed to vmap dma buf");
|
||||
goto vmap_err;
|
||||
}
|
||||
cfg->dbuf = dbuf;
|
||||
cfg->attach = d_att;
|
||||
cfg->vaddr = vaddr;
|
||||
cfg->sg = sg;
|
||||
return ret;
|
||||
|
||||
vmap_err:
|
||||
dma_buf_end_cpu_access(dbuf, dir);
|
||||
|
||||
access_err:
|
||||
dma_buf_unmap_attachment(d_att, sg, dir);
|
||||
|
||||
map_attach_err:
|
||||
dma_buf_detach(dbuf, d_att);
|
||||
|
||||
attach_err:
|
||||
dma_buf_put(dbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ge2d_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr)
|
||||
{
|
||||
struct sg_table *sg_table;
|
||||
struct page *page;
|
||||
int ret;
|
||||
|
||||
ret = ge2d_dma_buffer_map(cfg);
|
||||
if (ret < 0) {
|
||||
pr_err("gdc_dma_buffer_map failed\n");
|
||||
return ret;
|
||||
}
|
||||
if (cfg->sg) {
|
||||
sg_table = cfg->sg;
|
||||
page = sg_page(sg_table->sgl);
|
||||
*addr = PFN_PHYS(page_to_pfn(page));
|
||||
ret = 0;
|
||||
}
|
||||
ge2d_dma_buffer_unmap(cfg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg)
|
||||
{
|
||||
int fd = -1;
|
||||
struct dma_buf *dbuf = NULL;
|
||||
struct dma_buf_attachment *d_att = NULL;
|
||||
struct sg_table *sg = NULL;
|
||||
void *vaddr = NULL;
|
||||
struct device *dev = NULL;
|
||||
enum dma_data_direction dir;
|
||||
|
||||
if (cfg == NULL || (cfg->fd < 0) || cfg->dev == NULL
|
||||
|| cfg->dbuf == NULL || cfg->vaddr == NULL
|
||||
|| cfg->attach == NULL || cfg->sg == NULL) {
|
||||
pr_err("Error input param");
|
||||
return;
|
||||
}
|
||||
fd = cfg->fd;
|
||||
dev = cfg->dev;
|
||||
dir = cfg->dir;
|
||||
dbuf = cfg->dbuf;
|
||||
vaddr = cfg->vaddr;
|
||||
d_att = cfg->attach;
|
||||
sg = cfg->sg;
|
||||
|
||||
dma_buf_vunmap(dbuf, vaddr);
|
||||
|
||||
dma_buf_end_cpu_access(dbuf, dir);
|
||||
|
||||
dma_buf_unmap_attachment(d_att, sg, dir);
|
||||
|
||||
dma_buf_detach(dbuf, d_att);
|
||||
|
||||
dma_buf_put(dbuf);
|
||||
}
|
||||
|
||||
void ge2d_dma_buffer_dma_flush(struct device *dev, int fd)
|
||||
{
|
||||
struct dma_buf *dmabuf;
|
||||
struct aml_dma_buf *buf;
|
||||
|
||||
ge2d_log_dbg("ge2d_dma_buffer_dma_flush fd=%d\n", fd);
|
||||
dmabuf = dma_buf_get(fd);
|
||||
if (IS_ERR(dmabuf)) {
|
||||
pr_err("dma_buf_get failed\n");
|
||||
return;
|
||||
}
|
||||
buf = dmabuf->priv;
|
||||
if (!buf) {
|
||||
pr_err("error input param");
|
||||
return;
|
||||
}
|
||||
if (buf->size > 0)
|
||||
dma_sync_single_for_device(buf->dev, buf->dma_addr,
|
||||
buf->size, DMA_TO_DEVICE);
|
||||
dma_buf_put(dmabuf);
|
||||
}
|
||||
|
||||
void ge2d_dma_buffer_cache_flush(struct device *dev, int fd)
|
||||
{
|
||||
struct dma_buf *dmabuf;
|
||||
struct aml_dma_buf *buf;
|
||||
|
||||
ge2d_log_dbg("ge2d_dma_buffer_cache_flush fd=%d\n", fd);
|
||||
dmabuf = dma_buf_get(fd);
|
||||
if (IS_ERR(dmabuf)) {
|
||||
pr_err("dma_buf_get failed\n");
|
||||
return;
|
||||
}
|
||||
buf = dmabuf->priv;
|
||||
if (!buf) {
|
||||
pr_err("error input param");
|
||||
return;
|
||||
}
|
||||
if (buf->size > 0)
|
||||
dma_sync_single_for_device(buf->dev, buf->dma_addr,
|
||||
buf->size, DMA_FROM_DEVICE);
|
||||
dma_buf_put(dmabuf);
|
||||
}
|
||||
|
||||
|
||||
81
drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h
Normal file
81
drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* drivers/amlogic/media/common/ge2d/ge2d_dmabuf.h
|
||||
*
|
||||
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _GE2D_DMABUF_H_
|
||||
#define _GE2D_DMABUF_H_
|
||||
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
/* Amlogic Headers */
|
||||
#include <linux/amlogic/media/ge2d/ge2d.h>
|
||||
|
||||
#define AML_MAX_DMABUF 32
|
||||
|
||||
struct aml_dma_buf {
|
||||
struct device *dev;
|
||||
void *cookie;
|
||||
void *vaddr;
|
||||
unsigned int size;
|
||||
enum dma_data_direction dma_dir;
|
||||
unsigned long attrs;
|
||||
unsigned int index;
|
||||
dma_addr_t dma_addr;
|
||||
atomic_t refcount;
|
||||
struct sg_table *sgt_base;
|
||||
/* DMABUF related */
|
||||
struct dma_buf_attachment *db_attach;
|
||||
};
|
||||
|
||||
struct aml_dma_buf_priv {
|
||||
void *mem_priv;
|
||||
int index;
|
||||
unsigned int alloc;
|
||||
struct dma_buf *dbuf;
|
||||
};
|
||||
|
||||
struct aml_dma_buffer {
|
||||
struct mutex lock;
|
||||
struct aml_dma_buf_priv gd_buffer[AML_MAX_DMABUF];
|
||||
};
|
||||
|
||||
struct aml_dma_cfg {
|
||||
int fd;
|
||||
void *dev;
|
||||
void *vaddr;
|
||||
struct dma_buf *dbuf;
|
||||
struct dma_buf_attachment *attach;
|
||||
struct sg_table *sg;
|
||||
enum dma_data_direction dir;
|
||||
};
|
||||
|
||||
|
||||
void *ge2d_dma_buffer_create(void);
|
||||
void ge2d_dma_buffer_destroy(struct aml_dma_buffer *buffer);
|
||||
int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer,
|
||||
struct device *dev,
|
||||
struct ge2d_dmabuf_req_s *ge2d_req_buf);
|
||||
int ge2d_dma_buffer_free(struct aml_dma_buffer *buffer, int index);
|
||||
int ge2d_dma_buffer_export(struct aml_dma_buffer *buffer,
|
||||
struct ge2d_dmabuf_exp_s *ge2d_exp_buf);
|
||||
int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg);
|
||||
void ge2d_dma_buffer_unmap(struct aml_dma_cfg *cfg);
|
||||
int ge2d_dma_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr);
|
||||
void ge2d_dma_buffer_dma_flush(struct device *dev, int fd);
|
||||
void ge2d_dma_buffer_cache_flush(struct device *dev, int fd);
|
||||
#endif
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/clk.h>
|
||||
#ifdef CONFIG_COMPAT
|
||||
@@ -47,6 +48,7 @@
|
||||
#include "ge2dgen.h"
|
||||
#include "ge2d_log.h"
|
||||
#include "ge2d_wq.h"
|
||||
#include "ge2d_dmabuf.h"
|
||||
|
||||
#define GE2D_CLASS_NAME "ge2d"
|
||||
#define MAX_GE2D_CLK 500000000
|
||||
@@ -210,6 +212,197 @@ static int ge2d_open(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ge2d_ioctl_config_ex_mem(struct ge2d_context_s *context,
|
||||
unsigned int cmd, unsigned long args)
|
||||
{
|
||||
struct config_para_ex_memtype_s *ge2d_config_ex_mem;
|
||||
struct config_ge2d_para_ex_s ge2d_para_config;
|
||||
int ret = 0;
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct compat_config_para_ex_memtype_s __user *uf_ex_mem;
|
||||
struct compat_config_ge2d_para_ex_s __user *uf_ge2d_para;
|
||||
int r = 0;
|
||||
int i, j;
|
||||
#endif
|
||||
void __user *argp = (void __user *)args;
|
||||
|
||||
memset(&ge2d_para_config, 0, sizeof(struct config_ge2d_para_ex_s));
|
||||
switch (cmd) {
|
||||
case GE2D_CONFIG_EX_MEM:
|
||||
ret = copy_from_user(&ge2d_para_config, argp,
|
||||
sizeof(struct config_ge2d_para_ex_s));
|
||||
ge2d_config_ex_mem = &(ge2d_para_config.para_config_memtype);
|
||||
ret = ge2d_context_config_ex_mem(context, ge2d_config_ex_mem);
|
||||
break;
|
||||
#ifdef CONFIG_COMPAT
|
||||
case GE2D_CONFIG_EX32_MEM:
|
||||
uf_ge2d_para = (struct compat_config_ge2d_para_ex_s *)argp;
|
||||
r |= get_user(ge2d_para_config.para_config_memtype.ge2d_magic,
|
||||
&uf_ge2d_para->para_config_memtype.ge2d_magic);
|
||||
ge2d_config_ex_mem = &(ge2d_para_config.para_config_memtype);
|
||||
|
||||
if (ge2d_para_config.para_config_memtype.ge2d_magic
|
||||
== sizeof(struct config_para_ex_memtype_s)) {
|
||||
struct config_para_ex_ion_s *pge2d_config_ex;
|
||||
|
||||
uf_ex_mem =
|
||||
(struct compat_config_para_ex_memtype_s *)argp;
|
||||
pge2d_config_ex =
|
||||
&(ge2d_config_ex_mem->_ge2d_config_ex);
|
||||
r = copy_from_user(
|
||||
&pge2d_config_ex->src_para,
|
||||
&uf_ex_mem->_ge2d_config_ex.src_para,
|
||||
sizeof(struct src_dst_para_ex_s));
|
||||
r |= copy_from_user(
|
||||
&pge2d_config_ex->src2_para,
|
||||
&uf_ex_mem->_ge2d_config_ex.src2_para,
|
||||
sizeof(struct src_dst_para_ex_s));
|
||||
r |= copy_from_user(
|
||||
&pge2d_config_ex->dst_para,
|
||||
&uf_ex_mem->_ge2d_config_ex.dst_para,
|
||||
sizeof(struct src_dst_para_ex_s));
|
||||
r |= copy_from_user(&pge2d_config_ex->src_key,
|
||||
&uf_ex_mem->_ge2d_config_ex.src_key,
|
||||
sizeof(struct src_key_ctrl_s));
|
||||
r |= copy_from_user(&pge2d_config_ex->src2_key,
|
||||
&uf_ex_mem->_ge2d_config_ex.src2_key,
|
||||
sizeof(struct src_key_ctrl_s));
|
||||
|
||||
r |= get_user(pge2d_config_ex->src1_cmult_asel,
|
||||
&uf_ex_mem->_ge2d_config_ex.src1_cmult_asel);
|
||||
r |= get_user(pge2d_config_ex->src2_cmult_asel,
|
||||
&uf_ex_mem->_ge2d_config_ex.src2_cmult_asel);
|
||||
r |= get_user(pge2d_config_ex->alu_const_color,
|
||||
&uf_ex_mem->_ge2d_config_ex.alu_const_color);
|
||||
r |= get_user(pge2d_config_ex->src1_gb_alpha_en,
|
||||
&uf_ex_mem->_ge2d_config_ex.src1_gb_alpha_en);
|
||||
r |= get_user(pge2d_config_ex->src1_gb_alpha,
|
||||
&uf_ex_mem->_ge2d_config_ex.src1_gb_alpha);
|
||||
#ifdef CONFIG_GE2D_SRC2
|
||||
r |= get_user(pge2d_config_ex->src2_gb_alpha_en,
|
||||
&uf_ex_mem->_ge2d_config_ex.src2_gb_alpha_en);
|
||||
r |= get_user(pge2d_config_ex->src2_gb_alpha,
|
||||
&uf_ex_mem->_ge2d_config_ex.src2_gb_alpha);
|
||||
#endif
|
||||
r |= get_user(pge2d_config_ex->op_mode,
|
||||
&uf_ex_mem->_ge2d_config_ex.op_mode);
|
||||
r |= get_user(pge2d_config_ex->bitmask_en,
|
||||
&uf_ex_mem->_ge2d_config_ex.bitmask_en);
|
||||
r |= get_user(pge2d_config_ex->bytemask_only,
|
||||
&uf_ex_mem->_ge2d_config_ex.bytemask_only);
|
||||
r |= get_user(pge2d_config_ex->bitmask,
|
||||
&uf_ex_mem->_ge2d_config_ex.bitmask);
|
||||
r |= get_user(pge2d_config_ex->dst_xy_swap,
|
||||
&uf_ex_mem->_ge2d_config_ex.dst_xy_swap);
|
||||
r |= get_user(pge2d_config_ex->hf_init_phase,
|
||||
&uf_ex_mem->_ge2d_config_ex.hf_init_phase);
|
||||
r |= get_user(pge2d_config_ex->hf_rpt_num,
|
||||
&uf_ex_mem->_ge2d_config_ex.hf_rpt_num);
|
||||
r |= get_user(pge2d_config_ex->hsc_start_phase_step,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.hsc_start_phase_step);
|
||||
r |= get_user(pge2d_config_ex->hsc_phase_slope,
|
||||
&uf_ex_mem->_ge2d_config_ex.hsc_phase_slope);
|
||||
r |= get_user(pge2d_config_ex->vf_init_phase,
|
||||
&uf_ex_mem->_ge2d_config_ex.vf_init_phase);
|
||||
r |= get_user(pge2d_config_ex->vf_rpt_num,
|
||||
&uf_ex_mem->_ge2d_config_ex.vf_rpt_num);
|
||||
r |= get_user(pge2d_config_ex->vsc_start_phase_step,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.vsc_start_phase_step);
|
||||
r |= get_user(pge2d_config_ex->vsc_phase_slope,
|
||||
&uf_ex_mem->_ge2d_config_ex.vsc_phase_slope);
|
||||
r |= get_user(
|
||||
pge2d_config_ex->src1_vsc_phase0_always_en,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.src1_vsc_phase0_always_en);
|
||||
r |= get_user(
|
||||
pge2d_config_ex->src1_hsc_phase0_always_en,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.src1_hsc_phase0_always_en);
|
||||
r |= get_user(
|
||||
pge2d_config_ex->src1_hsc_rpt_ctrl,
|
||||
&uf_ex_mem->_ge2d_config_ex.src1_hsc_rpt_ctrl);
|
||||
r |= get_user(
|
||||
pge2d_config_ex->src1_vsc_rpt_ctrl,
|
||||
&uf_ex_mem->_ge2d_config_ex.src1_vsc_rpt_ctrl);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
struct config_planes_ion_s *psrc_planes;
|
||||
|
||||
psrc_planes =
|
||||
&pge2d_config_ex->src_planes[i];
|
||||
r |= get_user(psrc_planes->addr,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.src_planes[i].addr);
|
||||
r |= get_user(psrc_planes->w,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.src_planes[i].w);
|
||||
r |= get_user(psrc_planes->h,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.src_planes[i].h);
|
||||
r |= get_user(psrc_planes->shared_fd,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.src_planes[i].shared_fd);
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
struct config_planes_ion_s *psrc2_planes;
|
||||
|
||||
psrc2_planes =
|
||||
&pge2d_config_ex->src2_planes[i];
|
||||
r |= get_user(psrc2_planes->addr,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.src2_planes[i].addr);
|
||||
r |= get_user(psrc2_planes->w,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.src2_planes[i].w);
|
||||
r |= get_user(psrc2_planes->h,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.src2_planes[i].h);
|
||||
r |= get_user(psrc2_planes->shared_fd,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.src2_planes[i].shared_fd);
|
||||
}
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
struct config_planes_ion_s *pdst_planes;
|
||||
|
||||
pdst_planes =
|
||||
&pge2d_config_ex->dst_planes[j];
|
||||
r |= get_user(pdst_planes->addr,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.dst_planes[j].addr);
|
||||
r |= get_user(pdst_planes->w,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.dst_planes[j].w);
|
||||
r |= get_user(pdst_planes->h,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.dst_planes[j].h);
|
||||
r |= get_user(pdst_planes->shared_fd,
|
||||
&uf_ex_mem->_ge2d_config_ex
|
||||
.dst_planes[j].shared_fd);
|
||||
}
|
||||
|
||||
r |= get_user(ge2d_config_ex_mem->src1_mem_alloc_type,
|
||||
&uf_ex_mem->src1_mem_alloc_type);
|
||||
r |= get_user(ge2d_config_ex_mem->src2_mem_alloc_type,
|
||||
&uf_ex_mem->src2_mem_alloc_type);
|
||||
r |= get_user(ge2d_config_ex_mem->dst_mem_alloc_type,
|
||||
&uf_ex_mem->dst_mem_alloc_type);
|
||||
|
||||
}
|
||||
if (r) {
|
||||
pr_err("GE2D_CONFIG_EX32 get parameter failed .\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
ret = ge2d_context_config_ex_mem(context, ge2d_config_ex_mem);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
{
|
||||
struct ge2d_context_s *context = NULL;
|
||||
@@ -217,6 +410,8 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
struct ge2d_para_s para;
|
||||
struct config_para_ex_s ge2d_config_ex;
|
||||
struct config_para_ex_ion_s ge2d_config_ex_ion;
|
||||
struct ge2d_dmabuf_req_s ge2d_req_buf;
|
||||
struct ge2d_dmabuf_exp_s ge2d_exp_buf;
|
||||
int ret = 0;
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct compat_config_para_s __user *uf;
|
||||
@@ -226,12 +421,15 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
int i, j;
|
||||
#endif
|
||||
int cap_mask = 0;
|
||||
int index = 0, dma_fd;
|
||||
void __user *argp = (void __user *)args;
|
||||
|
||||
context = (struct ge2d_context_s *)filp->private_data;
|
||||
memset(&ge2d_config, 0, sizeof(struct config_para_s));
|
||||
memset(&ge2d_config_ex, 0, sizeof(struct config_para_ex_s));
|
||||
memset(&ge2d_config_ex_ion, 0, sizeof(struct config_para_ex_ion_s));
|
||||
memset(&ge2d_req_buf, 0, sizeof(struct ge2d_dmabuf_req_s));
|
||||
memset(&ge2d_exp_buf, 0, sizeof(struct ge2d_dmabuf_exp_s));
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D_MORE_SECURITY
|
||||
switch (cmd) {
|
||||
case GE2D_CONFIG:
|
||||
@@ -538,6 +736,39 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
case GE2D_SET_COEF:
|
||||
case GE2D_ANTIFLICKER_ENABLE:
|
||||
break;
|
||||
case GE2D_REQUEST_BUFF:
|
||||
ret = copy_from_user(&ge2d_req_buf, argp,
|
||||
sizeof(struct ge2d_dmabuf_req_s));
|
||||
if (ret < 0) {
|
||||
pr_err("Error user param\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case GE2D_EXP_BUFF:
|
||||
ret = copy_from_user(&ge2d_exp_buf, argp,
|
||||
sizeof(struct ge2d_dmabuf_exp_s));
|
||||
if (ret < 0) {
|
||||
pr_err("Error user param\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case GE2D_FREE_BUFF:
|
||||
ret = copy_from_user(&index, argp,
|
||||
sizeof(int));
|
||||
if (ret < 0) {
|
||||
pr_err("Error user param\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case GE2D_SYNC_DEVICE:
|
||||
case GE2D_SYNC_CPU:
|
||||
ret = copy_from_user(&dma_fd, argp,
|
||||
sizeof(int));
|
||||
if (ret < 0) {
|
||||
pr_err("Error user param\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case GE2D_CONFIG_OLD:
|
||||
case GE2D_CONFIG_EX_OLD:
|
||||
case GE2D_SRCCOLORKEY_OLD:
|
||||
@@ -568,6 +799,12 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
#endif
|
||||
ret = ge2d_context_config_ex_ion(context, &ge2d_config_ex_ion);
|
||||
break;
|
||||
case GE2D_CONFIG_EX_MEM:
|
||||
#ifdef CONFIG_COMPAT
|
||||
case GE2D_CONFIG_EX32_MEM:
|
||||
#endif
|
||||
ret = ge2d_ioctl_config_ex_mem(context, cmd, args);
|
||||
break;
|
||||
case GE2D_SET_COEF:
|
||||
ge2d_wq_set_scale_coef(context, args & 0xff, args >> 16);
|
||||
break;
|
||||
@@ -744,6 +981,27 @@ static long ge2d_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
|
||||
para.dst_rect.x, para.dst_rect.y,
|
||||
para.dst_rect.w, para.dst_rect.h);
|
||||
break;
|
||||
case GE2D_REQUEST_BUFF:
|
||||
ret = ge2d_buffer_alloc(&ge2d_req_buf);
|
||||
if (ret == 0)
|
||||
ret = copy_to_user(argp, &ge2d_req_buf,
|
||||
sizeof(struct ge2d_dmabuf_req_s));
|
||||
break;
|
||||
case GE2D_EXP_BUFF:
|
||||
ret = ge2d_buffer_export(&ge2d_exp_buf);
|
||||
if (ret == 0)
|
||||
ret = copy_to_user(argp, &ge2d_exp_buf,
|
||||
sizeof(struct ge2d_dmabuf_exp_s));
|
||||
break;
|
||||
case GE2D_FREE_BUFF:
|
||||
ret = ge2d_buffer_free(index);
|
||||
break;
|
||||
case GE2D_SYNC_DEVICE:
|
||||
ge2d_buffer_dma_flush(dma_fd);
|
||||
break;
|
||||
case GE2D_SYNC_CPU:
|
||||
ge2d_buffer_cache_flush(dma_fd);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -961,6 +1219,9 @@ static int ge2d_probe(struct platform_device *pdev)
|
||||
(void *)res.start, (int)resource_size(&res));
|
||||
}
|
||||
}
|
||||
ret = of_reserved_mem_device_init(&(pdev->dev));
|
||||
if (ret < 0)
|
||||
ge2d_log_info("reserved mem init failed\n");
|
||||
|
||||
ret = ge2d_wq_init(pdev, irq, clk_gate);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "ge2d_io.h"
|
||||
#include "ge2d_reg.h"
|
||||
#include "ge2d_wq.h"
|
||||
#include "ge2d_dmabuf.h"
|
||||
|
||||
#include "osd_io.h"
|
||||
#include "osd_hw.h"
|
||||
@@ -928,6 +929,49 @@ static int build_ge2d_addr_config_ion(
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int build_ge2d_addr_config_dma(
|
||||
struct config_planes_ion_s *plane,
|
||||
unsigned int format,
|
||||
unsigned int *addr,
|
||||
unsigned int *stride,
|
||||
unsigned int dir
|
||||
)
|
||||
{
|
||||
int ret = -1;
|
||||
int bpp_value = bpp(format);
|
||||
unsigned long addr_temp = 0;
|
||||
|
||||
bpp_value /= 8;
|
||||
ge2d_log_dbg("build_ge2d_addr_config_ion bpp_value=%d\n",
|
||||
bpp_value);
|
||||
if (plane) {
|
||||
if (plane[0].shared_fd) {
|
||||
struct aml_dma_cfg cfg;
|
||||
|
||||
cfg.fd = plane[0].shared_fd;
|
||||
cfg.dev = &(ge2d_manager.pdev->dev);
|
||||
cfg.dir = dir;
|
||||
ret = ge2d_dma_buffer_get_phys(&cfg, &addr_temp);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
plane[0].addr += addr_temp;
|
||||
if (plane[0].addr) {
|
||||
*addr = plane[0].addr;
|
||||
*stride = plane[0].w * bpp_value;
|
||||
ret = 0;
|
||||
}
|
||||
/* not support multi-src_planes */
|
||||
if ((plane[1].addr) ||
|
||||
(plane[2].addr) ||
|
||||
(plane[3].addr)) {
|
||||
ge2d_log_info("ge2d not support NV21 mode\n");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int build_ge2d_config_ex(struct config_planes_s *plane,
|
||||
unsigned int format,
|
||||
unsigned int *canvas_index,
|
||||
@@ -1066,6 +1110,84 @@ static int build_ge2d_config_ex_ion(struct config_planes_ion_s *plane,
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int build_ge2d_config_ex_dma(struct config_planes_ion_s *plane,
|
||||
unsigned int format,
|
||||
unsigned int *canvas_index,
|
||||
int index,
|
||||
unsigned int *r_offset,
|
||||
unsigned int dir)
|
||||
{
|
||||
int bpp_value = bpp(format);
|
||||
int ret = -1;
|
||||
unsigned long addr;
|
||||
|
||||
bpp_value /= 8;
|
||||
index &= 0xff;
|
||||
if (plane) {
|
||||
if (plane[0].shared_fd) {
|
||||
struct aml_dma_cfg cfg;
|
||||
|
||||
cfg.fd = plane[0].shared_fd;
|
||||
cfg.dev = &(ge2d_manager.pdev->dev);
|
||||
cfg.dir = dir;
|
||||
ret = ge2d_dma_buffer_get_phys(&cfg, &addr);
|
||||
ge2d_log_info("phys: addr=%lx\n", addr);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
plane[0].addr += addr;
|
||||
*canvas_index = index;
|
||||
*r_offset += 1;
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS
|
||||
canvas_config(index++, plane[0].addr,
|
||||
plane[0].w * bpp_value,
|
||||
plane[0].h,
|
||||
CANVAS_ADDR_NOWRAP,
|
||||
CANVAS_BLKMODE_LINEAR);
|
||||
#endif
|
||||
ret = 0;
|
||||
}
|
||||
/* multi-src_planes */
|
||||
if (plane[1].addr) {
|
||||
plane[1].addr += plane[0].addr;
|
||||
*canvas_index |= index << 8;
|
||||
*r_offset += 1;
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS
|
||||
canvas_config(index++, plane[1].addr,
|
||||
plane[1].w * bpp_value,
|
||||
plane[1].h,
|
||||
CANVAS_ADDR_NOWRAP,
|
||||
CANVAS_BLKMODE_LINEAR);
|
||||
#endif
|
||||
}
|
||||
if (plane[2].addr) {
|
||||
plane[2].addr += plane[0].addr;
|
||||
*canvas_index |= index << 16;
|
||||
*r_offset += 1;
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS
|
||||
canvas_config(index++, plane[2].addr,
|
||||
plane[2].w * bpp_value,
|
||||
plane[2].h,
|
||||
CANVAS_ADDR_NOWRAP,
|
||||
CANVAS_BLKMODE_LINEAR);
|
||||
#endif
|
||||
}
|
||||
if (plane[3].addr) {
|
||||
plane[3].addr += plane[0].addr;
|
||||
*canvas_index |= index << 24;
|
||||
*r_offset += 1;
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS
|
||||
canvas_config(index++, plane[3].addr,
|
||||
plane[3].w * bpp_value,
|
||||
plane[3].h,
|
||||
CANVAS_ADDR_NOWRAP,
|
||||
CANVAS_BLKMODE_LINEAR);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ge2d_context_config_ex(struct ge2d_context_s *context,
|
||||
struct config_para_ex_s *ge2d_config)
|
||||
{
|
||||
@@ -1814,6 +1936,516 @@ int ge2d_context_config_ex_ion(struct ge2d_context_s *context,
|
||||
|
||||
return 0;
|
||||
}
|
||||
int ge2d_context_config_ex_mem(struct ge2d_context_s *context,
|
||||
struct config_para_ex_memtype_s *ge2d_config_mem)
|
||||
{
|
||||
struct src_dst_para_s tmp;
|
||||
unsigned int index = 0;
|
||||
unsigned int alloc_canvas_offset = 0;
|
||||
struct ge2d_src1_gen_s *src1_gen_cfg;
|
||||
struct ge2d_src2_dst_data_s *src2_dst_data_cfg;
|
||||
struct ge2d_src2_dst_gen_s *src2_dst_gen_cfg;
|
||||
struct ge2d_dp_gen_s *dp_gen_cfg;
|
||||
struct ge2d_cmd_s *ge2d_cmd_cfg;
|
||||
int top, left, width, height;
|
||||
unsigned int src_addr = 0, src2_addr = 0, dst_addr = 0;
|
||||
unsigned int src_stride = 0, src2_stride = 0, dst_stride = 0;
|
||||
struct config_para_ex_ion_s *ge2d_config;
|
||||
|
||||
ge2d_config = &(ge2d_config_mem->_ge2d_config_ex);
|
||||
/* setup src and dst */
|
||||
switch (ge2d_config->src_para.mem_type) {
|
||||
case CANVAS_OSD0:
|
||||
case CANVAS_OSD1:
|
||||
if (setup_display_property(&tmp,
|
||||
(ge2d_config->src_para.mem_type == CANVAS_OSD0) ?
|
||||
OSD1_CANVAS_INDEX : OSD2_CANVAS_INDEX) < 0)
|
||||
return -1;
|
||||
ge2d_config->src_para.canvas_index = tmp.canvas_index;
|
||||
ge2d_config->src_para.format = tmp.ge2d_color_index;
|
||||
src_addr = tmp.phy_addr;
|
||||
src_stride = tmp.stride;
|
||||
|
||||
ge2d_log_dbg("ge2d: src1-->type: osd%d, format: 0x%x !!\n",
|
||||
ge2d_config->src_para.mem_type - CANVAS_OSD0,
|
||||
ge2d_config->src_para.format);
|
||||
|
||||
top = ge2d_config->src_para.top;
|
||||
left = ge2d_config->src_para.left;
|
||||
width = ge2d_config->src_para.width;
|
||||
height = ge2d_config->src_para.height;
|
||||
if ((left + width > tmp.xres) ||
|
||||
(top + height > tmp.yres)) {
|
||||
ge2d_log_dbg("ge2d src error: out of range\n");
|
||||
return -1;
|
||||
}
|
||||
ge2d_config->src_para.width = tmp.xres;
|
||||
ge2d_config->src_para.height = tmp.yres;
|
||||
ge2d_log_dbg("ge2d osd phy_addr:0x%x,stride=0x%x,format:0x%x\n",
|
||||
src_addr,
|
||||
src_stride,
|
||||
ge2d_config->src_para.format);
|
||||
break;
|
||||
case CANVAS_ALLOC:
|
||||
top = ge2d_config->src_para.top;
|
||||
left = ge2d_config->src_para.left;
|
||||
width = ge2d_config->src_para.width;
|
||||
height = ge2d_config->src_para.height;
|
||||
if ((left + width > ge2d_config->src_planes[0].w)
|
||||
|| (top + height > ge2d_config->src_planes[0].h)) {
|
||||
ge2d_log_dbg("ge2d error: src alloc, out of range\n");
|
||||
return -1;
|
||||
}
|
||||
if (ge2d_meson_dev.canvas_status == 1) {
|
||||
if (ge2d_config_mem->src1_mem_alloc_type ==
|
||||
AML_GE2D_MEM_ION) {
|
||||
if (build_ge2d_addr_config_ion(
|
||||
&ge2d_config->src_planes[0],
|
||||
ge2d_config->src_para.format,
|
||||
&src_addr,
|
||||
&src_stride) < 0)
|
||||
return -1;
|
||||
ge2d_log_dbg("ge2d ion alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n",
|
||||
src_addr,
|
||||
src_stride,
|
||||
ge2d_config->src_para.format);
|
||||
} else if (ge2d_config_mem->src1_mem_alloc_type ==
|
||||
AML_GE2D_MEM_DMABUF) {
|
||||
if (build_ge2d_addr_config_dma(
|
||||
&ge2d_config->src_planes[0],
|
||||
ge2d_config->src_para.format,
|
||||
&src_addr,
|
||||
&src_stride,
|
||||
DMA_TO_DEVICE) < 0)
|
||||
return -1;
|
||||
ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n",
|
||||
src_addr,
|
||||
src_stride,
|
||||
ge2d_config->src_para.format);
|
||||
}
|
||||
} else {
|
||||
if (ge2d_config_mem->src1_mem_alloc_type ==
|
||||
AML_GE2D_MEM_ION) {
|
||||
if (build_ge2d_config_ex_ion(
|
||||
&ge2d_config->src_planes[0],
|
||||
ge2d_config->src_para.format,
|
||||
&index,
|
||||
ALLOC_CANVAS_INDEX +
|
||||
alloc_canvas_offset,
|
||||
&alloc_canvas_offset) < 0)
|
||||
return -1;
|
||||
ge2d_config->src_para.canvas_index = index;
|
||||
ge2d_log_dbg("ge2d ion alloc canvas index:0x%x, format:0x%x\n",
|
||||
index, ge2d_config->src_para.format);
|
||||
} else if (ge2d_config_mem->src1_mem_alloc_type ==
|
||||
AML_GE2D_MEM_DMABUF) {
|
||||
if (build_ge2d_config_ex_dma(
|
||||
&ge2d_config->src_planes[0],
|
||||
ge2d_config->src_para.format,
|
||||
&index,
|
||||
ALLOC_CANVAS_INDEX +
|
||||
alloc_canvas_offset,
|
||||
&alloc_canvas_offset,
|
||||
DMA_TO_DEVICE) < 0)
|
||||
return -1;
|
||||
ge2d_config->src_para.canvas_index = index;
|
||||
ge2d_log_dbg("ge2d dma alloc canvas index:0x%x, format:0x%x\n",
|
||||
index, ge2d_config->src_para.format);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ge2d_config->src2_para.mem_type) {
|
||||
case CANVAS_OSD0:
|
||||
case CANVAS_OSD1:
|
||||
if (setup_display_property(&tmp,
|
||||
(ge2d_config->src2_para.mem_type == CANVAS_OSD0) ?
|
||||
OSD1_CANVAS_INDEX : OSD2_CANVAS_INDEX) < 0)
|
||||
return -1;
|
||||
ge2d_config->src2_para.canvas_index = tmp.canvas_index;
|
||||
ge2d_config->src2_para.format = tmp.ge2d_color_index;
|
||||
src2_addr = tmp.phy_addr;
|
||||
src2_stride = tmp.stride;
|
||||
|
||||
ge2d_log_dbg("ge2d: src2-->type: osd%d, format: 0x%x !!\n",
|
||||
ge2d_config->src2_para.mem_type - CANVAS_OSD0,
|
||||
ge2d_config->src2_para.format);
|
||||
|
||||
top = ge2d_config->src2_para.top;
|
||||
left = ge2d_config->src2_para.left;
|
||||
width = ge2d_config->src2_para.width;
|
||||
height = ge2d_config->src2_para.height;
|
||||
if ((left + width > tmp.xres) || (top + height > tmp.yres)) {
|
||||
ge2d_log_dbg("ge2d error: src2: osd%d, out of range\n",
|
||||
ge2d_config->src2_para.mem_type - CANVAS_OSD0);
|
||||
return -1;
|
||||
}
|
||||
ge2d_config->src2_para.width = tmp.xres;
|
||||
ge2d_config->src2_para.height = tmp.yres;
|
||||
ge2d_log_dbg("ge2d osd phy_addr:0x%x,stride=0x%x,format:0x%x\n",
|
||||
src2_addr,
|
||||
src2_stride,
|
||||
ge2d_config->src2_para.format);
|
||||
break;
|
||||
case CANVAS_ALLOC:
|
||||
top = ge2d_config->src2_para.top;
|
||||
left = ge2d_config->src2_para.left;
|
||||
width = ge2d_config->src2_para.width;
|
||||
height = ge2d_config->src2_para.height;
|
||||
if ((left + width > ge2d_config->src2_planes[0].w)
|
||||
|| (top + height > ge2d_config->src2_planes[0].h)) {
|
||||
ge2d_log_dbg("ge2d error: src2: alloc, out of range\n");
|
||||
return -1;
|
||||
}
|
||||
/*if (ge2d_config->src2_planes[0].addr ==
|
||||
* ge2d_config->src_planes[0].addr)
|
||||
* index = ge2d_config->src_para.canvas_index;
|
||||
* else
|
||||
*/
|
||||
if (ge2d_meson_dev.canvas_status == 1) {
|
||||
if (ge2d_config_mem->src2_mem_alloc_type ==
|
||||
AML_GE2D_MEM_ION) {
|
||||
if (build_ge2d_addr_config_ion(
|
||||
&ge2d_config->src2_planes[0],
|
||||
ge2d_config->src2_para.format,
|
||||
&src2_addr,
|
||||
&src2_stride) < 0)
|
||||
return -1;
|
||||
ge2d_log_dbg("ge2d ion alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n",
|
||||
src2_addr,
|
||||
src2_stride,
|
||||
ge2d_config->src2_para.format);
|
||||
} else if (ge2d_config_mem->src2_mem_alloc_type ==
|
||||
AML_GE2D_MEM_DMABUF) {
|
||||
if (build_ge2d_addr_config_dma(
|
||||
&ge2d_config->src2_planes[0],
|
||||
ge2d_config->src2_para.format,
|
||||
&src2_addr,
|
||||
&src2_stride,
|
||||
DMA_TO_DEVICE) < 0)
|
||||
return -1;
|
||||
ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n",
|
||||
src2_addr,
|
||||
src2_stride,
|
||||
ge2d_config->src2_para.format);
|
||||
}
|
||||
} else {
|
||||
if (ge2d_config_mem->src2_mem_alloc_type ==
|
||||
AML_GE2D_MEM_ION) {
|
||||
if (build_ge2d_config_ex_ion(
|
||||
&ge2d_config->src2_planes[0],
|
||||
ge2d_config->src2_para.format,
|
||||
&index,
|
||||
ALLOC_CANVAS_INDEX +
|
||||
alloc_canvas_offset,
|
||||
&alloc_canvas_offset) < 0)
|
||||
return -1;
|
||||
ge2d_config->src2_para.canvas_index = index;
|
||||
ge2d_log_dbg("ge2d src2 ion alloc, canvas index:0x%x,format:0x%x\n",
|
||||
index, ge2d_config->src2_para.format);
|
||||
} else if (ge2d_config_mem->src2_mem_alloc_type ==
|
||||
AML_GE2D_MEM_DMABUF) {
|
||||
if (build_ge2d_config_ex_dma(
|
||||
&ge2d_config->src2_planes[0],
|
||||
ge2d_config->src2_para.format,
|
||||
&index,
|
||||
ALLOC_CANVAS_INDEX +
|
||||
alloc_canvas_offset,
|
||||
&alloc_canvas_offset,
|
||||
DMA_TO_DEVICE) < 0)
|
||||
return -1;
|
||||
ge2d_config->src2_para.canvas_index = index;
|
||||
ge2d_log_dbg("ge2d src2 dma alloc, canvas index:0x%x,format:0x%x\n",
|
||||
index, ge2d_config->src2_para.format);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ge2d_config->dst_para.mem_type) {
|
||||
case CANVAS_OSD0:
|
||||
case CANVAS_OSD1:
|
||||
if (setup_display_property(&tmp,
|
||||
(ge2d_config->dst_para.mem_type == CANVAS_OSD0) ?
|
||||
OSD1_CANVAS_INDEX : OSD2_CANVAS_INDEX) < 0)
|
||||
return -1;
|
||||
ge2d_config->dst_para.canvas_index = tmp.canvas_index;
|
||||
ge2d_config->dst_para.format = tmp.ge2d_color_index;
|
||||
dst_addr = tmp.phy_addr;
|
||||
dst_stride = tmp.stride;
|
||||
|
||||
ge2d_log_dbg("ge2d: dst-->type: osd%d, format: 0x%x !!\n",
|
||||
ge2d_config->dst_para.mem_type - CANVAS_OSD0,
|
||||
ge2d_config->dst_para.format);
|
||||
|
||||
top = ge2d_config->dst_para.top;
|
||||
left = ge2d_config->dst_para.left;
|
||||
width = ge2d_config->dst_para.width;
|
||||
height = ge2d_config->dst_para.height;
|
||||
if ((left + width > tmp.xres) || (top + height > tmp.yres)) {
|
||||
ge2d_log_dbg("ge2d error: dst: osd%d, out of range\n",
|
||||
ge2d_config->dst_para.mem_type - CANVAS_OSD0);
|
||||
return -1;
|
||||
}
|
||||
ge2d_config->dst_para.width = tmp.xres;
|
||||
ge2d_config->dst_para.height = tmp.yres;
|
||||
ge2d_log_dbg("ge2d osd phy_addr:0x%x,stride=0x%x,format:0x%x\n",
|
||||
dst_addr,
|
||||
dst_stride,
|
||||
ge2d_config->dst_para.format);
|
||||
break;
|
||||
case CANVAS_ALLOC:
|
||||
top = ge2d_config->dst_para.top;
|
||||
left = ge2d_config->dst_para.left;
|
||||
width = ge2d_config->dst_para.width;
|
||||
height = ge2d_config->dst_para.height;
|
||||
if ((left + width > ge2d_config->dst_planes[0].w)
|
||||
|| (top + height > ge2d_config->dst_planes[0].h)) {
|
||||
ge2d_log_dbg("ge2d error: dst: alloc, out of range\n");
|
||||
return -1;
|
||||
}
|
||||
/*if (ge2d_config->dst_planes[0].addr ==
|
||||
* ge2d_config->src_planes[0].addr)
|
||||
* index = ge2d_config->src_para.canvas_index;
|
||||
* else if (ge2d_config->dst_planes[0].addr ==
|
||||
* ge2d_config->src2_planes[0].addr)
|
||||
* index = ge2d_config->src2_para.canvas_index;
|
||||
* else
|
||||
*/
|
||||
if (ge2d_meson_dev.canvas_status == 1) {
|
||||
if (ge2d_config_mem->dst_mem_alloc_type ==
|
||||
AML_GE2D_MEM_ION) {
|
||||
if (build_ge2d_addr_config_ion(
|
||||
&ge2d_config->dst_planes[0],
|
||||
ge2d_config->dst_para.format,
|
||||
&dst_addr,
|
||||
&dst_stride) < 0)
|
||||
return -1;
|
||||
ge2d_log_dbg("ge2d ion alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n",
|
||||
dst_addr,
|
||||
dst_stride,
|
||||
ge2d_config->dst_para.format);
|
||||
} else if (ge2d_config_mem->dst_mem_alloc_type ==
|
||||
AML_GE2D_MEM_DMABUF) {
|
||||
if (build_ge2d_addr_config_dma(
|
||||
&ge2d_config->dst_planes[0],
|
||||
ge2d_config->dst_para.format,
|
||||
&dst_addr,
|
||||
&dst_stride,
|
||||
DMA_FROM_DEVICE) < 0)
|
||||
return -1;
|
||||
ge2d_log_dbg("ge2d dma alloc phy_addr:0x%x,stride=0x%x,format:0x%x\n",
|
||||
dst_addr,
|
||||
dst_stride,
|
||||
ge2d_config->dst_para.format);
|
||||
}
|
||||
} else {
|
||||
if (ge2d_config_mem->dst_mem_alloc_type ==
|
||||
AML_GE2D_MEM_ION) {
|
||||
if (build_ge2d_config_ex_ion(
|
||||
&ge2d_config->dst_planes[0],
|
||||
ge2d_config->dst_para.format,
|
||||
&index,
|
||||
ALLOC_CANVAS_INDEX +
|
||||
alloc_canvas_offset,
|
||||
&alloc_canvas_offset) < 0)
|
||||
return -1;
|
||||
ge2d_config->dst_para.canvas_index = index;
|
||||
ge2d_log_dbg("ge2d: dst ion alloc, index:0x%x, format:0x%x\n",
|
||||
index, ge2d_config->dst_para.format);
|
||||
} else if (ge2d_config_mem->dst_mem_alloc_type ==
|
||||
AML_GE2D_MEM_DMABUF) {
|
||||
if (build_ge2d_config_ex_dma(
|
||||
&ge2d_config->dst_planes[0],
|
||||
ge2d_config->dst_para.format,
|
||||
&index,
|
||||
ALLOC_CANVAS_INDEX +
|
||||
alloc_canvas_offset,
|
||||
&alloc_canvas_offset,
|
||||
DMA_FROM_DEVICE) < 0)
|
||||
return -1;
|
||||
ge2d_config->dst_para.canvas_index = index;
|
||||
ge2d_log_dbg("ge2d: dst dma alloc, index:0x%x, format:0x%x\n",
|
||||
index, ge2d_config->dst_para.format);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ge2dgen_rendering_dir(context, ge2d_config->src_para.x_rev,
|
||||
ge2d_config->src_para.y_rev,
|
||||
ge2d_config->dst_para.x_rev,
|
||||
ge2d_config->dst_para.y_rev,
|
||||
ge2d_config->dst_xy_swap);
|
||||
ge2dgen_const_color(context, ge2d_config->alu_const_color);
|
||||
|
||||
ge2dgen_src(context, ge2d_config->src_para.canvas_index,
|
||||
ge2d_config->src_para.format,
|
||||
src_addr,
|
||||
src_stride);
|
||||
ge2dgen_src_clip(context, ge2d_config->src_para.left,
|
||||
ge2d_config->src_para.top,
|
||||
ge2d_config->src_para.width,
|
||||
ge2d_config->src_para.height);
|
||||
ge2dgen_src_key(context, ge2d_config->src_key.key_enable,
|
||||
ge2d_config->src_key.key_color,
|
||||
ge2d_config->src_key.key_mask,
|
||||
ge2d_config->src_key.key_mode);
|
||||
#ifdef CONFIG_GE2D_SRC2
|
||||
ge2dgent_src_gbalpha(context, ge2d_config->src1_gb_alpha,
|
||||
ge2d_config->src2_gb_alpha);
|
||||
#else
|
||||
ge2dgent_src_gbalpha(context, ge2d_config->src1_gb_alpha, 0);
|
||||
#endif
|
||||
ge2dgen_src_color(context, ge2d_config->src_para.color);
|
||||
|
||||
ge2dgen_src2(context, ge2d_config->src2_para.canvas_index,
|
||||
ge2d_config->src2_para.format,
|
||||
src2_addr,
|
||||
src2_stride);
|
||||
ge2dgen_src2_clip(context, ge2d_config->src2_para.left,
|
||||
ge2d_config->src2_para.top,
|
||||
ge2d_config->src2_para.width,
|
||||
ge2d_config->src2_para.height);
|
||||
|
||||
ge2dgen_dst(context, ge2d_config->dst_para.canvas_index,
|
||||
ge2d_config->dst_para.format,
|
||||
dst_addr,
|
||||
dst_stride);
|
||||
ge2dgen_dst_clip(context, ge2d_config->dst_para.left,
|
||||
ge2d_config->dst_para.top,
|
||||
ge2d_config->dst_para.width,
|
||||
ge2d_config->dst_para.height,
|
||||
DST_CLIP_MODE_INSIDE);
|
||||
|
||||
src1_gen_cfg = ge2d_wq_get_src_gen(context);
|
||||
src1_gen_cfg->fill_mode = ge2d_config->src_para.fill_mode;
|
||||
src1_gen_cfg->chfmt_rpt_pix = 0;
|
||||
src1_gen_cfg->cvfmt_rpt_pix = 0;
|
||||
/* src1_gen_cfg->clipx_start_ex = 0; */
|
||||
/* src1_gen_cfg->clipx_end_ex = 1; */
|
||||
/* src1_gen_cfg->clipy_start_ex = 1; */
|
||||
/* src1_gen_cfg->clipy_end_ex = 1; */
|
||||
|
||||
src2_dst_data_cfg = ge2d_wq_get_dst_data(context);
|
||||
src2_dst_data_cfg->src2_def_color = ge2d_config->src2_para.color;
|
||||
|
||||
src2_dst_gen_cfg = ge2d_wq_get_dst_gen(context);
|
||||
src2_dst_gen_cfg->src2_fill_mode = ge2d_config->src2_para.fill_mode;
|
||||
|
||||
dp_gen_cfg = ge2d_wq_get_dp_gen(context);
|
||||
|
||||
dp_gen_cfg->src1_vsc_phase0_always_en =
|
||||
ge2d_config->src1_hsc_phase0_always_en;
|
||||
dp_gen_cfg->src1_hsc_phase0_always_en =
|
||||
ge2d_config->src1_vsc_phase0_always_en;
|
||||
if ((context->config.v_scale_coef_type == FILTER_TYPE_GAU0) ||
|
||||
(context->config.v_scale_coef_type == FILTER_TYPE_GAU0_BOT) ||
|
||||
(context->config.v_scale_coef_type == FILTER_TYPE_GAU1) ||
|
||||
(context->config.h_scale_coef_type == FILTER_TYPE_GAU0) ||
|
||||
(context->config.h_scale_coef_type == FILTER_TYPE_GAU0_BOT) ||
|
||||
(context->config.h_scale_coef_type == FILTER_TYPE_GAU1)) {
|
||||
/* 1bit, 0: using minus, 1: using repeat data */
|
||||
dp_gen_cfg->src1_hsc_rpt_ctrl = ge2d_config->src1_hsc_rpt_ctrl;
|
||||
/* 1bit, 0: using minus 1: using repeat data */
|
||||
dp_gen_cfg->src1_vsc_rpt_ctrl = ge2d_config->src1_vsc_rpt_ctrl;
|
||||
} else {
|
||||
/* 1bit, 0: using minus, 1: using repeat data */
|
||||
dp_gen_cfg->src1_hsc_rpt_ctrl = 1;
|
||||
/* 1bit, 0: using minus 1: using repeat data */
|
||||
dp_gen_cfg->src1_vsc_rpt_ctrl = 1;
|
||||
}
|
||||
dp_gen_cfg->src1_gb_alpha = ge2d_config->src1_gb_alpha & 0xff;
|
||||
dp_gen_cfg->src1_gb_alpha_en = ge2d_config->src1_gb_alpha_en & 1;
|
||||
#ifdef CONFIG_GE2D_SRC2
|
||||
dp_gen_cfg->src2_gb_alpha = ge2d_config->src2_gb_alpha & 0xff;
|
||||
dp_gen_cfg->src2_gb_alpha_en = ge2d_config->src2_gb_alpha_en & 1;
|
||||
#endif
|
||||
dp_gen_cfg->src2_key_en = ge2d_config->src2_key.key_enable;
|
||||
dp_gen_cfg->src2_key_mode = ge2d_config->src2_key.key_mode;
|
||||
dp_gen_cfg->src2_key = ge2d_config->src2_key.key_color;
|
||||
dp_gen_cfg->src2_key_mask = ge2d_config->src2_key.key_mask;
|
||||
|
||||
dp_gen_cfg->bitmask_en = ge2d_config->bitmask_en;
|
||||
dp_gen_cfg->bitmask = ge2d_config->bitmask;
|
||||
dp_gen_cfg->bytemask_only = ge2d_config->bytemask_only;
|
||||
|
||||
ge2d_cmd_cfg = ge2d_wq_get_cmd(context);
|
||||
|
||||
ge2d_cmd_cfg->src1_fill_color_en = ge2d_config->src_para.fill_color_en;
|
||||
|
||||
ge2d_cmd_cfg->src2_x_rev = ge2d_config->src2_para.x_rev;
|
||||
ge2d_cmd_cfg->src2_y_rev = ge2d_config->src2_para.y_rev;
|
||||
ge2d_cmd_cfg->src2_fill_color_en =
|
||||
ge2d_config->src2_para.fill_color_en;
|
||||
#ifdef CONFIG_GE2D_SRC2
|
||||
ge2d_cmd_cfg->src2_cmult_ad = ge2d_config->src2_cmult_ad;
|
||||
#endif
|
||||
|
||||
ge2d_cmd_cfg->vsc_phase_slope = ge2d_config->vsc_phase_slope;
|
||||
ge2d_cmd_cfg->vsc_ini_phase = ge2d_config->vf_init_phase;
|
||||
ge2d_cmd_cfg->vsc_phase_step = ge2d_config->vsc_start_phase_step;
|
||||
ge2d_cmd_cfg->vsc_rpt_l0_num = ge2d_config->vf_rpt_num;
|
||||
|
||||
/* let internal decide */
|
||||
ge2d_cmd_cfg->hsc_phase_slope = ge2d_config->hsc_phase_slope;
|
||||
ge2d_cmd_cfg->hsc_ini_phase = ge2d_config->hf_init_phase;
|
||||
ge2d_cmd_cfg->hsc_phase_step = ge2d_config->hsc_start_phase_step;
|
||||
ge2d_cmd_cfg->hsc_rpt_p0_num = ge2d_config->hf_rpt_num;
|
||||
ge2d_cmd_cfg->src1_cmult_asel = ge2d_config->src1_cmult_asel;
|
||||
ge2d_cmd_cfg->src2_cmult_asel = ge2d_config->src2_cmult_asel;
|
||||
context->config.update_flag = UPDATE_ALL;
|
||||
/* context->config.src1_data.ddr_burst_size_y = 3; */
|
||||
/* context->config.src1_data.ddr_burst_size_cb = 3; */
|
||||
/* context->config.src1_data.ddr_burst_size_cr = 3; */
|
||||
/* context->config.src2_dst_data.ddr_burst_size= 3; */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ge2d_buffer_alloc(struct ge2d_dmabuf_req_s *ge2d_req_buf)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = &(ge2d_manager.pdev->dev);
|
||||
return ge2d_dma_buffer_alloc(ge2d_manager.buffer,
|
||||
dev, ge2d_req_buf);
|
||||
}
|
||||
|
||||
int ge2d_buffer_export(struct ge2d_dmabuf_exp_s *ge2d_exp_buf)
|
||||
{
|
||||
return ge2d_dma_buffer_export(ge2d_manager.buffer, ge2d_exp_buf);
|
||||
}
|
||||
|
||||
int ge2d_buffer_free(int index)
|
||||
{
|
||||
return ge2d_dma_buffer_free(ge2d_manager.buffer, index);
|
||||
|
||||
}
|
||||
|
||||
void ge2d_buffer_dma_flush(int dma_fd)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = &(ge2d_manager.pdev->dev);
|
||||
ge2d_dma_buffer_dma_flush(dev, dma_fd);
|
||||
}
|
||||
|
||||
void ge2d_buffer_cache_flush(int dma_fd)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = &(ge2d_manager.pdev->dev);
|
||||
ge2d_dma_buffer_cache_flush(dev, dma_fd);
|
||||
}
|
||||
|
||||
struct ge2d_context_s *create_ge2d_work_queue(void)
|
||||
{
|
||||
int i;
|
||||
@@ -1933,6 +2565,9 @@ int ge2d_wq_init(struct platform_device *pdev,
|
||||
INIT_LIST_HEAD(&ge2d_manager.process_queue);
|
||||
ge2d_manager.last_wq = NULL;
|
||||
ge2d_manager.ge2d_thread = NULL;
|
||||
ge2d_manager.buffer = ge2d_dma_buffer_create();
|
||||
if (!ge2d_manager.buffer)
|
||||
return -1;
|
||||
ge2d_clk_config(true);
|
||||
ge2d_soft_rst();
|
||||
ge2d_gen_cfg.interrupt_ctrl = 0x02;
|
||||
@@ -1966,6 +2601,8 @@ int ge2d_wq_deinit(void)
|
||||
}
|
||||
ge2d_irq = -1;
|
||||
clk_disable_unprepare(ge2d_clk);
|
||||
ge2d_dma_buffer_destroy(ge2d_manager.buffer);
|
||||
ge2d_manager.buffer = NULL;
|
||||
ge2d_manager.pdev = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -34,4 +34,9 @@ extern int ge2d_wq_init(struct platform_device *pdev,
|
||||
int irq, struct clk *clk);
|
||||
extern int ge2d_wq_deinit(void);
|
||||
|
||||
int ge2d_buffer_alloc(struct ge2d_dmabuf_req_s *ge2d_req_buf);
|
||||
int ge2d_buffer_free(int index);
|
||||
int ge2d_buffer_export(struct ge2d_dmabuf_exp_s *ge2d_exp_buf);
|
||||
void ge2d_buffer_dma_flush(int dma_fd);
|
||||
void ge2d_buffer_cache_flush(int dma_fd);
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,12 @@
|
||||
#include <linux/compat.h>
|
||||
#endif
|
||||
|
||||
enum ge2d_memtype_s {
|
||||
AML_GE2D_MEM_ION,
|
||||
AML_GE2D_MEM_DMABUF,
|
||||
AML_GE2D_MEM_INVALID,
|
||||
};
|
||||
|
||||
|
||||
#define MAX_BITBLT_WORK_CONFIG 4
|
||||
#define MAX_GE2D_CMD 32 /* 64 */
|
||||
@@ -610,6 +616,12 @@ struct ge2d_config_s {
|
||||
unsigned int update_flag;
|
||||
};
|
||||
|
||||
struct ge2d_dma_buf_s {
|
||||
dma_addr_t paddr;
|
||||
void *vaddr;
|
||||
int len;
|
||||
};
|
||||
|
||||
enum ge2d_src_dst_e {
|
||||
OSD0_OSD0 = 0,
|
||||
OSD0_OSD1,
|
||||
@@ -663,6 +675,7 @@ struct ge2d_manager_s {
|
||||
struct ge2d_context_s *last_wq;
|
||||
struct task_struct *ge2d_thread;
|
||||
struct ge2d_event_s event;
|
||||
struct aml_dma_buffer *buffer;
|
||||
int irq_num;
|
||||
int ge2d_state;
|
||||
int process_queue_state;
|
||||
@@ -949,6 +962,56 @@ struct compat_config_para_ex_ion_s {
|
||||
struct compat_config_planes_ion_s dst_planes[4];
|
||||
};
|
||||
#endif
|
||||
|
||||
struct config_para_ex_memtype_s {
|
||||
int ge2d_magic;
|
||||
struct config_para_ex_ion_s _ge2d_config_ex;
|
||||
/* memtype*/
|
||||
unsigned int src1_mem_alloc_type;
|
||||
unsigned int src2_mem_alloc_type;
|
||||
unsigned int dst_mem_alloc_type;
|
||||
};
|
||||
|
||||
struct config_ge2d_para_ex_s {
|
||||
union {
|
||||
struct config_para_ex_ion_s para_config_ion;
|
||||
struct config_para_ex_memtype_s para_config_memtype;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct compat_config_para_ex_memtype_s {
|
||||
int ge2d_magic;
|
||||
struct compat_config_para_ex_ion_s _ge2d_config_ex;
|
||||
/* memtype*/
|
||||
unsigned int src1_mem_alloc_type;
|
||||
unsigned int src2_mem_alloc_type;
|
||||
unsigned int dst_mem_alloc_type;
|
||||
};
|
||||
|
||||
struct compat_config_ge2d_para_ex_s {
|
||||
union {
|
||||
struct compat_config_para_ex_ion_s para_config_ion;
|
||||
struct compat_config_para_ex_memtype_s para_config_memtype;
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
/* for ge2d dma buf define */
|
||||
struct ge2d_dmabuf_req_s {
|
||||
int index;
|
||||
unsigned int len;
|
||||
unsigned int dma_dir;
|
||||
};
|
||||
|
||||
struct ge2d_dmabuf_exp_s {
|
||||
int index;
|
||||
unsigned int flags;
|
||||
int fd;
|
||||
};
|
||||
/* end of ge2d dma buffer define */
|
||||
|
||||
struct ge2d_device_data_s {
|
||||
int ge2d_rate;
|
||||
int src2_alp;
|
||||
@@ -990,6 +1053,21 @@ extern struct ge2d_device_data_s ge2d_meson_dev;
|
||||
_IOW(GE2D_IOC_MAGIC, 0x03, struct compat_config_para_ex_ion_s)
|
||||
#endif
|
||||
|
||||
#define GE2D_REQUEST_BUFF _IOW(GE2D_IOC_MAGIC, 0x04, struct ge2d_dmabuf_req_s)
|
||||
#define GE2D_EXP_BUFF _IOW(GE2D_IOC_MAGIC, 0x05, struct ge2d_dmabuf_exp_s)
|
||||
#define GE2D_FREE_BUFF _IOW(GE2D_IOC_MAGIC, 0x06, int)
|
||||
|
||||
#define GE2D_CONFIG_EX_MEM \
|
||||
_IOW(GE2D_IOC_MAGIC, 0x07, struct config_ge2d_para_ex_s)
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
#define GE2D_CONFIG_EX32_MEM \
|
||||
_IOW(GE2D_IOC_MAGIC, 0x07, struct compat_config_ge2d_para_ex_s)
|
||||
#endif
|
||||
|
||||
#define GE2D_SYNC_DEVICE _IOW(GE2D_IOC_MAGIC, 0x08, int)
|
||||
#define GE2D_SYNC_CPU _IOW(GE2D_IOC_MAGIC, 0x09, int)
|
||||
|
||||
extern void ge2d_set_src1_data(struct ge2d_src1_data_s *cfg);
|
||||
extern void ge2d_set_src1_gen(struct ge2d_src1_gen_s *cfg);
|
||||
extern void ge2d_set_src2_dst_data(struct ge2d_src2_dst_data_s *cfg);
|
||||
@@ -1010,6 +1088,8 @@ extern int ge2d_context_config_ex(struct ge2d_context_s *context,
|
||||
struct config_para_ex_s *ge2d_config);
|
||||
extern int ge2d_context_config_ex_ion(struct ge2d_context_s *context,
|
||||
struct config_para_ex_ion_s *ge2d_config);
|
||||
extern int ge2d_context_config_ex_mem(struct ge2d_context_s *context,
|
||||
struct config_para_ex_memtype_s *ge2d_config_mem);
|
||||
extern struct ge2d_context_s *create_ge2d_work_queue(void);
|
||||
extern int destroy_ge2d_work_queue(struct ge2d_context_s *wq);
|
||||
extern int ge2d_wq_remove_config(struct ge2d_context_s *wq);
|
||||
|
||||
Reference in New Issue
Block a user