From c5f63891e072e880c5365ee30bb55ac2cd3692c7 Mon Sep 17 00:00:00 2001 From: Lian Xu Date: Wed, 9 Mar 2022 11:17:57 +0800 Subject: [PATCH] media: rockchip: isp: add the rockit buff Change-Id: Id74df5de928a176c598ba624d21366fae95230ac Signed-off-by: Lian Xu --- drivers/media/platform/rockchip/isp/Makefile | 3 +- .../media/platform/rockchip/isp/capture_v32.c | 14 +- .../media/platform/rockchip/isp/capture_v3x.h | 8 + .../media/platform/rockchip/isp/isp_rockit.c | 322 ++++++++++++++++++ include/soc/rockchip/rockchip_rockit.h | 85 +++++ 5 files changed, 428 insertions(+), 4 deletions(-) create mode 100644 drivers/media/platform/rockchip/isp/isp_rockit.c create mode 100644 include/soc/rockchip/rockchip_rockit.h diff --git a/drivers/media/platform/rockchip/isp/Makefile b/drivers/media/platform/rockchip/isp/Makefile index 430de2e531d0..d168ffde50d1 100644 --- a/drivers/media/platform/rockchip/isp/Makefile +++ b/drivers/media/platform/rockchip/isp/Makefile @@ -41,7 +41,8 @@ video_rkisp-$(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V30) += \ video_rkisp-$(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V32) += \ capture_v32.o \ isp_params_v32.o \ - isp_stats_v32.o + isp_stats_v32.o \ + isp_rockit.o video_rkisp-$(CONFIG_ROCKCHIP_DVBM) += \ isp_dvbm.o diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index 48df3720850a..70f5d53d24bb 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -1055,7 +1055,10 @@ static int mi_frame_end(struct rkisp_stream *stream) stream->dbg.id = seq; stream->dbg.delay = ns - dev->isp_sdev.frm_timestamp; - vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE); + if (vb2_buf->memory) + vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE); + else + rkisp_rockit_buf_done(stream); } spin_lock_irqsave(&stream->vbq_lock, lock_flags); @@ -1300,8 +1303,10 @@ static void destroy_buf_queue(struct rkisp_stream *stream, buf = list_first_entry(&stream->buf_queue, struct rkisp_buffer, queue); list_del(&buf->queue); - vb2_buffer_done(&buf->vb.vb2_buf, state); + if (buf->vb.vb2_buf.memory) + vb2_buffer_done(&buf->vb.vb2_buf, state); } + rkisp_rockit_buf_free(stream); spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); } @@ -1450,7 +1455,8 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) if (ret < 0) goto buffer_done; - if (count == 0 && !stream->dummy_buf.mem_priv) { + if (count == 0 && !stream->dummy_buf.mem_priv && + list_empty(&stream->buf_queue)) { v4l2_err(v4l2_dev, "no buf for %s\n", node->vdev.name); ret = -EINVAL; goto buffer_done; @@ -1615,6 +1621,8 @@ int rkisp_register_stream_v32(struct rkisp_device *dev) rkisp_dvbm_get(dev); + rkisp_rockit_dev_init(dev); + ret = rkisp_stream_init(dev, RKISP_STREAM_MP); if (ret < 0) goto err; diff --git a/drivers/media/platform/rockchip/isp/capture_v3x.h b/drivers/media/platform/rockchip/isp/capture_v3x.h index fc82a7699990..4270c6403039 100644 --- a/drivers/media/platform/rockchip/isp/capture_v3x.h +++ b/drivers/media/platform/rockchip/isp/capture_v3x.h @@ -25,11 +25,19 @@ int rkisp_register_stream_v32(struct rkisp_device *dev); void rkisp_unregister_stream_v32(struct rkisp_device *dev); void rkisp_mi_v32_isr(u32 mis_val, struct rkisp_device *dev); void rkisp_mipi_v32_isr(u32 phy, u32 packet, u32 overflow, u32 state, struct rkisp_device *dev); + +int rkisp_rockit_buf_free(struct rkisp_stream *stream); +void rkisp_rockit_dev_init(struct rkisp_device *dev); +int rkisp_rockit_buf_done(struct rkisp_stream *stream); #else static inline int rkisp_register_stream_v32(struct rkisp_device *dev) { return -EINVAL; } static inline void rkisp_unregister_stream_v32(struct rkisp_device *dev) {} static inline void rkisp_mi_v32_isr(u32 mis_val, struct rkisp_device *dev) {} static inline void rkisp_mipi_v32_isr(u32 phy, u32 packet, u32 overflow, u32 state, struct rkisp_device *dev) {} + +static inline int rkisp_rockit_buf_free(struct rkisp_stream *stream) { return -EINVAL; } +static inline void rkisp_rockit_dev_init(struct rkisp_device *dev) { return; } +static inline int rkisp_rockit_buf_done(struct rkisp_stream *stream) { return -EINVAL; } #endif #if IS_ENABLED(CONFIG_ROCKCHIP_DVBM) diff --git a/drivers/media/platform/rockchip/isp/isp_rockit.c b/drivers/media/platform/rockchip/isp/isp_rockit.c new file mode 100644 index 000000000000..9d6200b68f6c --- /dev/null +++ b/drivers/media/platform/rockchip/isp/isp_rockit.c @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2022 Rockchip Electronics Co., Ltd */ + +#define pr_fmt(fmt) "isp_rockit: %s:%d " fmt, __func__, __LINE__ + +#include +#include +#include + +#include "dev.h" +#include "capture.h" + +static struct rockit_cfg *rockit_cfg; + +struct rkisp_rockit_buffer { + struct rkisp_buffer isp_buf; + struct dma_buf *dmabuf; + void *mpi_mem; + void *mpi_buf; + struct list_head queue; + int buf_id; + union { + u32 buff_addr; + void *vaddr; + }; +}; + +static struct rkisp_stream *rkisp_rockit_get_stream(struct rockit_cfg *input_rockit_cfg) +{ + struct rkisp_device *ispdev = NULL; + struct rkisp_stream *stream = NULL; + u8 i; + + if (rockit_cfg == NULL) { + pr_err("rockit_cfg is null get stream failed"); + return NULL; + } + + for (i = 0; i < rockit_cfg->isp_num; i++) { + if (!strcmp(rockit_cfg->rkisp_dev_cfg[i].isp_name, + input_rockit_cfg->current_name)) { + ispdev = rockit_cfg->rkisp_dev_cfg[i].isp_dev; + break; + } + } + + if (ispdev == NULL) { + pr_err("Can not find ispdev!"); + return NULL; + } + + switch (input_rockit_cfg->nick_id) { + case 0: + stream = &ispdev->cap_dev.stream[RKISP_STREAM_MP]; + break; + case 1: + stream = &ispdev->cap_dev.stream[RKISP_STREAM_SP]; + break; + case 2: + stream = &ispdev->cap_dev.stream[RKISP_STREAM_BP]; + break; + case 3: + stream = &ispdev->cap_dev.stream[RKISP_STREAM_MPDS]; + break; + case 4: + stream = &ispdev->cap_dev.stream[RKISP_STREAM_BPDS]; + break; + case 5: + stream = &ispdev->cap_dev.stream[RKISP_STREAM_LUMA]; + break; + default: + stream = NULL; + break; + } + + return stream; +} + +int rkisp_rockit_buf_queue(struct rockit_cfg *input_rockit_cfg) +{ + struct rkisp_stream *stream = NULL; + struct rkisp_rockit_buffer *isprk_buf = NULL; + struct rkisp_device *ispdev = NULL; + const struct vb2_mem_ops *g_ops = NULL; + int i, ret, height, offset; + struct rkisp_stream_cfg *stream_cfg = NULL; + void *mem = NULL; + struct sg_table *sg_tbl; + unsigned long lock_flags = 0; + + stream = rkisp_rockit_get_stream(input_rockit_cfg); + + if (stream == NULL) { + pr_err("the stream is NULL"); + return -EINVAL; + } + + ispdev = stream->ispdev; + g_ops = ispdev->hw_dev->mem_ops; + stream_cfg = &rockit_cfg->rkisp_stream_cfg[stream->id]; + + for (i = 0; i < ROCKIT_BUF_NUM_MAX; i++) { + if (stream_cfg->buff_id[i] == input_rockit_cfg->mpi_id) { + input_rockit_cfg->is_alloc = 0; + break; + } + } + + stream_cfg->node = input_rockit_cfg->node; + if (input_rockit_cfg->is_alloc) { + for (i = 0; i < ROCKIT_BUF_NUM_MAX; i++) { + if (stream_cfg->buff_id[i] == 0) { + stream_cfg->rkisp_buff[i] = + kzalloc(sizeof(struct rkisp_rockit_buffer), GFP_KERNEL); + if (stream_cfg->rkisp_buff[i] == NULL) { + pr_err("rkisp_buff alloc failed!\n"); + return -EINVAL; + } + stream_cfg->buff_id[i] = input_rockit_cfg->mpi_id; + break; + } + } + if (i == ROCKIT_BUF_NUM_MAX) + return -EINVAL; + + isprk_buf = stream_cfg->rkisp_buff[i]; + mem = g_ops->attach_dmabuf(stream->ispdev->hw_dev->dev, + input_rockit_cfg->buf, + input_rockit_cfg->buf->size, + DMA_BIDIRECTIONAL); + if (IS_ERR(mem)) + pr_err("the g_ops->attach_dmabuf is error!\n"); + + isprk_buf->mpi_mem = mem; + isprk_buf->dmabuf = input_rockit_cfg->buf; + isprk_buf->mpi_buf = input_rockit_cfg->mpibuf; + + ret = g_ops->map_dmabuf(mem); + if (ret) + pr_err("the g_ops->map_dmabuf is error!\n"); + + if (stream->ispdev->hw_dev->is_dma_sg_ops) { + sg_tbl = (struct sg_table *)g_ops->cookie(mem); + isprk_buf->buff_addr = sg_dma_address(sg_tbl->sgl); + } else { + isprk_buf->buff_addr = *((u32 *)g_ops->cookie(mem)); + } + get_dma_buf(input_rockit_cfg->buf); + } else { + for (i = 0; i < ROCKIT_BUF_NUM_MAX; i++) { + isprk_buf = stream_cfg->rkisp_buff[i]; + if (stream_cfg->buff_id[i] == input_rockit_cfg->mpi_id) + break; + } + } + for (i = 0; i < stream->out_isp_fmt.mplanes; i++) + isprk_buf->isp_buf.buff_addr[i] = isprk_buf->buff_addr; + + if (stream->out_isp_fmt.mplanes == 1) { + for (i = 0; i < stream->out_isp_fmt.cplanes - 1; i++) { + height = stream->out_fmt.height; + if (ispdev->cap_dev.wrap_line && stream->id == RKISP_STREAM_MP) + height = ispdev->cap_dev.wrap_line; + offset = (i == 0) ? + stream->out_fmt.plane_fmt[i].bytesperline * height : + stream->out_fmt.plane_fmt[i].sizeimage; + isprk_buf->isp_buf.buff_addr[i + 1] = + isprk_buf->isp_buf.buff_addr[i] + offset; + } + } + + v4l2_dbg(2, rkisp_debug, &ispdev->v4l2_dev, + "stream:%d rockit_queue buf:0x%x\n", + stream->id, isprk_buf->isp_buf.buff_addr[0]); + + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + /* single sensor with pingpong buf, update next if need */ + if (stream->ispdev->hw_dev->is_single && + stream->id != RKISP_STREAM_VIR && + stream->id != RKISP_STREAM_LUMA && + stream->streaming && !stream->next_buf) { + stream->next_buf = &isprk_buf->isp_buf; + stream->ops->update_mi(stream); + } else { + list_add_tail(&isprk_buf->isp_buf.queue, &stream->buf_queue); + } + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + + return 0; +} + +int rkisp_rockit_buf_done(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + struct rkisp_rockit_buffer *isprk_buf = + container_of(stream->curr_buf, struct rkisp_rockit_buffer, isp_buf); + struct rkisp_stream_cfg *stream_cfg = &rockit_cfg->rkisp_stream_cfg[stream->id]; + + if (!rockit_cfg->rkisp_rockit_mpibuf_done) { + pr_err("mpi_buf_done is null\n"); + return -EINVAL; + } + + rockit_cfg->frame.u32Height = stream->out_fmt.height; + + rockit_cfg->frame.u32Width = stream->out_fmt.width; + + rockit_cfg->frame.enPixelFormat = stream->out_fmt.pixelformat; + + rockit_cfg->frame.u32VirWidth = stream->out_fmt.width; + + rockit_cfg->frame.u32VirHeight = stream->out_fmt.height; + + rockit_cfg->frame.u64PTS = stream->curr_buf->vb.vb2_buf.timestamp; + + rockit_cfg->frame.u32TimeRef = stream->curr_buf->vb.sequence; + + rockit_cfg->current_name = dev->name; + + rockit_cfg->node = stream_cfg->node; + + rockit_cfg->mpibuf = isprk_buf->mpi_buf; + + if (list_empty(&stream->buf_queue)) + rockit_cfg->is_empty = true; + else + rockit_cfg->is_empty = false; + + if (rockit_cfg->rkisp_rockit_mpibuf_done) + rockit_cfg->rkisp_rockit_mpibuf_done(rockit_cfg); + + return 0; +} + +int rkisp_rockit_buf_free(struct rkisp_stream *stream) +{ + struct rkisp_rockit_buffer *isprk_buf = NULL; + int i = 0; + const struct vb2_mem_ops *g_ops = stream->ispdev->hw_dev->mem_ops; + struct rkisp_stream_cfg *stream_cfg = &rockit_cfg->rkisp_stream_cfg[stream->id]; + + for (i = 0; i < ROCKIT_BUF_NUM_MAX; i++) { + if (stream_cfg->rkisp_buff[i]) { + isprk_buf = (struct rkisp_rockit_buffer *)stream_cfg->rkisp_buff[i]; + if (isprk_buf->mpi_mem) { + g_ops->unmap_dmabuf(isprk_buf->mpi_mem); + g_ops->detach_dmabuf(isprk_buf->mpi_mem); + dma_buf_put(isprk_buf->dmabuf); + } + kfree(stream_cfg->rkisp_buff[i]); + stream_cfg->rkisp_buff[i] = NULL; + stream_cfg->buff_id[i] = 0; + } + } + return 0; +} + +void rkisp_rockit_dev_init(struct rkisp_device *dev) +{ + int i = 0; + + if (rockit_cfg == NULL) { + rockit_cfg = kzalloc(sizeof(struct rockit_cfg), GFP_KERNEL); + if (rockit_cfg == NULL) + return; + } + rockit_cfg->isp_num = dev->hw_dev->dev_num; + for (i = 0; i < rockit_cfg->isp_num; i++) { + if (dev->hw_dev->isp[i]) { + rockit_cfg->rkisp_dev_cfg[i].isp_name = + dev->hw_dev->isp[i]->name; + rockit_cfg->rkisp_dev_cfg[i].isp_dev = + dev->hw_dev->isp[i]; + } + } +} + +void *rkisp_rockit_function_register(void *function, int cmd) +{ + if (rockit_cfg == NULL) { + pr_err("rockit_cfg is null function register failed"); + return NULL; + } + + switch (cmd) { + case ROCKIT_BUF_QUE: + function = rkisp_rockit_buf_queue; + break; + case ROCKIT_MPIBUF_DONE: + rockit_cfg->rkisp_rockit_mpibuf_done = function; + if (!rockit_cfg->rkisp_rockit_mpibuf_done) + pr_err("get rkisp_rockit_buf_queue failed!"); + break; + default: + break; + } + return function; +} +EXPORT_SYMBOL(rkisp_rockit_function_register); + +int rkisp_rockit_get_ispdev(char **name) +{ + int i = 0; + + if (rockit_cfg == NULL) { + pr_err("rockit_cfg is null"); + return -EINVAL; + } + + if (name == NULL) { + pr_err("the name is null"); + return -EINVAL; + } + + for (i = 0; i < rockit_cfg->isp_num; i++) + name[i] = rockit_cfg->rkisp_dev_cfg[i].isp_name; + if (name[0] == NULL) + return -EINVAL; + else + return 0; +} +EXPORT_SYMBOL(rkisp_rockit_get_ispdev); diff --git a/include/soc/rockchip/rockchip_rockit.h b/include/soc/rockchip/rockchip_rockit.h new file mode 100644 index 000000000000..e938a204f2b8 --- /dev/null +++ b/include/soc/rockchip/rockchip_rockit.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd + */ +#ifndef __SOC_ROCKCHIP_ROCKIT_H +#define __SOC_ROCKCHIP_ROCKIT_H + +#include + +#define ROCKIT_BUF_NUM_MAX 3 +#define ROCKIT_ISP_NUM_MAX 5 +#define ROCKIT_STREAM_NUM_MAX 13 + +enum function_cmd { + ROCKIT_BUF_QUE, + ROCKIT_MPIBUF_DONE +}; + +struct rkisp_stream_cfg { + struct rkisp_rockit_buffer *rkisp_buff[ROCKIT_BUF_NUM_MAX]; + int buff_id[ROCKIT_BUF_NUM_MAX]; + void *node; +}; + +struct ISP_VIDEO_FRAMES { + u32 pMbBlk; + u32 u32Width; + u32 u32Height; + u32 u32VirWidth; + u32 u32VirHeight; + u32 enField; + u32 enPixelFormat; + u32 enVideoFormat; + u32 enCompressMode; + u32 enDynamicRange; + u32 enColorGamut; + u32 u32TimeRef; + u64 u64PTS; + + u64 u64PrivateData; + u32 u32FrameFlag; /* FRAME_FLAG_E, can be OR operation. */ +}; + +struct rkisp_dev_cfg { + char *isp_name; + void *isp_dev; +}; + +struct rockit_cfg { + u32 nick_id; + int *buff_id; + int mpi_id; + void *vvi_dev[ROCKIT_ISP_NUM_MAX]; + void *node; + void *mpibuf; + char *current_name; + bool is_alloc; + bool is_empty; + struct dma_buf *buf; + dma_addr_t dma_addr; + struct ISP_VIDEO_FRAMES frame; + struct rkisp_dev_cfg rkisp_dev_cfg[ROCKIT_ISP_NUM_MAX]; + struct rkisp_stream_cfg rkisp_stream_cfg[ROCKIT_STREAM_NUM_MAX]; + int isp_num; + int (*rkisp_rockit_mpibuf_done)(struct rockit_cfg *rockit_isp_cfg); +}; + +#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V32) + +void *rkisp_rockit_function_register(void *function, int cmd); +int rkisp_rockit_get_ispdev(char **name); +int rkisp_rockit_buf_queue(struct rockit_cfg *input_rockit_cfg); + +#else + +static inline void rkisp_rockit_function_register(void *function, int cmd) { return } +static inline int rkisp_rockit_get_ispdev(char **name) { return -EINVAL; } +static inline int rkisp_rockit_buf_queue(struct rockit_cfg *input_rockit_cfg) +{ + return -EINVAL; +} + +#endif + +#endif