diff --git a/drivers/media/platform/rockchip/isp/isp_external.h b/drivers/media/platform/rockchip/isp/isp_external.h index b7447cef83b7..866ab3ffa1dc 100644 --- a/drivers/media/platform/rockchip/isp/isp_external.h +++ b/drivers/media/platform/rockchip/isp/isp_external.h @@ -11,8 +11,12 @@ #define RKISP_VICAP_CMD_INIT_BUF \ _IOW('V', BASE_VIDIOC_PRIVATE + 1, int) +#define RKISP_VICAP_CMD_RX_BUFFER_FREE \ + _IOW('V', BASE_VIDIOC_PRIVATE + 2, struct rkisp_rx_buf) + #define RKISP_VICAP_BUF_CNT 1 -#define RKISP_RX_BUF_POOL_MAX (RKISP_VICAP_BUF_CNT * 3) +#define RKISP_VICAP_BUF_CNT_MAX 8 +#define RKISP_RX_BUF_POOL_MAX (RKISP_VICAP_BUF_CNT_MAX * 3) struct rkisp_vicap_input { u8 merge_num; @@ -42,10 +46,11 @@ struct rkisp_rx_buf_pool { struct rkisp_rx_buf { struct list_head list; struct dma_buf *dbuf; - enum rx_buf_type type; u64 timestamp; u32 sequence; + u32 type; bool is_init; + bool is_first; }; #endif diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index bb7b7700b6df..fa97cccf359a 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -2658,6 +2658,70 @@ static int rkisp_isp_sd_s_stream(struct v4l2_subdev *sd, int on) return 0; } +static void rkisp_rx_buf_free(struct rkisp_device *dev, struct rkisp_rx_buf *dbufs) +{ + const struct vb2_mem_ops *g_ops = dev->hw_dev->mem_ops; + struct rkisp_rx_buf_pool *pool; + int i = 0; + + if (!dbufs) + return; + + for (i = 0; i < RKISP_RX_BUF_POOL_MAX; i++) { + pool = &dev->pv_pool[i]; + if (dbufs == pool->dbufs) { + if (pool->mem_priv) { + g_ops->unmap_dmabuf(pool->mem_priv); + g_ops->detach_dmabuf(pool->mem_priv); + dma_buf_put(pool->dbufs->dbuf); + pool->mem_priv = NULL; + } + pool->dbufs = NULL; + break; + } + } +} + +static int rkisp_rx_buf_update(struct rkisp_device *dev, + struct rkisp_rx_buf *dbufs) +{ + struct rkisp_stream *stream; + struct rkisp_rx_buf_pool *pool; + int i; + u32 val; + + for (i = 0; i < RKISP_RX_BUF_POOL_MAX; i++) { + pool = &dev->pv_pool[i]; + if (dbufs == pool->dbufs) + break; + } + + if (pool->dbufs == NULL || pool->dbufs != dbufs) + return -EINVAL; + switch (dbufs->type) { + case BUF_SHORT: + stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD2]; + break; + case BUF_MIDDLE: + stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD0]; + break; + case BUF_LONG: + default: + stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD1]; + + } + val = pool->dma; + rkisp_write(dev, stream->config->mi.y_base_ad_init, val, false); + if (dev->hw_dev->is_unite) { + val += (stream->out_fmt.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL) * + stream->out_isp_fmt.bpp[0] / 8; + rkisp_next_write(dev, stream->config->mi.y_base_ad_init, val, false); + } + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, + "%s dma:0x%x vaddr:%p", __func__, (u32)pool->dma, pool->vaddr); + return 0; +} + void rkisp_rx_buf_pool_free(struct rkisp_device *dev) { const struct vb2_mem_ops *g_ops = dev->hw_dev->mem_ops; @@ -2731,7 +2795,10 @@ static int rkisp_rx_buf_pool_init(struct rkisp_device *dev, stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD1]; } - stream->ops->config_mi(stream); + if (dbufs->is_first) { + stream->ops->config_mi(stream); + dbufs->is_first = false; + } val = pool->dma; rkisp_write(dev, stream->config->mi.y_base_ad_init, val, false); if (dev->hw_dev->is_unite) { @@ -2760,6 +2827,8 @@ static int rkisp_sd_s_rx_buffer(struct v4l2_subdev *sd, dbufs = buf; if (!dbufs->is_init) ret = rkisp_rx_buf_pool_init(dev, dbufs); + else + ret = rkisp_rx_buf_update(dev, dbufs); /* TODO qbuf/debuf for more buffer */ @@ -3055,6 +3124,7 @@ static long rkisp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) struct rkisp_thunderboot_resmem_head *head; struct rkisp_thunderboot_shmem *shmem; struct isp2x_buf_idxfd *idxfd; + struct rkisp_rx_buf *dbufs; void *resmem_va; long ret = 0; @@ -3156,6 +3226,10 @@ static long rkisp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) case RKISP_CMD_MESHBUF_FREE: rkisp_params_meshbuf_free(&isp_dev->params_vdev, *(u64 *)arg); break; + case RKISP_VICAP_CMD_RX_BUFFER_FREE: + dbufs = (struct rkisp_rx_buf *)arg; + rkisp_rx_buf_free(isp_dev, dbufs); + break; default: ret = -ENOIOCTLCMD; }