camera: rockchip: cif: use dmabuf in oneframe mode

Change-Id: Ic0acd28f569ce8f4b74ec2c60fe74fd998891464
Signed-off-by: Zhang Yunlong <dalon.zhang@rock-chips.com>
This commit is contained in:
Zhang Yunlong 2017-11-23 18:44:26 +08:00 committed by Tao Huang
parent 52e4502303
commit 0012af6f03

View File

@ -253,8 +253,10 @@ static inline unsigned int read_grf_reg(unsigned int addr)
1. support rk3368.
*v0.3.0:
* 1. supprot rk3228h
*v0.4.0:
* 1.cif uses dmabuf,in this case,vb->boff is buffer fd.
*/
#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 3, 0)
#define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 4, 0)
static int version = RK_CAM_VERSION_CODE;
module_param(version, int, S_IRUGO);
@ -290,6 +292,18 @@ struct rk_camera_buffer
u32 code;
int inwork;
};
#define RK_CAMERA_MODE_DMA_SG
#ifdef RK_CAMERA_MODE_DMA_SG
#define DMABUF_MAX_FRAME 32
struct rk_camera_dma_buf_s {
struct dma_buf *dma_buf;
struct dma_buf_attachment *attach;
struct sg_table *sgt;
dma_addr_t dma_addr;
int fd;
};
#endif
enum rk_camera_reg_state
{
Reg_Invalidate,
@ -442,8 +456,11 @@ struct rk_camera_dev
wait_queue_head_t cif_stop_done;
volatile bool cif_stopped;
struct timeval first_tv;
int chip_id;
#ifdef RK_CAMERA_MODE_DMA_SG
struct rk_camera_dma_buf_s dma_buffer[DMABUF_MAX_FRAME];
int dma_buf_cnt;
#endif
};
static const struct v4l2_queryctrl rk_camera_controls[] =
@ -540,6 +557,118 @@ static void rk_camera_cif_reset(struct rk_camera_dev *pcdev, int only_rst)
return;
}
#ifdef RK_CAMERA_MODE_DMA_SG
static int rk_camera_dma_attach_device(struct rk_camera_dev *pcdev)
{
struct device *dev = pcdev->dev;
int ret;
//to do something iommu future
ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
if (ret)
return ret;
return 0;
}
static void rk_camera_dma_detach_device(struct rk_camera_dev *pcdev)
{
//to do something iommu future
}
static int rk_camera_dmabuf_cb(struct rk_camera_dev *pcdev,
struct videobuf_buffer *vb,
bool on)
{
struct dma_buf *dma_buffer;
struct dma_buf_attachment *attach;
struct sg_table *sgt;
dma_addr_t dma_addr;
int index = 0;
int ret = 0;
if (on) {
index = vb->i;
if (index >= DMABUF_MAX_FRAME) {
RKCAMERA_TR("index (%d) is wrong, max support is %d.\n", index, DMABUF_MAX_FRAME);
return -EINVAL;
}
if (pcdev->dma_buf_cnt == 0) {
ret = rk_camera_dma_attach_device(pcdev);
if (ret) {
RKCAMERA_TR("rk_camera_dma_attach_device fail\n");
return ret;
}
}
dma_buffer = dma_buf_get(vb->boff);
if (IS_ERR(dma_buffer)) {
RKCAMERA_TR("dma_buf_get fail\n");
return PTR_ERR(dma_buffer);
}
attach = dma_buf_attach(dma_buffer, pcdev->dev);
if (IS_ERR(attach)) {
RKCAMERA_TR("dma_buf_attach fail\n");
dma_buf_put(dma_buffer);
return PTR_ERR(attach);
}
sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt)) {
RKCAMERA_TR("dma_buf_map_attachment fail\n");
dma_buf_detach(dma_buffer, attach);
dma_buf_put(dma_buffer);
return PTR_ERR(sgt);
}
dma_addr = sg_dma_address(sgt->sgl);
pcdev->dma_buffer[index].dma_addr = dma_addr;
pcdev->dma_buffer[index].attach = attach;
pcdev->dma_buffer[index].dma_buf = dma_buffer;
pcdev->dma_buffer[index].sgt = sgt;
pcdev->dma_buffer[index].fd = vb->boff;
pcdev->dma_buf_cnt++;
RKCAMERA_DG1
("dma buf map: dma_addr 0x%lx, attach %p, dma_buf %p,sgt %p,fd 0x%x,buf_cnt %d, index %d\n",
(unsigned long)dma_addr,
attach,
dma_buffer,
sgt,
(int)vb->boff,
pcdev->dma_buf_cnt,
index);
} else {
index = vb->i;
if (index >= DMABUF_MAX_FRAME) {
RKCAMERA_TR("index (%d) is wrong, max support is %d.\n", index, DMABUF_MAX_FRAME);
return -EINVAL;
}
if (pcdev->dma_buf_cnt == 0) {
RKCAMERA_DG1("dma_buf_cnt is %d.\n", pcdev->dma_buf_cnt);
return ret;
}
attach = pcdev->dma_buffer[index].attach;
dma_buffer = pcdev->dma_buffer[index].dma_buf;
sgt = pcdev->dma_buffer[index].sgt;
RKCAMERA_DG1
("dma buf unmap: attach %p,dma_buf %p,sgt %p,fd 0x%x,buf_cnt %d,index %d\n",
attach,
dma_buffer,
sgt,
(int)vb->boff,
pcdev->dma_buf_cnt,
index);
dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
dma_buf_detach(dma_buffer, attach);
dma_buf_put(dma_buffer);
if (pcdev->dma_buf_cnt == 1)
rk_camera_dma_detach_device(pcdev);
pcdev->dma_buf_cnt--;
pcdev->dma_buffer[index].fd = -1;
}
return ret;
}
#endif
/*
* Videobuf operations
@ -628,6 +757,11 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
}
#endif
}
#ifdef RK_CAMERA_MODE_DMA_SG
pcdev->dma_buf_cnt = 0;
for (i = 0; i < DMABUF_MAX_FRAME; i++)
pcdev->dma_buffer[i].fd = -1;
#endif
pcdev->video_vq = vq;
RKCAMERA_DG1("videobuf size:%d, vipmem_buf size:%d, count:%d \n",*size,pcdev->vipmem_size, *count);
@ -661,6 +795,8 @@ static void rk_videobuf_free(struct videobuf_queue *vq, struct rk_camera_buffer
static int rk_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field)
{
struct soc_camera_device *icd = vq->priv_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct rk_camera_dev *pcdev = ici->priv;
struct rk_camera_buffer *buf;
int ret;
int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
@ -668,7 +804,7 @@ static int rk_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer
debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
if ((bytes_per_line < 0) || (vb->boff == 0))
if ((bytes_per_line < 0) || (vb->boff == 0) || (vb->boff == -1))
return -EINVAL;
buf = container_of(vb, struct rk_camera_buffer, vb);
@ -700,9 +836,11 @@ static int rk_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer
if (ret) {
goto fail;
}
#ifdef RK_CAMERA_MODE_DMA_SG
rk_camera_dmabuf_cb(pcdev, vb, true);
#endif
vb->state = VIDEOBUF_PREPARED;
}
return 0;
fail:
rk_videobuf_free(vq, buf);
@ -728,8 +866,13 @@ static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_came
BUG();
}
} else {
#ifdef RK_CAMERA_MODE_DMA_SG
y_addr = (unsigned long)pcdev->dma_buffer[vb->i].dma_addr;
uv_addr = y_addr + vb->width * vb->height;
#else
y_addr = vb->boff;
uv_addr = y_addr + vb->width * vb->height;
#endif
}
#if defined(CONFIG_ARCH_RK3188)
rk_camera_cif_reset(pcdev,false);
@ -1373,10 +1516,12 @@ static void rk_videobuf_release(struct videobuf_queue *vq,
}
#endif
flush_workqueue(pcdev->camera_wq);
flush_workqueue(pcdev->camera_wq);
#ifdef RK_CAMERA_MODE_DMA_SG
rk_camera_dmabuf_cb(pcdev, vb, false);
#endif
rk_videobuf_free(vq, buf);
#if CAMERA_VIDEOBUF_ARM_ACCESS
if ((pcdev->vbinfo) && (vb->i < pcdev->vbinfo_count)) {
vb_info = pcdev->vbinfo + vb->i;