mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
media: rockchip: vicap: support reserved mem attach dma_buf with iommu
Change-Id: Ibd8d54ddda18d2cd5ac7d3d38808fd52a0048f43 Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
This commit is contained in:
@@ -6171,6 +6171,7 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num)
|
||||
if (buf->dbufs.is_init)
|
||||
v4l2_subdev_call(sd, core, ioctl,
|
||||
RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs);
|
||||
rkcif_free_reserved_mem_buf(dev, buf);
|
||||
memset(buf, 0, sizeof(*buf));
|
||||
buf->dummy.is_free = true;
|
||||
}
|
||||
|
||||
@@ -343,17 +343,42 @@ int rkcif_alloc_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffe
|
||||
{
|
||||
struct rkcif_dummy_buffer *dummy = &buf->dummy;
|
||||
u32 reserved_mem = 0;
|
||||
struct dma_buf_attachment *dba;
|
||||
struct sg_table *sgt;
|
||||
dma_addr_t dma;
|
||||
int ret = 0;
|
||||
u32 dma_addr = 0;
|
||||
|
||||
if (dev->pre_buf_num)
|
||||
reserved_mem = SHARED_MEM_RESERVED_HEAD_SIZE;
|
||||
dummy->dma_addr = reserved_mem + dev->resmem_pa + dummy->size * buf->buf_idx;
|
||||
if (dummy->dma_addr + dummy->size > dev->resmem_pa + dev->resmem_size)
|
||||
dma_addr = reserved_mem + dev->resmem_pa + dummy->size * buf->buf_idx;
|
||||
if (dma_addr + dummy->size > dev->resmem_pa + dev->resmem_size)
|
||||
return -EINVAL;
|
||||
buf->dbufs.dma = dummy->dma_addr;
|
||||
buf->dbufs.dma = dma_addr;
|
||||
buf->dbufs.is_resmem = true;
|
||||
buf->shmem.shm_start = dummy->dma_addr;
|
||||
buf->shmem.shm_start = dma_addr;
|
||||
buf->shmem.shm_size = dummy->size;
|
||||
dummy->dbuf = rkcif_shm_alloc(&buf->shmem);
|
||||
buf->dbufs.dbuf = dummy->dbuf;
|
||||
if (dev->hw_dev->iommu_en) {
|
||||
dba = dma_buf_attach(dummy->dbuf, dev->hw_dev->dev);
|
||||
if (IS_ERR(dba)) {
|
||||
ret = PTR_ERR(dba);
|
||||
goto err_alloc;
|
||||
}
|
||||
dummy->dba = dba;
|
||||
sgt = dma_buf_map_attachment(dba, DMA_BIDIRECTIONAL);
|
||||
if (IS_ERR(sgt)) {
|
||||
ret = PTR_ERR(sgt);
|
||||
goto err_alloc;
|
||||
}
|
||||
dummy->sgt = sgt;
|
||||
dma = sg_dma_address(sgt->sgl);
|
||||
get_dma_buf(dummy->dbuf);
|
||||
dummy->dma_addr = dma;
|
||||
} else {
|
||||
dummy->dma_addr = dma_addr;
|
||||
}
|
||||
if (dummy->is_need_vaddr) {
|
||||
struct iosys_map map;
|
||||
|
||||
@@ -361,6 +386,11 @@ int rkcif_alloc_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffe
|
||||
dummy->vaddr = map.vaddr;
|
||||
}
|
||||
return 0;
|
||||
err_alloc:
|
||||
v4l2_info(&dev->v4l2_dev,
|
||||
"can't match dma_buf 0x%x with iommu\n",
|
||||
(u32)dummy->dma_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rkcif_free_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffer *buf)
|
||||
@@ -396,13 +426,30 @@ void rkcif_free_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffe
|
||||
if (buf->dbufs.is_init)
|
||||
v4l2_subdev_call(sd, core, ioctl,
|
||||
RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs);
|
||||
if (dev->hw_dev->iommu_en) {
|
||||
if (dummy->dba) {
|
||||
if (dummy->sgt) {
|
||||
dma_buf_unmap_attachment(dummy->dba, dummy->sgt,
|
||||
DMA_BIDIRECTIONAL);
|
||||
dummy->sgt = NULL;
|
||||
}
|
||||
dma_buf_detach(dummy->dbuf, dummy->dba);
|
||||
dma_buf_put(dummy->dbuf);
|
||||
dummy->dba = NULL;
|
||||
}
|
||||
}
|
||||
if (dummy->is_need_vaddr)
|
||||
dummy->dbuf->ops->vunmap(dummy->dbuf, NULL);
|
||||
#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP
|
||||
free_reserved_area(phys_to_virt(buf->shmem.shm_start),
|
||||
phys_to_virt(buf->shmem.shm_start + buf->shmem.shm_size),
|
||||
-1, "rkisp_thunderboot");
|
||||
#endif
|
||||
dma_buf_put(dummy->dbuf);
|
||||
buf->dummy.is_free = true;
|
||||
}
|
||||
|
||||
void rkcif_free_reserved_mem(u32 start, u32 size)
|
||||
{
|
||||
#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP
|
||||
free_reserved_area(phys_to_virt(start),
|
||||
phys_to_virt(start + size),
|
||||
-1, "rkisp_thunderboot");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ void rkcif_free_common_dummy_buf(struct rkcif_device *dev, struct rkcif_dummy_bu
|
||||
|
||||
int rkcif_alloc_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffer *buf);
|
||||
void rkcif_free_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffer *buf);
|
||||
void rkcif_free_reserved_mem(u32 start, u32 size);
|
||||
|
||||
#endif /* _RKCIF_COMMON_H */
|
||||
|
||||
|
||||
@@ -81,6 +81,8 @@ struct rkcif_dummy_buffer {
|
||||
struct vb2_queue vb2_queue;
|
||||
struct list_head list;
|
||||
struct dma_buf *dbuf;
|
||||
struct dma_buf_attachment *dba;
|
||||
struct sg_table *sgt;
|
||||
dma_addr_t dma_addr;
|
||||
struct page **pages;
|
||||
void *mem_priv;
|
||||
|
||||
@@ -98,6 +98,7 @@ static void sditf_buffree_work(struct work_struct *work)
|
||||
if (rx_buf) {
|
||||
list_del(&rx_buf->list_free);
|
||||
rkcif_free_reserved_mem_buf(priv->cif_dev, rx_buf);
|
||||
rkcif_free_reserved_mem(rx_buf->shmem.shm_start, rx_buf->shmem.shm_size);
|
||||
memset(rx_buf, 0, sizeof(*rx_buf));
|
||||
rx_buf->dummy.is_free = true;
|
||||
}
|
||||
@@ -1444,7 +1445,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
|
||||
if (cif_dev->is_thunderboot ||
|
||||
cif_dev->is_rtt_suspend ||
|
||||
cif_dev->is_aov_reserved)
|
||||
dma_sync_single_for_device(cif_dev->dev,
|
||||
dma_sync_single_for_device(cif_dev->hw_dev->dev,
|
||||
rx_buf->dummy.dma_addr + rx_buf->dummy.size -
|
||||
stream->pixm.plane_fmt[0].bytesperline * 3,
|
||||
stream->pixm.plane_fmt[0].bytesperline * 3,
|
||||
@@ -1453,6 +1454,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
|
||||
cif_dev->hw_dev->mem_ops->prepare(rx_buf->dummy.mem_priv);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, flags);
|
||||
|
||||
if (dbufs->is_switch && dbufs->type == BUF_SHORT) {
|
||||
if (stream->is_in_vblank || !stream->dma_en) {
|
||||
@@ -1465,7 +1467,6 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
|
||||
v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev,
|
||||
"switch to online mode\n");
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags);
|
||||
stream->is_finish_single_cap = true;
|
||||
|
||||
Reference in New Issue
Block a user